feat(evil): optionally wrap move-window commands

Introduces an `+evil-want-move-window-to-wrap-around` option. If
non-nil, `+evil/window-move-*` commands will wrap around the frame. If
these commands are passed the prefix arg, behave as if
`+evil-want-move-window-to-wrap-around` were inverted (just once).

Close: #7218
Co-authored-by: agzam <agzam@users.noreply.github.com>
This commit is contained in:
Henrik Lissner 2024-07-29 18:40:22 -04:00
parent 2cb8328f68
commit 04efd82590
No known key found for this signature in database
GPG key ID: B60957CA074D39A3
2 changed files with 30 additions and 11 deletions

View file

@ -39,11 +39,16 @@ replacing its contents."
(let ((evil-kill-on-visual-paste (not evil-kill-on-visual-paste))) (let ((evil-kill-on-visual-paste (not evil-kill-on-visual-paste)))
(call-interactively #'evil-paste-after))) (call-interactively #'evil-paste-after)))
(defun +evil--window-swap (direction) (defun +evil--window-swap (direction &optional invert-wrap?)
"Move current window to the next window in DIRECTION. "Move current window to the next window in DIRECTION.
If there are no windows there and there is only one window, split in that If there are no windows there and there is only one window, split in that
direction and place this window there. If there are no windows and this isn't direction and place this window there. If there are no windows and this isn't
the only window, use evil-window-move-* (e.g. `evil-window-move-far-left')." the only window, uses evil-window-move-* (e.g. `evil-window-move-far-left').
If already at the edge of the frame and `+evil-want-move-window-to-wrap-around'
is non-nil, move the window to the other end of the frame. Inverts
`+evil-want-move-window-to-wrap-around' if INVERT-WRAP? is non-nil."
(unless (memq direction '(left right up down)) (unless (memq direction '(left right up down))
(user-error "Invalid direction: %s" direction)) (user-error "Invalid direction: %s" direction))
(when (window-dedicated-p) (when (window-dedicated-p)
@ -61,7 +66,14 @@ the only window, use evil-window-move-* (e.g. `evil-window-move-far-left')."
'(up down) '(left right)) '(up down) '(left right))
if (window-in-direction dir nil this-window) if (window-in-direction dir nil this-window)
return t))) return t)))
(user-error "Window is already at the edge") (if (funcall (if invert-wrap? #'not #'identity) +evil-want-move-window-to-wrap-around)
(call-interactively
(pcase direction
('left #'evil-window-move-far-right)
('right #'evil-window-move-far-left)
('up #'evil-window-move-very-bottom)
('down #'evil-window-move-very-top)))
(user-error "Window is already at the edge"))
(call-interactively (call-interactively
(pcase direction (pcase direction
('left #'evil-window-move-far-left) ('left #'evil-window-move-far-left)
@ -77,21 +89,25 @@ the only window, use evil-window-move-* (e.g. `evil-window-move-far-left')."
(select-window that-window)))) (select-window that-window))))
;;;###autoload ;;;###autoload
(defun +evil/window-move-left () (defun +evil/window-move-left (&optional arg)
"Swap windows to the left." "Swap windows to the left."
(interactive) (+evil--window-swap 'left)) (interactive "P")
(+evil--window-swap 'left (or arg +evil-want-move-window-to-wrap-around)))
;;;###autoload ;;;###autoload
(defun +evil/window-move-right () (defun +evil/window-move-right (&optional arg)
"Swap windows to the right" "Swap windows to the right"
(interactive) (+evil--window-swap 'right)) (interactive "P")
(+evil--window-swap 'right (or arg +evil-want-move-window-to-wrap-around)))
;;;###autoload ;;;###autoload
(defun +evil/window-move-up () (defun +evil/window-move-up (&optional arg)
"Swap windows upward." "Swap windows upward."
(interactive) (+evil--window-swap 'up)) (interactive "P")
(+evil--window-swap 'up (or arg +evil-want-move-window-to-wrap-around)))
;;;###autoload ;;;###autoload
(defun +evil/window-move-down () (defun +evil/window-move-down (&optional arg)
"Swap windows downward." "Swap windows downward."
(interactive) (+evil--window-swap 'down)) (interactive "P")
(+evil--window-swap 'down (or arg +evil-want-move-window-to-wrap-around)))
;;;###autoload ;;;###autoload
(defun +evil/window-split-and-follow () (defun +evil/window-split-and-follow ()

View file

@ -12,6 +12,9 @@ Set this to `nil' to disable universal-repeating on these keys.")
"If non-nil, the o/O keys will continue comment lines if the point is on a "If non-nil, the o/O keys will continue comment lines if the point is on a
line with a linewise comment.") line with a linewise comment.")
(defvar +evil-want-move-window-to-wrap-around nil
"If non-nil, `+evil/window-move-*' commands will wrap around.")
(defvar +evil-preprocessor-regexp "^\\s-*#[a-zA-Z0-9_]" (defvar +evil-preprocessor-regexp "^\\s-*#[a-zA-Z0-9_]"
"The regexp used by `+evil/next-preproc-directive' and "The regexp used by `+evil/next-preproc-directive' and
`+evil/previous-preproc-directive' on ]# and [#, to jump between preprocessor `+evil/previous-preproc-directive' on ]# and [#, to jump between preprocessor