aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEivind Fonn <evfonn@gmail.com>2019-12-30 11:02:18 +0100
committerGitHub <noreply@github.com>2019-12-30 11:02:18 +0100
commit30e951fd41ae408fab7fc19004f88c31205c0e4a (patch)
tree150579b63a26ac893f923c1323ffaaa57bdc7482
parent40bda9ed89c8a28109601e63962431ff69370828 (diff)
parent995df103d4cb1b0516683226b3fa38515f1b6e99 (diff)
Merge pull request #1130 from dzop/preserve-window-parameters
Better integration of window manipulation commands
-rw-r--r--evil-commands.el156
1 files changed, 66 insertions, 90 deletions
diff --git a/evil-commands.el b/evil-commands.el
index 4bc985c..b37b7d5 100644
--- a/evil-commands.el
+++ b/evil-commands.el
@@ -3835,6 +3835,19 @@ The 'bang' argument means to sort in reverse order."
;;; Window navigation
+(defmacro evil-save-side-windows (&rest body)
+ "Toggle side windows, evaluate BODY, restore side windows."
+ (declare (indent defun) (debug (&rest form)))
+ (let ((sides (make-symbol "sidesvar")))
+ `(let ((,sides (and (functionp 'window-toggle-side-windows)
+ (window-with-parameter 'window-side))))
+ (when ,sides
+ (window-toggle-side-windows))
+ (unwind-protect
+ (progn ,@body)
+ (when ,sides
+ (window-toggle-side-windows))))))
+
(defun evil-resize-window (new-size &optional horizontal)
"Set the current window's width or height to NEW-SIZE.
If HORIZONTAL is non-nil the width of the window is changed,
@@ -3842,28 +3855,35 @@ otherwise its height is changed."
(let ((count (- new-size (if horizontal (window-width) (window-height)))))
(enlarge-window count horizontal)))
-(defun evil-get-buffer-tree (wintree)
- "Extracts the buffer tree from a given window tree WINTREE."
- (if (consp wintree)
- (cons (car wintree) (mapcar #'evil-get-buffer-tree (cddr wintree)))
- (window-buffer wintree)))
-
-(defun evil-restore-window-tree (win tree)
- "Restore the given buffer-tree layout as subwindows of WIN.
-TREE is the tree layout to be restored.
-A tree layout is either a buffer or a list of the form (DIR TREE ...),
-where DIR is t for horizontal split and nil otherwise. All other
-elements of the list are tree layouts itself."
- (if (bufferp tree)
- (set-window-buffer win tree)
- ;; if tree is buffer list with one buffer only, do not split
- ;; anymore
- (if (not (cddr tree))
- (evil-restore-window-tree win (cadr tree))
- ;; tree is a regular list, split recursively
- (let ((newwin (split-window win nil (not (car tree)))))
- (evil-restore-window-tree win (cadr tree))
- (evil-restore-window-tree newwin (cons (car tree) (cddr tree)))))))
+(defun evil-move-window (side)
+ "Move the `selected-window' to SIDE.
+The state of the `selected-window' is saved along with the state
+of the window tree consisting of all the other windows. Then, all
+windows are deleted, the remaining window is split according to
+SIDE, the state of the window at SIDE is replaced with the saved
+state of the `selected-window', and, finally, the state of the
+saved window tree is reconstructed on the opposite side.
+
+SIDE has the same meaning as in `split-window'.
+
+Note, this function only operates on the window tree rooted in
+the frame's main window and effectively preserves any side
+windows \(i.e. windows with a valid window-side window
+parameter\)."
+ (evil-save-side-windows
+ (unless (one-window-p)
+ (save-excursion
+ (let ((w (window-state-get (selected-window))))
+ (delete-window)
+ (let ((wtree (window-state-get)))
+ (delete-other-windows)
+ (let ((subwin (selected-window))
+ ;; NOTE: SIDE is new in Emacs 24
+ (newwin (split-window nil nil side)))
+ (window-state-put wtree subwin)
+ (window-state-put w newwin)
+ (select-window newwin)))))
+ (balance-windows))))
(defun evil-alternate-buffer (&optional window)
"Return the last buffer WINDOW has displayed other than the
@@ -4142,98 +4162,54 @@ If ARG is empty, maximize the current window height."
(evil-window-decrease-height (- n))))))
(evil-define-command evil-window-rotate-upwards ()
- "Rotates the windows according to the currenty cyclic ordering."
+ "Rotates the windows according to the current cyclic ordering."
:repeat nil
- (let ((wlist (window-list))
- (blist (mapcar #'(lambda (w) (window-buffer w))
- (window-list))))
- (setq blist (append (cdr blist) (list (car blist))))
- (while (and wlist blist)
- (set-window-buffer (car wlist) (car blist))
- (setq wlist (cdr wlist)
- blist (cdr blist)))
- (select-window (car (last (window-list))))))
+ (evil-save-side-windows
+ (let ((wlist (window-list))
+ (slist (mapcar #'window-state-get (window-list))))
+ (setq slist (append (cdr slist) (list (car slist))))
+ (while (and wlist slist)
+ (window-state-put (car slist) (car wlist))
+ (setq wlist (cdr wlist)
+ slist (cdr slist)))
+ (select-window (car (last (window-list)))))))
(evil-define-command evil-window-rotate-downwards ()
- "Rotates the windows according to the currenty cyclic ordering."
+ "Rotates the windows according to the current cyclic ordering."
:repeat nil
- (let ((wlist (window-list))
- (blist (mapcar #'(lambda (w) (window-buffer w))
- (window-list))))
- (setq blist (append (last blist) blist))
- (while (and wlist blist)
- (set-window-buffer (car wlist) (car blist))
- (setq wlist (cdr wlist)
- blist (cdr blist)))
- (select-window (cadr (window-list)))))
+ (evil-save-side-windows
+ (let ((wlist (window-list))
+ (slist (mapcar #'window-state-get (window-list))))
+ (setq slist (append (last slist) slist))
+ (while (and wlist slist)
+ (window-state-put (car slist) (car wlist))
+ (setq wlist (cdr wlist)
+ slist (cdr slist)))
+ (select-window (cadr (window-list))))))
(evil-define-command evil-window-move-very-top ()
"Closes the current window, splits the upper-left one horizontally
and redisplays the current buffer there."
:repeat nil
- (unless (one-window-p)
- (save-excursion
- (let ((b (current-buffer)))
- (delete-window)
- (let ((btree (evil-get-buffer-tree (car (window-tree)))))
- (delete-other-windows)
- (let ((newwin (selected-window))
- (subwin (split-window)))
- (evil-restore-window-tree subwin btree)
- (set-window-buffer newwin b)
- (select-window newwin)))))
- (balance-windows)))
+ (evil-move-window 'above))
(evil-define-command evil-window-move-far-left ()
"Closes the current window, splits the upper-left one vertically
and redisplays the current buffer there."
:repeat nil
- (unless (one-window-p)
- (save-excursion
- (let ((b (current-buffer)))
- (delete-window)
- (let ((btree (evil-get-buffer-tree (car (window-tree)))))
- (delete-other-windows)
- (let ((newwin (selected-window))
- (subwin (split-window-horizontally)))
- (evil-restore-window-tree subwin btree)
- (set-window-buffer newwin b)
- (select-window newwin)))))
- (balance-windows)))
+ (evil-move-window 'left))
(evil-define-command evil-window-move-far-right ()
"Closes the current window, splits the lower-right one vertically
and redisplays the current buffer there."
:repeat nil
- (unless (one-window-p)
- (save-excursion
- (let ((b (current-buffer)))
- (delete-window)
- (let ((btree (evil-get-buffer-tree (car (window-tree)))))
- (delete-other-windows)
- (let ((subwin (selected-window))
- (newwin (split-window-horizontally)))
- (evil-restore-window-tree subwin btree)
- (set-window-buffer newwin b)
- (select-window newwin)))))
- (balance-windows)))
+ (evil-move-window 'right))
(evil-define-command evil-window-move-very-bottom ()
"Closes the current window, splits the lower-right one horizontally
and redisplays the current buffer there."
:repeat nil
- (unless (one-window-p)
- (save-excursion
- (let ((b (current-buffer)))
- (delete-window)
- (let ((btree (evil-get-buffer-tree (car (window-tree)))))
- (delete-other-windows)
- (let ((subwin (selected-window))
- (newwin (split-window)))
- (evil-restore-window-tree subwin btree)
- (set-window-buffer newwin b)
- (select-window newwin)))))
- (balance-windows)))
+ (evil-move-window 'below))
;;; Mouse handling