unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Single-use keybindings?
@ 2017-07-23  0:52 Eric Abrahamsen
  2017-07-23  1:00 ` Drew Adams
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23  0:52 UTC (permalink / raw)
  To: help-gnu-emacs

A few times I've found myself wanting the ability to set a single-use
keybinding: the next time the user hits "q" (or what have you), run this
command, then reset "q" to whatever it was before.

This feels hacky, obviously, but more importantly it feels like I'm
not using the right tools, or misusing what I've got. Has anyone else
wanted to do this? Any better solutions? Maybe I should be using a minor
mode that turns itself off after use, or...

Anyway, any thoughts would be much appreciation. Here's the function I
just wrote -- it pops to a certain buffer from wherever you are, and
when it gets there it rebinds "q" to pop back where you came from,
resetting "q" to it's original binding as it goes. It works, but I still
feel bad about it.

Eric

(defun ebdb-mua-in-ebdb-buffer ()
  "From an MUA, temporarily move point to the corresponding EBDB buffer.

All further operations will take place within the EBDB buffer as
per normal, with the exception that \"q\" will return point to
where it was in the MUA, rather than quitting the EBDB buffer."
  (interactive)
  (let* ((buf (get-buffer (ebdb-make-buffer-name)))
	 (w-conf (current-window-configuration))
	 (w-win (selected-window))
	 (w-point (window-point))
	 (e-win (or (get-buffer-window buf)
		    (ebdb-pop-up-window buf t (ebdb-make-buffer-name))))
	 q-bind)
    (select-window e-win t)
    (setq q-bind (key-binding "q"))
    (local-set-key
     "q"
     (lambda ()
       (interactive)
       (local-set-key (kbd "q") q-bind)
       (when (window-live-p w-win)
	 (set-window-configuration w-conf)
	 (goto-char w-point))))))




^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Single-use keybindings?
  2017-07-23  0:52 Single-use keybindings? Eric Abrahamsen
@ 2017-07-23  1:00 ` Drew Adams
  2017-07-23  1:04   ` Eric Abrahamsen
  2017-07-23  1:22   ` Eric Abrahamsen
  2017-07-23  5:51 ` Emanuel Berg
  2017-07-23 22:04 ` Michael Heerdegen
  2 siblings, 2 replies; 12+ messages in thread
From: Drew Adams @ 2017-07-23  1:00 UTC (permalink / raw)
  To: Eric Abrahamsen, help-gnu-emacs

> A few times I've found myself wanting the ability to set a single-use
> keybinding: the next time the user hits "q" (or what have you), run this
> command, then reset "q" to whatever it was before.
> 
> This feels hacky, obviously, but more importantly it feels like I'm
> not using the right tools, or misusing what I've got. Has anyone else
> wanted to do this? Any better solutions? Maybe I should be using a minor
> mode that turns itself off after use, or...

See `set-transient-map'.  From (elisp) `Controlling Active Maps':

  This function adds KEYMAP as a “transient” keymap, which takes
  precedence over other keymaps for one (or more) subsequent keys.

  Normally, KEYMAP is used just once, to look up the very next key.
  If the optional argument KEEP-PRED is ‘t’, the map stays active as
  long as the user types keys defined in KEYMAP; when the user types
  a key that is not in KEYMAP, the transient keymap is deactivated
  and normal key lookup continues for that key.

  The KEEP-PRED argument can also be a function.  In that case, the
  function is called with no arguments, prior to running each
  command, while KEYMAP is active; it should return non-‘nil’ if
  KEYMAP should stay active.

  The optional argument ON-EXIT, if non-nil, specifies a function
  that is called, with no arguments, after KEYMAP is deactivated.

  This function works by adding and removing KEYMAP from the variable
  ‘overriding-terminal-local-map’, which takes precedence over all
  other active keymaps (see Searching Keymaps).



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23  1:00 ` Drew Adams
@ 2017-07-23  1:04   ` Eric Abrahamsen
  2017-07-23  1:22   ` Eric Abrahamsen
  1 sibling, 0 replies; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23  1:04 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> A few times I've found myself wanting the ability to set a single-use
>> keybinding: the next time the user hits "q" (or what have you), run this
>> command, then reset "q" to whatever it was before.
>> 
>> This feels hacky, obviously, but more importantly it feels like I'm
>> not using the right tools, or misusing what I've got. Has anyone else
>> wanted to do this? Any better solutions? Maybe I should be using a minor
>> mode that turns itself off after use, or...
>
> See `set-transient-map'.  From (elisp) `Controlling Active Maps':

