Is there a command to get bash to print a new prompt string and redraw the current line

bashcmd.execommand lineps1

Instead of waiting for slow commands to finish, I'd like to run them in the background. However, when they finish running and print to stdout, I get (where represents my cursor) this:

$ slowcmd &
$ cmd_output
█
  • There is no prompt string before my cursor.
  • and slowcmd can be any slow command (For the stuff I've tried, I just said alias slowcmd='sleep 1 && echo cmd_output')

Whereas I'd like something like this:

$ slowcmd && redrawPromptString &
$ cmd_output
$ █

Where after the command's output, a new Prompt String is printed out for me.

What I can do to make redrawPromptString do what I want? I've tried clear, kill $$ to send a ^C to the terminal, and finally printf "^C" (of course that didn't work). I'm running bash. (GNU bash, version 3.2.57).

Best Answer

Use redraw-current-line function of bind builtin. First check if it's already bound maybe:

bind -q redraw-current-line

I've never seen it bound by default, so you will probably need to bind it. Pick a key combination, let's say Ctrl+Y. Check if it's already taken:

bind -p | grep -F '"\C-y'

Empty output means the combination is unused. If so, let's bind redraw-current-line to it:

bind "\C-y":redraw-current-line

Now, whenever a background process messes with your command line, hit Ctrl+Y. Then your prompt will be redrawn along with whatever command you have just partially typed (if any), so you can continue as if nothing happened.

To make the binding permanent you could add the above command to your ~/.bashrc, but don't. The right approach is to modify ~/.inputrc (for user) or /etc/inputrc (system-wide). This way any program that uses readline(3) library will obey. The line to add to either file looks like this:

"\C-y":redraw-current-line

But if you create ~/.inputrc anew, make sure its first line says $include /etc/inputrc. This is because up to this point readline has used /etc/inputrc and maybe your workflow relies on what's in this file. From now on, the library will use your ~/.inputrc instead; the line $include /etc/inputrc makes it parse the system-wide file as well.

For more info see help bind and man 3 readline.

Related Question