GNU bug report logs - #41438
[PATCH] Allow windmove keys to be bound without prefix or modifiers

Previous Next

Package: emacs;

Reported by: "Philip K." <philip <at> warpmail.net>

Date: Thu, 21 May 2020 16:57:01 UTC

Severity: normal

Tags: fixed

Fixed in version 28.0.50

Done: Juri Linkov <juri <at> linkov.net>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 41438 in the body.
You can then email your comments to 41438 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Thu, 21 May 2020 16:57:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to "Philip K." <philip <at> warpmail.net>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Thu, 21 May 2020 16:57:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: "Philip K." <philip <at> warpmail.net>
To: bug-gnu-emacs <at> gnu.org
Subject: [PATCH] Allow windmove keys to be bound without prefix or modifiers
Date: Thu, 21 May 2020 18:56:28 +0200
[Message part 1 (text/plain, inline)]
Hi,

I'm probably not the only one who tends to use C-{f,b,n,p} over the
arrow keys, but also sometimes gets annoyed by navigating windows. I
recently realised that the reason I didn't use windmove as much as I
would want to, was that I coudln't find a satisfying modifier-key. My
idea was then to try windmove without any modifier, and I quite like
it. The only "annoying" thing is that I have to bind all keys
manually, instead of using a function like
`windmove-default-keybindings', because `nil' is interpreted as a
default binding.

This patch adds a pseudo-modifier (`none') to allow bindings the
windmove functions without any real modifier or prefix key, depending on
the function.

--

Another question I'd like to ask before trying it out: Would there be
any interest in adding user options for the "default" modifiers that
windmove should use? If yes, one could add a :set function that
automatically calls the apropriate bindings function, when it's value
is non-nil. I have a very customize-centric configuration, where something
this would fit in very well.

-- 
	Philip K.

[0001-Allow-windmove-keys-to-be-bound-without-prefix-or-mo.patch (text/x-diff, inline)]
From 0fb951817fc11983498052f2a4fdb8815bc89b92 Mon Sep 17 00:00:00 2001
From: Philip K <philip <at> warpmail.net>
Date: Thu, 21 May 2020 18:44:10 +0200
Subject: [PATCH] Allow windmove keys to be bound without prefix or modifiers

---
 lisp/windmove.el | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index f96383197b..3d7f86b9af 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -431,9 +431,12 @@ windmove-default-keybindings
   "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)
@@ -568,9 +571,12 @@ 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)
@@ -640,11 +646,16 @@ 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)
@@ -695,9 +706,13 @@ 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)
-- 
2.20.1


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Thu, 21 May 2020 22:34:02 GMT) Full text and rfc822 format available.

Message #8 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: "Philip K." <philip <at> warpmail.net>
Cc: 41438 <at> debbugs.gnu.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Fri, 22 May 2020 01:18:18 +0300
> I'm probably not the only one who tends to use C-{f,b,n,p} over the
> arrow keys, but also sometimes gets annoyed by navigating windows. I
> recently realised that the reason I didn't use windmove as much as I
> would want to, was that I coudln't find a satisfying modifier-key. My
> idea was then to try windmove without any modifier, and I quite like
> it. The only "annoying" thing is that I have to bind all keys
> manually, instead of using a function like
> `windmove-default-keybindings', because `nil' is interpreted as a
> default binding.
>
> This patch adds a pseudo-modifier (`none') to allow bindings the
> windmove functions without any real modifier or prefix key, depending on
> the function.

Thanks, since `nil' means a default binding it seems there is no other way
than using a pseudo-modifier `none'.

> Another question I'd like to ask before trying it out: Would there be
> any interest in adding user options for the "default" modifiers that
> windmove should use? If yes, one could add a :set function that
> automatically calls the apropriate bindings function, when it's value
> is non-nil. I have a very customize-centric configuration, where something
> this would fit in very well.

I think that adding defcustoms (including a new const `none')
would be the most natural way to customize windmove modifiers
(provided that the existing functions should remain).




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Fri, 22 May 2020 18:27:02 GMT) Full text and rfc822 format available.

Message #11 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: philip <at> warpmail.net (Philip K.)
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, emacs-devel <at> gnu.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Fri, 22 May 2020 20:26:07 +0200
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>> Another question I'd like to ask before trying it out: Would there be
>> any interest in adding user options for the "default" modifiers that
>> windmove should use? If yes, one could add a :set function that
>> automatically calls the apropriate bindings function, when it's value
>> is non-nil. I have a very customize-centric configuration, where something
>> this would fit in very well.
>
> I think that adding defcustoms (including a new const `none')
> would be the most natural way to customize windmove modifiers
> (provided that the existing functions should remain).

I made a first concept, but it doesn't work unless windmove is explicity
required (see below). As far as I know, autoloading variables isn't good
style, so is there any other way to invoke the :set property of a user
option?

-- 
	Philip K.

[0001-Implement-user-options-for-windmove-modifiers-and-pr.patch (text/x-diff, inline)]
From b35173936e681e170172eb3d4548a2f91f70dad3 Mon Sep 17 00:00:00 2001
From: Philip K <philip <at> warpmail.net>
Date: Fri, 22 May 2020 20:21:59 +0200
Subject: [PATCH] Implement user options for windmove modifiers and prefixes

---
 lisp/windmove.el | 103 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 95 insertions(+), 8 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index 3d7f86b9af..95f74bfb81 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -162,6 +162,19 @@ 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))
+  "Customisation type for windmove modifiers")
+
 
 ;; Note:
 ;;
@@ -419,6 +432,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,9 +447,10 @@ 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))
+  (unless modifiers
+    (setq modifiers windmove-modifiers))
   (when (eq modifiers 'none) (setq modifiers nil))
   (unless (listp modifiers) (setq modifiers (list modifiers)))
   (global-set-key (vector (append modifiers '(left)))  'windmove-left)
@@ -443,6 +458,25 @@ windmove-default-keybindings
   (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)
+         (when val
+           (windmove-swap-states-default-keybindings val))
+         (set-default sym val)))
+
 
 ;;; Directional window display and selection
 
@@ -565,6 +599,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.
@@ -573,7 +609,7 @@ 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)))
   (when (eq modifiers 'none) (setq modifiers nil))
@@ -586,6 +622,17 @@ 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))
 
+(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)
+         (when val
+           (windmove-display-default-keybindings val))
+         (set-default sym val)))
+
 
 ;;; Directional window deletion
 
@@ -640,6 +687,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.
@@ -649,12 +699,13 @@ 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)
@@ -662,6 +713,28 @@ 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
+  :set (lambda (sym val)
+         (windmove-delete-default-keybindings
+          val windmove-delete-modifiers)
+         (set-default sym val)))
+
+(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 (lambda (sym val)
+         (when val
+           (windmove-delete-default-keybindings
+            windmove-delete-prefix val))
+         (set-default sym val)))
+
 
 ;;; Directional window swap states
 
@@ -700,6 +773,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.
@@ -709,9 +784,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)
@@ -719,6 +795,17 @@ 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))
 
+(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-swap-states-default-keybindings val)
+         (set-default sym val)))
+
 
 (provide 'windmove)
 
-- 
2.20.1


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Fri, 22 May 2020 19:16:02 GMT) Full text and rfc822 format available.

Message #14 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Drew Adams <drew.adams <at> oracle.com>
To: philip <at> warpmail.net, Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, emacs-devel <at> gnu.org
Subject: RE: bug#41438: [PATCH] Allow windmove keys to be bound without prefix
 or modifiers
Date: Fri, 22 May 2020 12:15:50 -0700 (PDT)
Please don't send the same mail to both the bug list and emacs-devel.  Thx.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sat, 23 May 2020 22:57:03 GMT) Full text and rfc822 format available.

Message #17 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: philip <at> warpmail.net (Philip K.)
Cc: 41438 <at> debbugs.gnu.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sun, 24 May 2020 01:12:42 +0300
>>> Another question I'd like to ask before trying it out: Would there be
>>> any interest in adding user options for the "default" modifiers that
>>> windmove should use? If yes, one could add a :set function that
>>> automatically calls the apropriate bindings function, when it's value
>>> is non-nil. I have a very customize-centric configuration, where something
>>> this would fit in very well.
>>
>> I think that adding defcustoms (including a new const `none')
>> would be the most natural way to customize windmove modifiers
>> (provided that the existing functions should remain).
>
> I made a first concept, but it doesn't work unless windmove is explicity
> required (see below). As far as I know, autoloading variables isn't good
> style, so is there any other way to invoke the :set property of a user
> option?

Recently we had a similar problem in char-fold.el that was solved using
defconst for the default value and a :set function, this might help here.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Fri, 26 Jun 2020 19:52:02 GMT) Full text and rfc822 format available.

Message #20 received at submit <at> debbugs.gnu.org (full text, mbox):

From: "Philip K." <philip <at> warpmail.net>
To: juri <at> linkov.net
Cc: 41438 <at> bugs.debian.org
Subject: bug#41438: [PATCH] Allow windmove keys to be bound without prefix
 or modifiers 
Date: Fri, 26 Jun 2020 21:46:17 +0200
> Recently we had a similar problem in char-fold.el that was solved
> using defconst for the default value and a :set function, this might
> help here.

I've been trying to understand what was changed there (I presume you're
referring to 376f5df), but I don't think I can quite follow. What
difference does adding the defconst forms to the eval-and-compile block
do?

