From 466642c0ff3999cbc8b51431c97a74a5ebef6cb7 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 5 Nov 2022 13:03:44 -0700 Subject: rework some of my cycling bindings inc. introduce use of windmove --- .config/i3/config | 12 ++--- .config/sway/config | 12 ++--- .emacs.d/init.el | 132 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 98 insertions(+), 58 deletions(-) diff --git a/.config/i3/config b/.config/i3/config index e4b6fae5..786700d5 100644 --- a/.config/i3/config +++ b/.config/i3/config @@ -262,9 +262,9 @@ bindsym Mod1+Ctrl+i kill bindsym Ctrl+minus layout toggle split # Cycle through all workspaces on monitor. -bindsym Ctrl+3 workspace prev_on_output +bindsym Ctrl+1 workspace prev_on_output bindsym Ctrl+4 workspace next_on_output -bindsym Mod1+Ctrl+3 move container to workspace prev_on_output, \ +bindsym Mod1+Ctrl+1 move container to workspace prev_on_output, \ workspace prev_on_output bindsym Mod1+Ctrl+4 move container to workspace next_on_output, \ workspace next_on_output @@ -283,10 +283,10 @@ bindsym Mod1+Ctrl+4 move container to workspace next_on_output, \ # bindsym Mod4+Ctrl+Mod2+KP_Right move workspace to output right # bindsym Mod4+Ctrl+KP_6 move workspace to output right -bindsym Ctrl+1 focus output left -bindsym Mod1+Ctrl+1 move workspace to output left -bindsym Ctrl+2 focus output right -bindsym Mod1+Ctrl+2 move workspace to output right +bindsym Ctrl+2 focus output left +bindsym Mod1+Ctrl+2 move workspace to output left +bindsym Ctrl+3 focus output right +bindsym Mod1+Ctrl+3 move workspace to output right # Start i3bar to display a workspace bar (plus the system information i3status # finds out, if available) diff --git a/.config/sway/config b/.config/sway/config index 9b8e7e21..66ed4f3f 100644 --- a/.config/sway/config +++ b/.config/sway/config @@ -282,19 +282,19 @@ bindsym Ctrl+minus layout toggle split # Warp the cursor to a point on the screen which is hopefully a titlebar. # This means that cycling through workspaces does not abruptly stop because, # e.g., a VNC client has grabbed the keyboard upon entry to the workspace. -bindsym Ctrl+3 seat - cursor set 0 0, workspace prev_on_output +bindsym Ctrl+1 seat - cursor set 0 0, workspace prev_on_output bindsym Ctrl+4 seat - cursor set 0 0, workspace next_on_output -bindsym Mod1+Ctrl+3 seat - cursor set 0 0, \ +bindsym Mod1+Ctrl+1 seat - cursor set 0 0, \ move container to workspace prev_on_output, \ workspace prev_on_output bindsym Mod1+Ctrl+4 seat - cursor set 0 0, \ move container to workspace next_on_output, \ workspace next_on_output -bindsym Ctrl+1 focus output left -bindsym Mod1+Ctrl+1 move workspace to output left -bindsym Ctrl+2 focus output right -bindsym Mod1+Ctrl+2 move workspace to output right +bindsym Ctrl+2 focus output left +bindsym Mod1+Ctrl+2 move workspace to output left +bindsym Ctrl+3 focus output right +bindsym Mod1+Ctrl+3 move workspace to output right # Start swaybar to display a workspace bar (plus the system information # i3status finds out, if available) diff --git a/.emacs.d/init.el b/.emacs.d/init.el index c195f234..d9f22481 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -400,6 +400,8 @@ windows side-by-side in the frame." '(tramp-verbose 1 nil nil "Manual says this should improve performance.") '(transient-cycles-buffer-siblings-mode t) '(transient-cycles-tab-bar-mode t) + '(transient-cycles-window-buffers-cycle-backwards-key [?\M-1]) + '(transient-cycles-window-buffers-cycle-forwards-key [?\M-4]) '(transient-cycles-window-buffers-mode t) '(transient-mark-mode nil) '(uniquify-buffer-name-style 'post-forward nil (uniquify)) @@ -783,28 +785,28 @@ to open them using `spw/try-external-open'") ;;;; General editing +(define-minor-mode spw/personal-bindings-mode + "A simple way to overcome problems overriding major mode bindings. +To be used only when it seems to be necessary." + :init-value t :lighter nil :keymap (make-sparse-keymap) :global t) + ;; Bind a key simply to (re-)activate the mark which does not ;; involve moving point, as `exchange-point-and-mark' does. This is ;; useful if you use isearch to select a region but realise only after ;; you've left the intended start of the region that you need to do a -;; second isearch to extend it far enough: e.g. C-s first M-i C-s second RET +;; second isearch to extend it far enough: e.g. C-s first M-6 C-s second RET ;; ;; Activating the region prevents the second isearch from resetting ;; the mark. Having this binding removes the need to activate the ;; region before entering the first isearch, which is useful both with ;; and without `transient-mark-mode'. ;; -;; This makes M-i a sort of prefix command: "execute the next command in +;; This makes M-6 a sort of prefix command: "execute the next command in ;; temporary Transient Mark mode / as if Transient Mark mode were turned on" (defun spw/activate-mark (&rest _ignore) (interactive) (activate-mark)) -(global-set-key "\M-i" #'spw/activate-mark) - -;; resettle the previous occupants of M-i -(global-set-key "\M-I" #'tab-to-tab-stop) -(spw/feature-define-keys ((gnus-sum gnus-summary-mode-map)) - "\M-i" nil "\M-I" gnus-symbolic-argument) +(define-key spw/personal-bindings-mode-map "\M-6" #'spw/activate-mark) ;; Regarding `set-mark-command-repeat-pop': if this is set to t, then ;; re-setting the mark right after popping to it -- to go and edit somewhere @@ -936,7 +938,8 @@ to open them using `spw/try-external-open'") (let (case-fold-search) (apply #',cmd ,args)))))) (global-set-key [remap zap-to-char] (case-sensitively zap-to-char)) - (define-key spw/ctl-z-map "z" (case-sensitively zap-up-to-char))) + (define-key spw/personal-bindings-mode-map + "\M-5" (case-sensitively zap-up-to-char))) (global-set-key [remap dabbrev-expand] #'hippie-expand) @@ -959,9 +962,17 @@ to open them using `spw/try-external-open'") (revert-buffer (not current-prefix-arg) t))) ;; These don't work in text terminals, so unbind to avoid developing any -;; habits of using them. In recent Emacs you can release the meta key after -;; typing the first digit or minus sign of a numeric argument, rendering these -;; other bindings less useful anyway. +;; habits of using them. Further, if the goal is to avoid having to release +;; modifier keys between typing numeric prefix arguments and commands, then in +;; most cases this will mean one-handed chording, which should be avoided. If +;; the goal is instead to reduce the total number of keypresses, then it +;; should be sufficient to use only the M- bindings, releasing the meta key +;; after typing the first digit or minus sign. But that's a minor benefit +;; over just starting with C-u. Indeed, I rebind M-0..9 for other purposes. +;; +;; (M-- remains bound to `negative-argument' because it's particularly useful +;; for 'M-- M-l' and 'M-- M-u'. So, C-u and M-- are the two keys I use to +;; supply non-negative and negative numeric prefix arguments, respectively.) (cl-loop for i from ?0 to ?9 for key = (read (format "[?\\C-%c]" i)) do (global-unset-key key) (define-key esc-map key nil)) @@ -1035,7 +1046,7 @@ to open them using `spw/try-external-open'") (diminish 'eldoc-mode) ;; Invert meaning of C-u for M-= except when the region is active (though, -;; M-i M-= is easier to type than C-u M-=). +;; M-6 M-= is easier to type than C-u M-=). (defun spw/count-words () (interactive) (if (or (use-region-p) (not current-prefix-arg)) @@ -1208,7 +1219,8 @@ Permits globally re-binding the four arrow keys without rendering it impossible to access mode-specific bindings for those four keys (e.g. the use of the left and right arrow keys in `fido-mode' minibuffers)." - :init-value t :lighter nil :keymap spw/arrow-keys-mode-map :global t) + ;; :init-value t + :lighter nil :keymap spw/arrow-keys-mode-map :global t) (defun spw/arrow-keys-mode-passthru () (interactive) @@ -1243,21 +1255,13 @@ don't consider windows satisfying the predicate EXCLUDE." (interactive "P") (if arg ;; if there's a prefix arg then just `other-window', so that's still - ;; available on M-1 C-x o + ;; available on C-u 1 C-x o (call-interactively #'other-window) (if-let ((window (spw/get-mru-window))) (select-window window) (user-error "No other window to select")))) (global-set-key [remap other-window] #'spw/back-and-forth) -(defun spw/other-window-noselect (count &optional interactive) - (interactive "p\np") - (cl-flet ((old-select-window (symbol-function 'select-window))) - (cl-letf (((symbol-function 'select-window) - (lambda (window &rest _ignore) - (old-select-window window 'mark-for-redisplay)))) - (other-window count nil interactive)))) - ;;; Initial motivation for `transient-cycles' work is that we want all these ;;; commands to be easily repeatable but without setting a transient map which ;;; binds self-insert chars, as might want to type those just after switching. @@ -1268,21 +1272,57 @@ don't consider windows satisfying the predicate EXCLUDE." ;;; sequences which already belong to other keys, one idea is to add ;;; C-c/C-z {h,j,k,l} to `input-decode-map' for the arrow keys (or bind them ;;; to commands setting `unread-command-events'), without any transient maps. - -;; C-x o is easier to type than these, but these are wanted for tapping -;; repeatedly when there are more than two windows. We could allow left/right -;; to have their normal bindings when there is only one window. -(transient-cycles-define-commands () - ;; Don't select the windows we cycle through, so that the window where we - ;; started becomes the most recently selected window. - (([right] . spw/other-window-noselect) - (([left] . spw/backward-other-window-noselect) - (count &optional interactive) - (interactive "p\np") - (spw/other-window-noselect (* -1 count) interactive))) - (lambda (_ignore) #'spw/other-window-noselect) - ;; Select the destination window again with NOSELECT nil. - :on-exit (select-window (selected-window)) :keymap spw/arrow-keys-mode-map) +;;; +;;; Previously we used / for custom next- and previous-window +;;; commands with transient cycling, and didn't use any windmove commands. +;;; However, because / are my default transient cycling keys, +;;; this led to situations where I tried to use / to switch +;;; window and found myself continuing transient cycling for the previous +;;; command instead. So, should probably avoid putting anything on unmodified +;;; /. We could still put something on unmodified /, +;;; which I used to use for `tab-bar-history-mode' forward & back commands. +;;; (`spw/arrow-keys-mode' made it feasible to bind things to unmodified arrow +;;; keys in the global map. That's disabled at present, as the unmodified +;;; arrow keys are not in use.) +;;; +;;; We might put one of the other sets of windmove commands, such as +;;; windmove-swap-states-* commands, on C-z M-7/8/9/0, or possibly +;;; C-c w M-7/8/9/0. C-c / are also available, as they tacitly +;;; belong to `winner-mode' / `tab-bar-history-mode'. + +(defvar spw/windmove-transient-map (make-sparse-keymap)) + +(cl-macrolet + ((add-direction (key direction) + (let* ((init (intern (format "spw/windmove-%s" direction))) + (noselect + (intern + (format "spw/windmove-%s-noselect" direction))) + (noselect-body + `(cl-flet ((old-s-w (symbol-function 'select-window))) + (cl-letf (((symbol-function 'select-window) + (lambda (window &rest _ignore) + (old-s-w window 'mark-for-redisplay)))) + (call-interactively + #',(intern (format "windmove-%s" direction))))))) + `(progn (defun ,noselect () (interactive) ,noselect-body) + (define-key spw/windmove-transient-map ,key #',noselect) + (defun ,init () + (interactive) + ;; Don't select the windows we move through, so that the + ;; window where we started becomes the most recently + ;; selected window. Then in the ON-EXIT function, select + ;; the destination window again with the NOSELECT argument + ;; to `select-window' nil. + ,noselect-body + (set-transient-map spw/windmove-transient-map t + (lambda () + (select-window (selected-window))))) + (global-set-key ,key #',init))))) + (add-direction "\M-7" "left") + (add-direction "\M-8" "down") + (add-direction "\M-9" "up") + (add-direction "\M-0" "right")) ;; We might resettle `pop-global-mark' to C-z C-SPC. (define-key ctl-x-map "\C-@" #'transient-cycles-window-buffers-back-and-forth) @@ -1296,19 +1336,19 @@ don't consider windows satisfying the predicate EXCLUDE." ;; `winner-mode', `tab-bar-history-mode' does not restore just one value for ;; point for all of the windows in the configuration showing a single buffer. (transient-cycles-define-commands () - (([up] . tab-bar-history-back) - ([down] . tab-bar-history-forward)) + (("\M-3" . tab-bar-history-back) + ("\M-2" . tab-bar-history-forward)) (lambda (_ignore) (lambda (count) (interactive "p") (if (> count 0) (tab-bar-history-forward) (tab-bar-history-back)))) - :keymap spw/arrow-keys-mode-map - :cycle-backwards-key [up] :cycle-forwards-key [down]) + :cycle-backwards-key "\M-3" :cycle-forwards-key "\M-2") + +(define-key transient-cycles-window-buffers-mode-map "\M-1" #'previous-buffer) +(define-key transient-cycles-window-buffers-mode-map "\M-4" #'next-buffer) ;; Start transient cycling among the current buffer's siblings. ;; Can be usefully prefixed with C-x 4 4 etc. to start cycling elsewhere. -(spw/reclaim-keys-from - tab-bar tab-bar-history-mode-map [?\C-c left] [?\C-c right]) (defun spw/cycle-from-here () (interactive) (push last-command-event unread-command-events) @@ -1317,8 +1357,8 @@ don't consider windows satisfying the predicate EXCLUDE." ;; window's previous buffers. (pop-to-buffer-same-window (current-buffer)))) (spw/transient-cycles-define-buffer-switch - (([?\C-c left] . spw/cycle-from-here) - ([?\C-c right] . spw/cycle-from-here))) + (([?\C-x left] . spw/cycle-from-here) + ([?\C-x right] . spw/cycle-from-here))) (setq display-buffer-alist `(;; This is meant to say: for these buffers which, unusually, do not -- cgit v1.2.3