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: Thu, 19 Oct 2023 17:11:25 +0200
User-agent: Evolution 3.50.0-1

On Sat, 2023-10-07 at 12:44 +0900, Koichi Murase wrote:
> So, looking at an example in another email, I guess you are trying to
> chain the sequences by sending \e[5n and receiving \e[0n.

Yes that was the idea (not mine ^^).



> Then, what
> happens when a user quickly inputs the sequences \ecxxxx (where xxxx
> might contain conflicting sequences) before the terminal receives
> \e[5n from mycdfunc?

Well, whether something like that can happen was part of my question.

When I do:
$ bind -x '"\ec": sleep 1; echo func; sleep 1'

And press Alt-c twice (fast)... it already runs func twice.
So it seems that while executing bind -x’s shell code, bash doesn't
somehow ignore furter keyseqs, right?

So could be that my function, that is bound to \ec, sets READLINE_LINE
to the new cd command, prints \e[5n, then bash processes another keyseq
the user may have typed (and which e.g. inserts `; rm -rf /`), only
then the  \e[0n arrives and my code executes altogether?

Is that the problem you think about?




Right now my code would look like this (with error messages, handling
of default values and numerous checks removed for simplicity):

__fzf_bash_integration_widget_cd()
{
    local tmp=''
    local starting_points=()
    
    local OPTARG=''
    local OPTIND=1
    while getopts ':_s:' tmp; do
        case "$tmp" in
        (_)
            #restore the readline line buffer
            if [[ -v FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_LINE] ]]  &&  
               [[ -v FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_POINT] ]]  &&  
               [[ -v FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_MARK] ]]; then
                
READLINE_LINE="${FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_LINE]}"
                
READLINE_POINT="${FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_POINT]}"
                
READLINE_MARK="${FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_MARK]}"
                
                unset -v FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_LINE] 
FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_POINT] 
FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_MARK]
            fi
            
            return 0
            ;;
        (s) starting_points+=("$OPTARG") ;;
        (*) return 1
        esac
    done
    shift "$(( ${OPTIND} - 1 ))"
    
    tmp="$( command find "${starting_points[@]}" -mindepth 1 -type d -printf 
'%P\n' 2>/dev/null | fzf )"
    
    FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_LINE]="${READLINE_LINE}"
    FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_POINT]="${READLINE_POINT}"
    FZF_BASH_INTEGRATION[__ORIGINAL_READLINE_MARK]="${READLINE_MARK}"
    
    READLINE_LINE="cd -- $( printf '%q' "${tmp}" )"
    READLINE_POINT=0
    READLINE_MARK=0
    
    bind '"\C-m": accept-line'
    bind -x '"\C-j": __fzf_bash_integration_widget_cd -_'
    bind '"\e[0n": "\C-m\C-j"'
    printf '\e[5n'
}


The idea would be to add much more features than just -s for setting
the starting points of the search (e.g. to . or /), but also for
setting further options to find (or other find command like fd), fzf,
etc. pp.

The user should then be able to not have just one binding but as many
as he likes with different settings, like:

bind -x '"\ec": __fzf_bash_integration_widget_cd -s .'
bind -x '"\ef": __fzf_bash_integration_widget_cd -s /'
...



> If it were me, I'd use a technique similar to the one described in
> [3]

Let me see whether I understand hat:
> bind -x '"\xC0\a":printf "%(%T)T "'
> bind '"\xC0\r":accept-line'
> bind '"\r":"\xC0\a\xC0\r"'

Translated to my use case you'd do:

bind '"\ec":"\xC0\a\xC0\r\xC0\n"' <= \ec starts the whole thing off
bind -x '"\xC0\a": store_and_set' <= store_and_set would run fzf, store
                                     the old READLINE_* run fzf and set
                                     the new (to cd something)
bind '"\xC0\r":accept-line'       <= would execute the current
                                     READLINE_* and thus the cd
bind -x '"\xC0\n": store_and_set' <= would restore the old READLINE_*

Is that about the idea?

1) I assume that this would also prevent the problem that some other
   keyseq could break the whole thing like above?
   I.e. once \ec is recognised, it first runs \xC0\a then \xC0\r and
   then \xC0\n and nothing can come in between?

2) But the downside is, I couldn't set/restore the keybindings other
   than the "main" one, right?!
   So as soon as the user would use any of these keyseqs for anything
   else, either that would break, or mine.
   As above, a user could have bound any of the helper keyseqs e.g.
   \xC0\n to do something really bad, any my "main" keyseq might run
   that.

3) The whole idea of allowing a user to easily set up many such
   bindings with different parameters would be more difficult, and each
   would need further keybindings that replace "\xC0\a" with different
   parameters?


So whatever I do it seems I have to live with possible breakage because
of keyseqs:
- either (when using "my" approach) because there are other keyseqs
  in-between, that break my own
- or (when using your approach) because I may break other keybindings
  or others may break mine
?
Sounds like bad vs. terrible.


Can't there be just a simple way to have PS1 re-evaluated?! 


Thanks,
Chris.



reply via email to

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