-- 
	Philip K.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Fri, 26 Jun 2020 19:52:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 28 Jun 2020 00:19:01 GMT) Full text and rfc822 format available.

Message #26 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: "Philip K." <philip <at> warpmail.net>
Cc: 41438 <at> debbugs.gnu.org, 41438 <at> bugs.debian.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sun, 28 Jun 2020 02:53:54 +0300
>> Recently we had a similar problem in char-fold.el that was solved
>> using defconst for the default value and a :set function, this might
>> help here.
>
> I've been trying to understand what was changed there (I presume you're
> referring to 376f5df), but I don't think I can quite follow. What
> difference does adding the defconst forms to the eval-and-compile block
> do?

Actually, I meant not so much the defconst form (that is an unimportant
detail), but more the :set function, and also I forgot to mention
:initialize.  Their combination in char-fold.el looks like:

  :initialize #'custom-initialize-default
  :set (lambda (sym val)
         (custom-set-default sym val)
         (char-fold-update-table))

Then after loading char-fold.el, this function is executed at the top level:

(char-fold-update-table)

Maybe something like this could help to initialize default keybindings
after loading windmove.el.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 28 Jun 2020 08:32:02 GMT) Full text and rfc822 format available.

Message #29 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: "Philip K." <philip <at> warpmail.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sun, 28 Jun 2020 10:30:49 +0200
Juri Linkov <juri <at> linkov.net> writes:

> Actually, I meant not so much the defconst form (that is an unimportant
> detail), but more the :set function, and also I forgot to mention
> :initialize.  Their combination in char-fold.el looks like:
>
>   :initialize #'custom-initialize-default
>   :set (lambda (sym val)
>          (custom-set-default sym val)
>          (char-fold-update-table))
>
> Then after loading char-fold.el, this function is executed at the top level:
>
> (char-fold-update-table)
>
> Maybe something like this could help to initialize default keybindings
> after loading windmove.el.

I get what you were saying, but it seems the issue with windmove is the
opposite. Just loading windmove shouldn't create any new keybindings,
but customising the new user options should, *even if* windmove hasn't
been loaded yet (ideally).

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 28 Jun 2020 23:59:01 GMT) Full text and rfc822 format available.

Message #32 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: "Philip K." <philip <at> warpmail.net>
Cc: 41438 <at> debbugs.gnu.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Mon, 29 Jun 2020 02:37:10 +0300
> I get what you were saying, but it seems the issue with windmove is the
> opposite. Just loading windmove shouldn't create any new keybindings,
> but customising the new user options should, *even if* windmove hasn't
> been loaded yet (ideally).

Then it seems explicitly requiring windmove and autoloading variables
is unavoidable, so your previous patch was the right thing to do.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Wed, 05 Aug 2020 18:06:02 GMT) Full text and rfc822 format available.

Message #35 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, "Philip K." <philip <at> warpmail.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Wed, 05 Aug 2020 20:05:36 +0200
Juri Linkov <juri <at> linkov.net> writes:

>> I get what you were saying, but it seems the issue with windmove is the
>> opposite. Just loading windmove shouldn't create any new keybindings,
>> but customising the new user options should, *even if* windmove hasn't
>> been loaded yet (ideally).
>
> Then it seems explicitly requiring windmove and autoloading variables
> is unavoidable, so your previous patch was the right thing to do.

The patch wasn't applied, though?  I know nothing about windmove, so I'm
not really qualified to have an opinion, but if you think it's the right
thing to do, then you should apply it?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Thu, 06 Aug 2020 00:16:02 GMT) Full text and rfc822 format available.

Message #38 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, "Philip K." <philip <at> warpmail.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Thu, 06 Aug 2020 02:40:46 +0300
>>> I get what you were saying, but it seems the issue with windmove is the
>>> opposite. Just loading windmove shouldn't create any new keybindings,
>>> but customising the new user options should, *even if* windmove hasn't
>>> been loaded yet (ideally).
>>
>> Then it seems explicitly requiring windmove and autoloading variables
>> is unavoidable, so your previous patch was the right thing to do.
>
> The patch wasn't applied, though?  I know nothing about windmove, so I'm
> not really qualified to have an opinion, but if you think it's the right
> thing to do, then you should apply it?

Philip, could you please prepare the final version of your patch
(I see there were some unfinished parts in your previous patch).




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Thu, 06 Aug 2020 09:29:02 GMT) Full text and rfc822 format available.

Message #41 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: "Philip K." <philipk <at> posteo.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, larsi <at> gnus.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Thu, 06 Aug 2020 11:28:24 +0200
Juri Linkov <juri <at> linkov.net> writes:

> Philip, could you please prepare the final version of your patch

Sure, I'll try to finish it today.

> (I see there were some unfinished parts in your previous patch).

It's been a while since I submitted it, so I had to re-read the thread,
but I'm not quite sure what the "unfinished" parts were, aside from the
missing autoload cookies. Sorry if I missed something :/

Also, the second patch (the one with the user options) depended on the
previous one in this thread[0], that introduced the "none" prefix. Is
that fine, or should I just merge both patches into one.

[0] https://debbugs.gnu.org/cgi/bugreport.cgi?bug=41438#5

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Fri, 07 Aug 2020 00:53:02 GMT) Full text and rfc822 format available.

