From c009311887372e1e822739edc050a802bfa4d1d8 Mon Sep 17 00:00:00 2001 From: Philip K Date: Fri, 7 Aug 2020 12:35:49 +0200 Subject: [PATCH] Add user options to bind windmove commands * windmove.el (windmove-modifier-type): Create (windmove--unbind): New constant (windmove-modifiers): New user option (windmove-default-keybindings): Use windmove-modifiers (windmove-display-modifiers): New user option (windmove-display-default-keybindings): Use windmove-display-modifiers (windmove-delete-prefix): New user option (windmove-delete-modifiers): New user option (windmove-delete-default-keybindings): Use windmove-delete-prefix and windmove-delete-modifiers (windmove-swap-states-modifiers): New user option (windmove-swap-states-default-keybindings): Use windmove-swap-states-modifiers --- lisp/windmove.el | 154 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 145 insertions(+), 9 deletions(-) diff --git a/lisp/windmove.el b/lisp/windmove.el index 613727f8ed..9b68f9a5b9 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -162,6 +162,40 @@ windmove-window-distance-delta (make-obsolete-variable 'windmove-window-distance-delta "no longer used." "27.1") +(defconst windmove-modifier-type + '(choice (set :tag "Modifier Symbols" + :greedy t + ;; See `(elisp) Keyboard Events' + (const :tag "Meta" meta) + (const :tag "Control" control) + (const :tag "Shift" shift) + (const :tag "Hyper" hyper) + (const :tag "Super" super) + (const :tag "Alt" alt)) + (const :tag "No modifier" none) + (const :tag "Not bound" nil)) + "Customisation type for windmove modifiers") + +(defun windmove--unbind (prefix modifiers fns &optional extra) + "Unbind windmove commands, bound by PREFIX and MODIFIER. +To ensure that only windmove functions are unbound, the command +must be member of the list FNS. +By default only the left, right, up and down keys are unbound, +but further keys can be added via EXTRA." + (setq prefix + (cond ((eq prefix 'none) nil) + ((not (listp prefix)) (list prefix)) + (t prefix))) + (setq modifiers + (cond ((eq modifiers 'none) nil) + ((not (listp modifiers)) (list modifiers)) + (t modifiers))) + (dolist (dir (append '(left right up down) extra)) + (let* ((key (append modifiers (list dir))) + (key (vconcat prefix (list key)))) + (when (memq (lookup-key global-map key) fns) + (global-set-key key nil))))) + ;; Note: ;; @@ -419,6 +453,7 @@ windmove-down (interactive "P") (windmove-do-window-select 'down (and arg (prefix-numeric-value arg)))) +(defvar windmove-modifiers) ;;; set up keybindings ;; Idea for this function is from iswitchb.el, by Stephen Eglen @@ -433,16 +468,41 @@ windmove-default-keybindings where MODIFIERS is either a list of modifiers or a single modifier. If MODIFIERS is `none', the keybindings will be directly bound to the arrow keys. -Default value of MODIFIERS is `shift'." +Default value of MODIFIERS is stored in `windmove-modifiers'." (interactive) - (unless modifiers (setq modifiers 'shift)) (when (eq modifiers 'none) (setq modifiers nil)) + (unless modifiers + (setq modifiers windmove-modifiers)) (unless (listp modifiers) (setq modifiers (list modifiers))) (global-set-key (vector (append modifiers '(left))) 'windmove-left) (global-set-key (vector (append modifiers '(right))) 'windmove-right) (global-set-key (vector (append modifiers '(up))) 'windmove-up) (global-set-key (vector (append modifiers '(down))) 'windmove-down)) +;; has to be declared AFTER windmove-default-keybindings, or else +;; windmove is recursivly loaded +;;;###autoload +(defcustom windmove-modifiers '(shift super) + "Modifiers for `windmove-default-keybindings'. +Can either be a symbol or list of modifier symbols, +i.e. `meta',`control', `shift', `hyper', `super', or `alt' +representing modifier keys to use with the arrow keys. + +If the value is just `none', the arrow keys will be directly +bound to the windmove functions." + :type windmove-modifier-type + :require 'windmove + :initialize #'custom-initialize-changed + :set (lambda (sym val) + (windmove--unbind nil (default-value sym) + '(windmove-left + windmove-right + windmove-up + windmove-down)) + (when val + (windmove-default-keybindings val)) + (set-default sym val))) + ;;; Directional window display and selection @@ -543,6 +603,8 @@ windmove-display-new-tab (interactive "P") (windmove-display-in-direction 'new-tab arg)) +(defvar windmove-display-modifiers) + ;;;###autoload (defun windmove-display-default-keybindings (&optional modifiers) "Set up keybindings for directional buffer display. @@ -551,9 +613,10 @@ windmove-display-default-keybindings where MODIFIERS is either a list of modifiers or a single modifier. If MODIFIERS is `none', the keybindings will be directly bound to the arrow keys. -Default value of MODIFIERS is `shift-meta'." +Default value of MODIFIERS is stored in `windmove-display-modifiers'." (interactive) - (unless modifiers (setq modifiers '(shift meta))) + (unless modifiers + (setq modifiers windmove-display-modifiers)) (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) (global-set-key (vector (append modifiers '(left))) 'windmove-display-left) @@ -564,6 +627,27 @@ windmove-display-default-keybindings (global-set-key (vector (append modifiers '(?f))) 'windmove-display-new-frame) (global-set-key (vector (append modifiers '(?t))) 'windmove-display-new-tab)) +;;;###autoload +(defcustom windmove-display-modifiers '(shift meta) + "Modifiers for `windmove-display-default-keybindings'. +Analogous to `windmove-modifiers'." + :type windmove-modifier-type + :require 'windmove + :initialize #'custom-initialize-changed + :set (lambda (sym val) + (windmove--unbind nil (default-value sym) + '(windmove-display-left + windmove-display-right + windmove-display-up + windmove-display-down + windmove-display-same-window + windmove-display-new-frame + windmove-display-new-tab) + '(?0 ?f ?t)) + (when val + (windmove-display-default-keybindings val)) + (set-default sym val))) + ;;; Directional window deletion @@ -618,6 +702,9 @@ windmove-delete-down (interactive "P") (windmove-delete-in-direction 'down arg)) +(defvar windmove-delete-prefix) +(defvar windmove-delete-modifiers) + ;;;###autoload (defun windmove-delete-default-keybindings (&optional prefix modifiers) "Set up keybindings for directional window deletion. @@ -627,12 +714,15 @@ windmove-delete-default-keybindings a single modifier. If PREFIX is `none', no prefix is used. If MODIFIERS is `none', the keybindings are directly bound to the arrow keys. -Default value of PREFIX is `C-x' and MODIFIERS is `shift'." +The default values for PREFIX and MODIFIERS are stored in `windmove-delete-prefix' +and `windmove-delete-modifiers' respectively." (interactive) - (unless prefix (setq prefix '(?\C-x))) + (unless prefix + (setq prefix (list windmove-delete-prefix))) (when (eq prefix 'none) (setq prefix nil)) (unless (listp prefix) (setq prefix (list prefix))) - (unless modifiers (setq modifiers '(shift))) + (unless modifiers + (setq modifiers windmove-delete-modifiers)) (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) (global-set-key (vector prefix (append modifiers '(left))) 'windmove-delete-left) @@ -640,6 +730,32 @@ windmove-delete-default-keybindings (global-set-key (vector prefix (append modifiers '(up))) 'windmove-delete-up) (global-set-key (vector prefix (append modifiers '(down))) 'windmove-delete-down)) +(defcustom windmove-delete-prefix (kbd "C-x") + "Prefix for `windmove-delete-default-keybindings'." + :type 'key-sequence + :require 'windmove + :initialize #'custom-initialize-changed) + +;;;###autoload +(defcustom windmove-delete-modifiers '(shift) + "Modifiers for `windmove-delete-default-keybindings'. +See `windmove-modifiers' for more details" + :type windmove-modifier-type + :require 'windmove + :initialize #'custom-initialize-changed + :set-after '(windmove-delete-prefix) + :set (lambda (sym val) + (windmove--unbind windmove-delete-prefix + (default-value sym) + '(windmove-delete-left + windmove-delete-right + windmove-delete-up + windmove-delete-down)) + (when val + (windmove-delete-default-keybindings + windmove-delete-prefix val)) + (set-default sym val))) + ;;; Directional window swap states @@ -678,6 +794,8 @@ windmove-swap-states-right (interactive) (windmove-swap-states-in-direction 'right)) +(defvar windmove-swap-states-modifiers) + ;;;###autoload (defun windmove-swap-states-default-keybindings (&optional modifiers) "Set up keybindings for directional window swap states. @@ -687,9 +805,10 @@ windmove-swap-states-default-keybindings or a single modifier. If MODIFIERS is `none', the keybindings will be directly bound to the arrow keys. -Default value of MODIFIERS is `shift-super'." +Default value of MODIFIERS is stored in `windmove-swap-states-modifiers'." (interactive) - (unless modifiers (setq modifiers '(shift super))) + (unless modifiers + (setq modifiers windmove-swap-states-modifiers)) (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) (global-set-key (vector (append modifiers '(left))) 'windmove-swap-states-left) @@ -697,6 +816,23 @@ windmove-swap-states-default-keybindings (global-set-key (vector (append modifiers '(up))) 'windmove-swap-states-up) (global-set-key (vector (append modifiers '(down))) 'windmove-swap-states-down)) +;;;###autoload +(defcustom windmove-swap-states-modifiers '(shift super) + "Modifiers for `windmove-swap-states-default-keybindings'. +Analogous to `windmove-modifiers'." + :type windmove-modifier-type + :require 'windmove + :initialize #'custom-initialize-changed + :set (lambda (sym val) + (windmove--unbind nil (default-value sym) + '(windmove-swap-states-left + windmove-swap-states-right + windmove-swap-states-up + windmove-swap-states-downp)) + (when val + (windmove-swap-states-default-keybindings val)) + (set-default sym val))) + (provide 'windmove) -- 2.20.1