This config is originally based on slimzsh, which is nice and small. Everything that’s broken was afterwards done by me…
This file is my todo list and notes for my config.
git clone https://github.com/QWxleA/qwZsh.git ~/.config/zsh
or:
git clone git@github.com:QWxleA/qwZsh.git ~/.config/zsh
To keep home
clean, put this in /etc/zsh/zshenv
:
#zsh does not use $XDG export ZDOTDIR=$HOME/.config/zsh
See: zshrc
% setopt autocd
% setopt $OPTION % man zshoptions
Supports csh style bang history expansion.
% history # last 16 events % history -E 0 # all history events including date/time information % !23 # Re-execute history command 23 % !! # The last command. % !$ # Last word of the last command. % !-2 # The last but one command. % !-2$ # The last word of the command before the last command. % !#$ # The last word of the current command line. % !#0 # The first word of the current command line. % !?foo # The last command that matches the pattern `foo'. % !?foo?1 # The second word of the last command line that matches `foo'.
…and that’s really just the start. History expansion is extremely versatile and powerful - but also a bit cryptic for the untrained eye. Practice, young padawan, makes perfect. .o( man zshexpn | less -p ‘\^HISTO.*ANSION$’ )
=hist_ignore_all_dups updates the timestamp (if using extended history)
See: history.plugin.zsh
% setopt append_history share_history hist_ignore_all_dups
- fc -p/fc -a/fc -P deals with the “history stack”
- “fc -p” clears out the current history and starts with a new one, until you run fc -P, which will restore the old history again
- You can use that to “bind” certain histories to specific directories.
Check your history for most frequently used commands and create aliases/functions for them (AKA top10):
% print -l -- ${(o)history%% *} | uniq -c | sort -nr | head -n 10
% autoload -U zmv % touch 1\ 2 3\ 4\ 5 % zmv '* *' '$f:gs/ /_'
% autoload run-help % echo foo | xargs <esc-h> and then: % git commit<esc-h> or even ('g' being an alias for git and 'co' and git alias for commit): % g co<esc-h>
% autoload compinit && compinit % kill c<tab> % man z<tab> % dpkg -L <tab>
% zstyle ':completion:*' menu select
Layout is :completion:FUNCTION:COMPLETER:COMMAND-OR-MAGIC-CONTEXT:ARGUMENT:TAG
Tip: Get completion help running ‘ctrl-x h’.
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
% bindkey -M menuselect "+" accept-and-menu-complete % ls <tab> +
Makes find(1) useless for many jobs.
% setopt extendedglob % rm ../debianpackage(.) # remove files only % ls -d *(/) # list directories only % ls /etc/*(@) # list symlinks only % ls -l *.(png|jpg|gif) # list pictures only % ls *(*) # list executables only % ls /etc/**/zsh # which directories contain 'zsh'? % ls **/*(-@) # list dangling symlinks ('**' recurses down directory trees) % ls foo*~*bar* # match everything that starts with foo but doesn't contain bar
The e glob qualifier - e.g. to match all files of which file says that they are JPEGs:
% ls *(e:'file $REPLY | grep -q JPEG':)
- (#s) or (#e) for what ^ and $ are in regexps (beginning of line/end of line)
- (#b) or (#m) to enable backreferences
- (#i) to match case insensitive
- (#a) to match approximately (certain errors are ignored, e.g. “(#a1)foo*” matches the string “ofobar”)
Tip: run e.g. `ls *(<tab>` to get help regarding globbing.
See: keys.plugin.zsh
Notes:
- \^ := ctrl
- \^[ := esc
Zsh defaults to vi keybindings (‘bindkey -v’) if $VISUAL or $EDITOR contain string ‘vi’. Run ‘bindkey -e’ to get emacs-like keybindings then.
Keybinding | Meaning |
---|---|
ctrl-d | complete + EOF |
ctrl-l | clear screen |
ctrl-w | delete last word |
ctrl-\_ | undo |
tab | complete and take first result |
esc-./alt-. | insert last parameter of last typed command (similar to typing !$) |
ctrl-a | begin of line |
ctrl-e | end of line |
alt-’ | quote-line (”) |
alt-? | which-command |
ctrl-k | kill line |
ctrl-u | kill while line (kill-ring) |
ctrl-w | copy last word (kill-ring) |
ctrl-y | yank (insert kill-ring) |
esc-q | push line |
#+caption slash-backward-kill-word
% slash-backward-kill-word() { local WORDCHARS="${WORDCHARS:s@/@}" zle backward-kill-word } % zle -N slash-backward-kill-word % bindkey '\e^?' slash-backward-kill-word % cd /usr/share/doc/mutt/examples/<alt+backspace>
Note: configured by default in grml-zshrc, added to functions.plugin.zsh
% echo 123 % echo 234 % ls and then: % echo <cursor-up|down> vs. % echo 2<page-up|down>
% <ctrl-r>scp*r
- It’s what readline is for bash (move, delete, copy words/lines/…)
- Basic layout of custom widgets, used like functions:
% foobar() { LBUFFER="foobar $LBUFFER"; } # function % zle -N foobar # declare function as bindable widget % bindkey '^x^s' foobar # bind command to a keybinding
- ctrl-x-z provides help_zle_parse_keybindings in grml-zshrc
% autoload edit-command-line && zle -N edit-command-line % bindkey '\ee' edit-command-line % $SOME_COMMAND_LINE <esc-e>
% insert-last-typed-word() { zle insert-last-word -- 0 -1 }; % zle -N insert-last-typed-word; % bindkey "\em" insert-last-typed-word % mv foobar <esc-m>
% autoload -U tetris % tetris
% autoload -U url-quote-magic % zle -N self-insert url-quote-magic
Disclaimer: annoying when using e.g. http://example.org/foo{1,2,3}.tgz
% autoload -U promptinit % promptinit % prompt fire % prompt <tab>
precmd () { RPROMPT="%(?..:()%" }
autoload -Uz vcs_info precmd() { psvar=() vcs_info [[ -n $vcs_info_msg_0_ ]] && psvar[1]="$vcs_info_msg_0_" } PS1="%m%(1v.%F{green}%1v%f.)%# "
% hash -d doc=/usr/share/doc % cd ~doc % hash -d deb=/var/cache/apt/archives % sudo dpkg -i ~deb/foobar*deb
% vared PATH
% mkdir -p /tmp/linux-2.6.3{8,9}/demo % cd /tmp/linux-2.6.38/demo % cd 38 <tab> % echo foo % ^foo^bar % echo foo_bar % echo !$:s/foo/baz/
% alias -s txt=vim % foobar.txt % alias -s pdf=xpdf % print.pdf
% cp file /tmp/doesnotexist/<ctrl-xM>
% cdt
See http://michael-prokop.at/blog/2009/05/30/directory-specific-shell-configuration-with-zsh/ Hint: do you remember the fc section? You can combine the directory specific shell configuration with ‘fc -p $file’!
% which cd cd () { if [[ -f ${1} ]] then [[ ! -e ${1:h} ]] && return 1 print "Correcting ${1} to ${1:h}" builtin cd ${1:h} else builtin cd ${1} fi } % cd /etc/fstab
% vim # ... <ctrl-z> % echo foobar % <ctrl-z>
% which sudo-command-line sudo-command-line () { [[ -z $BUFFER ]] && zle up-history if [[ $BUFFER != sudo\ * ]] then BUFFER="sudo $BUFFER" CURSOR=$(( CURSOR+5 )) fi } % gparted /dev/sda <ctrl-o s>
Long version | Short version |
---|---|
for i in $(seq 2 9); do echo $i ; done | for i in {2..9}; echo $i |
ls $(which vim) | ls =vim |
cat bar baz $PIPECHAR sort | sort <b{ar,az} |
ls /usr/share/doc/mutt/examples | ls /u/s/d/m/e<tab> |
gzip -cd foo.gz && less foo | less <(gzip -cd foo.gz) |
ls >file1; ls >file2; ls >file3 | ls >file1 >file2 >file3 |
- | less <file1 <file2 |
- | diff <(sort foo) <(sort bar) |
- | xpdf =(zcat ~doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz) |
- Q: How to I get a listing of all my currently in use options?
Answer:
setopt ksh_option_print && setopt or: printf '%s=%s\n' "${(@kv)options}"
- Q: Why do I get “zsh: command not found:” even though I just installed the program?
Answer: execute:
% rehash
or use completion system as provided by grml-zshrc (completion will rehash automatically).
- Q: What’s this strange word splitting thing?
Answer: see http://zsh.sourceforge.net/FAQ/zshfaq03.html
% var="foo bar" % args() { echo $#; } % args $var 1 % setopt shwordsplit % args $var 2
- Zsh Homepage: http://zsh.sourceforge.net/
- Zsh Wiki: http://zshwiki.org
- Zsh Manpages: man zshall
- Zsh Reference Card: http://www.bash2zsh.com/zsh_refcard/refcard.pdf
- User’s Guide to ZSH: http://zsh.sourceforge.net/Guide/ (old but still interesting)
- Zsh Talk by caphuso: ftp://ft.bewatermyfriend.org/comp/zshtalk.html
- English Book: http://www.bash2zsh.com/
- German Book: http://zshbuch.org/
- Grml’s Zsh stuff: http://grml.org/zsh/
- This README file is almost completely (initially) lifted from The Zsh Pony ((c) 2011 by Michael Prokop <mika@grml.org>). All errors later added by me.