Message #44 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: "Philip K." <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, larsi <at> gnus.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Fri, 07 Aug 2020 02:43:03 +0300
>> (I see there were some unfinished parts in your previous patch).
>
> It's been a while since I submitted it, so I had to re-read the thread,
> but I'm not quite sure what the "unfinished" parts were, aside from the
> missing autoload cookies. Sorry if I missed something :/

I don't know, my impression seems to suggest the first version was not
completely tested, for example, windmove-modifiers defcustom called
windmove-swap-states-default-keybindings, not windmove-default-keybindings.
But maybe you already fixed this.

> Also, the second patch (the one with the user options) depended on the
> previous one in this thread[0], that introduced the "none" prefix. Is
> that fine, or should I just merge both patches into one.

This is perfectly fine - better to commit two separate patches.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Fri, 07 Aug 2020 10:54:02 GMT) Full text and rfc822 format available.

Message #47 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: "Philip K." <philipk <at> posteo.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, larsi <at> gnus.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Fri, 07 Aug 2020 12:53:10 +0200
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>>> (I see there were some unfinished parts in your previous patch).
>>
>> It's been a while since I submitted it, so I had to re-read the thread,
>> but I'm not quite sure what the "unfinished" parts were, aside from the
>> missing autoload cookies. Sorry if I missed something :/
>
> I don't know, my impression seems to suggest the first version was not
> completely tested, for example, windmove-modifiers defcustom called
> windmove-swap-states-default-keybindings, not windmove-default-keybindings.
> But maybe you already fixed this.

You're right, I still had a few local changes. A noteworthy addition is
that the user options unbind their previous bindings, before binding the
new ones. This should lead to more consistent behaviour when updating
the option a few times in the same session.

>> Also, the second patch (the one with the user options) depended on the
>> previous one in this thread[0], that introduced the "none" prefix. Is
>> that fine, or should I just merge both patches into one.
>
> This is perfectly fine - better to commit two separate patches.

Ok. I added both below.

But there are a few general issues I noticed:

1. windmove-display-{same-window,new-{frame,tab}} can disturb regular
   input when the modifier is set to shift or none. Possible solutions
   could be to prohibit using these modifiers or to add a prefix key and
   generate a warning when eg. "S-t" or "t" would be rebound.
2. The new function windmove--unbind works with the global-map, so when
   someone sets a prefix to none, and then changes it to something else,
   the arrow keys are left undefined. I could either see this being
   fixed by using a separate map or by somehow memorising what the
   previous key was (eg. by using the property list of the windmove
   command's symbol).

These are the only edge-cases I found, but I didn't fix them yet, as I'm
not sure what would be preferred. So the patches should not be applies yet.

-- 
	Philip K.

[0001-Allow-windmove-keys-to-be-bound-without-prefix-or-mo.patch (text/x-diff, inline)]
From f87d057b72f0cc374c132100664c5b8553bd58e2 Mon Sep 17 00:00:00 2001
From: Philip K <philip <at> warpmail.net>
Date: Thu, 21 May 2020 18:44:10 +0200
Subject: [PATCH] Allow windmove keys to be bound without prefix or modifiers

---
 lisp/windmove.el | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index 6557960064..613727f8ed 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -431,9 +431,12 @@ windmove-default-keybindings
   "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)
@@ -546,9 +549,12 @@ 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)
@@ -618,11 +624,16 @@ 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)
@@ -673,9 +684,13 @@ 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)
-- 
2.20.1

[0001-Add-user-options-to-bind-windmove-commands.patch (text/x-diff, inline)]
From c009311887372e1e822739edc050a802bfa4d1d8 Mon Sep 17 00:00:00 2001
From: Philip K <philipk <at> posteo.net>
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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 09 Aug 2020 00:16:01 GMT) Full text and rfc822 format available.

Message #50 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: "Philip K." <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, larsi <at> gnus.org
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sun, 09 Aug 2020 02:54:17 +0300
> But there are a few general issues I noticed:
>
> 1. windmove-display-{same-window,new-{frame,tab}} can disturb regular
>    input when the modifier is set to shift or none. Possible solutions
>    could be to prohibit using these modifiers or to add a prefix key and
>    generate a warning when eg. "S-t" or "t" would be rebound.

Perhaps displaying a warning should be sufficient.

> 2. The new function windmove--unbind works with the global-map, so when
>    someone sets a prefix to none, and then changes it to something else,
>    the arrow keys are left undefined. I could either see this being
>    fixed by using a separate map or by somehow memorising what the
>    previous key was (eg. by using the property list of the windmove
>    command's symbol).

I'm not sure whether such complication is necessary.  Usually
users will try to customize the option and then restart Emacs.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Wed, 12 May 2021 20:39:01 GMT) Full text and rfc822 format available.

Message #53 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: "Philip K." <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Wed, 12 May 2021 22:38:33 +0200
"Philip K." <philipk <at> posteo.net> writes:

> These are the only edge-cases I found, but I didn't fix them yet, as I'm
> not sure what would be preferred. So the patches should not be applies yet.

Have you done any further work on this?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Removed tag(s) patch. Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Wed, 12 May 2021 20:39:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Wed, 12 May 2021 21:28:02 GMT) Full text and rfc822 format available.

Message #58 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Wed, 12 May 2021 21:27:45 +0000
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> "Philip K." <philipk <at> posteo.net> writes:
>
>> These are the only edge-cases I found, but I didn't fix them yet, as I'm
>> not sure what would be preferred. So the patches should not be applies yet.
>
> Have you done any further work on this?

No, not since whenever that message was sent.

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sat, 22 May 2021 20:31:01 GMT) Full text and rfc822 format available.

Message #61 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sat, 22 May 2021 20:29:50 +0000
[Message part 1 (text/plain, inline)]
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> "Philip K." <philipk <at> posteo.net> writes:
>
>> These are the only edge-cases I found, but I didn't fix them yet, as I'm
>> not sure what would be preferred. So the patches should not be applies yet.
>
> Have you done any further work on this?

I have been thinking about this a bit more, and tried a different
approach. The implementation is not prefect, but basically I am playing
with emulation-mode-map-alists to bind the keys, instead of using the
global map.

The should solve the two issues I brought up, because I do not have to
worry about restoring the previous keys, and some edge-cases are
avoided, where e.g. doc-view would override up and down breaking the
expected behaviour when setting the prefix to 'none.

The code should probably be refactored, moving more of the common
functionality into it's own function, but I am primarily wondering if
using emulation-mode-map-alists the way I am proposing it here is ok. Or
should I prefer minor-mode-map-alist?

-- 
	Philip K.

[0001-Allow-windmove-keys-to-be-bound-without-prefix-or-mo.patch (text/x-diff, inline)]
From eba161853d50c2a6ce27af5907efdae4f6ab81eb Mon Sep 17 00:00:00 2001
From: Philip K <philipk <at> posteo.net>
Date: Sat, 22 May 2021 22:03:22 +0200
Subject: [PATCH] Allow windmove keys to be bound without prefix or modifiers

---
 lisp/windmove.el | 91 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 70 insertions(+), 21 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index e4ea8e0f69..acd9cb41fc 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -426,19 +426,35 @@ 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-map (make-sparse-keymap)
