From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Philip Kaludercic Newsgroups: gmane.emacs.bugs Subject: bug#41438: [PATCH] Allow windmove keys to be bound without prefix or modifiers Date: Mon, 31 May 2021 08:50:57 +0000 Message-ID: <871r9ncmmm.fsf@posteo.net> References: <87imgpw7k3.fsf@warpmail.net> <87mu36enhl.fsf@posteo.net> <8735uru1py.fsf@gnus.org> <871r9yjyv5.fsf@posteo.net> <87h7irqtvf.fsf@gnus.org> <87im37p2b4.fsf@icterid> <875yz68yoq.fsf@mail.linkov.net> <87r1hucws6.fsf@icterid> <87k0nl420l.fsf@mail.linkov.net> <87zgwg302t.fsf@icterid> <87im2zzy82.fsf@mail.linkov.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="34787"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 41438@debbugs.gnu.org, Lars Ingebrigtsen To: Juri Linkov Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon May 31 10:52:18 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lndej-0008m3-PI for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 31 May 2021 10:52:17 +0200 Original-Received: from localhost ([::1]:40902 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lndeh-0003aA-SJ for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 31 May 2021 04:52:15 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45656) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lndeW-0003YK-40 for bug-gnu-emacs@gnu.org; Mon, 31 May 2021 04:52:05 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:49514) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lndeU-00044s-4x for bug-gnu-emacs@gnu.org; Mon, 31 May 2021 04:52:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1lndeU-0005eb-3j for bug-gnu-emacs@gnu.org; Mon, 31 May 2021 04:52:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Philip Kaludercic Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 31 May 2021 08:52:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 41438 X-GNU-PR-Package: emacs Original-Received: via spool by 41438-submit@debbugs.gnu.org id=B41438.162245107421667 (code B ref 41438); Mon, 31 May 2021 08:52:02 +0000 Original-Received: (at 41438) by debbugs.gnu.org; 31 May 2021 08:51:14 +0000 Original-Received: from localhost ([127.0.0.1]:32827 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lnddh-0005dO-L4 for submit@debbugs.gnu.org; Mon, 31 May 2021 04:51:14 -0400 Original-Received: from mout02.posteo.de ([185.67.36.66]:36467) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lnddc-0005d1-TA for 41438@debbugs.gnu.org; Mon, 31 May 2021 04:51:12 -0400 Original-Received: from submission (posteo.de [89.146.220.130]) by mout02.posteo.de (Postfix) with ESMTPS id 9DAE02400FD for <41438@debbugs.gnu.org>; Mon, 31 May 2021 10:51:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1622451061; bh=XZ0W7LNbpJyxkTQxUWRsrLY9dzncTldRSxd3wDXJs9o=; h=From:To:Cc:Subject:Autocrypt:Date:From; b=ZH4a/j6d41k7tiSjqTbaGCZioRBQzCDtwAIWbOApchzN46tutvt/g9eW7gYL4WF1x cwY9tZKujVW6wYPoN70tq5KIkNhkeCBxoRoP5hEcZ+/dwalGeZIQXoiq1Q3vTXrxmp /Dl1ByWfJU9fWW/d54sf1xTgH5XGCN1UL0h2aIqFHHsud5nfna6xAn3cdCUdm8XcwP SMcxnEX/RO+jnUrg+SYnoXUQ5M0ulKOi0W/qc87dmOT5/p7QPGl9SgbKN50LQ1RxIG lViqnH2MFXZwzftWVhUHi8oAS36AUBxlWs5q4NkhPZu8aW3VAdIJPnRxHIydPmBtVf 9kOC5Cz+0Uabw== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4Ftpst48r0z9rxg; Mon, 31 May 2021 10:50:58 +0200 (CEST) Autocrypt: addr=philipk@posteo.net; prefer-encrypt=mutual; keydata= mDMEYHHqUhYJKwYBBAHaRw8BAQdAp3GdmYJ6tm5McweY6dEvIYIiry+Oz9rU4MH6NHWK0Ee0QlBo aWxpcCBLYWx1ZGVyY2ljIChnZW5lcmF0ZWQgYnkgYXV0b2NyeXB0LmVsKSA8cGhpbGlwa0Bwb3N0 ZW8ubmV0PoiQBBMWCAA4FiEEDM2H44ZoPt9Ms0eHtVrAHPRh1FwFAmBx6lICGwMFCwkIBwIGFQoJ CAsCBBYCAwECHgECF4AACgkQtVrAHPRh1FyTkgEAjlbGPxFchvMbxzAES3r8QLuZgCxeAXunM9gh io0ePtUBALVhh9G6wIoZhl0gUCbQpoN/UJHI08Gm1qDob5zDxnIHuDgEYHHqUhIKKwYBBAGXVQEF AQEHQNcRB+MUimTMqoxxMMUERpOR+Q4b1KgncDZkhrO2ql1tAwEIB4h4BBgWCAAgFiEEDM2H44Zo Pt9Ms0eHtVrAHPRh1FwFAmBx6lICGwwACgkQtVrAHPRh1Fw1JwD/Qo7kvtib8jy7puyWrSv0MeTS g8qIxgoRWJE/KKdkCLEA/jb9b9/g8nnX+UcwHf/4VfKsjExlnND3FrBviXUW6NcB In-Reply-To: <87im2zzy82.fsf@mail.linkov.net> (Juri Linkov's message of "Mon, 31 May 2021 01:11:57 +0300") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:207688 Archived-At: --=-=-= Content-Type: text/plain Juri Linkov writes: >>> Maybe it's possible to add new user options without deprecating the >>> existing functions? Then for users an alternative way would be to >>> customize these options, and enable windmove-mode in the init file. >> >> Of course, why not? The patches below should implement that. > > Thanks, I tried out your patches. The customization saved them > in such format: > > '(windmove-default-keybindings '([ignore] hyper)) > '(windmove-delete-default-keybindings '("\30" hyper)) > '(windmove-display-default-keybindings '([ignore] meta hyper)) > '(windmove-swap-states-default-keybindings '([ignore] shift hyper)) > > But I guess it's not a problem that it saves nil as [ignore]. > > The real problem is that after replacing this with a manual configuration: > > (use-package windmove > :custom > (windmove-default-keybindings '(nil hyper)) > (windmove-delete-default-keybindings `(,(kbd "C-x") hyper)) > (windmove-display-default-keybindings '(nil meta hyper)) > (windmove-swap-states-default-keybindings '(nil shift hyper))) > > Then every startup pops up the *Warnings* buffer with: > > Warning (emacs): Overriding 1 with windmove-delete-left [Disable showing] [Disable logging] > > But still all keybindings work correctly. I was under the impression that this was fixed, but it turns out I did not read the lookup-key doc string carefully enough: A number as value means KEY is "too long"; that is, characters or symbols in it except for the last one fail to be a valid sequence of prefix characters in KEYMAP. The number is how many characters at the front of KEY it takes to reach a non-prefix key. But this case can be safely ignored, as define-key will take care of the prefix. To solve this, the warning is only trigged when a function is over-riden. -- Philip K. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Improve-windmove-default-keybindings-fuctions.patch >From 42a66e87af83817b9e989624fdbf9c7ee7c347c7 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 25 May 2021 11:47:51 +0200 Subject: [PATCH 1/2] Improve windmove-*-default-keybindings fuctions * windmove.el (windmove-mode-map): Add special map for windmove commands (windmove-mode): Add minor mode for activating windmove-mode-map (windmove-install-defaults): Add general function for manipulating windmove-mode-map (windmove-default-keybindings): Use windmove-install-defaults (windmove-display-default-keybindings): Use windmove-install-defaults (windmove-delete-default-keybindings): Use windmove-install-defaults (windmove-swap-states-default-keybindings): Use windmove-install-defaults --- lisp/windmove.el | 91 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/lisp/windmove.el b/lisp/windmove.el index e4ea8e0f69..cd8592f341 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -426,19 +426,53 @@ windmove-down ;; I don't think these bindings will work on non-X terminals; you ;; probably want to use different bindings in that case. +(defvar windmove-mode-map (make-sparse-keymap) + "Map used by `windmove-install-defaults'.") + +(define-minor-mode windmove-mode + "Global minor mode for default windmove commands." + :keymap windmove-mode-map + :init-value t + :global t) + +(defun windmove-install-defaults (prefix modifiers alist &optional uninstall) + "Install keys as specified by ALIST. +Every element of ALIST has the form (FN KEY), where KEY is +appended to MODIFIERS, adding PREFIX to the beginning, before +installing the key. Previous bindings of FN are unbound. +If UNINSTALL is non-nil, just remove the keys from ALIST." + (dolist (bind alist) + (dolist (old (where-is-internal (car bind) windmove-mode-map)) + (define-key windmove-mode-map old nil)) + (unless uninstall + (let ((key (vconcat (if (or (equal prefix [ignore]) + (eq prefix 'none)) + nil prefix) + (list (append modifiers (cdr bind)))))) + (when (eq (key-binding key) #'self-insert-command) + (warn "Command %S is shadowing self-insert-key" (car bind))) + (let ((old-fn (lookup-key windmove-mode-map key))) + (when old-fn + (warn "Overriding %S with %S" old-fn (car bind)))) + (define-key windmove-mode-map key (car bind)))))) + ;;;###autoload (defun windmove-default-keybindings (&optional modifiers) "Set up keybindings for `windmove'. Keybindings are of the form MODIFIERS-{left,right,up,down}, 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'." (interactive) (unless modifiers (setq modifiers 'shift)) + (when (eq modifiers 'none) (setq modifiers nil)) (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)) + (windmove-install-defaults nil modifiers + '((windmove-left left) + (windmove-right right) + (windmove-up up) + (windmove-down down)))) ;;; Directional window display and selection @@ -546,17 +580,21 @@ windmove-display-default-keybindings Keys are bound to commands that display the next buffer in the specified direction. Keybindings are of the form MODIFIERS-{left,right,up,down}, 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'." (interactive) (unless modifiers (setq modifiers '(shift meta))) + (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) - (global-set-key (vector (append modifiers '(left))) 'windmove-display-left) - (global-set-key (vector (append modifiers '(right))) 'windmove-display-right) - (global-set-key (vector (append modifiers '(up))) 'windmove-display-up) - (global-set-key (vector (append modifiers '(down))) 'windmove-display-down) - (global-set-key (vector (append modifiers '(?0))) 'windmove-display-same-window) - (global-set-key (vector (append modifiers '(?f))) 'windmove-display-new-frame) - (global-set-key (vector (append modifiers '(?t))) 'windmove-display-new-tab)) + (windmove-install-defaults nil modifiers + '((windmove-display-left left) + (windmove-display-right right) + (windmove-display-up up) + (windmove-display-down down) + (windmove-display-same-window ?0) + (windmove-display-new-frame ?f) + (windmove-display-new-tab ?t)))) ;;; Directional window deletion @@ -618,16 +656,22 @@ windmove-delete-default-keybindings Keys are bound to commands that delete windows in the specified direction. Keybindings are of the form PREFIX MODIFIERS-{left,right,up,down}, where PREFIX is a prefix key and MODIFIERS is either a list of modifiers or -a single modifier. Default value of PREFIX is `C-x' and MODIFIERS is `shift'." +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'." (interactive) (unless prefix (setq prefix '(?\C-x))) + (when (eq prefix 'none) (setq prefix nil)) (unless (listp prefix) (setq prefix (list prefix))) (unless modifiers (setq modifiers '(shift))) + (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) - (global-set-key (vector prefix (append modifiers '(right))) 'windmove-delete-right) - (global-set-key (vector prefix (append modifiers '(up))) 'windmove-delete-up) - (global-set-key (vector prefix (append modifiers '(down))) 'windmove-delete-down)) + (windmove-install-defaults prefix modifiers + '((windmove-delete-left left) + (windmove-delete-right right) + (windmove-delete-up up) + (windmove-delete-down down)))) ;;; Directional window swap states @@ -673,14 +717,19 @@ windmove-swap-states-default-keybindings Keys are bound to commands that swap the states of the selected window with the window in the specified direction. Keybindings are of the form MODIFIERS-{left,right,up,down}, where MODIFIERS is either a list of modifiers -or a single modifier. Default value of MODIFIERS is `shift-super'." +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'." (interactive) (unless modifiers (setq modifiers '(shift super))) + (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) - (global-set-key (vector (append modifiers '(right))) 'windmove-swap-states-right) - (global-set-key (vector (append modifiers '(up))) 'windmove-swap-states-up) - (global-set-key (vector (append modifiers '(down))) 'windmove-swap-states-down)) + (windmove-install-defaults nil modifiers + '((windmove-swap-states-left left) + (windmove-swap-states-right right) + (windmove-swap-states-up up) + (windmove-swap-states-down down)))) (provide 'windmove) -- 2.30.2 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0002-Add-user-options-for-default-windmove-commands.patch >From 21a8a8854249d24d62d4dd8e17c1f1d20de04fd6 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 27 May 2021 12:24:42 +0200 Subject: [PATCH 2/2] Add user options for default windmove commands * windmove.el (windmove--default-keybindings-type): Add type (windmove-default-keybindings): Add user option (windmove-display-default-keybindings): Add user option (windmove-delete-default-keybindings): Add user option (windmove-swap-states-default-keybindings): Add user option --- lisp/windmove.el | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/lisp/windmove.el b/lisp/windmove.el index cd8592f341..488962c063 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -731,6 +731,86 @@ windmove-swap-states-default-keybindings (windmove-swap-states-up up) (windmove-swap-states-down down)))) + + +(defconst windmove--default-keybindings-type + `(choice (const :tag "Don't bind" nil) + (cons :tag "Bind using" + (key-sequence :tag "Prefix") + (set :tag "Modifier" + :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)))) + "Customisation type for windmove modifiers.") + +(defcustom windmove-default-keybindings nil + "Default bindings for regular windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-left left) + (windmove-right right) + (windmove-up up) + (windmove-down down)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + +(defcustom windmove-display-default-keybindings nil + "Default bindings for display windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-display-left left) + (windmove-display-right right) + (windmove-display-up up) + (windmove-display-down down) + (windmove-display-same-window ?0) + (windmove-display-new-frame ?f) + (windmove-display-new-tab ?t)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + +(defcustom windmove-delete-default-keybindings nil + "Default bindings for delete windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-delete-left left) + (windmove-delete-right right) + (windmove-delete-up up) + (windmove-delete-down down)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + +(defcustom windmove-swap-states-default-keybindings nil + "Default bindings for swap-state windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-swap-states-left left) + (windmove-swap-states-right right) + (windmove-swap-states-up up) + (windmove-swap-states-down down)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + (provide 'windmove) -- 2.30.2 --=-=-=--