2

First you may refer to this great post here: Bash bind for better understanding what I am trying to achieve.

I want to achieve that when I hit the enter then update the shell prompt dynamically, now I already had is:

__update_shell_prompt () {
  # according what I had done in the terminal regenerate the new shell prompt
  # new_shell_prompt
  export PS1=$new_shell_prompt
}

bind '"\C-M":"\n__update_shell_prompt\n"'

It works as expected, just after each command I executed it would echo the text __update_shell_prompt also, like:

enter image description here

I also tried to use the bind with the -x option like this:

bind -x '"\C-M":"\n__update_shell_prompt\n"''

Then it doesn't respect the \n, so it totally doesn't work, if I remove the \n, it still doesn't work, and bring another serious problem in, the command I tried to execute just remain in the screen and never would get executed, like so: all commands just get stuck there...

enter image description here

So:

  1. How can I make that don't echo the command text...
  2. If this is not the right way to achieve this(dynamically update shell prompt upon enter hitting), then how should I do this?
Braiam
  • 1
  • 11
  • 47
  • 78
lnshi
  • 2,310
  • 3
  • 19
  • 42
  • @Dennis Williamson If you are still there, that would be help a lot. – lnshi Jun 06 '17 at 05:53
  • Questions about interactive use (as opposed to scripting) are typically a better fit for [Unix SE](https://unix.stackexchange.com/) or [SuperUser](https://superuser.com/). – Charles Duffy Jun 07 '17 at 01:41
  • @CharlesDuffy oh, thank u, do u have solution for this? – lnshi Jun 07 '17 at 01:44
  • Doesn't `PROMPT_COMMAND=__update_shell_prompt` suffice for your use case, without `bind` being involved anywhere? So while my primary issue with this question surrounds a lack of topicality, the secondary one is that it presumes a specific approach to resolving your underlying problem, as opposed to letting someone writing an answer suggest the approach that makes the most sense. (Related: [What is the XY Problem?](https://meta.stackexchange.com/a/66378/144918)) – Charles Duffy Jun 07 '17 at 01:48
  • i tried to use `PROMPT_COMMAND ` both in the `~/.bash_profile` and in this bash `completion` script, the problem here is there is no way to trigger this `__update_shell_prompt ` function to be invoked, so I am trying to find a way to invoke this function after the user executing some command – lnshi Jun 07 '17 at 01:52
  • I'm not sure I follow -- triggering the function before rendering the prompt is *exactly* what `PROMPT_COMMAND` is supposed to do. Do you mean you want to rerender the prompt in place on a prior terminal line? – Charles Duffy Jun 07 '17 at 01:53
  • @charlesduffy, for giving you more information, pls refer to this gist: https://gist.github.com/lnshi/c27b79bd565ec4ce5b96d55eb1435a4a – lnshi Jun 07 '17 at 01:53
  • I find the gist unenlightening -- that you wanted to run a function to update the value of PS1 was already well-established. This is, again, exactly what `PROMPT_COMMAND` does. – Charles Duffy Jun 07 '17 at 01:54
  • Yes, i want to re-render the value of the PS1 in place based on one command the user try to execute. – lnshi Jun 07 '17 at 01:56
  • Ahh. Potentially feasible -- if you use `tput` to look up the terminal sequences to move the cursor up a line and clear that line, that would put you in a good place for re-rendering. That said, this is going to be fragile -- it'll need to know how many lines of text a given prompt renders to, for example, and I'd expect the corner cases to deal with around line wrap to be fairly nasty. – Charles Duffy Jun 07 '17 at 01:57
  • See https://www.gnu.org/software/termutils/manual/termutils-2.0/html_chapter/tput_1.html, particularly `cup` (moving the cursor up) and `el` (clearing the current line). – Charles Duffy Jun 07 '17 at 02:00
  • So u mean after I invoke the `__update_shell_prompt `, i just do more things: clean the echoed text? seems a practicable solution, I am very unfamiliar with the `tput`, can you generally post your solutions as an answer, I find there is quite few questions about the `bind` function. Thank you very much. – lnshi Jun 07 '17 at 02:02

1 Answers1

0

First thanks @Charles Duffy, I followed his suggestion and used the tput.

The solution is simple, use tput cup to move the cursor up, then use tput el to delete that line, as below:

# Get the current cursor coordinate.
IFS=';' read -sdR -p $'\E[6n' ROW COL; local current_row=`echo "${ROW#*[}"`

# Move the cursor up then delete that line
tput cup $((current_row-2)) 0 && tput el

Tips:

  1. To prevent the potential commands history pollution, you can put export HISTCONTROL=ignorespace into your ~/.bash_profile or ~/.bashrc;

  2. Then invoke the command with prefixed space.

The problem I used this scenario to solve can be referred here: docker-machine PR #4127.

lnshi
  • 2,310
  • 3
  • 19
  • 42