+  "Keymap to bind windmove keys to.")
+
+(add-to-list 'emulation-mode-map-alists
+             (list (cons t windmove-map)))
+
 ;;;###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))
+  (dolist (bind '((windmove-left left)
+                  (windmove-right right)
+                  (windmove-up up)
+                  (windmove-down down)))
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-map))
+        (define-key windmove-map old nil))
+      (define-key windmove-map
+        (vector (append modifiers (cdr bind)))
+        (car bind)))))
 
 
 ;;; Directional window display and selection
@@ -546,17 +562,27 @@ 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))
+  (dolist (bind '((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)))
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-map))
+        (define-key windmove-map old nil))
+      (define-key windmove-map
+        (vector (append modifiers (cdr bind)))
+        (car bind)))))
 
 
 ;;; Directional window deletion
@@ -618,16 +644,28 @@ 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))
+  (dolist (bind '((windmove-delete-left left)
+                  (windmove-delete-right right)
+                  (windmove-delete-up up)
+                  (windmove-delete-down down)))
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-map))
+        (define-key windmove-map old nil))
+      (define-key windmove-map
+        (vector (append modifiers (cdr bind)))
+        (car bind)))))
 
 
 ;;; Directional window swap states
@@ -673,14 +711,25 @@ 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))
+  (dolist (bind '((windmove-swap-states-left left)
+                  (windmove-swap-states-right right)
+                  (windmove-swap-states-up up)
+                  (windmove-swap-states-down down)))
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-map))
+        (define-key windmove-map old nil))
+      (define-key windmove-map
+        (vector (append modifiers (cdr bind)))
+        (car bind)))))
 
 
 (provide 'windmove)
-- 
2.30.2


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sat, 22 May 2021 21:10:01 GMT) Full text and rfc822 format available.

Message #64 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sat, 22 May 2021 21:09:00 +0000
[Message part 1 (text/plain, inline)]
Philip Kaludercic <philipk <at> posteo.net> writes:

> The code should probably be refactored, moving more of the common
> functionality into it's own function, but I am primarily wondering if
> using emulation-mode-map-alists the way I am proposing it here is ok. Or
> should I prefer minor-mode-map-alist?

Here is a slightly cleaner version.

-- 
	Philip K.

[0001-Allow-windmove-keys-to-be-bound-without-prefix-or-mo.patch (text/x-diff, inline)]
From 03248e79527f9603aa944e7e147fc67a8886eb3a Mon Sep 17 00:00:00 2001
From: Philip K <philipk <at> posteo.net>
Date: Sat, 22 May 2021 22:03:22 +0200
Subject: [PATCH] Allow windmove keys to be bound without prefix or modifiers

---
 lisp/windmove.el | 79 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 58 insertions(+), 21 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index e4ea8e0f69..bb9478eab4 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -426,19 +426,41 @@ 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-default-map (make-sparse-keymap)
+  "Map used by `windmove-install-defaults'.")
+
+(defun windmove-install-defaults (modifiers alist)
+  "Install keys as specified by ALIST.
+Every element of ALIST has the form (FN KEY), where KEY is
+appended to MODIFIERS, before installing the key.  Previous
+bindings of FN are unbound."
+  (add-to-list 'emulation-mode-map-alists `((t . ,windmove-default-map)))
+  (dolist (bind alist)
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-default-map))
+        (define-key windmove-default-map old nil))
+      (define-key windmove-default-map
+        (vector (append modifiers (cdr bind)))
+        (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 modifiers
+                             '((windmove-left left)
+                               (windmove-right right)
+                               (windmove-up up)
+                               (windmove-down down))))
 
 
 ;;; Directional window display and selection
@@ -546,17 +568,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 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 +644,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 modifiers
+                             '((windmove-delete-left left)
+                               (windmove-delete-right right)
+                               (windmove-delete-up up)
+                               (windmove-delete-down down))))
 
 
 ;;; Directional window swap states
@@ -673,14 +705,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 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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 23 May 2021 06:50:02 GMT) Full text and rfc822 format available.

Message #67 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, larsi <at> gnus.org, juri <at> linkov.net
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without prefix
 or modifiers
Date: Sun, 23 May 2021 09:49:26 +0300
> From: Philip Kaludercic <philipk <at> posteo.net>
> Date: Sat, 22 May 2021 21:09:00 +0000
> Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
> 
> Philip Kaludercic <philipk <at> posteo.net> writes:
> 
> > The code should probably be refactored, moving more of the common
> > functionality into it's own function, but I am primarily wondering if
> > using emulation-mode-map-alists the way I am proposing it here is ok. Or
> > should I prefer minor-mode-map-alist?
> 
> Here is a slightly cleaner version.

Thanks.  Should this be in NEWS?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 23 May 2021 12:37:01 GMT) Full text and rfc822 format available.

Message #70 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 41438 <at> debbugs.gnu.org, larsi <at> gnus.org, juri <at> linkov.net
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Sun, 23 May 2021 12:36:43 +0000
Eli Zaretskii <eliz <at> gnu.org> writes:

>> From: Philip Kaludercic <philipk <at> posteo.net>
>> Date: Sat, 22 May 2021 21:09:00 +0000
>> Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
>> 
>> Philip Kaludercic <philipk <at> posteo.net> writes:
>> 
>> > The code should probably be refactored, moving more of the common
>> > functionality into it's own function, but I am primarily wondering if
>> > using emulation-mode-map-alists the way I am proposing it here is ok. Or
>> > should I prefer minor-mode-map-alist?
>> 
>> Here is a slightly cleaner version.
>
> Thanks.  Should this be in NEWS?

I think so. IIRC the plan was to add a few additional user options to
make it easier to configure.

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 05:13:02 GMT) Full text and rfc822 format available.

Message #73 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 07:12:36 +0200
Philip Kaludercic <philipk <at> posteo.net> writes:

> The code should probably be refactored, moving more of the common
> functionality into it's own function, but I am primarily wondering if
> using emulation-mode-map-alists the way I am proposing it here is ok. Or
> should I prefer minor-mode-map-alist?

Making windmove into a regular (global) minor mode would be less
surprising, I think, but I'm not really familiar with windmove, and
whether that would be an easy rewrite?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 07:26:01 GMT) Full text and rfc822 format available.

Message #76 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 07:25:10 +0000
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> Philip Kaludercic <philipk <at> posteo.net> writes:
>
>> The code should probably be refactored, moving more of the common
>> functionality into it's own function, but I am primarily wondering if
>> using emulation-mode-map-alists the way I am proposing it here is ok. Or
>> should I prefer minor-mode-map-alist?
>
> Making windmove into a regular (global) minor mode would be less
> surprising, I think, but I'm not really familiar with windmove, and
> whether that would be an easy rewrite?

From my experience, it should be possible, I'll try preparing a
patch. The only issue is that most people won't realize there is a minor
mode at first, but that should be OK as long as the actual windmove
commands do not depend on said minor mode.

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 09:54:02 GMT) Full text and rfc822 format available.

Message #79 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 09:53:19 +0000
[Message part 1 (text/plain, inline)]
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> Philip Kaludercic <philipk <at> posteo.net> writes:
>
>> The code should probably be refactored, moving more of the common
>> functionality into it's own function, but I am primarily wondering if
>> using emulation-mode-map-alists the way I am proposing it here is ok. Or
>> should I prefer minor-mode-map-alist?
>
> Making windmove into a regular (global) minor mode would be less
> surprising, I think, but I'm not really familiar with windmove, and
> whether that would be an easy rewrite?

