From 04efd825900849e1b601c00c0a5c78706c83721b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 29 Jul 2024 18:40:22 -0400 Subject: [PATCH] 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 --- modules/editor/evil/autoload/evil.el | 38 ++++++++++++++++++++-------- modules/editor/evil/config.el | 3 +++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/modules/editor/evil/autoload/evil.el b/modules/editor/evil/autoload/evil.el index dfb0748ee..8746e5736 100644 --- a/modules/editor/evil/autoload/evil.el +++ b/modules/editor/evil/autoload/evil.el @@ -39,11 +39,16 @@ replacing its contents." (let ((evil-kill-on-visual-paste (not evil-kill-on-visual-paste))) (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. + 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 -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)) (user-error "Invalid direction: %s" direction)) (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)) if (window-in-direction dir nil this-window) 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 (pcase direction ('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)))) ;;;###autoload -(defun +evil/window-move-left () +(defun +evil/window-move-left (&optional arg) "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 -(defun +evil/window-move-right () +(defun +evil/window-move-right (&optional arg) "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 -(defun +evil/window-move-up () +(defun +evil/window-move-up (&optional arg) "Swap windows upward." - (interactive) (+evil--window-swap 'up)) + (interactive "P") + (+evil--window-swap 'up (or arg +evil-want-move-window-to-wrap-around))) ;;;###autoload -(defun +evil/window-move-down () +(defun +evil/window-move-down (&optional arg) "Swap windows downward." - (interactive) (+evil--window-swap 'down)) + (interactive "P") + (+evil--window-swap 'down (or arg +evil-want-move-window-to-wrap-around))) ;;;###autoload (defun +evil/window-split-and-follow () diff --git a/modules/editor/evil/config.el b/modules/editor/evil/config.el index e8f31550a..5a20a7007 100644 --- a/modules/editor/evil/config.el +++ b/modules/editor/evil/config.el @@ -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 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_]" "The regexp used by `+evil/next-preproc-directive' and `+evil/previous-preproc-directive' on ]# and [#, to jump between preprocessor