help-bash
[Top][All Lists]
Advanced

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

Re: could there be a bash built-in that allows executing readline functi


From: Christoph Anton Mitterer
Subject: Re: could there be a bash built-in that allows executing readline functions?
Date: Mon, 23 Oct 2023 23:53:00 +0200
User-agent: Evolution 3.50.0-1

On Mon, 2023-10-23 at 15:15 -0400, Chet Ramey wrote:
> What makes that superior to something like a readline function to
> execute
> a named readline command, like M-x does in emacs?

AFAIU, the following applies:

- users may use multiple programs, that may change keybindings

at least with respect to the use case that I was talking about in this
thread:

- the approach suggested by Koichi:
    bind    '"\ec":    "\xC0\a\xC0\r\xC0\n"'
    bind -x '"\xC0\a": store_and_set'
    bind    '"\xC0\r": accept-line'
    bind -x '"\xC0\n": restore_and_set'
  which uses the first in that list to guarantee that the following are
  executed in that order and with nothing in between, set up these
  bindings once statically.

  That it works itself (and doesn't break anything else) depends fully
  on the likeliness that one uses keyseqs that no-one else use.

  While one could add some checks (when the bindings are set) whether
  the bindings are already in use (presumably by someone else) and
  thereby prevent breaking something else, there is no way to make sure
  that nothing else breaks the own functionality.
  Cause even if one would re-set the bindings in store_and_set(),
  it could be just that which has been accidentally overwritten.

  In my example, one bad thing that may happen is that a user had a
  readline of "rm -rf *", realised he's in the wrong directory, wants
  to use my widget to change that, \xC0\a is however accidentally
  overwritten and does nothing, so the readline stays "rm -rf *" and
  \xC0\r causes it to be executed.

  Chances may be small, yes, but still seems a risk I wouldn't want to
  be responsible for.

- "my" approach:
     bind -x '"\ec":    store_and_set'
     bind    '"\e[0n":  "\xC0\r\xC0\a"'
     bind    '"\xC0\r": accept-line'
     bind -x '"\xC0\a": restore_and_set'
   with store_and_set and set eventually printing \e[5n ...
   has the advantage that it can set all binds other than the main one
   (\ec) in store_and_set, where it also removes all other bindings to
   make sure that nothing is in the queue right after \ec and with
   someĀ tricks one can IMO even prevent any bigger damage in case any
   of the 3 other bindings were in the queue.
   By restoring the original bindings, the shell should never see
   any other binding than the one for \ec, so one can avoid to
   accidentally break other stuff.

   But, that requires numerous hacks (fragile stuff like
   storing/restoring/removing all bindings, which may fail with any
   bash version).
   It may no work as expected when the function is interrupted by some
   signal (e.g. leave back the shell with no bindings at all).
   And, as Koichi pointed out, requires a round-trip with the terminal
   (which I guess in may in principle not even support the
   \e[5n -> \e[0n).

Both suffer from the problem, that PROMPT_COMMAND or PS1 (and perhaps
even by other means I'm not aware of) the bindings may be broken again,
after the accept-line.


So both feel fragile to me and depend on some luck.
Which would be fine if this was just about printing some time before
the prompt and the worst thing that may happen is that the prompt is
messed up - but seems not fine to me, if some arbitrary command gets
accidentally executed.


My hope was - and of course I may be totally wrong - that a built-in
that allows me to execute the accept-line from the function would make
all the voodoo unnecessary and be safe in all cases, like that:
  bind -x '"\ec": dir="$(find) | fzf)"; store_current_readline; 
READLINE_LINE="$dir";   magic_built_in accept-line;   restore_old_readline'

No multiple bindings needed, no fragile functions, no awk, sed, whatsoever.

Here, even if some weird PS1 or PROMPT_COMMAND would break any
bindings... doesn't matter: since I only need \ec the worst thing that
could happen is that the next \ec doesn't work (which would then
however clearly in someone else's responsibility).

Since all happens from one function, one could even make the originals
of READLINE_* a local var and thereby rule out that anyone messes with
those.



Before I've ended up asking on help-bash for help, I did of course
search for solutions on stackoverflow and the likes.
Seems, that there were quite some questions like "how can one execute
two readline functions in a row".

I haven't really checked whether their uses cases are valid, but could
at least mean that such built in would help more people, and not just
me.


Cheers,
Chris.



reply via email to

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