help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: how to save/restore (all?) bindings


From: Christoph Anton Mitterer
Subject: Re: how to save/restore (all?) bindings
Date: Fri, 20 Oct 2023 01:29:56 +0200
User-agent: Evolution 3.50.0-1

Hey.

I continued looking in how I can solve the problem.

First I already thought I'd have found a solution in the following:


The user would only set:
  bind -x '"\ec": __fzf_bash_integration_widget_cd -s / -o -f ...'

In this mode, when called with neither `-.` nor `-_`,
__fzf_bash_integration_widget_cd would *not* run find/fzf
but:

1) store the current key bindings in some global variable
2) set up these key bindings:
   bind    '"\e[0n":  "\xC0\a\xC0\r\xC0\n"'
   bind -x '"\xC0\a": __fzf_bash_integration_widget_cd -. <the same
options from above>'
   bind    '"\xC0\r": accept-line'
   bind -x '"\xC0\n": __fzf_bash_integration_widget_cd -_'
3) printf '\e[5n'


So first, there would again be only one key-binding "\ec" (or more like
that, if the user wants to have the widget with different options like
one that starts find at . or /tmp).

Printing the \e[5n causes the \e[0n, which executes the first bind (and
AFAIU, that one is guaranteed to run a row and nothing can come in
between, right?
If so, when called with -. it would have stored the current READLINE_*,
set the new one with the cd, the next macro would have done the accept-
line and the next, when called with -_ would have restored the bindings
and the READLINE_* .


Now I thoroughly tried to betray myself ;-) ... cause even if
everything from the \xC0\a\xC0\r\xC0\n would truly run without anything
being able to come in between, it's still possible in theory, that
after the \e[5n, but before the \e[0n, somehing reset part of my binds.

This however could again break everything. In the worst case, something
like:
"\xC0\a", which should replace READLINE_LINE with my cd command is
replaced by accept-line, and the current READLINE_LINE was rm -rf / 
and is then executed by accident.



So... I continued to think and what if in step (2) I don't just set the
bindings I need, but completely remove any others (before doing the
printf '\e[5n')?

Even if some keyseq is already in the queue, e.g. because the user did
a fast \ecXXXX, XXXX, whatever it is, should(?) have no effect when
it's finally processed after the function returns after the
printf '\e[5n'.


I tried that with some simple examples:
a) bind -x '"\C-f": echo foo; sleep 5'
   bind -x '"\C-a": echo bar'

   If  now do <Ctrl-f><Ctrl-A>, I get:
      foo
   and after 5s:
      bar

but doing:

b) bind -x '"\C-f": bind -r "\C-a"; echo foo; sleep 5'
   bind -x '"\C-a": echo bar'

   and then again <Ctrl-f><Ctrl-A>, I get only:
      foo


=> So seems, that the bind -r has an effect on anything "already
   queued".
   It works also when removing after the sleep:
   bind -x '"\C-f": echo foo; sleep 5; bind -r "\C-a"'


Does that mean, that I can even do my original schema (which is the
code from __fzf_bash_integration_widget_cd() as given here:
https://lists.gnu.org/archive/html/help-bash/2023-10/msg00033.html )
that is:
    bind    '"\C-m":  accept-line'
    bind -x '"\C-j":  __fzf_bash_integration_widget_cd -_'
    bind    '"\e[0n": "\C-m\C-j"'
    <magically remove ALL other bindings>
    printf '\e[5n'

and be save?

Or are there any other subtle cases?


One might be, that probably after the accept-line, e.g. PS1 or
PROMPT_COMMAND is executed and that again could mess up my bindings.

But I would think, that - when I remove all bindings except mine - the
following is guaranteed to run on order, before anything else can
happen:
1. me backing up the old binds, setting the new, backing up the old
   READLINE_* and setting up the new with the cd command
2. printf '\e[5n'
3. receiving the \e[0n
4. because of (3), doing accept-line
<-- here, PS1 and PROMPT_COMMAND could in principle overwrite my \C-j
    if they do not even the following should be guaranteed:
5. because of (3) doing the __fzf_bash_integration_widget_cd -_ which
   restores everything

Even if that happens after (4), I'd hope that it would be still
guaranteed that the accept-line could have only executed my cd command
and nothing else.
So the worst thing that could happen is, that "I" execute now a
dangerous \C-j ... and that my restoration doesn't work.

So if the restoration doesn't work... well... not ideal, but no problem
either. Just start a new shell. Still better than an accidental
rm -rf / .

If I swap \C-j and \C-m above, then it's hopefully even less likely,
that after (4) a problematic \C-m might be used (seriously, who else
overwrites \C-m?).


What about signals?
Once I'd have removed all bindings other than mine, if someone Ctrl-Cs
the __fzf_bash_integration_widget_cd function, the shell might end up
in a state where it's not automatically restored to something usable.
But still, I'd say not that big deal?


Any other issues? 




*If* all the above would work as hoped and *if* what Grisha said in
https://lists.gnu.org/archive/html/help-bash/2023-10/msg00035.html
means that I can indeed (with the next version) bind -ps’s and bind -
X’s output "as is" for restoring (which would be much simpler than
Koichi's complex function - which I rather don't understand ^^)...

... then all I'd be left in need with would be a way to remove all
bindings.
Which seems more difficult than expected:

The first double-quoted field can contain space, : and " it seems.
So I cannot just split the string.

Any ideas how to get just the first field?


Thanks,
Chris.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]