I have tried this out, and it seems somewhat elegant.  From my testing,
it seems to behave the same way as the previous approach.

-- 
	Philip K.

[0001-Improve-windmove-default-keybindings-fuctions.patch (text/x-diff, inline)]
From 2f7a8d89cdb5835cf875bc1f2bcfcb6755a0e0c0 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
Date: Tue, 25 May 2021 11:47:51 +0200
Subject: [PATCH] Improve windmove-*-default-keybindings fuctions

* windmove.el (windmove-default-map): Add special map for windmove
commands
(windmove-mode): Add minor mode for activating windmove-default-map
(windmove-install-defaults): Add general function for manipulating
windmove-default-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 | 84 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 21 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index e4ea8e0f69..5a81893bf9 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -426,19 +426,46 @@ 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-default-map (make-sparse-keymap)
+  "Map used by `windmove-install-defaults'.")
+
+(define-minor-mode windmove-mode
+  "Global minor mode for default windmove commands."
+  :keymap windmove-default-map
+  :init-value t
+  :global t)
+
+(defun windmove-install-defaults (modifiers alist)
+  "Install keys as specified by ALIST.
+Every element of ALIST has the form (FN KEY), where KEY is
+appended to MODIFIERS, before installing the key.  Previous
+bindings of FN are unbound."
+  (dolist (bind alist)
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-default-map))
+        (define-key windmove-default-map old nil))
+      (define-key windmove-default-map
+        (vector (append modifiers (cdr bind)))
+        (car bind)))))
+
 ;;;###autoload
 (defun windmove-default-keybindingsq (&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 modifiers
+                             '((windmove-left left)
+                               (windmove-right right)
+                               (windmove-up up)
+                               (windmove-down down))))
 
 
 ;;; Directional window display and selection
@@ -546,17 +573,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 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 +649,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 modifiers
+                             '((windmove-delete-left left)
+                               (windmove-delete-right right)
+                               (windmove-delete-up up)
+                               (windmove-delete-down down))))
 
 
 ;;; Directional window swap states
@@ -673,14 +710,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 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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 11:17:02 GMT) Full text and rfc822 format available.

Message #82 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Arthur Miller <arthur.miller <at> live.com>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 13:16:24 +0200
Philip Kaludercic <philipk <at> posteo.net> writes:

> Lars Ingebrigtsen <larsi <at> gnus.org> writes:
>
>> Philip Kaludercic <philipk <at> posteo.net> writes:
>>
>>> The code should probably be refactored, moving more of the common
>>> functionality into it's own function, but I am primarily wondering if
>>> using emulation-mode-map-alists the way I am proposing it here is ok. Or
>>> should I prefer minor-mode-map-alist?
>>
>> Making windmove into a regular (global) minor mode would be less
>> surprising, I think, but I'm not really familiar with windmove, and
>> whether that would be an easy rewrite?
>
> I have tried this out, and it seems somewhat elegant.  From my testing,
> it seems to behave the same way as the previous approach.
>
> -- 
> 	Philip K.
>
> From 2f7a8d89cdb5835cf875bc1f2bcfcb6755a0e0c0 Mon Sep 17 00:00:00 2001
> From: Philip Kaludercic <philipk <at> posteo.net>
> Date: Tue, 25 May 2021 11:47:51 +0200
> Subject: [PATCH] Improve windmove-*-default-keybindings fuctions
>
> * windmove.el (windmove-default-map): Add special map for windmove
> commands
> (windmove-mode): Add minor mode for activating windmove-default-map
> (windmove-install-defaults): Add general function for manipulating
> windmove-default-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 | 84 ++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 63 insertions(+), 21 deletions(-)
>
> diff --git a/lisp/windmove.el b/lisp/windmove.el
> index e4ea8e0f69..5a81893bf9 100644
> --- a/lisp/windmove.el
> +++ b/lisp/windmove.el
> @@ -426,19 +426,46 @@ 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-default-map (make-sparse-keymap)
> +  "Map used by `windmove-install-defaults'.")
Sorry if I ask, but wouldn't ordinary windmove-mode-map do here?

Since it is a convention to have mode maps called modename-mode-maps,
if people would like to change, or add a binding in the windmove mode
they would probably automatically try to alter windmove-mode-map instead
of windmove-default-map.


