Process the bash output with color code - bash

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).

Related

GNU Screen tab titles all just 'zsh'

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 '...'

change color of prompt in bash profile

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.

.tmux.conf color codes causing strange output

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!

Customizing bash completion output: each suggestion on a new line

When you type something, you often use bash autocompletion: you start writing a command, for example, and you type TAB to get the rest of the word.
As you have probably noticed, when multiple choices match your command, bash displays them like this :
foobar#myserv:~$ admin-
admin-addrsync admin-adduser admin-delrsync admin-deluser admin-listsvn
admin-addsvn admin-chmod admin-delsvn admin-listrsync
I'm looking for a solution to display each possible solution on a new line, similar to the last column on a ls -l. Ever better, it would be perfect if I could apply a rule like this: "if you find less than 10 suggestions, display them one by line, if more => actual display".
bash prior to version 4.2 doesn't allow any control over the output format of completions, unfortunately.
Bash 4.2+ allows switching to 1-suggestion-per-line output globally, as explained in Grisha Levit's helpful answer, which also links to a clever workaround to achieve a per-completion-function solution.
The following is a tricky workaround for a custom completion.
Solving this problem generically, for all defined completions, would be much harder (if there were a way to invoke readline functions directly, it might be easier, but I haven't found a way to do that).
To test the proof of concept below:
Save to a file and source it (. file) in your interactive shell - this will:
define a command named foo (a shell function)
whose arguments complete based on matching filenames in the current directory.
(When foo is actually invoked, it simply prints its argument in diagnostic form.)
Invoke as:
foo [fileNamePrefix], then press tab:
If between 2 and 9 files in the current directory match, you'll see the desired line-by-line display.
Otherwise (1 match or 10 or more matches), normal completion will occur.
Limitations:
Completion only works properly when applied to the LAST argument on the command line being edited.
When a completion is actually inserted in the command line (once the match is unambiguous), NO space is appended to it (this behavior is required for the workaround).
Redrawing the prompt the first time after printing custom-formatted output may not work properly: Redrawing the command line including the prompt must be simulated and since there is no direct way to obtain an expanded version of the prompt-definition string stored in $PS1, a workaround (inspired by https://stackoverflow.com/a/24006864/45375) is used, which should work in typical cases, but is not foolproof.
Approach:
Defines and assigns a custom completion shell function to the command of interest.
The custom function determines the matches and, if their count is in the desired range, bypasses the normal completion mechanism and creates custom-formatted output.
The custom-formatted output (each match on its own line) is sent directly to the terminal >/dev/tty, and then the prompt and command line are manually "redrawn" to mimic standard completion behavior.
See the comments in the source code for implementation details.
# Define the command (function) for which to establish custom command completion.
# The command simply prints out all its arguments in diagnostic form.
foo() { local a i=0; for a; do echo "\$$((i+=1))=[$a]"; done; }
# Define the completion function that will generate the set of completions
# when <tab> is pressed.
# CAVEAT:
# Only works properly if <tab> is pressed at the END of the command line,
# i.e., if completion is applied to the LAST argument.
_complete_foo() {
local currToken="${COMP_WORDS[COMP_CWORD]}" matches matchCount
# Collect matches, providing the current command-line token as input.
IFS=$'\n' read -d '' -ra matches <<<"$(compgen -A file "$currToken")"
# Count matches.
matchCount=${#matches[#]}
# Output in custom format, depending on the number of matches.
if (( matchCount > 1 && matchCount < 10 )); then
# Output matches in CUSTOM format:
# print the matches line by line, directly to the terminal.
printf '\n%s' "${matches[#]}" >/dev/tty
# !! We actually *must* pass out the current token as the result,
# !! as it will otherwise be *removed* from the redrawn line,
# !! even though $COMP_LINE *includes* that token.
# !! Also, by passing out a nonempty result, we avoid the bell
# !! signal that normally indicates a failed completion.
# !! However, by passing out a single result, a *space* will
# !! be appended to the last token - unless the compspec
# !! (mapping established via `complete`) was defined with
# !! `-o nospace`.
COMPREPLY=( "$currToken" )
# Finally, simulate redrawing the command line.
# Obtain an *expanded version* of `$PS1` using a trick
# inspired by https://stackoverflow.com/a/24006864/45375.
# !! This is NOT foolproof, but hopefully works in most cases.
expandedPrompt=$(PS1="$PS1" debian_chroot="$debian_chroot" "$BASH" --norc -i </dev/null 2>&1 | sed -n '${s/^\(.*\)exit$/\1/p;}')
printf '\n%s%s' "$expandedPrompt" "$COMP_LINE" >/dev/tty
else # Just 1 match or 10 or more matches?
# Perform NORMAL completion: let bash handle it by
# reporting matches via array variable `$COMPREPLY`.
COMPREPLY=( "${matches[#]}" )
fi
}
# Map the completion function (`_complete_foo`) to the command (`foo`).
# `-o nospace` ensures that no space is appended after a completion,
# which is needed for our workaround.
complete -o nospace -F _complete_foo -- foo
bash 4.2+ (and, more generally, applications using readline 6.2+) support this with the use of the completion-display-width variable.
The number of screen columns used to display possible matches when performing completion. The value is ignored if it is less than 0 or greater than the terminal screen width. A value of 0 will cause matches to be displayed one per line. The default value is -1.
Run the following to set the behavior for all completions1 for your current session:
bind 'set completion-display-width 0'
Or modify your ~/.inputrc2 file to have:
set completion-display-width 0
to change the behavior for all new shells.
1 See here for a method for controlling this behavior for individual custom completion functions.
2 The search path for the readline init file is $INPUTRC, ~/.inputrc, /etc/inputrc so modify the file appropriate for you.

To get colors to Less in Ubuntu's Zsh

How can you get similar highlightings to Zsh's Less than Bash's Less in Ubuntu?
I switched from OS X to Ubuntu. My Less do not work as expected in Zsh.
Manuals in my Less are green and black with or without the following code.
# comment these out in Ubuntu
export LESS_TERMCAP_mb=$'\E[01;31m' # begin blinking
export LESS_TERMCAP_me=$'\E[0m' # end mode
export LESS_TERMCAP_se=$'\E[0m' # end standout-mode
export LESS_TERMCAP_so=$'\E[38;5;246m' # begin standout-mode - info box
export LESS_TERMCAP_ue=$'\E[0m' # end underline
export LESS_TERMCAP_us=$'\E[04;33;146m' # begin underline is now yellow
# | | |
# | |----------------- yellow
# |-------------------- underline
# to have the indication of cursor's location and line numbers, and R
export LESS="-mNR"
# |--------- only ASCII color
The code makes manuals readable in OS X, but it does not work for Ubuntu in Zsh.
Ubuntu has excellent highlightings in Bash's Less. My manuals have the colors yellow, green and black in Bash without my code. Both Zsh and Bash use the same Less at /usr/bin/less. This suggests me that Ubuntu's Bash has some dot-files which configure it somewhere.
Where are highlightings for Ubuntu's Less in Bash?
This works for me in zsh on archlinux:
$ mkdir ~/.terminfo/ && cd ~/.terminfo
Now get the terminfo description:
$ wget http://nion.modprobe.de/mostlike.txt
Now compile it using tic (the terminfo entry-description compiler)
$ tic mostlike.txt
(you may want to delete the mostlike.txt file after compiling)
mostlike.txt is this
# Reconstructed via infocmp from file: /usr/share/terminfo/x/xterm-pcolor
mostlike|manpages with color looking like most,
am, hs, km, mir, msgr, xenl,
cols#80, it#8, lines#24, wsl#40,
acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
bel=^G, bold=\E[1m\E[31m, clear=\E[H\E[2J, cr=^M,
csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM, dl1=\E[M,
dsl=\E]0;\007, ed=\E[J, el=\E[K, enacs=\E)0, fsl=^G,
home=\E[H, ht=^I, hts=\EH, il=\E[%p1%dL, il1=\E[L, ind=^J,
is2=\E7\E[r\E[m\E[?7h\E[?1;3;4;6l\E[4l\E8\E>, kbs=^H,
kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
kdch1=\E[3~, kf1=\E[11~, kf10=\E[21~, kf11=\E[23~,
kf12=\E[24~, kf13=\E[25~, kf14=\E[26~, kf15=\E[28~,
kf16=\E[29~, kf17=\E[31~, kf18=\E[32~, kf19=\E[33~,
kf2=\E[12~, kf20=\E[34~, kf3=\E[13~, kf4=\E[14~,
kf5=\E[15~, kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~,
kfnd=\E[1~, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
kslt=\E[4~, rc=\E8, rev=\E[7m\E[34m, ri=\EM, rmacs=^O,
rmcup=\E[2J\E[?47l\E8, rmir=\E[4l, rmkx=\E[?1l\E>,
rmso=\E[m, rmul=\E[m,
rs2=\E7\E[r\E8\E[m\E[?7h\E[?1;3;4;6l\E[4l\E>, sc=\E7,
sgr0=\E[m, smacs=^N, smcup=\E7\E[?47h, smir=\E[4h,
smkx=\E[?1h\E=, smso=\E[1;30m\E[47m, smul=\E[32m,
tbc=\E[3g, tsl=\E]0;, u6=\E[%i%d;%dR, u7=\E[6n,
u8=\E[?1;2c, u9=\E[c,
And then just define an alias in the rc file of your favorite shell:
alias man="TERMINFO=~/.terminfo/ LESS=C TERM=mostlike PAGER=less man"
My default shell is bash so take this with a grain of salt. Start with /etc/profile and see how it sources bash-specific files. You need to re-create that logic for zsh. Maybe the zsh-lovers package can help, at least its title of tips, tricks and examples for the zsh
is suggestive.

Resources