1

Is there's a way to update READLINE_LINE while running a command, and update it again when the command is complete?

Looking at Bash builtins docs:

-x keyseq:shell-command

Cause shell-command to be executed whenever keyseq is entered. When shell-command is executed, the shell sets the READLINE_LINE variable to the contents of the Readline line buffer and the READLINE_POINT and READLINE_MARK variables to the current location of the insertion point and the saved insertion point (the mark), respectively. If the executed command changes the value of any of READLINE_LINE, READLINE_POINT, or READLINE_MARK, those new values will be reflected in the editing state.

It's not very explicit, perhaps it means that the prompt is updated only once, after the shell-command is complete?

For instance, if I add this to .bashrc

bind -x '"\C-g":foobar'

foobar()
{
    READLINE_LINE="# working on it..."
    sleep 10
    READLINE_LINE="# foo bar done"
}

when I press Ctrl-g, whatever typed disappears, leaving the prompt empty for 10 seconds, until it shows # foo bar done. The terminal never shows # working on it.... (Bash 5.1, tested on ubuntu and macos).

Any suggestion about changing the prompt multiple times, e.g. to show some progress in case the command takes long?

Devis L.
  • 313
  • 2
  • 11
  • Take a look at [this answer](https://stackoverflow.com/questions/25178632/modify-readline-line-and-readline-point-values-inside-bash-script), I think it can help. – bert May 20 '22 at 05:43
  • But I think that the key fact is `... When shell-command is executed, the shell sets the READLINE_LINE variable to the contents of the Readline line buffer ...`. So basically, when you press the CTRL+g, the READLINE_LINE content is set to the Readline line buffer, which in your case might be empty. – bert May 20 '22 at 05:45
  • actually I get the user input fine (e.g `local TEXT="$READLINE_LINE"` works fine), I don't know why it disappears (separate problem, maybe a bug?). My challenge is about showing to the user multiple+temporary text while the function is running to calculate the final value to be displayed. – Devis L. May 21 '22 at 00:02
  • have you considered other options such as https://stackoverflow.com/questions/12498304/using-bash-to-display-a-progress-indicator? – bert May 25 '22 at 07:48
  • 1
    I'll take a look, thank you for digging that up. It might not be what I'm after, but if there's a way to produce a clean experience that would be useful – Devis L. May 31 '22 at 00:22

1 Answers1

0

I left a comment but I guess you were looking for a proper answer. In this case, the reported behaviour is completely normal as of mentioned in here.

Quoting the previous answer: Environment variables are heritable, not shareable.

When you run a command on the command line, it runs in its own process, being those processes children of the shell process in which they run. That means that child processes can read all parent’s variables, but can‘t set new values back.

There are some exceptions to this behaviour, for example: printf, echo, kill, among others, which are built in commands for the given shell.

bert
  • 372
  • 4
  • 13
  • 1
    hi @ixperdomo, the linked post is pointing out how variables are isolated, which I think is a different topic. $READLINE_LINE is an example where one can change a value and Bash will use the updated value. My problem is that Bash ignores intermediate values, showing only the last one to the user. In the example above, if you type "hello" and press Ctrl-g, the value is replaced with "# foo bar done", after 10 seconds. During the 10 seconds, "hello" disappears, leaving the prompt empty. I was looking for a way to show a *temporary value* like "work in progress please wait..." – Devis L. May 20 '22 at 23:57
  • 1
    Alright, I'll take a deeper look later, but yeah looks like a different issue. Hmm I guess I'll leave the "answer" for the sake of it, but if I find an explanation for this behaviour I'll write another answer. – bert May 21 '22 at 05:31
  • I think that in some way, running the sleep process blocks displaying READLINE_LINE. I could only think of echoing the message, but I get that this is not expected behaviour. – bert May 23 '22 at 05:11