> +(define-minor-mode windmove-mode
> +  "Global minor mode for default windmove commands."
> +  :keymap windmove-default-map
> +  :init-value t
> +  :global t)
> +
> +(defun windmove-install-defaults (modifiers alist)
> +  "Install keys as specified by ALIST.
> +Every element of ALIST has the form (FN KEY), where KEY is
> +appended to MODIFIERS, before installing the key.  Previous
> +bindings of FN are unbound."
> +  (dolist (bind alist)
> +    (when (or (memq (cadr bind) '(left right up down))
> +              (not (null modifiers)))
> +      (dolist (old (where-is-internal (car bind) windmove-default-map))
> +        (define-key windmove-default-map old nil))
> +      (define-key windmove-default-map
> +        (vector (append modifiers (cdr bind)))
> +        (car bind)))))
> +
>  ;;;###autoload
>  (defun windmove-default-keybindingsq (&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 modifiers
> +                             '((windmove-left left)
> +                               (windmove-right right)
> +                               (windmove-up up)
> +                               (windmove-down down))))
>  
>  
>  ;;; Directional window display and selection
> @@ -546,17 +573,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 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 +649,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 modifiers
> +                             '((windmove-delete-left left)
> +                               (windmove-delete-right right)
> +                               (windmove-delete-up up)
> +                               (windmove-delete-down down))))
>  
>  
>  ;;; Directional window swap states
> @@ -673,14 +710,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 modifiers
> +                             '((windmove-swap-states-left left)
> +                               (windmove-swap-states-right right)
> +                               (windmove-swap-states-up up)
> +                               (windmove-swap-states-down down))))
>  
>  
>  (provide 'windmove)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 11:37:01 GMT) Full text and rfc822 format available.

Message #85 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Arthur Miller <arthur.miller <at> live.com>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 13:36:22 +0200
Philip Kaludercic <philipk <at> posteo.net> writes:

If you are already patching windmove.el, can you consider adding
bindings for these funcitions too (defined in window.el):

enlarge-window-horizontally
shrink-window-horizontally

As well as add these two wrappers for vertical operations:

#+begin_src emacs-lisp

;;;###autoload
(defun enlarge-window-vertically (delta)
  "Make selected window DELTA columns wider.
Interactively, if no argument is given, make selected window one
column wider."
  (interactive "p")
  (enlarge-window delta nil))

;;;###autoload
(defun shrink-window-vertically (delta)
  "Make selected window DELTA columns narrower.
Interactively, if no argument is given, make selected window one
column narrower."
  (interactive "p")
  (shrink-window delta nil))

#+end_src

I have been using those for long time myself since I prefer to do
everything from the keyboard. Maybe someone else finds them useful too;
they have been in my config on GH for long time.

> Lars Ingebrigtsen <larsi <at> gnus.org> writes:
>
>> Philip Kaludercic <philipk <at> posteo.net> writes:
>>
>>> The code should probably be refactored, moving more of the common
>>> functionality into it's own function, but I am primarily wondering if
>>> using emulation-mode-map-alists the way I am proposing it here is ok. Or
>>> should I prefer minor-mode-map-alist?
>>
>> Making windmove into a regular (global) minor mode would be less
>> surprising, I think, but I'm not really familiar with windmove, and
>> whether that would be an easy rewrite?
>
> I have tried this out, and it seems somewhat elegant.  From my testing,
> it seems to behave the same way as the previous approach.
>
> -- 
> 	Philip K.
>
> From 2f7a8d89cdb5835cf875bc1f2bcfcb6755a0e0c0 Mon Sep 17 00:00:00 2001
> From: Philip Kaludercic <philipk <at> posteo.net>
> Date: Tue, 25 May 2021 11:47:51 +0200
> Subject: [PATCH] Improve windmove-*-default-keybindings fuctions
>
> * windmove.el (windmove-default-map): Add special map for windmove
> commands
> (windmove-mode): Add minor mode for activating windmove-default-map
> (windmove-install-defaults): Add general function for manipulating
> windmove-default-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 | 84 ++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 63 insertions(+), 21 deletions(-)
>
> diff --git a/lisp/windmove.el b/lisp/windmove.el
> index e4ea8e0f69..5a81893bf9 100644
> --- a/lisp/windmove.el
> +++ b/lisp/windmove.el
> @@ -426,19 +426,46 @@ 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-default-map (make-sparse-keymap)
> +  "Map used by `windmove-install-defaults'.")
> +
> +(define-minor-mode windmove-mode
> +  "Global minor mode for default windmove commands."
> +  :keymap windmove-default-map
> +  :init-value t
> +  :global t)
> +
> +(defun windmove-install-defaults (modifiers alist)
> +  "Install keys as specified by ALIST.
> +Every element of ALIST has the form (FN KEY), where KEY is
> +appended to MODIFIERS, before installing the key.  Previous
> +bindings of FN are unbound."
> +  (dolist (bind alist)
> +    (when (or (memq (cadr bind) '(left right up down))
> +              (not (null modifiers)))
> +      (dolist (old (where-is-internal (car bind) windmove-default-map))
> +        (define-key windmove-default-map old nil))
> +      (define-key windmove-default-map
> +        (vector (append modifiers (cdr bind)))
> +        (car bind)))))
> +
>  ;;;###autoload
>  (defun windmove-default-keybindingsq (&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 modifiers
> +                             '((windmove-left left)
> +                               (windmove-right right)
> +                               (windmove-up up)
> +                               (windmove-down down))))
>  
>  
>  ;;; Directional window display and selection
> @@ -546,17 +573,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 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 +649,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 modifiers
> +                             '((windmove-delete-left left)
> +                               (windmove-delete-right right)
> +                               (windmove-delete-up up)
> +                               (windmove-delete-down down))))
>  
>  
>  ;;; Directional window swap states
> @@ -673,14 +710,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 modifiers
> +                             '((windmove-swap-states-left left)
> +                               (windmove-swap-states-right right)
> +                               (windmove-swap-states-up up)
> +                               (windmove-swap-states-down down))))
>  
>  
>  (provide 'windmove)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 11:44:02 GMT) Full text and rfc822 format available.

Message #88 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Arthur Miller <arthur.miller <at> live.com>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 11:42:56 +0000
Arthur Miller <arthur.miller <at> live.com> writes:

> Philip Kaludercic <philipk <at> posteo.net> writes:
>> +(defvar windmove-default-map (make-sparse-keymap)
>> +  "Map used by `windmove-install-defaults'.")
>
> Sorry if I ask, but wouldn't ordinary windmove-mode-map do here?

You are probably right -- my thought was that the minor mode exists for
the sake of the map.

> Since it is a convention to have mode maps called modename-mode-maps,
> if people would like to change, or add a binding in the windmove mode
> they would probably automatically try to alter windmove-mode-map instead
> of windmove-default-map.

That's the question: should windmove-default-map be accessed by default
or only via the -default-keybindings functions? Either way something
should be changed, if windmove-default-map it should be renamed to
windmove--default-map to explicitly mark it as an internal
map. Otherwise it should be renamed to windmove-mode-map as you suggest.

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 11:47:01 GMT) Full text and rfc822 format available.

Message #91 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Arthur Miller <arthur.miller <at> live.com>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 11:46:31 +0000
Arthur Miller <arthur.miller <at> live.com> writes:

> If you are already patching windmove.el, can you consider adding
> bindings for these funcitions too (defined in window.el):
>
> enlarge-window-horizontally
> shrink-window-horizontally
>
> As well as add these two wrappers for vertical operations:
>
> #+begin_src emacs-lisp
>
> ;;;###autoload
> (defun enlarge-window-vertically (delta)
>   "Make selected window DELTA columns wider.
> Interactively, if no argument is given, make selected window one
> column wider."
>   (interactive "p")
>   (enlarge-window delta nil))
>
> ;;;###autoload
> (defun shrink-window-vertically (delta)
>   "Make selected window DELTA columns narrower.
> Interactively, if no argument is given, make selected window one
> column narrower."
>   (interactive "p")
>   (shrink-window delta nil))
>
> #+end_src
>
> I have been using those for long time myself since I prefer to do
> everything from the keyboard. Maybe someone else finds them useful too;
> they have been in my config on GH for long time.

I am not sure if these commands should be added as part of the same
changeset. The point of this commit is to make configuring windmove keys
using windmove-default-keybindings & co. more consistent.

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 13:32:01 GMT) Full text and rfc822 format available.

Message #94 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Arthur Miller <arthur.miller <at> live.com>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 15:31:43 +0200
Philip Kaludercic <philipk <at> posteo.net> writes:

> Arthur Miller <arthur.miller <at> live.com> writes:
>
>> Philip Kaludercic <philipk <at> posteo.net> writes:
>>> +(defvar windmove-default-map (make-sparse-keymap)
>>> +  "Map used by `windmove-install-defaults'.")
>>
>> Sorry if I ask, but wouldn't ordinary windmove-mode-map do here?
>
> You are probably right -- my thought was that the minor mode exists for
> the sake of the map.

Yeah, exactly in this case. I am not sure if I understand correctly, you
mean people will set new map for the mode to change bindings?

I just remarked on the name you choose for the mode map, most peeps like
me probably expect it to be names after the convention 'modename-mode-map'.

>> Since it is a convention to have mode maps called modename-mode-maps,
>> if people would like to change, or add a binding in the windmove mode
>> they would probably automatically try to alter windmove-mode-map instead
>> of windmove-default-map.
>
> That's the question: should windmove-default-map be accessed by default
> or only via the -default-keybindings functions? Either way something

I think you are thinking about default keybindings reather than default
map. If I assume correctly. If I understand corectly you would like to
preserve some default bindings, the map is just a mean to accomplish it.

> should be changed, if windmove-default-map it should be renamed to
> windmove--default-map to explicitly mark it as an internal
> map. Otherwise it shsould be renamed to windmove-mode-map as you suggest.

Either use default map stored some "default var", and add a function
that restores mode map, or just add a function that resets keybindings
into mode map directly, which might be sufficient. I don't know matter
of taste? A default mode map in a variable is cleaner but more costly?

