lean prompt (for zsh)
Make me a sandwich, MAKE me a sandwich
We all know this comic:
And now in zsh!
With the following snippet all commands that are started with an uppercase word
will be prefixed with sudo and then executed.
So MAKE me a sandwich, becomes sudo make me a sandwich.
accept-line() {
local B
B=(${=BUFFER})
if [[ "$B[1]" != [A-Z]* ]]; then
zle .accept-line
return
fi
if [[ $B[1] != "" && $B[1] == $B[1]:u ]]; then
BUFFER="sudo $B[1]:l $B[2,-1]"
fi
zle .accept-line
}
And activate with:
color me, color you
In the xoria256m post, I introduced my xoria256 like color scheme. Again, inspired by solarized, I extended this to other applications. So now I use this in the following apps:
- vim (see that previous post);
- mutt (idem);
- zsh;
- dircolors;
- git (a bit).
zsh
See this file to setup the colors. Then in my prompt I have stuff like:
PS1=$'${vcs_info_msg_0_}$FG[067]%(1j.$myjobs% $FX[reset].$FX[reset])$FG[179]%#$FX[reset] '
RPS1="$RPSL%$MAXMID<...<$mypath$RPSR$FG[239]$FX[bold]$__ZH$FX[reset]${vcs_info_msg_1_}"
RPSR=$'$FX[reset]$FG[009]%(0?.$FG[reset]. $E)$FX[reset]'
For zsh I have two files that make up my prompt:
My f() function in Zsh (and maybe Bash)
Familiar with the following?
You are aware of (shell)file which contains a interesting line and you think: “I want to execute this line on the command prompt”. Most people will do the following:
% more <file>
[select interesting bit with your mouse]
[paste]<enter>
And the code gets executed.
I propose the following function: f(), which does the following:
- It opens the file in $EDITOR (:=
vimof course); - You delete everything you don’t want to execute;
- What’s left gets executed;
- And it is added to your shell’s history.
The code of the function looks like this:
Case insensitive cd
Do I want this?
% ls -ld Joe_Cocker_-_The_Definitive_Collection
drwxr-xr-x 2 miekg admin 4.0K Jul 20 22:20 Joe_Cocker_-_The_Definitive_Collection/
% cd *joe*
cd: no such file or directory: *joe*
% unsetop case_glob
% cd *joe*
% pwd
/shared/vol/music/J/Joe_Cocker_-_The_Definitive_Collection
Zsh prompt updates
I wanted some git information in the prompt I currently have.
While thinking and googling about this, a quote on
Bart’s log got me thinking. I don’t need
to see my current host, nor do I need to see my current user name.
I always login under my own account (miekg) and if I do change
accounts, I probably will be forced to use bash. So showing the current user name
is quite useless.
The builtin test operator
In bash (and other shells) you can use the [[ construct
From the bash manpage:
[[ expression ]]
Return a status of 0 or 1 depending on the evaluation of the
conditional expression expression. Expressions are composed of
the primaries described below under CONDITIONAL EXPRESSIONS.
Word splitting and pathname expansion are not performed on the
words between the [[ and ]]; tilde expansion, parameter and
variable expansion, arithmetic expansion, command substitution,
process substitution, and quote removal are performed. Condi‐
tional operators such as -f must be unquoted to be recognized as
primaries.
So no word splitting and pathname expansion.
ssh’s ControlMaster with zsh
You are using the ControlMaster
feature of ssh and you are having problems remembering
which shell is the master?
That’s why I’ve made zsh display this in the prompt.
You get a m@ when a connection is a master connection and
an @ if it is a slave.
setting up
The check if we are a master works by creating a file
which has $SSH_CLIENT as the name, as the following snippet shows.
updated gitvi script
The script in
using git and vi
together
was a little bit borked, as too many git repo’s were created. Hence a
new and improved version. This one will look up the directory tree to
spot an existing git repository - is nothing found a new one will be
created in $PWD.
code
#!/bin/zsh
# a wrapper around git and vi
# expands $Hash$ to $Hash: file short_hash epoch committer $
# git checkout HEAD $file? when would I need this
# TODO: spaces in filename
[[ ! -x =git ]] && exit 1
who=$SUDO_USER
who=${who:-$LOGNAME}
function search_git_dir {
gpath="$1"
[[ -d "$gpath/.git" ]] && echo "$gpath" && return
[[ -z "$gpath" ]] && echo "" && return
# strip that last path component and try again
search_git_dir "${gpath%/*}"
}
for file in "$@"; do
dir=$(dirname $file); cd $dir
base=$(basename $file)
if [[ -z $(search_git_dir $PWD) ]]; then
# make a new one in $PWD
git init || exit 1
else
#echo FOUND ONE
fi
chmod +w $base 2> /dev/null
if vi $base; then
[[ ! -e $base ]] && exit 0
git add $base
# collapse $Hash: id $ line
sed -i -e 's/\$Hash:.*\$/$Hash$/' $base
git commit $base
fi
id=$(git-show -s --pretty=format:$base\ %h\ %ct\ $who%n -- $base)
[[ -z $id ]] && exit 1
# re-add $Hash: sha1hash$ line
sed -i -e 's/\$Hash\$'/\$Hash:\ $id\ \$/ $base
chmod a-w $base 2> /dev/null
done
manpage And ofcourse the manpage.
Using GIT and VI together
A long while back I used vi together with rcs to manage files
in /etc. This worked, but I found rcs to be clunky. So welcome
to the 21st century and my git + vi script.
It is a wrapper around git, which will create a new
git repository, add the file and commit it when changed.
The script will also expand $Hash$ to
$Hash: basename-of-file short-commit-hash epoch committer`
a typical example is
f()
You all, of course, know about the fc command. From bash’s help system:
fc: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
fc is used to list or edit and re-execute commands from the history list. FIRST and LAST can be numbers specifying the range, or FIRST can be a string, which means the most recent command beginning with that string.
Now I had the following problem: you have a file with shell commands in it. Next you want to select a few lines from this file to be executed in your running shell. A way to do this is: