A minor mode to show code context for code above the window similar to the excellent context.vim plugin. Like a little stool for your window that you can use to view stuff in the buffer above the window.
Using only indentation means we can use this in non treesitter based modes as well, but I’m not against adding some treesitter support (I just need to find time to dig into the treesitter api)
It can be a little janky at times, since I had to do some hacky things with overlays since headerline doesn’t support multiple lines. Essentially on every scroll, we have to move the overlay to go back to the top of the screen so it acts like a pseudo multi-line header-line. It works pretty well with my usage of mostly golang and elisp.
Also has some support for org mode as well.
Primarily tested on emacs29 with doom and with vanilla.
I really liked context.vim when I was using vim and I couldn’t really find something that fit exactly.
I used some of the other packages like the breadcrumb headerline of lsp mode, which-function-mode and topsy, but they weren’t quite the same.
With emacs 29 we have built in package-vc-install
(package-vc-install "https://github.com/JasZhe/window-stool")
With straight:
(straight-use-package
'(window-stool :type git :host github :repo "jaszhe/window-stool"))
With doom:
(package! window-stool :recipe (:host github :repo "jaszhe/window-stool" :files ("*.el")))
Add a hook to prog-mode (or any other mode) with a use-package config
(use-package window-stool
:config
(add-hook 'prog-mode-hook #'window-stool-mode))
window-stool-face
- the overlay will inherit this face if you want to change from the default fringe
inheritance with :extend t
window-stool-n-from-top
and window-stool-n-from-bottom
- optionally limit the amount of context to show. The default is to take the first context line from the outer most context, (this is usually the function signature, for example) and then 2 lines of the inner most context (like the most recent if statement you just passed by)
window-stool-major-mode-functions-alist
- a list of (major-mode . function) for specific context rules outside of the basic indentation based one. An org one is provided as an example (although feel free to change it).
Note: I would still classify this as somewhat experimental. I do think the current contract for this makes sense (it just returns a list of strings) but there is a small chance this might change if I get some feedback about it.
window-stool-valid-indentation-ctx-regex
- an alist of (major-mode . regex) to match “useful” lines based on the current major mode. The default, if major mode isn’t found, is any line with at least 2 alphanumeric characters.
This only affects the default indentation based context function. Context functions provided above will not inherit this.
This way we avoid taking lines of only opening braces like in this example:
if condition
{
blah
}
When we’re inside the block, we want to see the if statement instead of just “{” as the outermost context.
window-stool-use-overlays
- the default is to use overlays. Instead of an overlay, a minimally sized window will be shown at the top of the currently selected window that houses the context. To limit complexity, only one of these context windows exists at a time. It follows the selected window.
Also note, that this will add some advice to some window movement commands so that we can “skip” over the context window, in the case where you have windows on top of each other.
It’s also recommended to turn off window-divider-mode
or set window-divider-default-places
to right-only
since it makes the context window stick out less, like how an overlay would look.
Another thing that’s useful if you want the window-stool to appear with consult previews is to add
(add-to-list 'consult-preview-allowed-hooks #'window-stool-mode)
(theme is modus-operandi built into emacs 29)
Most of the alternatives use a single line via the header-line, but they’re also probably much more performant than this package. This package also takes up more screen real estate than the single header-line ones.
This package also behaves more like topsy/org-sticky-header in that it starts the context search from the beginning of the window rather than at point itself like the other packages.
Any feedback via the issues tab would be appreciated :)