Emacs provides windows, so I think there should also be a default way of
moving cursor between them, manipulate them and so on. Thus I think
windmove operations should be on by default, I don't think C-x 1/2/3/o
are satisfying when we have more then 2 widows.

A minor mode is probably a good balance between altering Emacs defaults,
so not break someones config, and to give people an option to easily
turn on some useful feature/configuration.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 13:59:02 GMT) Full text and rfc822 format available.

Message #97 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Arthur Miller <arthur.miller <at> live.com>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 15:58:03 +0200
Philip Kaludercic <philipk <at> posteo.net> writes:

> Arthur Miller <arthur.miller <at> live.com> writes:
>
>> If you are already patching windmove.el, can you consider adding
>> bindings for these funcitions too (defined in window.el):
>>
>> enlarge-window-horizontally
>> shrink-window-horizontally
>>
>> As well as add these two wrappers for vertical operations:
>>
>> #+begin_src emacs-lisp
>>
>> ;;;###autoload
>> (defun enlarge-window-vertically (delta)
>>   "Make selected window DELTA columns wider.
>> Interactively, if no argument is given, make selected window one
>> column wider."
>>   (interactive "p")
>>   (enlarge-window delta nil))
>>
>> ;;;###autoload
>> (defun shrink-window-vertically (delta)
>>   "Make selected window DELTA columns narrower.
>> Interactively, if no argument is given, make selected window one
>> column narrower."
>>   (interactive "p")
>>   (shrink-window delta nil))
>>
>> #+end_src
>>
>> I have been using those for long time myself since I prefer to do
>> everything from the keyboard. Maybe someone else finds them useful too;
>> they have been in my config on GH for long time.
>
> I am not sure if these commands should be added as part of the same
> changeset.
Those two wrappers itself are not necessary to add, they are just they
for the sake of naming. It looks better and more clear what a binding
does in "whick-key" window, in help buffers, and provides better
symmetry to shrink/enlarge-window-horizontally.

original functions are all in window.el:

shrink-window
enlarge-window
shrink-window-horizontally
enlarge-window-horizontally

> The point of this commit is to make configuring windmove keys
> using windmove-default-keybindings & co. more consistent.

I completeley understand you are concentrated just on windmove keys.

This is just a suggestion. I think windmove should have probably be
named from the beginning as "windoperations", since it does more than
just move corsor between windows.

Shrinking and enlarging windows is definitely a useful window operation
to beind on a key, in my opinion should have been in windmove.el since
beginning.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 14:40:02 GMT) Full text and rfc822 format available.

Message #100 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Arthur Miller <arthur.miller <at> live.com>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 14:39:05 +0000
Arthur Miller <arthur.miller <at> live.com> writes:

> Philip Kaludercic <philipk <at> posteo.net> writes:
>
>> Arthur Miller <arthur.miller <at> live.com> writes:
>>
>>> Philip Kaludercic <philipk <at> posteo.net> writes:
>>>> +(defvar windmove-default-map (make-sparse-keymap)
>>>> +  "Map used by `windmove-install-defaults'.")
>>>
>>> Sorry if I ask, but wouldn't ordinary windmove-mode-map do here?
>>
>> You are probably right -- my thought was that the minor mode exists for
>> the sake of the map.
>
> Yeah, exactly in this case. I am not sure if I understand correctly, you
> mean people will set new map for the mode to change bindings?

No, that is why the minor mode is active by default. The only reason the
minor mode is defined is to modify minor-mode-map-alist.

>> That's the question: should windmove-default-map be accessed by default
>> or only via the -default-keybindings functions? Either way something
>
> I think you are thinking about default keybindings reather than default
> map. If I assume correctly. If I understand corectly you would like to
> preserve some default bindings, the map is just a mean to accomplish it.

I am not sure what you are referring to, the map is manipulated by
windmove-install-defaults, which in turn is used by

* windmove-default-keybindings
* windmove-display-default-keybindings
* windmove-delete-default-keybindings
* windmove-swap-states-default-keybindings

So it is not just about preserving some default bindings, but ensuring
that the explicitly requested bindings are installed correctly.

>> should be changed, if windmove-default-map it should be renamed to
>> windmove--default-map to explicitly mark it as an internal
>> map. Otherwise it shsould be renamed to windmove-mode-map as you suggest.
>
> Either use default map stored some "default var", and add a function
> that restores mode map, or just add a function that resets keybindings
> into mode map directly, which might be sufficient. I don't know matter
> of taste? A default mode map in a variable is cleaner but more costly?
>
> Emacs provides windows, so I think there should also be a default way of
> moving cursor between them, manipulate them and so on. Thus I think
> windmove operations should be on by default, I don't think C-x 1/2/3/o
> are satisfying when we have more then 2 widows.
>
> A minor mode is probably a good balance between altering Emacs defaults,
> so not break someones config, and to give people an option to easily
> turn on some useful feature/configuration.

I'm sorry, either I am missing something or we are talking besides one
another.

-- 
	Philip K.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 19:14:02 GMT) Full text and rfc822 format available.

Message #103 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Arthur Miller <arthur.miller <at> live.com>
Cc: 41438 <at> debbugs.gnu.org, Philip Kaludercic <philipk <at> posteo.net>,
 Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 21:13:14 +0200
Arthur Miller <arthur.miller <at> live.com> writes:

> If you are already patching windmove.el, can you consider adding
> bindings for these funcitions too (defined in window.el):

This seems unrelated to this current bug report, but you could open a
new wishlist bug report for this.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 19:17:01 GMT) Full text and rfc822 format available.

Message #106 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 21:16:23 +0200
Philip Kaludercic <philipk <at> posteo.net> writes:

> I have tried this out, and it seems somewhat elegant.  From my testing,
> it seems to behave the same way as the previous approach.

Looks good to me.  One minor thing:

> +(defvar windmove-default-map (make-sparse-keymap)
> +  "Map used by `windmove-install-defaults'.")

This should be called -mode-map.

I don't actually use windmove -- could somebody else who's using this
try this patch out and see whether it works well for them?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 19:26:01 GMT) Full text and rfc822 format available.

Message #109 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 41438 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 19:25:16 +0000
[Message part 1 (text/plain, inline)]
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> Philip Kaludercic <philipk <at> posteo.net> writes:
>
>> I have tried this out, and it seems somewhat elegant.  From my testing,
>> it seems to behave the same way as the previous approach.
>
> Looks good to me.  One minor thing:
>
>> +(defvar windmove-default-map (make-sparse-keymap)
>> +  "Map used by `windmove-install-defaults'.")
>
> This should be called -mode-map.

Ok, the patch is below. I also added warning this time to net people
know if automatically bound keys would conflict.

> I don't actually use windmove -- could somebody else who's using this
> try this patch out and see whether it works well for them?

-- 
	Philip K.

