My bash prompt, which I'll admit to have stolen from a few places and cobbled together, will sometimes add part of previous commands to its length when scrolling the bash history with up/down arrows.
For example, if my previous commands were:
ls
cd /home/caleb
vim .bashrc
When I was at my prompt and scrolled up twice it might look like:
$ vim .bcd /home/caleb
Where the first five characters are left over from last command.
Does anyone have any idea why this is happening, and how it can be stopped?
My prompt is set with this code (way to long to include here): https://gist.github.com/1679352
-
1Set PS1 to a value without the whole vcs crap and see what happens. That's my guess.Daniel Beck– Daniel Beck ♦2012年01月26日 00:44:19 +00:00Commented Jan 26, 2012 at 0:44
-
Have you already found the culprit in your prompt? I'm having the same issue.acme– acme2014年07月10日 08:58:28 +00:00Commented Jul 10, 2014 at 8:58
-
Yeah bash loses it on colors, and is unable to separate the length of strings with color escapes from the length of the visible string. This is what SiegeX was getting at. I ended up switching to ZSH and using a different prompt. ZSH doesn't have the same issue.Caleb Hearth– Caleb Hearth2014年07月11日 13:45:19 +00:00Commented Jul 11, 2014 at 13:45
-
2Both previous answer didn't get my problem solved, and did not give any explaination why this happened. Please check Custom Bash prompt is overwriting itself, if anyone have search to this point.D3Hunter– D3Hunter2014年12月22日 03:05:54 +00:00Commented Dec 22, 2014 at 3:05
-
Related issue unix.stackexchange.com/questions/105958/…Matthias Beaupère– Matthias Beaupère2019年06月27日 14:21:27 +00:00Commented Jun 27, 2019 at 14:21
7 Answers 7
Somewhere your prompt is fubar. What usually happens is that your shell thinks its outputting non-printable term codes and expecting it to take up space. The best advice I can give you is to systematically add to (or take away from) your prompt until this behavior stops to isolate the code that is causing this issue.
The color codes need to be wrapped in square brackets. The brackets inform bash that the enclosed text should not be printed
building on @Phreditor's example, this shows that any formatting done after the newline will result in the original issue:
export PS1="\n\n\[033円[01;33m[\w]033円[00m\n033円[0;90m\$ "
wrapping the format code in [] ensures that annoying behavior never happens:
export PS1="\n\[\[033円[01;33m\][\w]\[033円[00m\]\n\[033円[0;90m\]\$ "
The documentation: http://tldp.org/HOWTO/Bash-Prompt-HOWTO/nonprintingchars.html
Since PS1 formatting causes the value to be so long and hard to read I put the format codes in variables:
BYELLOW='\[033円[01;33m\]'
IBLACK='\[033円[0;90m\]'
PS_CLEAR='\[033円[0m\]'
export PS1="\n${BYELLOW}[\w]${PS_CLEAR}\n${IBLACK}\$ "
-
4This should be the accepted answer. Did solve the issue.Atcold– Atcold2017年10月26日 00:50:01 +00:00Commented Oct 26, 2017 at 0:50
-
2It should be noted (because I failed to note it ;) ), that in that mess of backslashes and square brackets, the square brackets that follow the escape sequence
033円should NOT be escaped. Only the wrapping square brackets are to be escaped.Benjam– Benjam2018年01月31日 16:29:22 +00:00Commented Jan 31, 2018 at 16:29 -
1Way to confusing for me to deal with all those special characters, using the first google result helped generate a working prompt exactly how I wanted it: ezprompt.netMallox– Mallox2018年06月26日 19:26:48 +00:00Commented Jun 26, 2018 at 19:26
-
I have been wanting to customize my prompt colors for YEARS but never have since I always had this issue! I could never figure out why so I just stopped and kept everything white... I was just setting up a new computer and it finally dawned on me to actually Google the issue for once... So glad I did! Thank you for this wonderful lesson.TylerH4– TylerH42019年06月13日 17:20:42 +00:00Commented Jun 13, 2019 at 17:20
-
I cannot even begin to explain the amount of pointless frustration this issue has been giving me. Thank you kindly, sir.Adam Johnston– Adam Johnston2020年04月04日 22:06:25 +00:00Commented Apr 4, 2020 at 22:06
I had the same problem and it was related to the color definitions.
In my case, I have a multi-line prompt (gives most space for current command regardless of path length displayed by prompt).
Bad version:
export PS1="\n\n\[033円[01;33m[\w]\n033円[00m\$ "
Good version:
export PS1="\n\n\[033円[01;33m[\w]033円[00m\n\$ "
033円[00m terminates the color. If it is after the new line (\n), it prevents proper redraw in the terminal, to overwrite previous commands with background color. Moving it behind the new line resolved the problem.
(using Terminal in Mac OS 10.8)
-
This pinpointed the issue for me, while the current accepted answer was too generic.notbrain– notbrain2014年12月20日 17:38:34 +00:00Commented Dec 20, 2014 at 17:38
-
This is the more precise answer and should be the winner (and was the solution to my problem as well).craveytrain– craveytrain2015年04月24日 15:49:16 +00:00Commented Apr 24, 2015 at 15:49
I actually think this has to do with a missing 'non-printing character' delimiter. I had exactly the same issue, but moving it before the newline (\n) didn't fix it. Instead I correctly surrounded all non-printing characters (here, colouring commands) with '\[' and '\]'.
Bad (works, but has the history-mashing problem described above):
PS1="\e[32m\u\e[35m@\e[32m\h \e[33m\w\e[36m\n\$\e[0m"
Good (surrounded all colour commands with '\[' and '\]' - does not show mashed command history):
PS1="\[\e[32m\]\u\[\e[35m\]@\[\e[32m\]\h \[\e[33m\]\w\[\e[36m\]\n\$\[\e[0m\]"
i.e. "\e[...m" --becomes--> "\[\e[...m\]"
And if you are putting this into something like SecureCRT to auto-send upon login to a system, you may have to double escape everything (put double backslashes everywhere) if auto-login system consumes the first backslash itself to determine the character to be sent:
PS1="\\[\\e[32m\\]\\u\\[\\e[35m\\]@\\[\\e[32m\\]\\h \\[\\e[33m\\]\\w\\[\\e[36m\\]\\n\\$\\[\\e[0m\\]"
i.e. "\..." --becomes--> "\\..."
(This is definitely true of SecureCRT and may be true of others, such as PuTTY or TeraTerm - testing required on your part.)
I was with this issue. What i detected?
When you have colors inside PS1 variable (ex: "\e[35m" ) it ALWAYS have to be surrounded by "\[" and "\]" (ex: "\[\e[35m\]" ).
When i marked all colours in PS1 according to this rule, it worked!
No more problems with scrolling the history of bash.
BAD EXAMPLE: PS1="\e[0;36m[\u@\h[\e[1;31m$ORACLESID\e[0;36m] \W]\e[0m"; export PS1
GOOD EXAMPLE: PS1="\[\e[0;36m\][\u@\h[\[\e[1;31m\]$ORACLESID\[\e[0;36m\]]\W]\[\e[0m\] "; export PS1
Building upon others answers, most likely there's some line in your .zshrc or .zshenv or somewhere else you edited is messing up your command line because it has the wrong syntax, usually a good place to start looking for the source of the issue is anything related to colors. For me it was this line:
PROMPT="$fg[blue]%}myhostrname ${PROMPT}"
When I properly wrapped $fg[blue] inside %{$fg[blue]%} like so:
PROMPT="%{$fg[blue]%}myhostrname ${PROMPT}"
It was fixed.
Context: Zsh theme I was using didn't display the host's name on the terminal so I hardcoded it via this command, but I missed up the color's syntax which caused the command line to freak out with unexpected behavior on several occasions. Been like that for a year or so and I only finally decided to fix it lol.
In my case, I wrote a Perl script to dinamically change the folders in prompt to "something shorter". The script was successful, prompt get updated automatically when cd, but if I navigated history (with arrow up/down), history used to overwrite one part of the new prompt. The ugly part of this issue is that the command line doesn't get cleared by moving through history, so one "short history" could apear INSIDE a previous "printed" PS1.
The solution is in the end.
My conclusions were two:
1- Dynamic PS1 with \[`executables`\] in the PS1 body are not guaranteed to keep the size when navigating history, because it seems that history forces to 2 characters margin in the left (maybe related to an ancester "$_" prompt)
2- To have an immutable length prompt, PS1 must be a fixed size string. Documentation allows to use \[ and \] where I ran a dynamic code inside to transform \w, but it presented that weakness.
Here is a nice example of fixed size PS1:
export PS1='\[033円[01;32m\]\u\[033円[00m\]:\[033円[01;36m\]\w\[033円[00m\]\$ '
My solution:
I rewrote the cd function in a file that is executable and sourced in both .profile and .bashrc.
This function then exports the new FIXED SIZE PS1 exactly in the change of pwd. Now history is NOT messing the prompt because the PS1 body has no longer dynamic parts. I execute the script out and concatenate the result, generating a new fixed size PS1 to export.
function cd {
MYDIR="${1:-${HOME}}"
builtin cd "${MYDIR}"
# echo 'from generic cd'
export PWD=`pwd`
#Dynamic script invoked out of PS1:
folders=`getPs1`
export PS1='\[033円[01;36m\]'$folders'\[033円[00m\]\$ '
}