Break line in terminal PS1 fix - macos

I have this code to color my terminal:
export PS1="\e[1;30m\][\e[\e[1;30m\]\e[1;33m\] \u#\H \[\e[1;32m\]\w\[\e[0m\] \e[1;30m\]]\n[\[ \e[1;31m\]\T\[\e[0m\]\e[1;30m\] ] > \e[37m\]"
But I have one problem, when text should be in the new line it overwrites the first line.
Example:

In order for bash to figure out how much screen space your prompt takes up (and therefore where the actual command line starts), you have to enclose the non-printing parts of the prompt in \[...\]. Mostly, that means escape sequences like \e[1;30m need to be written as \[\e[1;30m\]. You have some \['s and \]'s in your prompt, but they're in the wrong places, which is making bash very confused. Finding all the printing and non-printing parts of a prompt as complex as yours is not trivial, but I think this gets it right:
export PS1='\[\e[1;30m[\e[\e[1;30m\e[1;33m\] \u#\H \[\e[1;32m\]\w\[\e[0m\] \[\e[1;30m\]]\n[ \[\e[1;31m\]\T\[\e[0m\e[1;30m\] ] > \[\e[37m\]'

Related

How to interpret the PS1 variable in BASH?

I have a bash command prompt like this:
someone#some-host:~$
I checked the PS1:
echo $PS1
It shows this:
\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$
How to interpret it? Why is it so complex?
I thought "\u#\h:\w$" should be enough. And I tried to set PS1 to it. It works the same or at least looks so.
How to interpret it?
\[ ... \] is interpreted by Bash as not visible. It matters if you want for example Home key to jump to the beginning of the line but right after prompt. Bash has to know, how many characters to jump to place the cursor right after the prompt, so it has to know how many characters were printed when printing the prompt.
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Controlling-the-Prompt
\e]0;\u#\h: \w\a sets the title of your terminal. https://en.wikipedia.org/wiki/ANSI_escape_code#OSC_(Operating_System_Command)_sequences
${debian_chroot:+($debian_chroot)} Expands to the string (<value of debian_chroot>) when variable debian_chroot is set, otherwise expands to nothing. Basically it adds ( ) to the value of debian_chroot, when it is set to display it nicely. https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion

bash prompt line setting issue [duplicate]

This question already has an answer here:
Bash Prompt Wrapping Issue
(1 answer)
Closed 1 year ago.
I am using xshell to connect a cloud service of centos, and I set the $PS1 value in /etc/bashrc as \e[0;34m[\u#\h \W]$ \e[m which makes my promt a blue color so that I can tell which is my command input and which is the output.
However, this prompt could not automatically add a new line if my command is more than one line. If one line is full, it just starts padding from the left of the same line. You can see the screenshots as follows:
What I want is that the command can automatically add a new line when one line is full.
I tried \n but that just add a new line before command which is not the effect I want.
Now I tried PS1='[\e[0;34m[\u#\h \W]$ \e[m]', the effect is like:
bash can't tell how much space your prompt actually occupies on screen, because the ANSI escape sequences that set colors don't take any space. You need to enclose them (and only them) inside \[...\] to tell bash as much.
PS1='\[\e[0;34m\][\u#\h \W]$ \[\e[m\]'
bash already knows how to handle its own escape sequences \u, \h, and \W. The ANSI escape sequences only have special meaning to the terminal.
That is, \u et al are expanded before bash tries to determine how many characters are in the prompt. For all it knows, \e, [, 0, ;, 3, 4, and m will all be displayed literally as single characters. The terminal sees them, and instead of displaying them, changes the color used to print the following characters.

Bash prompt changes when using arrow keys sometimes

When I use my terminal (iTerm 2 Mac) with my PS1 set to "\[\e[38;5;117m\W \e[39;38;5;104m\$\e[39;0m\] " and I use the arrow keys to go through my bash history it sometimes changes my prompt from ~ $ to just the first character of it and whatever command I'm looking at. For example, going to rvim .bashrc from randomDir $ ls. This problem also persists in the default terminal app.
\W and \$ should not go inside the \[...\], since bash will know how much space each takes up on the terminal.
PS1="\[\e[38;5;117m\]\W \[\e[39;38;5;104m\]\$\[\e[39;0m\] "
Only the characters that make up the ANSI escape sequence (which only instruct the terminal to change colors, without displaying a single additional character) are enclosed in \[...\].
Putting them inside \[...\] tells bash to ignore their contribution to the length of the prompt, leading to incorrect redraws.

What in PS1 is causing my Terminal.app commands to get stuck on the screen?

When cycling through statements entered to the console, I occasionally find that the text I entered isn't refreshed and the prompt is moved to the right.
My original, intended prompt: http://cl.ly/image/04080N260L1V.
What happens after hitting the Up and Down arrows about a dozen times: http://cl.ly/image/1n3S2K31340R.
In case the screenshots aren't clear, the underlined text (in this case, "vim ~/.bas") is getting "added" to the prompt. I can't delete it out. However, if I delete as much as I can, clearing any text after the prompt, and hit Enter, I'm greeted with my clean, original prompt again: http://cl.ly/image/2O1h1Z2y0n2I.
Here's what ~/.bash_profile contains:
# Simpler bash prompt in Terminal.app
promptColor="\e[1;34m"
endColor="\e[m"
#export PS1='\e[0;36m\w$ \e[0m'
export PS1="$promptColor\w$ $endColor"
# Syntax highlighting for commands like `ls` and such
alias ls="ls -G"
# PATH ammendment to put Homebrew-installed apps in front of system-provided ones
homebrew=/usr/local/bin:/usr/local/sbin:/usr/local/share/npm/bin
export PATH=$homebrew:$PATH
I've narrowed the culprit down to the PS1 variable. (You can see I've tried this a few different ways.) Based on what I've read, I'm using the color codes correctly.
Any help would be fantastic. Thanks.
This is a FAQ. In order for Bash to be able to compute the display length of the prompt correctly, any non-printing sequences such as color codes need to be inside a \[...\] sequence.
I think you want:
promptColor='\e[1;34m'
endColor='\e[m'
export PS1="$promptColor"'\w$ '"$endColor"
(Notice all the subtle changes from double to single-quotes)
The problem is that bash is doing expansion on the following when they need to be interpreted explicitly:
\e[1;34m
\w$
\e[m
Single-quotes and double-quotes mean different things in shell: Strong Quoting vs. Weak Quoting.
I would also just copy and paste the lines with escaped characters and modify them (note that they aren't the same as literal representations)

KornShell (ksh) wraparound

Okay, I am sure this is simple but it is driving me nuts. I recently went to work on a program where I have had to step back in time a bit and use Redhat 9. When I'm typing on the command line from a standard xterm running KornShell (ksh), and I reach the end of the line the screen slides to the right (cutting off the left side of my command) instead of wrapping the text around to a new line. This makes things difficult for me because I can't easily copy and paste from the previous command straight from the command line. I have to look at the history and paste the command from there. In case you are wondering, I do a lot of command-line awk scripts that cause the line to get quite long.
Is there a way to force the command line to wrap instead of shifting visibility to the right side of the command I am typing?
I have poured through man page options with no luck.
I'm running:
XFree86 4.2.99.903(174)
KSH 5.2.14.
Thanks.
Did you do man ksh?
You want to do a set -o multiline.
Excerpt from man ksh:
multiline:
The built-in editors will use multiple lines on the screen for
lines that are longer than the width of the screen. This may not
work for all terminals.
eval $(resize) should do it.
If possible, try to break the command down to multiple lines by adding \
ie:
$ mycommand -a foo \
-f bar \
-c dif
The simple answer is:
$ set -o multiline
ksh earlier than 5.12, like the ksh shipped with NetBSD 6.1, doesn't have this option. You will have to turn off current Interactive Input Line Editing mode, which is usually emacs:
$ set +o emacs
This turns off a lot of featuers altogether, like tab-completion or the use of 'Up-arrow' key to roll back the previous command.
If you decide to get used to emacs mode somehow, remember ^a goes to the begining of the line ("Home" key won't workk) and ^e goes to the end.
I don't know of a way of forcing the shell to wrap, but I would ask why you'd be writing lines that long. With awk scripts, I simply wrap the script in single quotes, and then break the lines where I want. It only gets tricky if you need single quotes in the script -- and diabolical if you need both single and double quotes. Actually, the rule is simple enough: use single quotes to wrap the whole script, and when you want a single quote in the script, write '\''. The first quote terminates the previous single-quoted string; the backslash-single quote yields a single quote; and the last single quote starts a new single quoted string. It really gets hairy if you need to escape those characters for an eval or something similar.
The other question is - why not launch into an editor. Since I'm a die-hard vim nutcase (ok - I've been using vi for over 20 years, so it is easier for me than the alternatives), I have Korn shell set to vi mode (set -o vi), and can do escape-v to launch the editor on whatever I've typed.
This is kind of a pragmatic answer, but when that's an issue for me I usually do something like:
strings ~/.history | grep COMMAND
or
strings ~/.history | tail
(The history file has a little bit of binary data in it, hence 'strings')

Resources