diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2021-12-16 19:35:58 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2021-12-16 19:37:37 -0700 |
commit | 5ae9d44519494211febf0c32eede5e04421a6404 (patch) | |
tree | 1c6b9d71dc474ee6142fa58f0ca11308a7a487ed | |
parent | df44abebfac98be12732bb8234a5181d92ffcb5e (diff) | |
download | dotfiles-5ae9d445.tar.gz |
move most used window and buffer cycling bindings to the arrow keys
-rw-r--r-- | .emacs.d/init.el | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/.emacs.d/init.el b/.emacs.d/init.el index ab71aacf..e127ec10 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -46,14 +46,17 @@ add places the library might be available to `load-path'." ("MELPA Stable" . 5) ("MELPA" . 0))) -(defmacro spw/bind-command-with-cycling (bindings generator &optional on-exit map) +(defmacro spw/bind-command-with-cycling + (bindings generator &optional on-exit map cycle-backward-key cycle-forward-key) (list 'spw/bind-command-with-cycling* (spw/expand-binding-pairs bindings) `(lambda (_ignore) ,generator) `(lambda () ,on-exit) - map)) + map + cycle-backward-key + cycle-forward-key)) (cl-defmacro spw/bind-command-with-ret-val-cycling (bindings @@ -95,7 +98,8 @@ add places the library might be available to `load-path'." (let ((buffer (ring-ref buffers buffers-pos))) ,action)))) -(defun spw/bind-command-with-cycling* (bindings generator &optional on-exit map) +(defun spw/bind-command-with-cycling* + (bindings generator &optional on-exit map cycle-backward-key cycle-forward-key) (dolist (binding bindings) (let ((binding-fn (intern (concat "spw/" (spw/drop-prefix @@ -110,13 +114,14 @@ add places the library might be available to `load-path'." (tmap (make-sparse-keymap))) (define-key tmap - [left] + (or cycle-backward-key [left]) (lambda (count) (interactive "p") (funcall cycling-function (* -1 count)))) ;; Might be useful to bind C-c k in the transient map to ;; kill the current buffer and cycle one step. - (define-key tmap [right] cycling-function) + (define-key + tmap (or cycle-forward-key [right]) cycling-function) (set-transient-map tmap t on-exit) ;; showing a message here is wanted because experience has ;; shown that sometimes it can be hard to remember whether @@ -686,6 +691,37 @@ the non-side windows deleted by `delete-other-windows' will also reappear." (setq i (1+ i)))) (global-set-key [?\C-\M--] nil) +(defvar spw/arrow-keys-mode-map + (let ((map (make-sparse-keymap))) + (dolist (key '(up down left right)) + (define-key map (vector ?\C-x key) #'spw/arrow-keys-mode-passthru)) + map) + "Keymap for `spw/arrow-keys-mode'.") + +(define-minor-mode spw/arrow-keys-mode + "Apply the bindings in `spw/arrow-keys-mode-map', but +additionally bind the sequences of C-x followed by each of the +four arrow keys to activate a transient map in which the four +arrow keys have the bindings they would have absent this mode. + +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)." + t nil spw/arrow-keys-mode-map :global t :init-value t) + +(defun spw/arrow-keys-mode-passthru () + (interactive) + (let ((map (make-sparse-keymap)) + (keys (this-command-keys)) + (cell (cl-find 'spw/arrow-keys-mode minor-mode-map-alist :key #'car))) + (cl-letf (((car cell) nil)) + (dolist (key '([up] [down] [left] [right])) + (define-key map key (key-binding key)))) + (let ((key (vector (aref keys (1- (length keys)))))) + (call-interactively (lookup-key map key) t key)) + (set-transient-map map t))) + ;; C-x o is easier to type than these, but these are wanted for tapping ;; repeatedly when there are more than two windows (defun spw/other-window-noselect (count &optional interactive) @@ -695,18 +731,22 @@ the non-side windows deleted by `delete-other-windows' will also reappear." (lambda (window &rest _ignore) (old-select-window window 'mark-for-redisplay)))) (other-window count nil interactive)))) +(global-set-key [remap other-window] #'spw/back-and-forth-noselect) + (defun spw/backward-other-window-noselect (count &optional interactive) (interactive "p\np") (spw/other-window-noselect (* -1 count) interactive)) +;; We could additionally allow left/right to have their normal bindings when +;; there is only one window. (spw/bind-command-with-cycling ;; don't select the windows we cycle through, so that the window where we ;; started becomes the most recently selected window - (([?\C-x left] . spw/backward-other-window-noselect) - ([remap other-window] . spw/back-and-forth-noselect) - ([?\C-x right] . spw/other-window-noselect)) + (([left] . spw/backward-other-window-noselect) + ([right] . spw/other-window-noselect)) #'spw/other-window-noselect ;; select the destination window again with NOSELECT nil - (select-window (selected-window))) + (select-window (selected-window)) + spw/arrow-keys-mode-map) ;; ... and resettle old occupants of C-x <left> and C-x <right>. This is a ;; bit complicated but we want these commands to be easily repeatable but also @@ -714,9 +754,9 @@ the non-side windows deleted by `delete-other-windows' will also reappear." ;; to type those right after switching. ;; ;; A possible improvement would be to have C-c b always take you back to the -;; buffer you were in before starting to use these commands. E.g. C-c w -;; <left> <left> C-c b would take you back to where you started, and then C-c -;; b would take you back to where C-c w <left> <left> took you. +;; buffer you were in before starting to use these commands. E.g. C-c w <up> +;; <up> C-c b would take you back to where you started, and then C-c b would +;; take you back to where C-c w <up> <up> took you. (defun spw/maybe-next-buffer () (interactive) (cl-destructuring-bind @@ -731,23 +771,27 @@ the non-side windows deleted by `delete-other-windows' will also reappear." ;; buffers previously shown in the selected window come up first, as ;; desired. ;; + ;; We add bindings under C-c in addition to the arrow keys for use with + ;; terminals that have no arrow keys. 'w' is for "window's buffers". + ;; ;; Although C-c b can go backwards, really it's for going forwards; it is a ;; little tricky to use the arrow keys correctly right after C-c b if it ;; unexpectedly took us backwards (if we were expecting to go backwards, - ;; would have used C-c w). + ;; would have used C-c w/<up>). ;; ;; The fallback to going backwards is there only because it would be worse to ;; go round to the end of the list of buffers, but perhaps it should just do ;; nothing? - ;; - ;; 'w' is for "window's buffers". - (("\C-cw" . previous-buffer) + (([up] . previous-buffer) + ("\C-cw" . previous-buffer) + ([down] . spw/maybe-next-buffer) ("\C-cb" . spw/maybe-next-buffer)) (lambda (count) (interactive "p") (if (> count 0) (next-buffer count) - (previous-buffer (* -1 count))))) + (previous-buffer (* -1 count)))) + nil spw/arrow-keys-mode-map [up] [down]) (setq switch-to-prev-buffer-skip 'this) |