I suspected someone else would have wanted to do this, but I had no idea
it was that built-in! Thank you very much for the pointer.

E




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23  1:00 ` Drew Adams
  2017-07-23  1:04   ` Eric Abrahamsen
@ 2017-07-23  1:22   ` Eric Abrahamsen
  1 sibling, 0 replies; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23  1:22 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> A few times I've found myself wanting the ability to set a single-use
>> keybinding: the next time the user hits "q" (or what have you), run this
>> command, then reset "q" to whatever it was before.
>> 
>> This feels hacky, obviously, but more importantly it feels like I'm
>> not using the right tools, or misusing what I've got. Has anyone else
>> wanted to do this? Any better solutions? Maybe I should be using a minor
>> mode that turns itself off after use, or...
>
> See `set-transient-map'.  From (elisp) `Controlling Active Maps':

There's the new version, which I'm feeling much better about. Thanks
again.

(defun ebdb-mua-in-ebdb-buffer ()
  "From an MUA, temporarily move point to the corresponding EBDB buffer.

All further operations will take place within the EBDB buffer as
per normal, with the exception that \"q\" will return point to
where it was in the MUA, rather than quitting the EBDB buffer."
  (interactive)
  (let* ((buf (get-buffer (ebdb-make-buffer-name)))
	 (w-conf (current-window-configuration))
	 (w-win (selected-window))
	 (w-point (window-point))
	 (e-win (or (window-live-p (get-buffer-window buf))
		    (ebdb-pop-up-window buf t (ebdb-popup-window))))
	 (key-m (make-sparse-keymap)))
    (define-key key-m (kbd "q")
      (lambda ()
	(interactive)
	(when (window-live-p w-win)
	  (set-window-configuration w-conf)
	  (goto-char w-point))))
    (select-window e-win t)
    (set-transient-map key-m)))




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23  0:52 Single-use keybindings? Eric Abrahamsen
  2017-07-23  1:00 ` Drew Adams
@ 2017-07-23  5:51 ` Emanuel Berg
  2017-07-23 18:04   ` Eric Abrahamsen
  2017-07-23 22:04 ` Michael Heerdegen
  2 siblings, 1 reply; 12+ messages in thread
From: Emanuel Berg @ 2017-07-23  5:51 UTC (permalink / raw)
  To: help-gnu-emacs

Eric Abrahamsen wrote:

> Maybe I should be using a minor mode that
> turns itself off after use

You can, I've done exactly that! Create a copy
of the global-map and then
`substitute-key-definition' for a function
that, as you say, turns itself off after doing
its special thing.

But when I did that, I didn't know of that
other thing mentioned already, which is
probably the right way to do it - only it seems
a bit complicated...

If you succeed with a small snippet, feel free
to post it here!

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23  5:51 ` Emanuel Berg
@ 2017-07-23 18:04   ` Eric Abrahamsen
  2017-07-23 21:28     ` Eric Abrahamsen
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23 18:04 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <moasen@zoho.com> writes:

> Eric Abrahamsen wrote:
>
>> Maybe I should be using a minor mode that
>> turns itself off after use
>
> You can, I've done exactly that! Create a copy
> of the global-map and then
> `substitute-key-definition' for a function
> that, as you say, turns itself off after doing
> its special thing.
>
> But when I did that, I didn't know of that
> other thing mentioned already, which is
> probably the right way to do it - only it seems
> a bit complicated...

If I was trying to do something more complicated, it might be worth
looking into a minor mode. As it is, the transient key map is exactly
what I was wanting.

> If you succeed with a small snippet, feel free
> to post it here!

My previous message had it -- in fact, the revised version of the
function didn't look a whole lot different from my original version! But
it feels less fragile, and I'm more confident I'm DTRT.

Eric




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23 18:04   ` Eric Abrahamsen
@ 2017-07-23 21:28     ` Eric Abrahamsen
  2017-07-23 21:45       ` Emanuel Berg
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23 21:28 UTC (permalink / raw)
  To: help-gnu-emacs