[0001-Improve-windmove-default-keybindings-fuctions.patch (text/x-diff, inline)]
From d572168a4fce653dcded2c4ca54f324dca78e280 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
Date: Tue, 25 May 2021 11:47:51 +0200
Subject: [PATCH] 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 | 80 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 59 insertions(+), 21 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index e4ea8e0f69..479fdef512 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -426,19 +426,42 @@ 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'.")
+
+(defun windmove-install-defaults (modifiers alist)
+  "Install keys as specified by ALIST.
+Every element of ALIST has the form (FN KEY), where KEY is
+appended to MODIFIERS, before installing the key.  Previous
+bindings of FN are unbound."
+  (dolist (bind alist)
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-mode-map))
+        (define-key windmove-mode-map old nil))
+      (let ((key (vector (append modifiers (cdr 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 modifiers
+                             '((windmove-left left)
+                               (windmove-right right)
+                               (windmove-up up)
+                               (windmove-down down))))
 
 
 ;;; Directional window display and selection
@@ -546,17 +569,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 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 +645,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 modifiers
+                             '((windmove-delete-left left)
+                               (windmove-delete-right right)
+                               (windmove-delete-up up)
+                               (windmove-delete-down down))))
 
 
 ;;; Directional window swap states
@@ -673,14 +706,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 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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 20:39:02 GMT) Full text and rfc822 format available.

Message #112 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 23:18:13 +0300
> -  (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 modifiers
> +                             '((windmove-delete-left left)
> +                               (windmove-delete-right right)
> +                               (windmove-delete-up up)
> +                               (windmove-delete-down down))))

I haven't yet tested your patch, but after reading it seems 'prefix' is unused now?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Tue, 25 May 2021 21:46:01 GMT) Full text and rfc822 format available.

Message #115 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Tue, 25 May 2021 21:45:45 +0000
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>> -  (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 modifiers
>> +                             '((windmove-delete-left left)
>> +                               (windmove-delete-right right)
>> +                               (windmove-delete-up up)
>> +                               (windmove-delete-down down))))
>
> I haven't yet tested your patch, but after reading it seems 'prefix' is unused now?

You are right, I didn't test that specific function
properly. windmove-install-defaults had to be extended by another
argument to fix this.

What I don't really like is that only
windmove-delete-default-keybindings can make use of prefixes, while all
commands only use modifiers. Could it make sense to deprecate these
functions in favour of either new functions or user-options?

-- 
	Philip K.

[0001-Improve-windmove-default-keybindings-fuctions.patch (text/x-diff, inline)]
From ecbed85db9622ef5b1680472273163cb7789ae3f Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
Date: Tue, 25 May 2021 11:47:51 +0200
Subject: [PATCH] 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 | 87 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 66 insertions(+), 21 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index e4ea8e0f69..d7c1d25d82 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -426,19 +426,49 @@ 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)
+  "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."
+  (dolist (bind alist)
+    (when (or (memq (cadr bind) '(left right up down))
+              (not (null modifiers)))
+      (dolist (old (where-is-internal (car bind) windmove-mode-map))
+        (define-key windmove-mode-map old nil))
+      (let ((key (vconcat (if (eq prefix 'none) nil prefix)
+                          (list (append modifiers (cdr 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 +576,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 +652,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 +713,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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Wed, 26 May 2021 21:41:01 GMT) Full text and rfc822 format available.

Message #118 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Thu, 27 May 2021 00:35:46 +0300
> What I don't really like is that only
> windmove-delete-default-keybindings can make use of prefixes, while all
> commands only use modifiers. Could it make sense to deprecate these
> functions in favour of either new functions or user-options?

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.
Or maybe there will be a need to create separate modes for every
keymap, e.g. windmove-display-mode, windmove-delete-mode?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Thu, 27 May 2021 11:10:01 GMT) Full text and rfc822 format available.

Message #121 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Thu, 27 May 2021 11:09:14 +0000
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>> What I don't really like is that only
>> windmove-delete-default-keybindings can make use of prefixes, while all
>> commands only use modifiers. Could it make sense to deprecate these
>> functions in favour of either new functions or user-options?
>
> 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.

> Or maybe there will be a need to create separate modes for every
> keymap, e.g. windmove-display-mode, windmove-delete-mode?

I don't see why that should be necessary, as the proposed windmove-mode
doesn't even have the interest the user.

-- 
	Philip K.

[0001-Improve-windmove-default-keybindings-fuctions.patch (text/x-diff, inline)]
From 42a66e87af83817b9e989624fdbf9c7ee7c347c7 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
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

[0002-Add-user-options-for-default-windmove-commands.patch (text/x-diff, inline)]
From 21a8a8854249d24d62d4dd8e17c1f1d20de04fd6 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Sun, 30 May 2021 22:39:02 GMT) Full text and rfc822 format available.

Message #124 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Mon, 31 May 2021 01:11:57 +0300
>> 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.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Mon, 31 May 2021 08:52:02 GMT) Full text and rfc822 format available.

Message #127 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Mon, 31 May 2021 08:50:57 +0000
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> 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.

[0001-Improve-windmove-default-keybindings-fuctions.patch (text/x-diff, inline)]
From 42a66e87af83817b9e989624fdbf9c7ee7c347c7 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
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

[0002-Add-user-options-for-default-windmove-commands.patch (text/x-diff, inline)]
From 21a8a8854249d24d62d4dd8e17c1f1d20de04fd6 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Mon, 31 May 2021 20:32:01 GMT) Full text and rfc822 format available.

Message #130 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Mon, 31 May 2021 23:15:05 +0300
> 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.

Did you intend to send a new patch?  (the patches attached were the same as previous)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Mon, 31 May 2021 21:28:02 GMT) Full text and rfc822 format available.

Message #133 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Philip Kaludercic <philipk <at> posteo.net>
To: Juri Linkov <juri <at> linkov.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Mon, 31 May 2021 21:27:02 +0000
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>> 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.
>
> Did you intend to send a new patch?  (the patches attached were the same as previous)

Oops, I must have forgotten to regenerate patches. The important
difference was

+        (let ((old-fn (lookup-key windmove-mode-map key)))
+          (when (functionp old-fn)
+            (warn "Overriding %S with %S" old-fn (car bind))))


-- 
	Philip K.

[0001-Improve-windmove-default-keybindings-fuctions.patch (text/x-diff, inline)]
From 7e31b789da74655e931adc937b5a22a48d4f676e Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <philipk <at> posteo.net>
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 | 92 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 71 insertions(+), 21 deletions(-)

diff --git a/lisp/windmove.el b/lisp/windmove.el
index e4ea8e0f69..ba59e95624 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 (functionp 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 +581,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 +657,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 +718,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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41438; Package emacs. (Thu, 03 Jun 2021 20:38:01 GMT) Full text and rfc822 format available.

Message #136 received at 41438 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Philip Kaludercic <philipk <at> posteo.net>
Cc: 41438 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: bug#41438: [PATCH] Allow windmove keys to be bound without
 prefix or modifiers
Date: Thu, 03 Jun 2021 23:36:54 +0300
tags 41438 fixed
close 41438 28.0.50
thanks

>> Did you intend to send a new patch?  (the patches attached were the same as previous)
>
> Oops, I must have forgotten to regenerate patches. The important
> difference was
>
> +        (let ((old-fn (lookup-key windmove-mode-map key)))
> +          (when (functionp old-fn)
> +            (warn "Overriding %S with %S" old-fn (car bind))))

Thanks, I've tested your patches, and everything work nicely.
So pushed now.




Added tag(s) fixed. Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Thu, 03 Jun 2021 20:38:02 GMT) Full text and rfc822 format available.

bug marked as fixed in version 28.0.50, send any further explanations to 41438 <at> debbugs.gnu.org and "Philip K." <philip <at> warpmail.net> Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Thu, 03 Jun 2021 20:38:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 02 Jul 2021 11:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 2 years and 297 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.