OS X Terminal text stacking on top of itself - macos

I'm encountering a strange issue in the Terminal app in Mac OS X Lion. When I enter in a long line of text that should wrap to the next line when it reaches the edge of the Terminal window, it continues to type on top of the text from the line above it.
Here are some screenshots to help illustrate the issue:
Before my text reaches the window edge:
After the text reaches the window edge:
I've also supplied screenshots of my text and window settings in case those might be helpful.
Text settings:
Window settings:
Thanks in advance for any assistance offered. I've had this issue for a while and just never got around to it. It's now really becoming a pain in the ass when I get into things that require big grep commands and long path names.

PS1 environment variable determines what shell's prompt will look like. man bash gives full documentation on it. (There are actually several of them, for different modes).
There are number of files that may be setting it, usually one of ~/.profile, ~/.bashrc, /etc/profile or /etc/bashrc.
If you're going to have color codes or other control sequences inside it, you must wrap them with \[ and \] properly (and NOT wrap normal text), otherwise line editing may become messed up like in your case. I suggest resetting PS1 to the default value then carefully adding coloring back item by item.
For example:
PS1='\[\033[1m\033[32m\]\u#\h \w\[\033[0m\]\$ '
^^^^^^^^^^^^^^^ ^^^^^^^
Coloring commands are underlined. Note how they are surrounded with \[ \].

I have the same problem, i found if you change
Advanced > Emulation > Declare terminal as: ANSI.
This solves colored PS1 problem. With Mac Terminal
BUT creates a strange behavior:
I found a solution to my problem with #koiyu answer.
https://apple.stackexchange.com/questions/37001/strange-behavior-in-terminal-with-custom-bash-profile/37036#37036

I used to have the same issue due to incorrectly using color codes. Here is my PS1 which solved the issue. Also if you use GIT, then this will be also helpful to show git branch you are working on and if your working tree is dirty or not. Put this in your .profile or .bash_profile
# Git branch in prompt.
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
parse_git_dirty() {
st=$(git status 2>/dev/null | tail -n 1)
if [[ $st == "" ]]; then
echo ''
elif [[ $st == "nothing to commit (working directory clean)" ]]; then
echo ''
elif [[ $st == 'nothing added to commit but untracked files present (use "git add" to track)' ]]; then
echo '?'
else
echo '*'
fi
}
# coloring the terminal comman line
SB_GREEN="\[\033[1;32m\]"
SB_BLUE="\[\033[1;34m\]"
SB_RED="\[\033[1;31m\]"
SB_NOCOLOR="\[\033[0m\]"
export PS1="$SB_GREEN\u#\h$SB_NOCOLOR: $SB_BLUE\w$SB_GREEN\$(parse_git_branch)$SB_RED\$(parse_git_dirty)$SB_NOCOLOR $ "
Hope this helps.

With the guidance of hamstergene I was able to figure out how to make it play nice. Using this Geek Stuff guide and this It's Me Tommy tutorial, I was able to define how I wanted my PS1 text to display. Changing this to something much more simplified eliminated the weird overlapping text issue I was running into.
Before:
After:
I simply edited my .bash_profile and added the following line:
export PS1="[\u#\h] > ";
Then I went and changed the window colors for good measure because I can.

The original issue was that there was a new line in the PS1 (FYI for anybody running into this)
Typically its improperly escaped color codes, but if its not that its that you have a new line in your ps1