Eric Abrahamsen <eric@ericabrahamsen.net> writes:

> Emanuel Berg <moasen@zoho.com> writes:
>
>> Eric Abrahamsen wrote:
>>
>>> Maybe I should be using a minor mode that
>>> turns itself off after use
>>
>> You can, I've done exactly that! Create a copy
>> of the global-map and then
>> `substitute-key-definition' for a function
>> that, as you say, turns itself off after doing
>> its special thing.
>>
>> But when I did that, I didn't know of that
>> other thing mentioned already, which is
>> probably the right way to do it - only it seems
>> a bit complicated...
>
> If I was trying to do something more complicated, it might be worth
> looking into a minor mode. As it is, the transient key map is exactly
> what I was wanting.

Actually, it wasn't! The transient map disappears the first time any key
is hit that isn't in the map itself. What I wanted was to rewire "q",
and nothing but "q", until the first time that "q" is hit. I can
probably still get what I want by fooling with the KEEP-PRED argument to
`set-transient-map', but it's not the no-brainer I thought it was.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23 21:28     ` Eric Abrahamsen
@ 2017-07-23 21:45       ` Emanuel Berg
  2017-07-23 22:09         ` Eric Abrahamsen
  0 siblings, 1 reply; 12+ messages in thread
From: Emanuel Berg @ 2017-07-23 21:45 UTC (permalink / raw)
  To: help-gnu-emacs

Eric Abrahamsen wrote:

> Actually, it wasn't! The transient map
> disappears the first time any key is hit that
> isn't in the map itself. What I wanted was to
> rewire "q", and nothing but "q", until the
> first time that "q" is hit. I can probably
> still get what I want by fooling with the
> KEEP-PRED argument to `set-transient-map',
> but it's not the no-brainer I thought it was.

Here is the minor-mode-that-shuts-off-itself
idea. It has served me well. I wrote it in 2014
but it feels like 10 years ago. Man...

    http://user.it.uu.se/~embe8573/emacs-init/caps-back.el

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23  0:52 Single-use keybindings? Eric Abrahamsen
  2017-07-23  1:00 ` Drew Adams
  2017-07-23  5:51 ` Emanuel Berg
@ 2017-07-23 22:04 ` Michael Heerdegen
  2017-07-23 22:11   ` Emanuel Berg
  2017-07-23 22:18   ` Eric Abrahamsen
  2 siblings, 2 replies; 12+ messages in thread
From: Michael Heerdegen @ 2017-07-23 22:04 UTC (permalink / raw)
  To: Eric Abrahamsen; +Cc: help-gnu-emacs

Eric Abrahamsen <eric@ericabrahamsen.net> writes:

> A few times I've found myself wanting the ability to set a single-use
> keybinding: the next time the user hits "q" (or what have you), run this
> command, then reset "q" to whatever it was before.
>
> This feels hacky, obviously, but more importantly it feels like I'm
> not using the right tools, or misusing what I've got. Has anyone else
> wanted to do this? Any better solutions? Maybe I should be using a minor
> mode that turns itself off after use, or...

After thinking about it: I implemented something like this myself.
Because resetting is tricky - and sometimes even something that you
don't want! - I just use a key binding that was unbound before.  So I
simply don't use any kind of resetting.  Hitting the key (again) when it
makes no sense may result in an error.  That's the case for other keys,
too, so...


Michael.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23 21:45       ` Emanuel Berg
@ 2017-07-23 22:09         ` Eric Abrahamsen
  0 siblings, 0 replies; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23 22:09 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <moasen@zoho.com> writes:

> Eric Abrahamsen wrote:
>
>> Actually, it wasn't! The transient map
>> disappears the first time any key is hit that
>> isn't in the map itself. What I wanted was to
>> rewire "q", and nothing but "q", until the
>> first time that "q" is hit. I can probably
>> still get what I want by fooling with the
>> KEEP-PRED argument to `set-transient-map',
>> but it's not the no-brainer I thought it was.
>
> Here is the minor-mode-that-shuts-off-itself
> idea. It has served me well. I wrote it in 2014
> but it feels like 10 years ago. Man...
>
>     http://user.it.uu.se/~embe8573/emacs-init/caps-back.el

