help-bash
[Top][All Lists]
Advanced

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

how to save/restore (all?) bindings


From: Christoph Anton Mitterer
Subject: how to save/restore (all?) bindings
Date: Mon, 02 Oct 2023 02:38:48 +0200
User-agent: Evolution 3.50.0-1

Hey.


Recently (well, better late than never), I've stumbled over the
wonderful fzf[0].


Another problem there, about which I'll post a separate mail (titled
"re-evaluating prompt strings from a bind -x function") shortly,
brought me to the question on how one can save&restore the state of
(all?) bindings of a bash instance.



In fzf's
https://github.com/junegunn/fzf/blob/master/shell/key-bindings.bash
some of the bindings that are set up, like:
  bind -m emacs-standard '"\ec": " \C-b\C-k 
\C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d"'

assume various key-combos to have their default meaning, in order to
work.

Even if the particular problem why those are used with __fzf_cd__ and
for \ec (rather than bind -x) could be solved (the other mail will be
about this particular problem), the use of such sequences without -x
would still remain:
https://github.com/junegunn/fzf/blob/4fdc08295b90485b7ee30a35d77177699c070113/shell/key-bindings.bash#L109-L119
which is apparently necessary for old shells.

Apparently MacOSX still uses ancient bash versions and fzf upstream
doesn't want to drop support for that.


The problem is obviously:
If any of the key-combos is set to something non-default, they'll fail.
And if one blindly overwrites or removes (bind -r) them, the user may
loose his own bindings.


My idea, which may however not work for the bash versions without -x,
but should at least for a __fzf_cd__ with bind -x was to do something
like this:
1) bind -m emacs-standard -x '"\ec": mycdfunc'
   Well, "\ec" needs of course be overwritten... but ultimately this
   should become user-configurable, so it should be clear to the user,
   which particular keyseq he "looses" on this functionality.
2) mycdfunc would then cause:
   - save the current bindings
   - set the key bindings as needed (e.g. either manually to something,
     or back to their default with bind -r)
   - do the __fzf_cd__ magic
   - restore the previous bindings, in order to get any user
     customisations back


So a function is needed, that saves the current bindings so that they
can be brought back with eval, and that's what this mail is about.

My own "solution" would be this:
save_binds()
{
        local keymap="$1"
        local line=''
        
        
        bind ${keymap:+-m} ${keymap:+"${keymap}"} -p -s  |  
        while IFS='' read -r line; do
                [ -n "${line###*}" ]  &&
                { [ -n "${keymap}" ]  &&  printf 'bind -m %q %q\n' "${keymap}" 
"${line}"  ||  
                                          printf 'bind %q\n' "${line}"
                }
        done
        
        bind ${keymap:+-m} ${keymap:+"${keymap}"} -X  |  
        while IFS='' read -r line; do
                [ -n "${line###*}" ]  &&
                { [ -n "${keymap}" ]  &&  printf 'bind -m %q -x %q\n' 
"${keymap}" "${line}"  ||  
                                          printf 'bind -x %q\n' "${line}"
                }
        done
}

which, as far as my limited understanding of bash goes, works.

It's idea is to print a number of bind commands, one per line, so that
any changes of the bindings made via either of:
       bind [-m keymap] -x keyseq:shell-command
       bind [-m keymap] keyseq:function-name
       bind [-m keymap] keyseq:readline-command
       bind [-m keymap] [-q function] [-u function] [-r keyseq]
would be restored when `eval`ed.

It tries to not call non-built-in utilities for performance reasons
(though I haven't really tested, whether it would be actually even
faster to e.g. remove the comment lines from bind -p via grep, rather
than [ -n "${line###*}" ] .
I'm open for suggestions in terms of performance.

Similarly, the function tries to simply save the whole state, whereas
for my purpose it might be enough to just save&restore the state for
certain keyseqs.
Not really sure what would be better. At least it would make the
function more complex, if one could select certain keyseqs via
parameters.


It takes 0-1 arguments, if $1 is given it's the value to `bind`’s -m
option, if not, no -m option is used.
Quite some code above went into just differentiating between with -m
and no -m option.

I couldn't find what it means if no -m is given?

Also, some code went into allowing keymap's value to contain spaces...
yeah, it most likely never will, so that's probably stupid. ^^


I'd be happy to get any feedback on my function:
- improvements (performance, functionality)
- whether it's all wrong or I miss saving some statuses or could be
  done simpler
- or whether I've overseen any pitfalls in quoting, using %q, IFS and
  so on
- etc.



Thanks,
Chris.


[0] https://github.com/junegunn/fzf/



reply via email to

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