bash prompt line setting issue [duplicate] - bash

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.

Related

Bash prompt with custom PS1 including current git branch gets corrupt when using reverse-i-search etc [duplicate]

I recently added some color to my bash prompt, and now when I type a command the text doesn't wrap properly.
Here is an example:
MacBook-Pro:~ williamgiles$
long commandwilliamgiles$ this is a really long command,this is a really
My original PS1:
\h:\W \u\$
My new one with color:
\e[0;35m\h:\W \u$ \e[m
You need to mark the color-changing sequences as something that does not contribute to the length of the prompt on-screen.
PS1='\[\e[0;35m\]\h:\W \u$ \[\e[m\]'
bash already knows to take the expansion of \h, \W, and \u into account; it has no idea that \e[0;35m is not simply 7 characters that the terminal will display on screen.
Adding to #chepner's answer, I personally use \1 and \2 in my .inputrc
Here's an example:
set vi-ins-mode-string \1\e[38;5;015m\2╰─\1\e[0m\2\1\e[38;2;191;254;33m\2(ins)⫸\1\e[0m\2\1\e[5 q\2\1\e]12;rgb:bf/fe/21\e\\\2
set vi-cmd-mode-string \1\e[38;5;015m\2╰─\1\e[0m\2\1\e[38;2;191;121;33m\2(cmd)⫸\1\e[0m\2\1\e[2 q\2\1\e]12;rgb:bf/79/21\e\\\2
\1 denotes the start of a zero-length section, and \2 denotes the end.
(\001 and \002 also work)
I wrote a blog post about the topic not long ago. You might find it interesting.
What my shell ends up looking like (The top part is possible by using Oh-My-Posh:

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.

Adding ANSI color escape sequences to a bash prompt results in bad cursor position when recalling/editing commands

If I set my command prompt like:
export PS1='\033[0;33m[\u#\h \w]\$ \033[00m'
The color of the prompt will be yellow and everything after the '$' character will
be the default terminal color. This is what I expect. However, If I recall a command line and attempt to edit it, moving the cursor -- either UpArrow/Ctrl-A (set -o emacs) or ESC K (set -o vi)
if the command line I'm trying to edit is long enough, the cursor is not positioned at the beginning of the command. Typing either Ctrl-A (set -o emacs) or ^ (set -o vi) will not move the cursor to what I'm seeing as the beginning of the recalled line on the screen. Similarly, attempting to position the cursor to the end of the line (Ctrl-E or $, depending) results in it being placed several characters past what appears to be the end of the line.
It looks like bash is getting confused by the escape characters I've added to the prompt.
Is this just something I'll have to deal with, changing my prompt to a monochromatic one when I wish to edit recalled lines, or is there a way to get bash to correctly allow the editing of recalled commands with a colorful prompt?
You need to enclose the non-printing characters in \[ ... \] so that bash knows to ignore them when computing the length of the prompt:
export PS1='\[\033[0;33m\][\u#\h \w]\$ \[\033[00m\]'

Break line in terminal PS1 fix

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\]'

Bash programmation (Cygwin): Illegal Character ^M [duplicate]

This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 3 years ago.
I have a problem with a character. I think it's a conversion problem between dos and unix.
I have a variable that is a float value.
When I print it with the echo command i get:
0.495959
But when I try to make an operation on that value with the bc command (I am not sure how to write the bc command).
echo $mean *1000 |bc
I get:
(standard_in) 1 : illegal character: ^M
I already use the dos2unix command on my .sh file.
I think it's because my variable have the ^M character (not printed with the echo command)
How can i eliminate this error?
I don't have Cygwin handy, but in regular Bash, you can use the tr -d command to strip out specified characters, and you can use the $'...' notation to specify weird characters in a command-line argument (it's like a normal single-quoted string, except that it supports C/Java/Perl/etc.-like escape sequences). So, this:
echo "$mean" * 1000 | tr -d $'\r' | bc
will strip out carriage-returns on the way from echo to bc.
You might actually want to run this:
mean=$(echo "$mean" | tr -d $'\r')
which will modify $mean to strip out any carriage-returns inside, and then you won't have to worry about it in later commands that use it.
(Though it's also worth taking a look at the code that sets $mean to begin with. How does $mean end up having a carriage-return in it, anyway? Maybe you can fix that.)
This works:
${mean/^M/}
You can get ^M by typing Ctrl-V followed by Ctrl-M. Or, alternatively:
${mean/$(printf "\r")/}
The benefit of this method compared to #ruakh's is that here you are using bash built-ins only. The first will be faster as the second will run inside a subshell.
If you just want to "unixize" $mean:
mean="${mean/^M/}"
Edit: There's yet another way:
${mean/$'\r'/}
Running Windows stuff in cygwin has one nasty side-effect as you found out - capturing the output of Windows programs in a cygwin bash variable will also capture the CR output by the program.
Judicious use of d2u avoids the issue - for example,
runtime="`mediainfo --Inform='Video;%Duration%' ${movie} | d2u`"
(Without the d2u, ${runtime} would have a CR tacked on the end, which causes the problem you saw when you feed it to 'bc' for example.)
Maybe you should just save your script in UNIX format instead of DOS.
Try this:
echo `echo $mean` *1000 |bc
If echo really isn't printing it, it should work.
^M is a carriage return character that is used in Windows along with newline (\n) character to indicate next line. However, it is not how it is done in UNIX world, and so bash doesn't treat at as a special character and it breaks the syntax. What you need to do is to remove that character using one of many methods. dos2unix tool can come handy, for example.
As others have pointed out, this is a Windows line ending issue. There are many ways to fix the problem, but the question is why did this happen in the first place.
I can see this happening in several places:
This is a WINDOWS environment variable that was set when Cygwin started up. Sometimes these variables get a CRLF on the end of them. You mentioned this was a particular issue with this one variable, but you didn't specify where it was set.
You edited this file using a Windows text editor like Notepad or Winpad.
Never use a text editor to edit a program. Use a program editor. If you like VI, download VIM which is available on Windows and comes on Cygwin (and all other Unix-based platforms). If VIM isn't for you, try the more graphically based Notepad++. Both of these editors handle end of line issues, and can create scripts with Unix line endings in Windows or files with Windows line endings in Cygwin.
If you use VIM, you can do the following to change line endings and to set them:
To see the line ending in the current file, type :set ff? while in command mode.
To set the line ending for Unix, type :set ff=unix while in command mode.
To set the line ending for Windows, type :set ff=dos while in command mode.
If you use Notepad++
You can go into the Edit-->EOL Conversion menu item and see what your current line ending setting (it's the one not highlighted) and change it.
To have Notepad++ use Unix line endings as the default, go into the Settings-->Preferences menu item. In the Dialog box, select the New Document/Default Directory tab. In the Format section which is part of the New Document section, select the line ending you want. WARNING: Do not select Mac as an option. That doesn't even work on Macs. If you have a Mac, select Unix.

Resources