I got this working, and it seems to do the right thing. It did end up
being a lot of code, though. Note the second argument to
`set-transient-map', that's pretty much what makes it all work.

I'm kind of ambivalent about this now, but I guess it's still the best
solution.

  (let* ((buf (get-buffer (ebdb-make-buffer-name)))
	 (w-conf (current-window-configuration))
	 (w-win (selected-window))
	 (w-point (window-point))
	 (e-win (if (window-live-p (get-buffer-window buf))
		    (get-buffer-window buf)
		  (ebdb-pop-up-window buf t (ebdb-popup-window))))
	 (key-m (make-sparse-keymap)))
    (define-key key-m (kbd "q")
      (lambda ()
	(interactive)
	(when (window-live-p w-win)
	  (set-window-configuration w-conf)
	  (goto-char w-point))))
    (select-window e-win t)
    (set-transient-map
     key-m
     (lambda ()
       ;; Keep the transient map active until the user hits "q".
       (null
	(equal (this-command-keys-vector)
	       [?q])))))




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23 22:04 ` Michael Heerdegen
@ 2017-07-23 22:11   ` Emanuel Berg
  2017-07-23 22:18   ` Eric Abrahamsen
  1 sibling, 0 replies; 12+ messages in thread
From: Emanuel Berg @ 2017-07-23 22:11 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen wrote:

> After thinking about it: I implemented
> something like this myself. Because resetting
> is tricky - and sometimes even something that
> you don't want! - I just use a key binding
> that was unbound before. So I simply don't
> use any kind of resetting. Hitting the key
> (again) when it makes no sense may result in
> an error. That's the case for other keys,
> too, so...

For sure, should be used only for the really
odd case. Nothing for the entire keyboard.
Acid programming that would be...

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Single-use keybindings?
  2017-07-23 22:04 ` Michael Heerdegen
  2017-07-23 22:11   ` Emanuel Berg
@ 2017-07-23 22:18   ` Eric Abrahamsen
  1 sibling, 0 replies; 12+ messages in thread
From: Eric Abrahamsen @ 2017-07-23 22:18 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Eric Abrahamsen <eric@ericabrahamsen.net> writes:
>
>> A few times I've found myself wanting the ability to set a single-use
>> keybinding: the next time the user hits "q" (or what have you), run this
>> command, then reset "q" to whatever it was before.
>>
>> This feels hacky, obviously, but more importantly it feels like I'm
>> not using the right tools, or misusing what I've got. Has anyone else
>> wanted to do this? Any better solutions? Maybe I should be using a minor
>> mode that turns itself off after use, or...
>
> After thinking about it: I implemented something like this myself.
> Because resetting is tricky - and sometimes even something that you
> don't want! - I just use a key binding that was unbound before.  So I
> simply don't use any kind of resetting.  Hitting the key (again) when it
> makes no sense may result in an error.  That's the case for other keys,
> too, so...
>
>
> Michael.

This would have the added bonus that you have more freedom to make that
new keybinding do "more stuff". The only downside is that the user has
to learn and remember a new key. My use-case is still bare-bones enough
that I'll stick with the transient key map, but your approach makes
plenty of sense.




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-07-23 22:18 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-23  0:52 Single-use keybindings? Eric Abrahamsen
2017-07-23  1:00 ` Drew Adams
2017-07-23  1:04   ` Eric Abrahamsen
2017-07-23  1:22   ` Eric Abrahamsen
2017-07-23  5:51 ` Emanuel Berg
2017-07-23 18:04   ` Eric Abrahamsen
2017-07-23 21:28     ` Eric Abrahamsen
2017-07-23 21:45       ` Emanuel Berg
2017-07-23 22:09         ` Eric Abrahamsen
2017-07-23 22:04 ` Michael Heerdegen
2017-07-23 22:11   ` Emanuel Berg
2017-07-23 22:18   ` Eric Abrahamsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).