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: Wed, 25 Oct 2023 17:56:48 +0200
User-agent: Evolution 3.50.1-1

On Wed, 2023-10-25 at 10:51 -0400, Chet Ramey wrote:
> I would not say they are internal. Transient, maybe. Temporary,
> maybe.
> But they modify a shared global resource (the current keymap).

Well from a technical PoV, they're not internal, because they (have to)
modify the globally shared keymap.

But conceptually I think they are, as they're only set as a means to
get the actually desired effect and are in principle not intended to be
ever directly used by the user.


> > Sure, we can now simply define the others as being in the user's
> > responsibility, too. But I don't think it's feasible for the user
> > in
> > the real world to check all these things.
> 
> I wonder if this is an opportunity to add an option to bind that
> takes
> a key sequence and displays the name(s) of any function(s) it's bound
> to.
> Then your code could check whether or not a key sequence was bound
> and
> take whatever action you want.

While such functionality would be nice for e.g. storing&restoring the
keybindings, I'm not sure whether it would really fully "fix" the
problem.

I mean even now I grep through the output of bind -psX and see whether
a given keyseq is used.
But I don't see how this prevents the unlikely though possible problems
with either Koichi's approach or the ones when using \e[5n -> \e[0n .

With the former:
   bind '"\ec": "\xC0\a\xC0\r\xC0\n"'
Once the user has pressed \ec, we could still check no earlier than in
\xC0\a whether and how the keybindings are bound, and if that has been
accidentally overwritten, \xC0\r (being the accept-line) could still do
bad things.

And "my" approach, would still suffer from its fragilities and require
quite some hacks to get working.

And both would still suffer from the principle problem that
PS1/PROMPT_COMMAND could come in-between.


Especially because we have that shared resource (the keymap) and
everyone can change it in principle at every point in time, the only
solution is IMO to check every time \ec is done.
This however cannot be done with the '"\ec": "\xC0\a\xC0\r\xC0\n"'
approach, and with "mine" it can only be done partially and that only
with many hacks.


But one thing could indeed work - at least in the sense that it fails
more or less "gracefully":
Allow to make bindings readonly, i.e. once set in that fashion, they
cannot be changed anymore during the lifetime of the shell.

That way, when I set my bindings to some unlikely invalid unicode, I'd
know that they stay that forever, and if setting didn't work (because
already readonly) I could just fail gracefully and give an error
message.
Or even try with another "random" keyseq.

But to me, the idea with a bind -e for executing, would seem more
generally useful than that.

   
> > https://github.com/junegunn/fzf/blob/b1a0ab8086f061640948299b9ed90a6b0c61c143/shell/key-bindings.bash#L131
> 
> So they make assumptions you're not willing to.

Well at least what's done there is IMO quite likely to fail.
I for example have already customised \C-h to something else in my
.inputrc .
So their code doesn't work for me (it's just that the damage isn't big
in that case).



> > 
> > So presumably it would also see the READLINE_* vars, just as the
> > code
> > from -x does? 
> 
> Why would you assume this? This is a general mechanism to call a
> readline
> function, and readline functions operate on an existing readline line
> buffer, just as if it were invoked by a key binding.
> 
> > And if called via -x (as it would be the case in my
> > example) it would of course see the READLINE_* from that (which is
> > anyway the same).
> 
> Yes, those variables would be in the shell environment, but an
> internal
> readline function would never modify them.
> 
> The READLINE_* variables are an application-specific way for an
> application
> using readline (bash) to communicate changes back to readline about
> changes
> to the internal line buffer it uses made by a bindable command. This
> function (the one installed by bind -x) is, from readline's
> perspective,
> just another bindable function that may modify that line buffer. The
> internal readline functions that this new option would execute would
> operate on the internal readline line buffer as they always do.

Well that's what I meant, I guess?!

I.e. if there was a line:
  bind -e accept-line
either on the interactive readline, or - which as you said is the same
- when executing the code of a bind -x, it would operate on that state
of the readline.

Of course, when I'm on the live readline, and do:
  bind -e accept-line
this would get only executed with an accept-line itself.

So my assumption would be, that it looks like the following:
  $ bind -e accept-line<ENTER>
  $ 
  $
i.e. the first <ENTER> causes the readline to make a new empty line,
and *on that* the readline is executed.

While in the case of bind -x, I would assume that this happens:
  $ bind -x '"\C-f": echo foo; bind -e accept-line; echo bar'
  $ echo baz<CTRL-F>
  foo
  baz
  bar
  $ 

Does that make sense?


> > It would also see any other bindings as they are at the point of
> > being
> > executed.
> > So I guess when one would execute:
> >    bind -e "foobar"
> > it would be as if someone just typed foobar (obviously one would
> > need a
> > way to differentiate between macros and functions).
> 
> No. This is a way to execute a named command as if it had been bound
> to
> a key sequence and the key sequence had been read from the input.
> What
> you're asking for here is a way to stuff input so that it will seem
> to
> readline like it had been read from the input. I'm not considering
> that
> at this point.

Fine for me. See below.


> > 
> > Aren't there two things?
> > 1. executing some macro, like the \xC0\a\xC0\r\xC0\n
> 
> We're not talking about this.
> 
> > 2. executing some readline function
> 
> We're talking about this.

Well, (2) would be enough for me, and allowing (1) feels anyway
dangerous to allow.

> 


> > But perhaps there are people with uses cases that want that to
> > be queued up for until the next time readline is back in control?
> 
> I'm not really interested in doing that either. It leads to all sorts
> of
> state management issues.

Well I mostly just wrote it, cause I've assumed you wanted a
description on what should/could happen under all circumstances.

The more I think of it, the more I believe we should not allow the case
(1).
It somehow reminds me, why e.g. Linux disabled TIOCSTI per default.
Don't recall the details now, but I think there were numerous attacks
possible with that.



> > On Tue, 2023-10-24 at 14:32 -0400, Chet Ramey wrote:
> > > Should this mode run multiple readline commands per invocation?
> > 
> > I'm not sure whether I understand this.
> > You mean that I could do in the case (2):
> >     bind -e "accept-line, redraw-current-line"
> 
> Close, but not quite. You would treat each remaining argument to bind
> as
> the name of a readline command to execute.
> 
> It would be interesting to see how executing accept-line, which
> causes
> readline to clean up and return the line to its caller, would
> interact
> with the remaining code in a bindable function. My guess is not well.

Well that are deep internals which I have no real clue about :-(


Cheer,
Chris.



reply via email to

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