Follow-up to: Colored text printing spaces in shell script
I have a script I wrote (with some help from #Barmar) which displays my current CPU and memory load visually. The output looks like so:
I then put the following into my .tmux.conf file:
set -g status-right "#(~/load.sh)"
I reload my tmux config and get the following output in the bottom-right:
There are two issues:
The CPU section should contain 11 characters: a "clear color code" character (tput sgr0) and 10 spaces. Instead it contains (B[m
The MEM section... should exist. The entire [| ] has turned into a y> -- I don't even know how the square bracket is missing, that should get printed before any color codes or weird control characters
Can tmux status bars simply not contain color?
tmux status bars don't use ANSI escape codes, they use the same color code format as other things in tmux. You want something more like (assuming 256-color mode):
#[fg=colour28 bg=colour250]Hello World!
Related
OK, so I want to start by first explaining my setup. I have a windows desktop at home, and I am SSH'ing into an Amazon EC2 instance (via PuTTY) running Amazon Linux. I have zsh as my default shell, and oh-my-zsh installed as well. This "cloud developer desktop" model works well for me, but I am having one problem that I have poured more time into than I care to admit: GNU screen only shows 'zsh' as the title of every tab. This is despite using oh-my-zsh's screen plugin (which I think isn't doing anything). Anyone able to help me out? I'd love to have something more descriptive in the tab, perhaps just the last x characters of the current directory (or an open file name if one is open in vim).
Like many screen users, I've had what I'm asking for before, but on a new rig now and don't fully understand everything in my .screenrc:
# Many settings from https://gist.github.com/azitabh/7427682 and
# https://gist.github.com/joaopizani/2718397 and
# https://gist.github.com/ChrisWills/1337178
# Allow bold colors - necessary for some reason
attrcolor b ".I"
# Tell screen how to set colors. AB = background, AF=foreground
termcapinfo xterm "Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm"
# Erase background with current bg color
defbce "on"
# Cache 30000 lines for scroll back
defscrollback 30000
# add tabs on bottom
caption always "%{= bb}%{+b w}%n %t %h %=%l %H %c"
# Very nice tabbed colored hardstatus line
#hardstatus string '%{= Kd} %{= Kd}%-w%{= Kr}[%{= KW}%n %t%{= Kr}]%{= Kd}%+w %-= %{KG} %H%{KW}|%{KY}%101`%{KW}|%D %M %d %Y%{= Kc} %C%A%{-}'
hardstatus alwayslastline "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<"
#Remove vim buffer from scrollback history after quitting
altscreen on
# special xterm hardstatus: use the window title.
#termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'
#termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]1;screen\007'
# Enable 256 color term
term xterm-256color
# Enables use of shift-PgUp and shift-PgDn
termcapinfo xterm|xterms|xs|rxvt ti#:te#
# tell screen that xterm can switch to dark background and has function keys.
termcapinfo xterm 'VR=\E[?5h:VN=\E[?5l'
termcapinfo xterm 'k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~'
termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[H:kN=\E[6~'
# window numbering starts at 1 not 0
bind c screen 1
bind 0 select 10
screen 1
#allow mouse scrolling in screen
termcapinfo xterm* ti#:te#
# Automatically detach on hangup.
autodetach on
I also tried adding this to my .zshrc, and it helps, but isn't quite what I want, as if you run ls, now your title is ls. Ie, not very informative. But maybe editing here is actually the right way to go:
# So screen tabs receive running process title
# preexec () {
# echo -ne "\ek${1%% *}\e\\"
# }
Thanks in advance for your help!
Answering my own question a bit here:
Replacing the line in the preexec () function above with this helps:
echo -ne "\ek$(pwd)\e\\"
Would still be best to only grab the characters from the x-to-last '/' to the end though, replacing the initial string with '...'
I am trying to change the color of the prompt in my terminal to green text for the user at the start and white ~
Currently my .bash_profile file is configured the following way to provide a yellow color for the user name and a pink color for the ~
PS1='\e[33;1m\u#\h: \e[31m\W\e[0m\$'
Does anyone know how to modify the above to change to the colors to green and white?
Thanks!
PS1='\e[32;1m\u#\h: \e[37m\W\e[0m\$'
The numbers after the [ are the color codes. See this reference.
You are looking to change the ANSI escape sequences, specifically the colors.
\e[...m takes a semicolon-separate list of codes to manipulate how the following text is displayed. 33 represents yellow foreground text, 1 represents bold text, 31 represents red foreground text, and 0 resets all values (foreground and background colors, styles, etc) to their terminal defaults.
# Make text yellow and bold, then make it red (keeping it bold)
# and finally restore the default
PS1='\e[33;1m\u#\h: \e[31m\W\e[0m\$'
To use green/white instead of yellow/red, change 33 to 32 and 31 to 37. Also, be sure to enclose characters that do not take up any space on screen inside \[...\] so that the shell can properly determine the length of your prompt.
PS1='\[\e[32;1m\]\u#\h: \[\e[37m\]\W\[\e[0m\]\$'
This assumes that your terminal understands ANSI escape sequences; a more portable method is to use tput to output the codes your actual terminal uses:
PS1='\[$(tput bold; tput setaf 2)\u#\h: \[$(tput setaf y)\]\W$(tput sgr0)\$ '
zsh, incidentally, makes this much easier; it has built-in escapes for changing the color in a terminal-independent way:
# 1. Everything between %B and %b is in bold
# 2. Everything between %F{x} and %f is in a different color;
# x can be a color name, and you can switch from one
# color to another without using %f
# 3. zsh is smart enough to account for built-in escapes when
# computing the prompt lenght, so no equivalent of \[...\]
# is needed
# 4. %n is the same as \u
# 5. %m is the same as \h
# 6. %~ is roughly the same as \W
# 7. %# is roughly the same as \$
PS1='%B%F{green}%n#%m: %F{white}%~%b%f%# '
This approach has two benefits over the others:
it brackets the escape sequences using \[ and ``]to prevent character count problems withCTRL-A` editing of wrapped lines
it uses tput to change the colors so that it is a little more self-documenting what is being done:
PS1='\[$(tput setaf 2)\]\u#\h: \[$(tput setaf 7)\]\W\[$(tput sgr0)\]\$'
To change color of prompt in each section, try to use this simple repo:
https://github.com/joenmarz/bashrc-alias
You can change the color of each prompt section like:
username
'#' sign
hostname
time
bracket sign '[' and ']'
root indicator (# for root user), ($ for non-root user)
The look of your prompt will be like:
[username#hostname 00:00 AM ~/working/directory $]
Go to line 33 of this file (bashrc-alias/.bashrc) to customize each prompt section color variables:
open_brk_color to change open bracket color
closed_brk_color to change closed bracket color
at_color to change '#' sign color
username_color to change username color
hostname_color to change hostname color
time_color to change time prompt color
wd_color to change working directory prompt color
ri_color to change root indicator color
How To Install
Clone this repository at your home directory
git clone https://github.com/joenmarz/bashrc-alias
Add the file path inside your existing ~/.bash file:
. /home/$USER/bashrc-alias/aliases
refesh your .bashrc source by typing:
source ~/.bashrc
I made it easier by adding some variables to each prompt section.
I have a Mac App (CodeRunner) that executes a script in login mode and shows the output in a window.
In error condition, it returns the code with escape characters to make the output hard to read.
Is there a way to process the color code? Is there a filter to remove the color code?
With Mac OS X, I used stderred library.
#export DYLD_INSERT_LIBRARIES="/LOCATION_OF_THE_LIB/libstderred.dylib${DYLD_INSERT_LIBRARIES:+:$DYLD_INSERT_LIBRARIES}"
Removing this library setup shows the strings without the code.
If I understand your question, the easiest way to control color in bash (or any terminal that supports them) is with ANSI escape sequences. Example:
#!/bin/bash
blue='\e[0;34m' # ${blue}
green='\e[0;32m' # ${green}
nc='\e[0m' # ${nc} (no color - disables previous color selection)
printf "${blue}This text is blue, ${green}this is green${nc}\n"
exit 0
There are a number of complete references for the ANSI sequences available on the web, but for basic colors, the following is generally sufficient:
black='\e[0;30m' # ${black}
blue='\e[0;34m' # ${blue}
green='\e[0;32m' # ${green}
cyan='\e[0;36m' # ${cyan}
red='\e[0;31m' # ${red}
purple='\e[0;35m' # ${purple}
brown='\e[0;33m' # ${brown}
lightgray='\e[0;37m' # ${lightgray}
darkgray='\e[1;30m' # ${darkgray}
lightblue='\e[1;34m' # ${lightblue}
lightgreen='\e[1;32m' # ${lightgreen}
lightcyan='\e[1;36m' # ${lightcyan}
lightred='\e[1;31m' # ${lightred}
lightpurple='\e[1;35m' # ${lightpurple}
yellow='\e[1;33m' # ${yellow}
white='\e[1;37m' # ${white}
nc='\e[0m' # ${nc} (no color - disables previous color selection)
Note: always reset the color to default at the end of a string with ${nc} ('\e[0m') to prevent continuation of the color after your script finishes. Lastly, if using echo, you must use echo -e to process the ANSI codes.
Note2: since you are seeing the codes and not the color, you have several possibilities (1) you are using echo without the -e option to allow proper interpretation of the codes (or something similar); or (2) the terminal you are using lacks color capability (though that is doubtful, as just about all modern terminals are VT based with default color handling available).
As suggesting by the comments below, you can also set color with tput (setab # for background and setaf # for foreground).
Is there anyway to modify the bash profile scripts to always display a colored bar at top of screen. I have a requirement to show a colored hostname, username, and ipaddress on the screen at all times, but i don't want to overload PS1 as it would make the prompt take up over half of the default console width.
Not perfect, but this shows you how to fix part of your prompt on the first row of the screen:
PS1='\w \[\e[s\e[1;1H\e[42m\]\h \u ipaddress\[\e[0m\e[u\]\$ '
A breakdown:
\e[s - save the current cursor position
\e[1;1H - move the cursor to row 1, column 1 (numbered from the upper left-hand corner
\e[u - restore the cursor to the previously saved position
\e42m - make the background green
\e0m - restore the default foreground/background colors
\[...\] - enclose the various non-printing characters so that bash can correctly compute the length of the prompt.
Wikipedia lists other escape codes. The two things missing from this answer are how to extend the bar all the way across the string and how to set the correct IP address.
Update: I believe this covers the changes that ruckc made:
PS1='\[\e[s\e[1;1H\e[42m\e[K\h \u ipaddress\e[0m\e[u\]\w \$ '
How about add a \n inside your PS1, so that you always use a new line with full width?
if you are looking for something less hacky (but maybe overkill), consider byobu
https://en.wikipedia.org/wiki/Byobu_(software)
Alternatively, if you are using xterms, you could set the xterm title instead:
export PS1="\[\033]0;\u $(host $(hostname))\007\]\u#\h:\w\$ "
This sets your xterm title, and sets your prompt to contain username#host:pwd.
My .bashrc contains something like this so PS1 is set correctly depending on whether we're in an xterm or not:
if [[ -n "$TERM" ]] ; then
if ( echo $TERM | $GREP -q xterm ) ; then
export PS1="\[\033]0;\u#\h:\w\007\]\u#\h:\w\$ "
else
export PS1="\u#\h:\w\$ "
fi
fi
When I paste a long string (ie, more characters than the width of the terminal window), the terminal doesn't autoscroll and put them in multiple lines.
Instead, it basically wraps onto the same line. In other words, it prints until the end of the current line and then starts printing over the existing characters from the beginning of the same line...
Here's a screenshot. Notice the characters "789abc..." at the beginning of the line.
I'm on 10.8.3 with Terminal 2.3. $TERM is xterm-256color.
A colleague has the exact same machine setup (though different Terminal colors and probably other configs) and he can get it to scroll.
Any ideas?
Thanks!
It sounds like you don't have the nonprinting parts of your PS1 prompt string properly marked. The nonprinting parts (e.g. color change escape sequences) -- and only the nonprinting parts -- need to be marked with \[ ... \] so that the shell can tell they don't take up space on screen (and hence can tell where to wrap). For example, my prompt string is \[\e[0;32m\]\h\[\e[m\]:\W \[\e[0;34m\]\u\[\e[m\]$, which parses out as:
\[\e[0;32m\] - change color to green type (nonprinting, so it's wrapped in \[ ... \])
\h - the hostname (printing)
\[\e[m\] - normal print (no color) (nonprinting, hence wrapped)
:\W - the current directory (and delimiters) (printing)
\[\e[0;34m\] - change to blue type (nonprinting)
\u - the hostname (printing)
\[\e[m\] - normal type (nonprinting)
$ - final delimiter before the actual command