summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-12-16 19:35:58 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-12-16 19:37:37 -0700
commit5ae9d44519494211febf0c32eede5e04421a6404 (patch)
tree1c6b9d71dc474ee6142fa58f0ca11308a7a487ed
parentdf44abebfac98be12732bb8234a5181d92ffcb5e (diff)
downloaddotfiles-5ae9d445.tar.gz
move most used window and buffer cycling bindings to the arrow keys
-rw-r--r--.emacs.d/init.el78
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)