As others have said, you have to properly wrap your color commands in escaped square brackets. However, for me, this makes the string really, really confusing to look at!
As such, here's a trick I use to always get it right and also make it much more readable.
I first create a shell function called setColor like so...
setColor(){
echo "\[\033[${1}m\]"
}
Then I use it like this...
PS1="$(setColor 92)\u$(setColor 37):$(setColor 96)\w $(setColor)\$ "
That's the same as writing this...
\[\033[92m\]\u\[\033[37m\]:\[\033[96m\]\w \[\033[m\]$
...but as you can see, the former is much clearer and also guarantees everything's properly escaped.
Note, you can specify multiple colors too by using the ; character. The only thing is you have to explicitly escape it, so 92;41 becomes 92\;41, like so...
PS1="$(setColor 92\;41)\u$(setColor 37):$(setColor 96)\w $(setColor)\$ "
Again, still easier to read than this...
\[\033[92;41m\]\u\[\033[37m\]:\[\033[96m\]\w \[\033[m\]$
You can take this a step further by defining constants for the colors, or even 'wrapper' functions with the color names you use most, so you can write this...
PS1="$(setRed)\u$(setBlue):$(setGreen)\w $(resetColor)\$ "
Hope this helps!

Related

Bash : Autocompletion, echo and cursor movement

I am trying to code an autocomplete script. It should also outputs some description. I have one function that manage the autocompletation AND the fetching of the description. The autocompletion related part works fine but i have an issue when i want to display the help. In short, this is what i have now :
$> myFunction -myOption1<TAB>
Description for myOption1<CURSOR>
What i woud like :
$> myFunction -myOption1<TAB>
Description for myOption1
$> myFunction -myOption1<CURSOR>
There is no conflict between the autocompletion and the output. The description can only be displayed when the myOption1 is complete. (myOpt will be completed as myOption1 and hence, does not display the description). I made severals attempts to make it work but i guess i am missing a step. The "Description for myOption1" is an 'echo'. I think it's related because compgen is waiting for some value (I give it none for the moment). I tried to trick compgen with some escape characters, spaces : no successes. The autocomplete script should continue to run after this description.
Thanks in advance for the help ;-)
Kol
What I would do:
set COMPREPLY in every case (you don't want to mess with it). (move out of the else)
before messing the screen, I would do a tput sc before the echo, and tput rc afterwards. Note, that will still screw up your screen if your terminal scrolls because of your echo

How can I add a vertical space in 'Terminal' after each command?

I've just started using Terminal (the CLI for Mac OS X).
When I run a command, get some information back, run another command, get more info etc., it is hard (on the eyes) to find a certain point on the screen (e.g. the output for the command before last).
Is there a way of adding a vertical empty space to the end of each output/ after each command is run that has no output?
Each new command that you enter is preceded by a "prompt", and these can be customized (though the exact way to customize depends on the shell). Since you mention Mac OS X I'm assuming you are using the default bash shell, in which case the absolute simplest way to add a blank line is like this: PROMPT_COMMAND=echo. You can run that command to try it out, or add it to a startup file (like .profile in your home folder) to have it done automatically each time.
If you use Bash 4.4 and you want a blank line after your prompt, you could set the PS0 prompt to a newline:
PS0="\n"
Now, this will be inserted every time you run a command:
$ echo "Hello"
Hello
Wondering this too, I've looked at the menu options in Terminal & most of the control characters one can type in and nothing does this on a keystroke. You can however enter an echo command, it alone to leave a single blank line below it before the next prompt. echo \n will add an extra blank line to that, echo \n\n to do 2 extra, ie. 3 blank lines, etc. (you can also do echo;echo;echo getting the same effect)
You can create a shell alias like alias b='echo;echo' (i couldn't seem to get the \n notation to work in a alias), then entering b on a prompt will leave a double-blank line, not bad. Then you gotta figure out how to save aliases in your .profile script.
I tried making an alias for the command ' ' ie. space character, which I though you could type like \ (hmm, stack overflow not formatting this well, that's backslash followed by a space, then return to execute it), but the bash shell doesn't seem to allow an alias with that name. It probably wouldn't allow a function named that either (similar to alias), though I didn't check.
I often use the fish shell, and I found that it does allow a function with that name! Created with function ' '; echo \n; end and indeed it works; at the shell prompt, typing the command \ (again backslash space) leaves a double blank line.
Cool, but.. I tried saving this function using funcsave ' ' (how you save functions in fish, no messing with startup scripts!) and afterwards the function no longer works :^( This is probably a bug in the fish shell. It's in active development right now though, I think I'll report this as a bug since I would kind of like this to work myself.
One could also send Apple a feature request through their bug reporter for an Insert Blank Line menu/keyboard command in Terminal. If someone pays attention to your request it might be implemented in a year maybe.
I wanted to solve exactly the same, and for anyone interested in doing the same, I used what tripleee said in his comment here - I created a .bash_profile (see details here) with the line export PS1="\n\n$ ".
Hopefully that helps someone else too!

ZSH auto-complete screws up command name

When I start doing tab auto-complete of a command, it keeps what I initally typed next to it and the command becomes unreadable. In the example below, I typed 'git che' and hit tab. Once I select 'checkout' the command prompt becomes 'git che git checkout'. The command still works and in my history it stores 'git checkout'. But its pretty annoying visually. Is there anyway to change this behavior. I tried this in 2 different terminal emulators, so I can confirm its ZSH and not the emulator. Thanks
Screenshot
EDIT:
echo $ZSH_VERSION
4.3.10
It doesnt seem to happen with zsh -f. Though its hard to tell since the only autocomplete that works is directories. I'm using 'oh-my-zsh' with this custom theme:
autoload -U add-zsh-hook
add-zsh-hook chpwd do_ls_on_chdir
function do_ls_on_chdir() {
ls;
}
function dirStack(){
OUT='';
NUM=1;
for X in $(dirs | cut -d ' ' -f2-10); do
OUT="$OUT$1%B$NUM:%b$1$X ";
(( NUM=NUM+1 ))
done
echo $OUT;
}
ZSH_THEME_GIT_PROMPT_ADDED=""
ZSH_THEME_GIT_PROMPT_MODIFIED=""
ZSH_THEME_GIT_PROMPT_DELETED=""
ZSH_THEME_GIT_PROMPT_RENAMED=""
ZSH_THEME_GIT_PROMPT_UNMERGED=""
ZSH_THEME_GIT_PROMPT_UNTRACKED=""
ZSH_THEME_GIT_PROMPT_AHEAD="%{$fg_bold[yellow]%}↑"
ZSH_THEME_GIT_PROMPT_PREFIX=""
ZSH_THEME_GIT_PROMPT_SUFFIX=""
ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg_bold[red]%}✗"
ZSH_THEME_GIT_PROMPT_CLEAN=" %{$fg_bold[green]%}✔"
local user_color='blue'
local back="${BG[237]}"
test $UID -eq 0 && user_color='red'
PROMPT='$(dirStack $back)
$back%B%!%b$back %{$fg_bold[$user_color]%}%~%{$reset_color%}'\
'$back $(git_prompt_status)%{$reset_color%}'\
'$back%{$fg_bold[magenta]%}$(git_prompt_info)%{$reset_color%}'\
'$back$(git_prompt_ahead)$reset_color'\
'$back%(!.#.>)$reset_color '
PROMPT2='%{$fg[red]%}%_ %{$reset_color%}'
PROMPT3='%{$fg[red]%}... %{$reset_color%}'
RPROMPT='%(?..%{$fg_bold[red]%}exit %?%{$reset_color%})'\
' %{$FG[186]%}(%D %*)%{$reset_color%}'
SOLUTION:
NOTE: stackoverflow wont let me answer my own question since I asked it within the past 8 hours. I dont feel like waiting.
So I figured it out. It turns out I wasnt properly escaping the ANSI color codes (I think). Everywhere I had $reset_color in my PROMPT variable, I changed that to %{$reset_color%} and it fixed it.
So I figured it out. It turns out I wasnt properly escaping the ANSI color codes (I think). Everywhere I had $reset_color in my PROMPT variable, I changed that to %{$reset_color%} and it fixed it.
I only discovered this link tonight, after messing with my prompt - I'd always wondered why the ZSH prompt examples seemed so needlessly complex.
When you set up the colors in your zsh prompt, you should escape things with %{ [...] %}, so that 'the shell knows there is no output from these sequences and the cursor hasn't moved'.
If you don't escape this, the shell believes that your cursor has moved (even though it hasn't). This leads to messed up prompts, and rather annoying visual effects when you use tab-completion etc.
Here's some screenshots without escaping the reset-color prompt sequence (PR_NO_COLOUR="%{$terminfo[sgr0]%}", in my prompt settings). As we can see, the cursor starts in the wrong place:
It should be here:
And after trying tab-completion without escaping, the prompt is all confused about where the text is, and where the cursor should be placed:
(The cursor should be placed at the end of the directory, not halfway through).
So the prompt sequences look like this:
PS1="%{$fg[red]%}%n%{$reset_color%}#%{$fg[blue]%}%m %{$fg[yellow]%}%~ %{$reset_color%}%% "
because everything has to be escaped nicely inside %{...%} pairs.

Shell Prompt Line Wrapping Issue

I've done something to break my Bash Shell Prompt in OS X (10.5.7) Terminal.
This is the PS1 that I had configured:
PS1='\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
As far as I can tell I have the color commands escaping correctly. However when I scroll up and down in my command history I often get line wrapping issues if the historic commands wrap onto multiple lines.
I simplified my prompts to the following:
PS1='\[\e[1m\]\h:\w\$ \[\e[0m\]'
PS2='> '
And I still see something like:
localhost:~/Library/Application Support/Firefox/Profiles/knpmxpup.Defau
lt/extensions/{1A2D0EC4-75F5-4c91-89C4-3656F6E44B68}$ expocd \{1A2D0EC4-7
5F5-4c91-89C4-3656F6E export PS1="\[
\e[1;32m\]\h\[\e[0m\]: cd Library/Appl
ication\ Support/
I've also tried \033 instead of \e. I just included PS2 up there for information, I haven't changed that from the install default. If I completely remove the color codes then everything works fine, any ideas?
I am now using this PS1 with good effect:
green=$(tput setaf 2)
blue=$(tput setaf 4)
bold=$(tput bold)
reset=$(tput sgr0)
PS1="\[$green$bold\]\h\[$reset\]:\[$blue$bold\]\w\[$reset\]\$ "
Scrolling through my command history appears to handle line wraps now. However in the meantime since this question was asked I have also updated my OS X to 10.6.3
This stackoverflow thread seems relevant. As someone noted in that thread, the Bash FAQ at mywiki.wooledge.org discusses how to properly quote color codes in Bash prompts (FAQ 53), and the proper invocation of terminal colors (FAQ 37).
Line wrapping issues in Bash are nothing new. Your PS1 should work as is but there is a bug in Bash 3.2.49. Consult the mailing list, there's yet another bug regarding this which was confirmed to be fixed in 4.0.
You can't do much more than tagging unprintable characters with \[ and \], the rest must be done by the prompting code.
It seems that you have correctly escaped and enclosed sequences.
A workaround I use anyway it it to add a '\n' at the end. I find it clearer and lessen any problem with wrapping issues. The exact end of my PS1 is :
'\n\[\033[0;30m\]$\[\033[0m\]
An excellent howto you probably know :
Bash prompt howto
I noticed that there are some issues with the prompt cursor positioning even if there are no special character in the PS1 or PROMPT environment variable.
If we output a file that does not have a end-of-line char at the end. It will confuse the prompt.
You can reproduce this by doing:
curl https://gist.githubusercontent.com/martinos/d4aa0a7d4d752b0d0d9f/raw/3198c39f84a080c44227a084a19fb3a0bb661ee5/wrapping_issue.txt
and pressing the up key multiple times and you will see that the prompt get confused.
You can see an example of this in action:
https://asciinema.org/a/9mtjhi9dib6md4ocsbw210cca
When this occurs, just press <CTRL-C> and the prompt will come back to normal.
Note that ZShell does not have this issue.
For future reference, this is what I use:
export PS1="\[\033[0;31m\][\u#Project:\w]$\[\033[0m\] "
This would display my shell prompt as:
[ec2-user#Project:~]$
Helps me distinguish between live and dev sites.
Here's mine: it's the best one I've found, but the site where I originally found it was missing an escape character, leading to the line wrapping issue. I tinkered with it and finally got it working. It shows your user, path, and branch info with good contrast, color-wise.
export PS1='\[\e[1;37m\]\[\e[1;32m\]\u\[\e[0;39m\]:\[\e[1;33m\]\w\[\e[0;39m\]\[\e[1;35m\]$(__git_ps1 " (%s)")\[\e[0;39m\] \[\e[1;37m\]|\[\e[0;39m\]\$'
Also, add
GIT_PS1_SHOWDIRTYSTATE=true
To show a marker when a branch is "dirty" (changes to be committed exist)
export HISTCONTROL=ignoredups
Is also useful to ignore duplicates when scrolling up through bash history.
bind "set completion-ignore-case on"
Helps too.
Lastly,
shopt -s checkwinsize
May be helpful on OSX if issues persist.
'shopt -s checkwinsize' also works for Cygwin wrap problems also
If you're using the title bar trick "\e]2;titlebar\a", make sure to escape that too: "\[\e]2;titlebar\a\]"

Coloring directory name in ksh

In my current situation, it is not unusual for me to have several UNIX computers I connect to, as several different users depending on the situation, and to traverse through various directories on the machines doing things. I use ksh through the entire thing.
I was fiddling with my prompt recently, and I was able to get it to change some colors depending on my current username and current server. However, what I would also want is for it to change colors based on my current directory. For example, if I were in directory "foo", the prompt should be yellow, but if I were in directory "bar", the prompt would be magenta. In both cases, subdirectories should also count, so a simple substring check should be enough.
The problem I ran into, however, is that when I run my .profile script, it properly colors the directory--but it no longer dynamically updates whenever I switch to another directory--and I'm not sure how before I did all the branching, I was able to get it to print my current working directory correctly even after I switched directories.
I did some googling, and find information for bash, but ksh seems to be largely ignored. As I cannot figure out how to do this on my own, I must bring it to the Stack Overflow community, to add it to future knowledge. Thus, with my long-winded explanation, the "quick version" of my question is as follows:
In ksh, how can I set up my prompt to display the current working directory and color the text based on where the current working directory is? Is it even possible?
Why not using zsh? It is based on ksh, and it is much more powerful. In zsh you can write chpwd function that is implicitly called every time you change directory. In this function you can check your current directory and set PS1 to whatever you want.
Alternatively (even in ksh) you can create an alias for cd command:
change_my_ps() {
PS1=...
}
better_cd() {
builtin cd "$#"
change_my_ps
}
alias cd=better_cd
Something like this. I'm not sure it is proper, I don't remember ksh syntax.
I was able to dig up a semi-solution here:
http://books.google.com/books?id=QYu_v2R6fIQC&pg=PA71&lpg=PA71&dq=korn+dynamic+prompt&source=bl&ots=yMEZiWrGyU&sig=8KBbs12Mtk3eGNSZQiLVmFYZVFY&hl=en&ei=2HX4Sej0K6LWMP2NxakP&sa=X&oi=book_result&ct=result&resnum=2#PPA72,M1
Though enacting it is still difficult.
To display the current directory in ksh, put this in your .profile file:
export PS1="\$PWD "
That will dynamically update when you change directory without mucking around with functions.
Since nobody actually answered the part about the color, here's how I'd do it. I can't color the text, so I've also included a screenshot of my terminal.
See Wikipedia's page on ANSI escape codes for the full list of color codes and print --man and printf --man for the details of printing escape sequences in ksh.
(Note that ksh93v, currently in beta, will contain a prompt language based (I think) on bash's, which will make this sort of thing somewhat easier, though I think you'll probably still need to use something like this function to do complex conditional prompts like this one.)
> cat ~/scripts/prompt
function prompt
{
set -eu
typeset c=
case $PWD in
*/foo) c=3;; # yellow
*/bar) c=5;; # magenta
esac
print "\E[3${c}m$PWD\E[m > "
}
PS1='`prompt`'
> . ~/scripts/prompt
/Users/adavies > cd foo
/Users/adavies/foo > cd ../bar
/Users/adavies/bar >
I use this:
function chdir
{
cd "$#"
CWDH=${PWD%/*}
PS1="($_time)$hname:${CWDH##*/}/${PWD##*/} ->"
export PS1
}
alias cd=chdir
chdir .
Ignore the time and hname, but the rest should work for you. Changing colors is going to be terminal dependent. You need to know the escape codes for each color for the terminal you will be using. If you know you only ever use an xterm, it will be easier.

Resources