Also refactor purpose config in shell layer to use the correct `post-init-window-purpose` function.
7 KiB
Spacemacs-purpose layer
Description
This layer enables window-purpose, which provides an alternative, purpose-based window manager for Emacs. With this layer, your window layout should be robust and shouldn't change too much when opening all sorts of buffers.
Regular popwin is not triggered when window-purpose is enabled. However,
the window-purpose layer provides a purpose-popwin
extension, which
brings popwin's behavior to window-purpose and solves that problem.
Features:
- Window layout is more robust and less likely to change unintentionally
- Dedicate window to a purpose
- User-defined purposes
- Extensible window display behavior
- Empty
purpose-mode-map
, to avoid conflicts with other key maps - Replicate popwin behavior for purpose-mode - almost no regression in popup behavior from using window-purpose.
- Reuses popwin's settings:
popwin:special-display-config
,popwin:popup-window-height
andpopwin:popup-window-width
. - Difference from popwin: when several windows are open, popup window is sometimes bigger than with regular popwin in the same situation.
Purposes
window-purpose contains a configuration which assigns a purpose for each buffer. Later, when Emacs needs to display a buffer in a window, its purpose helps make a better decision of which window to use.
For example, consider the following case: Emacs frame shows three windows - one for code, one for a terminal and one general-purpose window. The general window is selected and you want to open a code file. How do you ensure that the code file will be displayed in the code window? With window-purpose you don't need to worry about it - you open the file and window-purpose places it in the correct window.
Additionally, you can dedicate a window to a purpose - so that window is reserved only for buffers that share that purpose.
switch-to-buffer and display-buffer
In regular Emacs, switch-to-buffer
follows different rules than the other
switching and popping commands, because it doesn't use display-buffer
(which
the other commands do). With window-purpose, this behavior is fixed. The
result is a better control over how buffers are displayed, since
switch-to-buffer
doesn't ignore the user's customizations anymore.
misc
- specialized helm source similar to
helm-source-buffers-list
Install
To use this configuration layer, add it to your ~/.spacemacs
. You will need to
add spacemacs-purpose
to the existing dotspacemacs-configuration-layers
list in
this file.
Usage
With window-purpose layer installed, purpose-mode
and pupo-mode
are enabled.
You can toggle purpose-mode
(SPC : purpose-mode
) at any time to return to
purpose-less behavior. You can toggle pupo-mode
(SPC : pupo-mode
) to turn
off only the purpose-popwin integration.
If you change popwin:special-display-config
in your dotspacemacs/config
, you
should call pupo/update-purpose-config
to update purpose-popwin with those
changes.
See window-purpose wiki to learn more about window-purpose.
Allocate purposes in layers
Layers can allocated buffers, which have been created by their packages, to certain purposes. This can either be done by a simple mode mapping or according to the buffer's name. This follows the same idea as the autocomplete and syntax-checking layers.
This means the configuration is not centralised in this layer but spread among the individual language layers. To ensure that users can still overwrite these configs it is important to declare them uniformly in Spacemacs.
To do so copy and adjust the following code:
;; This will only be called if `window-purpose` is listed
;; among the layer packages.
;; This code also takes care that the right loading
;; order is followed so there is no need for any
;; `with-eval-after-load` constructs.
(defun shell/post-init-window-purpose ()
(purpose-set-extension-configuration
:shell-layer
(purpose-conf :mode-purposes '((vterm-mode . terminal)
(eshell-mode . terminal)
(shell-mode . terminal)
(term-mode . terminal)))))
;; This can also be a static name allocation
;; :name-purposes '(("*Anaconda Help*" . Help))
;; or a dynamic one following a regexp
;; :regexp-purposes '(("^\\*Anaconda" . general))
Overwrite purposes in dotfile
With layers defining all kinds of purposes there will surely come the point where one wishes to change one or two of these allocations to match ones own personal needs.
This can easily be achieved by adding below code in `dotspacemacs/user-config`:
;; This will add user allocations with a higher
;; priority than the ones from the layers.
;; With this allocations can be completely
;; customised.
(purpose-add-user-purposes :names '(("*Anaconda Help*" . general))
:regexps '(("\\.hy$" . python)))
Key bindings
Key binding | Description |
---|---|
SPC r b |
Open a buffer. Only buffers with the same purpose as the current buffer are listed. |
SPC r B |
Open any buffer and ignore window-purpose when displaying the buffer. |
SPC r d |
Toggle dedication of selected window to its current purpose. |
SPC r D |
Delete all non-dedicated windows. |
SPC r p |
Choose a purpose and open a buffer with that purpose. |
SPC r P |
Change the purpose of the selected window. Changes the window's buffer accordingly. |
Caveats
Popwin and guide-key
If a buffer is displayed in two different windows, and only one of those windows is purpose-dedicated, then invoking guide-key will cause both windows to become purpose-dedicated.
Packages that do display management
Some packages that manage how windows are displayed, such as gdb
with
gdb-many-windows
, might not play nicely with window-purpose
. However, it is
usually possible to find a solution. After all, even helm
and popwin
work
with window-purpose
.