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: Chet Ramey
Subject: Re: could there be a bash built-in that allows executing readline functions?
Date: Fri, 27 Oct 2023 15:53:40 -0400
User-agent: Mozilla Thunderbird

On 10/25/23 11:56 AM, Christoph Anton Mitterer wrote:


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.

I'm not enthusiastic about that. It flies in the face of one essential
readline feature: the ability to customize any keybinding.




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?!

Then you understand that bind -e (or  whatever) would not have any effect
on the data held in the READLINE_ variables, and the state of those
variables wouldn't be reflected back into readline's line buffer until
the function bound by bind -x finished executing.

The basic readline execution loop looks like this:

1. read characters from the input until they resolve to a readline
   function;
2. execute that function, expecting it to update any or all of
   rl_line_buffer, rl_point, rl_mark, and rl_end;
3. invoke redisplay to display the new line

So a function invoked by a key sequence bound with bind -x executes
as step 2, just like readline's `forward-char' bindable command.

Bash arranges things so that function sees the READLINE_ variables
that mirror the values that readline maintains (rl_line_buffer and
so forth), and when the function or other script has finished
executing, takes those variables' values and modifies readline's variables
accordingly.

So such a function that used bind -e while executing would not act on
the data in the READLINE_ variables -- it would act on readline's internal
variables like rl_line_buffer *before* bash updated those variables based
on the values of the READLINE_ shell variables. This would mean that those
changes get overwritten at best and cause some weird state problems at
worst.


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.

No, not at least as we're discussing it. Readline's line buffer would be
in the same state it was when it returned the last line to the caller. In
this scenario, readline is not active when bind -e is executed.

It won't be active again until bind finishes executing and bash goes
back to get another line of input, and that's when it will reinitialize
its line state variables.

What you'd probably see is the same `bind -e' command echoed to the
display, but I haven't written any code to test, and it's dependent on
what the redisplay code thinks the current state of the displayed line is.

So it doesn't appear that something like bind -e would be useful, at
least not as useful as something like M-x, for this use case.


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?

Like I said, I haven't written any code, so maybe? It depends on the
behavior of accept-line: that it performs an out-of-sequence redisplay.
But if the code sequence bound to ^F modified the READLINE_ variables
then it's likely that the line readline returns to bash isn't what
accept-line displays on the screen, which is going to surprise some people
and anger others.


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

I do. That's how we figure out whether this is worth the work.


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 :-(

Sure, but those are going to determine whether or not something like this
is usable and worth it. (And accept-line itself won't return the line
to the caller, but it will make readline return the next time it goes
back to read a new character.)

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/




reply via email to

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