Weird behavior in mac os x terminal - macos

I started using this code from Mark Dotto (http://markdotto.com/2013/01/13/improved-terminal-hotness/) to make my terminal is bit sexier.
I just copied the code without editing it, so in my .bash_profile I added:
export PS1='\[\e[0:35m⌘\e[m \e[0:36m\w/\e[m \e[0:33m`git branch 2> /dev/null | grep -e ^* | sed -E s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\e[m\]'
Everything's working, but there is a weird thing: when I type 3 characters or less then I hit backspace, it deletes everything, even the informations on the left (the path and git branch).
This could be okay, but the problem is that when I keep typing after that, the command I started typing is still here (but hidden).
I guess you didn't understand so I'll try to show some code:
# this is what my prompt looks like
~/my/path/ (branch) |
# I start typing a command
~/my/path/ (branch) ls|
# now I hit backspace once
|
# everything is removed
# but if I type something else then hit return
git st|
# it throws an error as the `l` from the previous command is still here
-bash: lgit: command not found
I have absolutely know idea how this bash_profile works, anybody can help? Thanks

there appears to be some incorrect syntax in your PS1 variable that's causing some unexpected errors. try this revision instead:
export PS1='\[\e[36m\]\w \[\e[33m\]`git branch 2> /dev/null | grep -e ^* | sed -E s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /` \[\e[0m\]'
(note: i left the git ... grep ... sed pipeline alone and only edited the parts related to the prompt itself.)
edit - take out the 0: parts and the colors actually work. (i.e. \[\e[36m\] instead of \[\e[0:36m\])
and here's a breakdown of what's going on there:
\[\e[36m\] - this block sets a foreground text color (light blue/tealish)
\w - current working directory
\[\e[33m\] - sets a different text color (yellow)
git ... grep ... sed - retrieves your current git branch
\[\e[0m\] - resets the text color to white so you're not typing commands in yellow
if you don't care about colors, prompts are a fairly trivial thing. the color blocks make it a bit more complex, and (as you've seen) error prone.

First of all: Make sure you are using the BASH shell.
I am on Mountain Lion on a MacBook and the PS1 command sort of, kind of works. My prompt looks like this:
⌘ ~/SVN-Precommit-Kitchen-Sink-Hook.git/ (master) _
I guess the question is what do you want your prompt to do. BASH prompts can embed a whole bunch of escape sequences that can do all sorts of neat things that in Kornshell would take a wee bit of hacking.
Type man bash on the command line, and find the PROMPTING heading. You should see something like this:
When executing interactively, bash displays the primary prompt PS1 when it is ready to read a com-
mand, and the secondary prompt PS2 when it needs more input to complete a command. Bash allows these
prompt strings to be customized by inserting a number of backslash-escaped special characters that
are decoded as follows:
\a an ASCII bell character (07)
\d the date in "Weekday Month Date" format (e.g., "Tue May 26")
\D{format}
the format is passed to strftime(3) and the result is inserted into the prompt string;
an empty format results in a locale-specific time representation. The braces are
required
\e an ASCII escape character (033)
\h the hostname up to the first `.'
\H the hostname
\j the number of jobs currently managed by the shell
\l the basename of the shell's terminal device name
\n newline
\r carriage return
\s the name of the shell, the basename of $0 (the portion following the final slash)
\t the current time in 24-hour HH:MM:SS format
\T the current time in 12-hour HH:MM:SS format
\# the current time in 12-hour am/pm format
\A the current time in 24-hour HH:MM format
\u the username of the current user
\v the version of bash (e.g., 2.00)
\V the release of bash, version + patch level (e.g., 2.00.0)
\w the current working directory, with $HOME abbreviated with a tilde
\W the basename of the current working directory, with $HOME abbreviated with a tilde
\! the history number of this command
\# the command number of this command
\$ if the effective UID is 0, a #, otherwise a $
\nnn the character corresponding to the octal number nnn
\\ a backslash
\[ begin a sequence of non-printing characters, which could be used to embed a terminal
control sequence into the prompt
\] end a sequence of non-printing characters
Let's take a simple prompt. I want to display my user name, the system I'm on, and my current directory. I can set PS1 like this:
PS1="\u#\h:\w$ "
This will give me:
david#davebook:~$ _
The \u is my user name (david), the \h is my machine name (davebook), and the \w displays the current directory I'm in relation to my $HOME directory.
You can also embed commands in the prompt too:
PS1="\$(date) \u#\h:\w$ "
Now the date and time will be embedded in my prompt:
Fri Feb 1 09:45:53 EST 2013 david#DaveBook:~
Sort of silly (I should have formatted the date. Besides, BASH already has built in sequences for the date), but you get the idea.
I recommend that you build your own damn prompt. If you're a git user, and you're using command lines comfortably, you can probably make a nice prompt yourself to look the way you want. You can use the \$(command) syntax to include interactive commands that get executed with each new PS command. You can use ANSI escape codes to color different parts of your prompt, or make them do fantastic stuff.
Build your prompt slowly and bit-by-bit. Create a shell script that will set PS1, and source it in like this:
$ echo "PS='\u#\h:\w\$ " > prompt.sh
$ chmod a+x prompt.sh
$ . prompt.sh
Then, add more and more features to your prompt until you get it to work the way you want.
Personally, I avoid over fancy prompts simply because they tend to fall apart sometime when you least expect it. For example, I use VI sequences for editing, and that prompt simply falls completely apart whenever I try to edit my command line.
Fancy prompts remind me of programs like Talking Moose which are really cool for the first few minutes, then start getting really, really annoying after that.

Related

Added git branch to bash prompt, now it can't find the start of the command

I added the git branch to my bash command line according to the method in https://stackoverflow.com/a/35218509/19776334.
My .bashrc file contains the following lines:
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1] /'
}
PS1="\[${COLOR_LIGHT_RED}\]\d \t \[${COLOR_GREEN}\] \[\$(parse_git_branch)\]\[${COLOR_LIGHT_PURPLE}\]\w \[${COLOR_YELLOW}\]>> \[${COLOR_NC}\]"
It looks the way I want, but sometimes I get strange behavior. If I scroll up to a long command I had previously entered and press Home, the cursor goes to the middle of the branch name. If I then try typing, some of the command disappears.
I changed parse_git_branch to
parse_git_branch() {
echo
}
Then there was no problem with the column. I'm sure this isn't the right way to write in bash. I just wanted to keep the function but return an empty string.
The behavior you're seeing is what you'd get if readline mis-counts the column positions. The \[ ... \] sequences in PS1 tell readline that the characters output here are "invisible" (take up no screen columns), so you only want to use them when the characters are actually invisible.
Let's look at your PS1 setting, breaking it into parts:
PS1="\[${COLOR_LIGHT_RED}\]
This is good and right, because (presumably) the ${COLOR_LIGHT_RED} variable expands to a color-changing sequence that takes no display columns.
\d \t \[${COLOR_GREEN}\]
This, too, seems all good-and-right: \d and \t give the date and time, and do take up columns. The spaces, including the one after the switch to green color, do as well.
\[\$(parse_git_branch)\]
Uh oh! The parsed git branch is printed, and takes up columns, when there's a parsed branch. This should be counted.
\[${COLOR_LIGHT_PURPLE}\]\w \[${COLOR_YELLOW}\]>> \[${COLOR_NC}\]"
The rest looks fine.

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.

Why this two-line bash prompt is messing up the command history

I have my bash prompt as:
\u#\H: \w$(__git_ps1 "[\[\e[0;32m\]%s\[\e[0m\]\[\e[0;33m\]$(parse_git_dirty)\[\e[0m\]]")\n\e[1m\t\e[0m $
so the second line is to display current time.
However, I have found it is messing up the history - when use arrow key to move up, a port of command seems get "stuck" and won't change it anymore. The only way I get back is to press Enter again. How to fix it?
\u#\H: \w$(__git_ps1 "[\[\e[0;32m\]%s\[\e[0m\]\[\e[0;33m\]$(parse_git_dirty)\[\e[0m\]]")\n\e[1m\t\e[0m $
# ^^^^^ ^^^^^
All of the ANSI escape sequences on the first line are correctly surrounded by \[ and \], which tell Bash to not to count those characters when figuring out the visual length of the prompt. The ones on the second line are missing these delimiters.
PS1='\u#\H: \w$(__git_ps1 "[\[\e[0;32m\]%s\[\e[0m\]\[\e[0;33m\]$(parse_git_dirty)\[\e[0m\]]")\n\[\e[1m\]\t\[\e[0m\] $'
# ^^ ^^ ^^ ^^

Backspace deletes prompt in terminal

In the following scenario, my bash prompt looks like this:
Username#Hostname ~ $
If I type any number of characters, and then press the delete button one-too-many times, it will clear the entire line. For example:
Username#Hostname ~ $ ls
then I delete s
Username#Hostname ~ $ l
then I delete l
|
I'm then left with my cursor without any sort of prompt. I can type up commands normally and everything seems to function fine--but why does the prompt disappear? Is there a way to stop this behavior?
If you are using escape sequences to color (or otherwise add content) to your prompt without marking the escapes as "non-printing", bash will lose track of the column, and result in behavior like this.
bash's manual suggests that you put nonprinting characters in your prompt within \[ and \] markers.
For the given example
PS1='\[\033[1;32m\u#\h\[\033[00m \[\033[1;34m\w $\[\033[00m '
a possible improved version would be
PS1='\[\033[1;32m\]\u#\h\[\033[00m\] \[\033[1;34m\]\w $\[\033[00m\] '

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