Create window-purpose layer
- Proper integration with popwin - Integrate with Helm via helm-purpose - Integrate with Ivy via ivy-purpose - Integrate with opening a new eyebrowse workspace - Enable purpose-x-kill: purpose-aware replacement of a window's buffer when a buffer is killed
This commit is contained in:
parent
42a33f3ae8
commit
edb27a089e
|
@ -0,0 +1,117 @@
|
|||
#+TITLE: window-purpose contribution layer for Spacemacs
|
||||
|
||||
* Table of Contents :TOC@4:
|
||||
- [[#description][Description]]
|
||||
- [[#purposes][Purposes]]
|
||||
- [[#switch-to-buffer-and-display-buffer][switch-to-buffer and display-buffer]]
|
||||
- [[#features][Features]]
|
||||
- [[#window-purpose-purpose-mode][window-purpose (purpose-mode)]]
|
||||
- [[#purpose-popwinel-pupo-mode][purpose-popwin.el (pupo-mode)]]
|
||||
- [[#misc][misc]]
|
||||
- [[#install][Install]]
|
||||
- [[#usage][Usage]]
|
||||
- [[#key-bindings][Key Bindings]]
|
||||
- [[#caveats][Caveats]]
|
||||
- [[#popwin-and-guide-key][Popwin and guide-key]]
|
||||
- [[#packages-that-do-display-management][Packages that do display management]]
|
||||
|
||||
* Description
|
||||
|
||||
This layer enables [[https://github.com/bmag/emacs-purpose][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 [[https://github.com/m2ym/popwin-el][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.
|
||||
|
||||
** 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.
|
||||
|
||||
* Features
|
||||
|
||||
** window-purpose (purpose-mode)
|
||||
- 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
|
||||
|
||||
** purpose-popwin.el (pupo-mode)
|
||||
- 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= and =popwin:popup-window-width=.
|
||||
- difference from popwin: when several windows are open, popup window is
|
||||
sometimes bigger than with regular popwin in the same situation.
|
||||
|
||||
** misc
|
||||
- specialized helm source similar to =helm-source-buffers-list=
|
||||
|
||||
* Install
|
||||
|
||||
To use this contribution add it to your =~/.spacemacs=
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(setq-default dotspacemacs-configuration-layers '(window-purpose))
|
||||
#+END_SRC
|
||||
|
||||
* 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 [[https://github.com/bmag/emacs-purpose/wiki][window-purpose wiki]] to learn more about window-purpose.
|
||||
|
||||
* 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=.
|
|
@ -0,0 +1,242 @@
|
|||
;;; purpose-popwin.el --- Purpose extension to act like Popwin -*- lexical-binding: t -*-
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defconst pupo--direction-to-purpose '((left . popl)
|
||||
(right . popr)
|
||||
(top . popt)
|
||||
(bottom . popb))
|
||||
"Mapping of popwin positions to purposes.")
|
||||
|
||||
(defconst pupo--purposes
|
||||
(loop for (direction . purpose) in pupo--direction-to-purpose collect purpose)
|
||||
"List of purposes used to present popwin positions.")
|
||||
|
||||
(defvar pupo--windows nil
|
||||
"List of popup windows.")
|
||||
(defvar pupo--auto-windows nil
|
||||
"List of popup windows that should be closed automatically.")
|
||||
(defvar pupo--saved-buffers nil
|
||||
"Temporary list of displayed popup buffers.")
|
||||
(defvar pupo--saved-auto-buffers nil
|
||||
"Temporary list of non-sticky displayed popup buffers.")
|
||||
|
||||
(defun pupo//popup-function (position size)
|
||||
"Generate a display function to create a popup window.
|
||||
POSITION should be one of bottom, top, left and right.
|
||||
SIZE should be either a positive number of nil. Size is interpreted as
|
||||
width or height depending on POSITION."
|
||||
(let* ((size (cl-case position
|
||||
('left (purpose--normalize-width (or size
|
||||
popwin:popup-window-width)))
|
||||
('right (purpose--normalize-width (or size
|
||||
popwin:popup-window-width)))
|
||||
('top (purpose--normalize-height (or size
|
||||
popwin:popup-window-height)))
|
||||
('bottom (purpose--normalize-height (or size
|
||||
popwin:popup-window-height)))))
|
||||
(size (when size (- size)))
|
||||
(side (cl-case position
|
||||
('left 'left)
|
||||
('right 'right)
|
||||
('top 'above)
|
||||
('bottom 'below))))
|
||||
(lambda (buffer alist)
|
||||
(let ((window (ignore-errors
|
||||
(split-window (frame-root-window) size side))))
|
||||
(when window
|
||||
(purpose-change-buffer buffer window 'window alist))))))
|
||||
|
||||
(defun pupo//position-to-display-function (position width height)
|
||||
"Generate a display function for creating a popup window.
|
||||
POSITION defaults to bottom.
|
||||
WIDTH and HEIGHT should be either a positive number or nil."
|
||||
(cl-case (or position 'bottom)
|
||||
((left right) (pupo//popup-function position width))
|
||||
((top bottom) (pupo//popup-function position height))))
|
||||
|
||||
(defun pupo//position-to-purpose (position)
|
||||
"Translate POSITION to a purpose.
|
||||
Direction -> purpose:
|
||||
left -> popl
|
||||
right -> popr
|
||||
top -> popt
|
||||
bottom -> popb
|
||||
POSITION defaults to bottom."
|
||||
(cl-case (or position 'bottom)
|
||||
;; names are short so they don't take much room in the mode-line
|
||||
('left 'popl)
|
||||
('right 'popr)
|
||||
('top 'popt)
|
||||
('bottom 'popb)))
|
||||
|
||||
(defun pupo//actions (settings)
|
||||
"Generate list of display functions for displaying a popup window.
|
||||
SETTINGS is the settings for the popup buffer, and corresponds to what
|
||||
popwin calls \"config keywords\"."
|
||||
(delq nil
|
||||
(list #'purpose-display-reuse-window-buffer
|
||||
(unless (plist-get settings :dedicated)
|
||||
#'purpose-display-reuse-window-purpose)
|
||||
(pupo//position-to-display-function (plist-get settings :position)
|
||||
(plist-get settings :width)
|
||||
(plist-get settings :height)))))
|
||||
|
||||
(defun pupo/display-condition (_purpose buffer _alist)
|
||||
"A condition to be used in `purpose-special-action-sequences'.
|
||||
Return non-nil if BUFFER is a popup buffer, according to the settings in
|
||||
`popwin:special-display-config'.
|
||||
|
||||
See `purpose-special-action-sequences' for a description of _PURPOSE,
|
||||
BUFFER and _ALIST."
|
||||
(popwin:match-config buffer))
|
||||
|
||||
(defun pupo/display-function (buffer alist)
|
||||
"A display function to be used in `purpose-special-action-sequences'.
|
||||
Display BUFFER as a popup buffer, according to the settings in
|
||||
`popwin:special-display-config'.
|
||||
|
||||
See `purpose-special-action-sequences' for a description of BUFFER and
|
||||
ALIST."
|
||||
(do ((display-fns (pupo//actions (cdr (popwin:match-config buffer)))
|
||||
(cdr display-fns))
|
||||
(window nil (and display-fns (funcall (car display-fns) buffer alist))))
|
||||
((or window (null display-fns)) window)))
|
||||
|
||||
(defun pupo/after-display (window)
|
||||
"Additional initialization for popup windows.
|
||||
Sets properties for WINDOW and updates some variables, if WINDOW is a
|
||||
popup window.
|
||||
|
||||
This function should be hooked to `purpose-display-buffer-functions'."
|
||||
(let* ((buffer (window-buffer window))
|
||||
(config (popwin:match-config buffer))
|
||||
(settings (cdr (popwin:listify config))))
|
||||
(when config
|
||||
(setq pupo--windows (delete window pupo--windows))
|
||||
(push window pupo--windows)
|
||||
(when (plist-get settings :dedicated)
|
||||
(set-window-dedicated-p window t))
|
||||
(unless (plist-get settings :stick)
|
||||
(push window pupo--auto-windows))
|
||||
(unless (or (minibuffer-window-active-p (selected-window))
|
||||
(plist-get settings :noselect))
|
||||
;; popwin selects window unless :noselect is t
|
||||
;; in contrast, popwin doesn't prevent selection when :noselect is nil
|
||||
(select-window window))
|
||||
;; make \\[C-g] delete last popup window
|
||||
(global-set-key [remap keyboard-quit] #'pupo/close-window))))
|
||||
|
||||
(defun pupo//safe-delete-window (&optional window)
|
||||
"Delete WINDOW if possible.
|
||||
Return t if successful, nil otherwise.
|
||||
WINDOW defaults to the selected window."
|
||||
(ignore-errors (delete-window window) t))
|
||||
|
||||
(defun pupo/auto-delete-windows (window)
|
||||
"Delete all non-sticky popup windows, unless WINDOW is a popup window.
|
||||
This function should be hooked to `purpose-display-buffer-functions'."
|
||||
(unless (member (purpose-window-purpose window) pupo--purposes)
|
||||
(mapc #'pupo//safe-delete-window pupo--auto-windows)
|
||||
(setq pupo--auto-windows nil)))
|
||||
|
||||
(defun pupo/close-window ()
|
||||
"Close most recent popup window.
|
||||
This command can be used repeatedly to close all popup windows."
|
||||
(interactive)
|
||||
(let ((searching t))
|
||||
(while (and pupo--windows searching)
|
||||
(when (window-live-p (car pupo--windows))
|
||||
(pupo//safe-delete-window (car pupo--windows))
|
||||
(setq searching nil))
|
||||
(pop pupo--windows))
|
||||
(unless pupo--windows
|
||||
;; no more popup windows, revert \\[C-g] to `keyboard-quit'
|
||||
(global-set-key [remap keyboard-quit] nil))))
|
||||
|
||||
(defun pupo/close-all-windows ()
|
||||
"Close all popup windows."
|
||||
(interactive)
|
||||
(dolist (purpose pupo--purposes)
|
||||
(mapc #'pupo//safe-delete-window (purpose-windows-with-purpose purpose))))
|
||||
|
||||
(defun pupo/popwin-config-to-purpose-config ()
|
||||
"Create a purpose configuration matching current popwin's settings.
|
||||
Return a `purpose-conf' object.
|
||||
Popwin's settings are taken from `popwin:special-display-config'."
|
||||
(let (mode-purposes name-purposes regexp-purposes)
|
||||
(loop for config-entry in popwin:special-display-config
|
||||
for (pattern . settings) = (popwin:listify config-entry)
|
||||
do
|
||||
(push (cons pattern
|
||||
(pupo//position-to-purpose (plist-get settings :position)))
|
||||
(cond ((symbolp pattern) mode-purposes)
|
||||
((plist-get settings :regexp) regexp-purposes)
|
||||
(t name-purposes))))
|
||||
(purpose-conf "pupo"
|
||||
:mode-purposes mode-purposes
|
||||
:name-purposes name-purposes
|
||||
:regexp-purposes regexp-purposes)))
|
||||
|
||||
(defun pupo/update-purpose-config ()
|
||||
"Update purpose configuration according to current popwin's settings.
|
||||
Popwin's settings are taken from `popwin:special-display-config'."
|
||||
(purpose-set-extension-configuration :pupo (pupo/popwin-config-to-purpose-config)))
|
||||
|
||||
(define-minor-mode pupo-mode
|
||||
"Minor mode for combining `purpose-mode' and `popwin-mode'."
|
||||
:global t
|
||||
(if pupo-mode
|
||||
(progn
|
||||
(pupo/update-purpose-config)
|
||||
(push '(pupo/display-condition pupo/display-function)
|
||||
purpose-special-action-sequences)
|
||||
(add-hook 'purpose-display-buffer-functions #'pupo/after-display)
|
||||
(add-hook 'purpose-display-buffer-functions #'pupo/auto-delete-windows))
|
||||
(purpose-del-extension-configuration :pupo)
|
||||
(setq purpose-special-action-sequences
|
||||
(delete '(pupo/display-condition pupo/display-function)
|
||||
purpose-special-action-sequences))
|
||||
(remove-hook 'purpose-display-buffer-functions #'pupo/after-display)
|
||||
(remove-hook 'purpose-display-buffer-functions #'pupo/auto-delete-windows)))
|
||||
|
||||
(defadvice popwin:create-popup-window (before pupo/before-popwin-create)
|
||||
"Save current popup windows for later restoration.
|
||||
The windows are restored in `pupo/after-popwin-create'.
|
||||
Note that the windows themselves aren't saved, but some internal
|
||||
variables are updated instead."
|
||||
(setq pupo--saved-buffers (mapcar #'window-buffer pupo--windows))
|
||||
(setq pupo--saved-auto-buffers (mapcar #'window-buffer pupo--auto-windows)))
|
||||
|
||||
(defadvice popwin:create-popup-window (after pupo/after-popwin-create)
|
||||
"Restore popup windows.
|
||||
The windows were saved in `pupo/before-popwin-create'.
|
||||
Note that the windows themselves aren't restored, but some internal
|
||||
variables are updated instead."
|
||||
(setq pupo--windows nil)
|
||||
(loop for buffer in pupo--saved-buffers
|
||||
do (setq pupo--windows
|
||||
(append pupo--windows
|
||||
(get-buffer-window-list buffer))))
|
||||
(setq pupo--auto-windows nil)
|
||||
(loop for buffer in pupo--saved-auto-buffers
|
||||
do (setq pupo--auto-windows
|
||||
(append pupo--auto-windows
|
||||
(get-buffer-window-list buffer)))))
|
||||
|
||||
(defun pupo/sync-advices ()
|
||||
(if pupo-mode
|
||||
(progn
|
||||
(ad-enable-advice 'popwin:create-popup-window 'before 'pupo/before-popwin-create)
|
||||
(ad-enable-advice 'popwin:create-popup-window 'after 'pupo/after-popwin-create)
|
||||
(ad-update 'popwin:create-popup-window)
|
||||
(ad-activate 'popwin:create-popup-window))
|
||||
(ad-disable-advice 'popwin:create-popup-window 'before 'pupo/before-popwin-create)
|
||||
(ad-disable-advice 'popwin:create-popup-window 'after 'pupo/after-popwin-create)
|
||||
(ad-update 'popwin:create-popup-window)))
|
||||
(add-hook 'pupo-mode-hook #'pupo/sync-advices)
|
||||
|
||||
(provide 'purpose-popwin)
|
||||
;;; purpose-popwin.el ends here
|
|
@ -0,0 +1,169 @@
|
|||
;;; packages.el --- window-purpose Layer packages File for Spacemacs
|
||||
;;
|
||||
;; Copyright (c) 2012-2014 Sylvain Benner
|
||||
;; Copyright (c) 2014-2015 Sylvain Benner & Contributors
|
||||
;;
|
||||
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
|
||||
;; URL: https://github.com/syl20bnr/spacemacs
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
(setq window-purpose-packages '(eyebrowse
|
||||
(helm-purpose :toggle (configuration-layer/layer-usedp 'helm))
|
||||
(ivy-purpose :toggle (configuration-layer/layer-usedp 'ivy))
|
||||
popwin
|
||||
(purpose-popwin :location local)
|
||||
window-purpose))
|
||||
|
||||
(setq window-purpose-excluded-packages '())
|
||||
|
||||
(defun window-purpose/post-init-eyebrowse ()
|
||||
(defvar window-purpose--eyebrowse-new-workspace eyebrowse-new-workspace
|
||||
"Internal backup of `eyebrowse-new-workspace'.")
|
||||
|
||||
;; replacement for `eyebrowse-new-workspace' that handles purpose-dedicated
|
||||
;; windows correctly
|
||||
(defun window-purpose/new-workspace ()
|
||||
"Create a new eyebrowse workspace."
|
||||
;; call original `eyebrowse-new-workspace' (partially copied from
|
||||
;; `eyebrowse-switch-to-window-config')
|
||||
(cond
|
||||
((stringp window-purpose--eyebrowse-new-workspace)
|
||||
(switch-to-buffer (get-buffer-create window-purpose--eyebrowse-new-workspace)))
|
||||
((functionp window-purpose--eyebrowse-new-workspace)
|
||||
(funcall window-purpose--eyebrowse-new-workspace))
|
||||
(t (switch-to-buffer "*scratch*")))
|
||||
|
||||
;; in case opening the new buffer splitted the frame (e.g.
|
||||
;; `eyebrowse-switch-to-window-config' was called from a purpose-dedicated
|
||||
;; buffer)
|
||||
(delete-other-windows))
|
||||
|
||||
(defun window-purpose/sync-eyebrowse ()
|
||||
"Synchronize window-purpose layer with eyebrowse.
|
||||
Set `eyebrowse-new-workspace' value depending on the state of `purpose-mode'."
|
||||
(if purpose-mode
|
||||
(setq eyebrowse-new-workspace #'window-purpose/new-workspace)
|
||||
(setq eyebrowse-new-workspace window-purpose--eyebrowse-new-workspace)))
|
||||
(add-hook 'purpose-mode-hook #'window-purpose/sync-eyebrowse)
|
||||
(when (boundp 'purpose-mode)
|
||||
;; sync with eyebrowse now if window-purpose was already loaded
|
||||
(window-purpose/sync-eyebrowse)))
|
||||
|
||||
(defun window-purpose/init-helm-purpose ()
|
||||
(setq purpose-preferred-prompt 'helm)
|
||||
;; remap bindings defined with `spacemacs/set-leader-keys'
|
||||
(global-set-key [remap purpose-switch-buffer-with-purpose]
|
||||
#'helm-purpose-switch-buffer-with-purpose)
|
||||
(global-set-key [remap switch-buffer-without-purpose]
|
||||
#'helm-purpose-mini-ignore-purpose)
|
||||
(global-set-key [remap purpose-switch-buffer-with-some-purpose]
|
||||
#'helm-purpose-switch-buffer-with-some-purpose))
|
||||
|
||||
(defun window-purpose/init-ivy-purpose ()
|
||||
;; vanilla lets `ivy' take over
|
||||
(use-package ivy-purpose
|
||||
:defer t
|
||||
:commands (ivy-purpose-switch-buffer-with-purpose
|
||||
ivy-purpose-switch-buffer-without-purpose
|
||||
ivy-purpose-switch-buffer-with-some-purpose)
|
||||
:init
|
||||
(progn
|
||||
(setq purpose-preferred-prompt 'vanilla)
|
||||
(global-set-key [remap purpose-switch-buffer-with-purpose]
|
||||
#'ivy-purpose-switch-buffer-with-purpose)
|
||||
(global-set-key [remap purpose-switch-buffer-without-purpose]
|
||||
#'ivy-purpose-switch-buffer-without-purpose)
|
||||
(global-set-key [remap purpose-switch-buffer-with-some-purpose]
|
||||
#'ivy-purpose-switch-buffer-with-some-purpose))))
|
||||
|
||||
(defun window-purpose/post-init-popwin ()
|
||||
;; when popwin creates a popup window, it removes the `purpose-dedicated'
|
||||
;; window parameter from all windows, so we must save and restore it
|
||||
;; ourselves. this works well as long as no buffer is displayed in more than
|
||||
;; one window. if a buffer is displayed in several windows, and at least one
|
||||
;; of these windows is purpose-dedicated, then all these windows will become
|
||||
;; purpose-dedicated after popwin creates a popup window.
|
||||
;; there is no problem if the local purpose-popwin extension is used, as long
|
||||
;; as the user doesn't call `popwin:create-popup-window' directly (e.g. <f2>
|
||||
;; from `helm-mini')
|
||||
|
||||
(defvar window-purpose--dedicated-windows nil)
|
||||
|
||||
(defadvice popwin:create-popup-window (before window-purpose/save-dedicated-windows)
|
||||
(setq window-purpose--dedicated-windows
|
||||
(cl-loop for window in (window-list)
|
||||
if (purpose-window-purpose-dedicated-p window)
|
||||
collect (window-buffer window))))
|
||||
|
||||
(defadvice popwin:create-popup-window (after window-purpose/restore-dedicated-windows)
|
||||
(cl-loop for buffer in window-purpose--dedicated-windows
|
||||
do (cl-loop for window in (get-buffer-window-list buffer)
|
||||
do (purpose-set-window-purpose-dedicated-p window t))))
|
||||
|
||||
(defun window-purpose/sync-popwin ()
|
||||
"Synchronize window-purpose layer with popwin.
|
||||
Enable or disable advices to popwin, according to the state of `purpose-mode'."
|
||||
(if purpose-mode
|
||||
(progn
|
||||
(ad-enable-advice 'popwin:create-popup-window
|
||||
'before 'window-purpose/save-dedicated-windows)
|
||||
(ad-enable-advice 'popwin:create-popup-window
|
||||
'after 'window-purpose/restore-dedicated-windows)
|
||||
(ad-update 'popwin:create-popup-window)
|
||||
(ad-activate 'popwin:create-popup-window))
|
||||
(ad-disable-advice 'popwin:create-popup-window
|
||||
'before 'window-purpose/save-dedicated-windows)
|
||||
(ad-disable-advice 'popwin:create-popup-window
|
||||
'after 'window-purpose/restore-dedicated-windows)
|
||||
(ad-update 'popwin:create-popup-window)))
|
||||
(add-hook 'purpose-mode-hook #'window-purpose/sync-popwin)
|
||||
(when (boundp 'purpose-mode)
|
||||
;; sync with popwin now if window-purpose was already loaded
|
||||
(window-purpose/sync-popwin)))
|
||||
|
||||
(defun window-purpose/init-purpose-popwin ()
|
||||
(use-package purpose-popwin
|
||||
;; don't load purpose-popwin if popwin is excluded.
|
||||
;; can't wrap `window-purpose/init-purpose-popwin' in a top-level `when'
|
||||
;; because popwin isn't yet marked as used then. the condition won't work in
|
||||
;; top-level, only here
|
||||
:if (configuration-layer/package-usedp 'popwin)
|
||||
;; purpose-popwin needs to be configured after popwin and window-purpose.
|
||||
;; popwin is guaranteed to run before purpose-popwin due to alphabetic order,
|
||||
;; but for window-purpose we need to use :after
|
||||
:after window-purpose
|
||||
:config
|
||||
(progn
|
||||
(pupo-mode)
|
||||
;; override popwin commands with pupo commands
|
||||
(spacemacs/set-leader-keys
|
||||
"wpp" #'pupo/close-window
|
||||
"wpP" #'pupo/close-all-windows))))
|
||||
|
||||
(defun window-purpose/init-window-purpose ()
|
||||
(use-package window-purpose
|
||||
:init
|
||||
;; overriding `purpose-mode-map' with empty keymap, so it doesn't conflict
|
||||
;; with original `C-x C-f', `C-x b', etc. and `semantic' key bindings. must
|
||||
;; be done before `window-purpose' is loaded
|
||||
(setq purpose-mode-map (make-sparse-keymap))
|
||||
:config
|
||||
(progn
|
||||
;; 'r' is for "puRpose" ('w', 'p' are crowded, 'W', 'P' aren't comfortable)
|
||||
(spacemacs/set-leader-keys
|
||||
"rb" 'purpose-switch-buffer-with-purpose
|
||||
"rB" 'switch-buffer-without-purpose
|
||||
"rd" 'purpose-toggle-window-purpose-dedicated
|
||||
"rD" 'purpose-delete-non-dedicated-windows
|
||||
"rp" 'purpose-switch-buffer-with-some-purpose
|
||||
"rP" 'purpose-set-window-purpose)
|
||||
|
||||
(purpose-mode)
|
||||
(purpose-x-golden-ratio-setup)
|
||||
;; when killing a purpose-dedicated buffer that is displayed in a window,
|
||||
;; ensure that the buffer is replaced by a buffer with the same purpose
|
||||
;; (or the window deleted, if no such buffer)
|
||||
(purpose-x-kill-setup))))
|
Loading…
Reference in New Issue