zsh: add support for global dirstack handling
[grml-etc-core.git] / etc / zsh / zshrc
1 # Filename:      zshrc
2 # Purpose:       config file for zsh (z shell)
3 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
4 # Bug-Reports:   see http://grml.org/bugs/
5 # License:       This file is licensed under the GPL v2.
6 # Latest change: Don Nov 30 16:15:06 CET 2006 [mika]
7 ################################################################################
8 # This file is sourced only for interactive shells. It
9 # should contain commands to set up aliases, functions,
10 # options, key bindings, etc.
11 #
12 # Global Order: zshenv, zprofile, zshrc, zlogin
13 ################################################################################
14
15 # {{{ check for version/system
16 # check for versions (compatibility reasons)
17   if autoload is-at-least && is-at-least 2>/dev/null ; then
18      is4() { is-at-least 4 }
19      is42() { is-at-least 4.2 }
20   else
21     is4(){
22       [[ $ZSH_VERSION == 4.* ]] && return 0
23       return 1
24     }
25     is42(){
26       [[ $ZSH_VERSION == 4.<2->* ]] && return 0
27       return 1
28     }
29   fi
30
31 # grml specific stuff
32   isgrml(){
33     [ -f /etc/grml_version ] && return 0
34     return 1
35   }
36
37   isgrmlcd(){
38     [ -f /etc/grml_cd ] && return 0
39     return 1
40   }
41
42   if isgrml ; then
43     isgrmlsmall() {
44     [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
45   }
46   else
47     isgrmlsmall() { return 1 }
48   fi
49
50   # are we running within an utf environment?
51   isutfenv() {
52     case "$LANG $CHARSET $LANGUAGE" in
53       *utf*) return 0 ;;
54       *)     return 1 ;;
55     esac
56   }
57
58 # check for user, if not running as root set $SUDO to sudo
59  (( EUID != 0 )) && SUDO='sudo' || SUDO=''
60
61 # change directory to home on first invocation of zsh
62 # important for rungetty -> autologin
63 # Thanks go to Bart Schaefer!
64   isgrml && checkhome() {
65   if [[ -z "$ALREADY_DID_CD_HOME" ]]; then
66      export ALREADY_DID_CD_HOME=$HOME
67      cd
68   fi
69   }
70 # }}}
71
72 # {{{ set some variables
73   export EDITOR=${EDITOR:-vim}
74   export MAIL=${MAIL:-/var/mail/$USER}
75   [[ -f ~/.terminfo/m/mostlike ]] && MYLESS='LESS=C TERMINFO=~/.terminfo TERM=mostlike less' || MYLESS='less'
76   [[ -x /usr/bin/dircolors ]] && eval `dircolors -b`
77
78 # Search path for the cd comman
79 #  cdpath=(.. ~)
80
81 # Support our own site-functions
82   [ -d /etc/zsh/site-functions ] && FPATH=/etc/zsh/site-functions:$FPATH
83
84 # automatically remove duplicates from these arrays
85   typeset -U path cdpath fpath manpath
86 # }}}
87
88 # {{{ keybindings
89  if [[ "$TERM" != emacs ]]; then
90   [[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
91   [[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
92   [[ -z "$terminfo[kend]"  ]] || bindkey -M emacs "$terminfo[kend]"  end-of-line
93   [[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
94   [[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
95   [[ -z "$terminfo[kend]"  ]] || bindkey -M vicmd "$terminfo[kend]"  vi-end-of-line
96   [[ -z "$terminfo[cuu1]"  ]] || bindkey -M viins "$terminfo[cuu1]"  vi-up-line-or-history
97   [[ -z "$terminfo[cuf1]"  ]] || bindkey -M viins "$terminfo[cuf1]"  vi-forward-char
98   [[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
99   [[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
100   [[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
101   [[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char
102   # ncurses stuff:
103   [[ "$terminfo[kcuu1]" == "\eO"* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
104   [[ "$terminfo[kcud1]" == "\eO"* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
105   [[ "$terminfo[kcuf1]" == "\eO"* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
106   [[ "$terminfo[kcub1]" == "\eO"* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
107   [[ "$terminfo[khome]" == "\eO"* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
108   [[ "$terminfo[kend]"  == "\eO"* ]] && bindkey -M viins "${terminfo[kend]/O/[}"  end-of-line
109   [[ "$terminfo[khome]" == "\eO"* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
110   [[ "$terminfo[kend]"  == "\eO"* ]] && bindkey -M emacs "${terminfo[kend]/O/[}"  end-of-line
111 fi
112
113 ## keybindings (run 'bindkeys' for details, more details via man zshzle)
114 # use emacs style per default:
115   bindkey -e
116 # use vi style:
117 # bindkey -v
118
119 #if [[ "$TERM" == screen ]]; then
120   bindkey '\e[1~' beginning-of-line       # home
121   bindkey '\e[4~' end-of-line             # end
122   bindkey "^[[A"  up-line-or-search       # cursor up
123   bindkey "^[[B"  down-line-or-search     # <ESC>-
124   bindkey '^x'    history-beginning-search-backward # alternative ways of searching the shell history
125 # bindkey -s '^L' "|less\n"             # ctrl-L pipes to less
126 # bindkey -s '^B' " &\n"                # ctrl-B runs it in the background
127 # if terminal type is set to 'rxvt':
128   bindkey '\e[7~' beginning-of-line       # home
129   bindkey '\e[8~' end-of-line             # end
130 #fi
131
132 #  bindkey '\eq' push-line-or-edit
133 # }}}
134
135 # power completion - abbreviation expansion {{{
136 # power completion / abbreviation expansion / buffer expansion
137 # see http://zshwiki.org/home/examples/zleiab for details
138 # less risky than the global aliases but powerful as well
139 # just type the abbreviation key and afterwards ',.' to expand it
140   declare -A abk
141   setopt extendedglob
142   setopt interactivecomments
143   abk=(
144    # key  # value
145    'C'    '| wc -l'
146    '...' '../..'
147    '....' '../../..'
148    'BG' '& exit'
149    'C' '|wc -l'
150    'G' '|& grep --color=auto'
151    'H' '|head'
152    'Hl' ' --help |& less -r'
153    'L' '|less'
154    'LL' '|& less -r'
155    'M' '|most'
156    'N' '&>/dev/null'
157    'R' '| tr A-z N-za-m'
158    'SL' '| sort | less'
159    'S' '| sort -u'
160    'T' '|tail'
161    'V' '|& vim -'
162    'hide' "echo -en '\033]50;nil2\007'"
163    'tiny' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"'
164    'small' 'echo -en "\033]50;6x10\007"'
165    'medium' 'echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"'
166    'default' 'echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"'
167    'large' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"'
168    'huge' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"'
169    'smartfont' 'echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"'
170    'semifont' 'echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"'
171    'da' 'du -sch'
172    'j' 'jobs -l'
173    'u' 'translate -i'
174    'co' "./configure && make && sudo make install"
175    'CH' "./configure --help"
176    'conkeror' 'firefox -chrome chrome://conkeror/content'
177    'dir' 'ls -lSrah'
178    'lad' $'ls -d .*(/)\n# only show dot-directories'
179    'lsa' $'ls -a .*(.)\n# only show dot-files'
180    'lss' $'ls -l *(s,S,t)\n# only files with setgid/setuid/sticky flag'
181    'lsl' $'ls -l *(@[1,10])\n# only symlinks'
182    'lsx' $'ls -l *(*[1,10])\n# only executables'
183    'lsw' $'ls -ld *(R,W,X.^ND/)\n# world-{readable,writable,executable} files'
184    'lsbig' $'ls -flh *(.OL[1,10])\n# display the biggest files'
185    'lsd' $'ls -d *(/)\n# only show directories'
186    'lse' $'ls -d *(/^F)\n# only show empty directories'
187    'lsnew' $'ls -rl *(D.om[1,10])\n# display the newest files'
188    'lsold' $'ls -rtlh *(D.om[-11,-1])\n # display the oldest files'
189    'lssmall' $'ls -Srl *(.oL[1,10])\n# display the smallest files'
190    'rw-' 'chmod 600'
191    '600' 'chmod u+rw-x,g-rwx,o-rwx'
192    'rwx' 'chmod u+rwx'
193    '700' 'chmod u+rwx,g-rwx,o-rwx'
194    'r--' 'chmod u+r-wx,g-rwx,o-rwx'
195    '644' $'chmod u+rw-x,g+r-wx,o+r-wx\n # 4=r,2=w,1=x'
196    '755' 'chmod u+rwx,g+r-w+x,o+r-w+x'
197    'md' 'mkdir -p '
198    'cmplayer' 'mplayer -vo -fs -zoom fbdev'
199    'fbmplayer' 'mplayer -vo -fs -zoom fbdev'
200    'fblinks' 'links2 -driver fb'
201    'insecssh' 'ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
202    'fori' 'for i ({..}) { }'
203    'cx' 'chmod +x'
204    'e'  'print -l'
205    'se' 'setopt interactivecomments'
206    'va' 'valac --vapidir=../vapi/ --pkg=gtk+-2.0 gtktest.vala'
207    'fb2' '=mplayer -vo fbdev -fs -zoom 1>/dev/null -xy 2'
208    'fb3' '=mplayer -vo fbdev -fs  -zoom 1>/dev/null -xy 3'
209    'ci' 'centericq'
210    'D'  'export DISPLAY=:0.0'
211    'mp' 'mplayer -vo xv -fs -zoom'
212   )
213
214   globalias () {
215         local MATCH
216         matched_chars='[.-|_a-zA-Z0-9]#'
217         LBUFFER=${LBUFFER%%(#m)[.-|_a-zA-Z0-9]#}
218         LBUFFER+=${abk[$MATCH]:-$MATCH}
219   }
220
221   zle -N globalias
222   bindkey ",." globalias
223 # }}}
224
225 # {{{ autoloading
226   autoload -U zmv    # who needs mmv or rename?
227   autoload history-search-end
228
229   # we don't want to quote/espace URLs on our own...
230   # avoid 'url-quote-magic: function definition file not found' on some older boxes
231   if [ -f "/usr/share/zsh/$ZSH_VERSION/functions/Zle/url-quote-magic" ] && \
232      autoload -U url-quote-magic && zle -N self-insert url-quote-magic ; then
233      zle -N self-insert url-quote-magic
234   else
235      print 'Notice: no url-quote-magic available :('
236   fi
237
238   alias run-help >&/dev/null && unalias run-help
239   autoload run-help # use via 'esc-h'
240
241 # completion system
242   if autoload -U compinit && [ -f "/usr/share/zsh/$ZSH_VERSION/functions/Completion/compinit" ] && compinit 2>/dev/null ; then
243     compinit
244    else
245      print 'Notice: no compinit available :('
246      function zstyle { }
247      function compdef { }
248   fi
249
250   is4 && autoload -U zed                  # use ZLE editor to edit a file or function
251
252   is4 && for mod in complist deltochar mathfunc ; do
253              zmodload -i zsh/${mod}
254          done
255
256 # autoload zsh modules when they are referenced
257   is4 && for opt mod in a  stat    \
258                         a  zpty    \
259                         a  zprof   \
260                         ap mapfile ; do
261              zmodload -${opt} zsh/${mod} ${mod}
262          done ; unset opt mod
263
264   is4 && autoload -U insert-files && \
265   zle -N insert-files && \
266   bindkey "^Xf" insert-files # C-x-f
267
268   bindkey ' '   magic-space    # also do history expansion on space
269   bindkey '\ei' menu-complete  # menu completion via esc-i
270
271 # press esc-e for editing command line in $EDITOR or $VISUAL
272   is4 && autoload -U edit-command-line && \
273   zle -N edit-command-line && \
274   bindkey '\ee' edit-command-line
275
276 # menu selection: pick item but stay in the menu (press esc-return)
277   is4 && bindkey -M menuselect '\e^M' accept-and-menu-complete
278
279 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
280   _bkdate() { BUFFER="$BUFFER$(date '+%F')"; CURSOR=$#BUFFER; }
281   bindkey '\C-ed' _bkdate
282   zle -N _bkdate
283
284 # press esc-m for inserting last typed word again (thanks to caphuso!)
285   insert-last-typed-word() { zle insert-last-word -- 0 -1 }; \
286   zle -N insert-last-typed-word; bindkey "\em" insert-last-typed-word
287
288 # set command prediction from history, see 'man 1 zshcontrib'
289 #  is4 && autoload -U predict-on && \
290 #  zle -N predict-on         && \
291 #  zle -N predict-off        && \
292 #  bindkey "^X^Z" predict-on && \
293 #  bindkey "^Z" predict-off
294
295 # put job into foreground via ctrl-z:
296   bindkey -s '^z' "fg\n"
297
298 # press ctrl-q to quote line:
299 #  mquote () {
300 #        zle beginning-of-line
301 #        zle forward-word
302 #        # RBUFFER="'$RBUFFER'"
303 #        RBUFFER=${(q)RBUFFER}
304 #        zle end-of-line
305 #  }
306 #  zle -N mquote && bindkey '^q' mquote
307
308 # run command line as user root via sudo:
309   _sudo-command-line() {
310     [[ $BUFFER != sudo\ * ]] && LBUFFER="sudo $LBUFFER"
311   }
312   zle -N sudo-command-line _sudo-command-line
313   bindkey "^Os" sudo-command-line
314 # }}}
315
316 # {{{ set some important options
317   # umask 022
318   umask 002
319
320 # history:
321   setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
322   is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
323   setopt extended_history     # save each command's beginning timestamp and the duration to the history file
324   is4 && setopt histignorealldups # If  a  new  command  line being added to the history
325                               # list duplicates an older one, the older command is removed from the list
326   setopt histignorespace      # remove command lines from the history list when
327                               # the first character on the line is a space
328 #  setopt histallowclobber    # add `|' to output redirections in the history
329 #  setopt NO_clobber          # warning if file exists ('cat /dev/null > ~/.zshrc')
330   setopt auto_cd              # if a command is issued that can't be executed as a normal command,
331                               # and the command is the name of a directory, perform the cd command to that directory
332   setopt extended_glob        # in order to use #, ~ and ^ for filename generation
333                               # grep word *~(*.gz|*.bz|*.bz2|*.zip|*.Z) ->
334                               # -> searches for word not in compressed files
335                               # don't forget to quote '^', '~' and '#'!
336   setopt notify               # report the status of backgrounds jobs immediately
337   setopt hash_list_all        # Whenever a command completion is attempted, make sure \
338                               # the entire command path is hashed first.
339   setopt completeinword       # not just at the end
340 # setopt nocheckjobs          # don't warn me about bg processes when exiting
341   setopt nohup                # and don't kill them, either
342 # setopt printexitvalue       # alert me if something failed
343 # setopt dvorak               # with spelling correction, assume dvorak kb
344   setopt auto_pushd           # make cd push the old directory onto the directory stack.
345   setopt nonomatch            # try to avoid the 'zsh: no matches found...'
346   setopt nobeep               # avoid "beep"ing
347
348   MAILCHECK=30       # mailchecks
349   REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 secondes
350   watch=(notme root) # watch for everyone but me and root
351
352 # define word separators (for stuff like backward-word, forward-word, backward-kill-word,..)
353 #  WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' # the default
354 #  WORDCHARS=.
355 #  WORDCHARS='*?_[]~=&;!#$%^(){}'
356 #  WORDCHARS='${WORDCHARS:s@/@}'
357
358 # only slash should be considered as a word separator:
359   slash-backward-kill-word() {
360     local WORDCHARS="${WORDCHARS:s@/@}"
361     # zle backward-word
362     zle backward-kill-word
363   }
364   zle -N slash-backward-kill-word
365   bindkey '\ev' slash-backward-kill-word # press esc-v to delete a word until its last '/' (not the same as ctrl-w!)
366 # }}}
367
368 # {{{ history
369   export ZSHDIR=$HOME/.zsh
370   HISTFILE=$HOME/.zsh_history
371   isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
372   isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
373 # }}}
374
375 # dirstack handling {{{
376   DIRSTACKSIZE=20
377   if [[ -f ~/.zdirs ]] && [[ ${#dirstack[*]} -eq 0 ]]; then
378      dirstack=( ${(uf)"$(< ~/.zdirs)"} )
379      # "cd -" won't work after login by just setting $OLDPWD, so
380      cd $dirstack[0] && cd $OLDPWD
381   fi
382   chpwd() { dirs -pl >! ~/.zdirs }
383 # }}}
384
385 # {{{ display battery status on right side of prompt via running 'BATTERY=1 zsh'
386   if [ -n "$BATTERY" ] ; then
387      if [ -x =acpi ] ; then
388         PERCENT="${(C)${(s| |)$(acpi 2>/dev/null)}[4]}"
389         [ -z "$PERCENT" ] && PERCENT='acpi not present'
390         if [ "${PERCENT%%%}" -lt 20 ] ; then
391            PERCENT="warning: ${PERCENT}%"
392         fi
393      fi
394   fi
395 # }}}
396
397 # {{{ set prompt
398   if [ -f "/usr/share/zsh/$ZSH_VERSION/functions/Prompts/promptinit" ] && autoload promptinit && promptinit 2>/dev/null ; then
399      promptinit # people should be able to use their favourite prompt
400   else
401      print 'Notice: no promptinit available :('
402   fi
403
404 # precmd() => a function which is executed just before each prompt
405 # use 'NOPRECMD=1' to disable the precmd + preexec commands
406
407   # precmd () { setopt promptsubst; [[ -o interactive ]] && jobs -l;
408
409   is4 && [[ -z $NOPRECMD ]] && precmd () {
410       [[ -n $NOPRECMD ]] && return 0
411       # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
412       if [[ -z ${DONTSETRPROMPT} ]] ; then
413         if [ -n "$BATTERY" ] ; then
414           # RPROMPT="%(?..:()% ${PERCENT}${SCREENTITLE}"
415           RPROMPT="${PERCENT}${SCREENTITLE}"
416         else
417           # RPROMPT="%(?..:()% ${SCREENTITLE}"
418           RPROMPT="${SCREENTITLE}"
419         fi
420       fi
421       # adjust title of xterm
422       # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
423       case $TERM in (xterm*|rxvt)
424         print -Pn "\e]0;%n@%m: %~\a"
425         ;;
426       esac
427   }
428
429 # chpwd () => a function which is executed whenever the directory is changed
430
431 # preexec() => a function running before every command
432   is4 && [[ -z $NOPRECMD ]] && preexec () {
433       [[ -n $NOPRECMD ]] && return 0
434   # set hostname if not running on host with name 'grml'
435       local HOSTNAME=$(hostname)
436       if [[ "$HOSTNAME" != grml ]] ; then
437          NAME="@$HOSTNAME"
438       fi
439   # get the name of the program currently running and hostname of local machine
440   # set screen window title if running in a screen
441       if [[ "$TERM" == screen* ]]; then
442           # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]}       # dont't use hostname
443           local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname
444           echo -ne "\ek$CMD\e\\"
445       fi
446   # set the screen title to "zsh" when sitting at the command prompt:
447       if [[ "$TERM" == screen* ]]; then
448            SCREENTITLE=$'%{\ekzsh\e\\%}'
449       else
450            SCREENTITLE=''
451       fi
452   # adjust title of xterm
453       case $TERM in (xterm*|rxvt)
454         print -Pn "\e]0;%n@%m: $1\a"
455         ;;
456       esac
457   }
458
459 # set colors
460   if autoload colors && colors 2>/dev/null ; then
461      BLUE="%{${fg[blue]}%}"
462      RED="%{${fg_bold[red]}%}"
463      GREEN="%{${fg[green]}%}"
464      CYAN="%{${fg[cyan]}%}"
465      WHITE="%{${fg[white]}%}"
466      NO_COLOUR="%{${reset_color}%}"
467   else
468      BLUE="%{\e[1;34m%}"
469      RED="%{\e[1;31m%}"
470      GREEN="%{\e[1;32m%}"
471      CYAN="%{\e[1;36m%}"
472      WHITE="%{\e[1;37m%}"
473      NO_COLOUR="%{\e[0m%}"
474   fi
475
476   EXITCODE="%(?..%?%1v )"
477   PS2='`%_> '       # secondary prompt, printed when the shell needs more information to complete a command.
478   PS3='?# '         # selection prompt used within a select loop.
479   PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
480
481   # set variable debian_chroot if running in a chroot with /etc/debian_chroot
482   if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
483     debian_chroot=$(cat /etc/debian_chroot)
484   fi
485
486   # don't use colors on dumb terminals (like emacs):
487   if [[ "$TERM" == dumb ]] ; then
488     PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< %# "
489   else
490     # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt
491     # set variable identifying the chroot you work in (used in the prompt below)
492     if [[ -n "$GRMLPROMPT" ]]; then
493       PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D
494 ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
495     else
496       if (( EUID != 0 )); then
497         PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# " # primary prompt string
498       else
499         PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# " # primary prompt string
500       fi
501     fi
502   fi
503
504   # if we are inside a grml-chroot set a specific prompt theme
505   if [ -n "$GRML_CHROOT" ] ; then
506      PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# "
507   fi
508 # }}}
509
510 # {{{ 'hash' some often used directories
511   hash -d deb=/var/cache/apt/archives
512   hash -d doc=/usr/share/doc
513   hash -d linux=/lib/modules/$(command uname -r)/build/
514   hash -d log=/var/log
515   hash -d slog=/var/log/syslog
516   hash -d src=/usr/src
517   hash -d templ=/usr/share/doc/grml-templates
518   hash -d tt=/usr/share/doc/texttools-doc
519   hash -d www=/var/www
520 # }}}
521
522 # {{{ some aliases
523   if [ $UID = 0 ] ; then
524      [ -r /etc/grml/screenrc ] && alias screen='/usr/bin/screen -c /etc/grml/screenrc'
525   elif [ -r $HOME/.screenrc ] ; then
526      alias screen="/usr/bin/screen -c $HOME/.screenrc"
527   else
528      [ -r /etc/grml/screenrc_grml ] && alias screen='/usr/bin/screen -c /etc/grml/screenrc_grml'
529   fi
530
531   if ls --help 2>/dev/null |grep -- --color= >/dev/null && [ "$TERM" != dumb ] ; then
532      alias ls='ls -b -CF --color=auto' # do we have GNU ls with color-support?
533      alias la='ls -la --color=auto'
534      alias ll='ls -l --color=auto'
535      alias lh='ls -hAl --color=auto'
536      alias l='ls -lF --color=auto'
537   else
538      alias ls='ls -b -CF'
539      alias la='ls -la'
540      alias ll='ls -l'
541      alias lh='ls -hAl'
542      alias l='ls -lF'
543   fi
544
545   alias cp='nocorrect cp'         # no spelling correction on cp
546   alias mkdir='nocorrect mkdir'   # no spelling correction on mkdir
547   alias mv='nocorrect mv'         # no spelling correction on mv
548   alias rm='nocorrect rm'         # no spelling correction on rm
549
550   alias rd='rmdir'
551   alias md='mkdir'
552
553   alias swspeak="setopt singlelinezle ; unsetopt prompt_cr ; export PS1='%m%# ' ; speechd-up" # set up software synth.
554
555 # truecrypt; use e.g. via 'truec /dev/ice' /mnt/ice' or 'truec -i'
556   if [ -x /usr/sbin/truecrypt ] ; then
557      if isutfenv ; then
558         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" '
559      else
560         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" '
561      fi
562   fi
563
564   zsh-help(){print "$bg[white]$fg[black]
565 zsh-help - hints for use of zsh on grml
566 =======================================$reset_color
567
568 Main configuration of zsh happens in /etc/zsh/zshrc (global)
569 and /etc/skel/.zshrc which is copied to \$HOME/.zshrc once.
570 The files are part of the package grml-etc-core, if you want to
571 use them on a non-grml-system just get the tar.gz from
572 http://deb.grml.org/ or get the files from the mercurial
573 repository:
574
575   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/skel/.zshrc
576   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/zsh/zshrc
577
578 If you want to stay in sync with zsh configuration of grml
579 run 'ln -sf /etc/skel/.zshrc \$HOME/.zshrc' and configure
580 your own stuff in \$HOME/.zshrc.local. System wide configuration
581 without touching configuration files of grml can take place
582 in /etc/zsh/zshrc.local.
583
584 If you want to use the configuration of user grml also when
585 running as user root just run 'zshskel' which will source
586 the file /etc/skel/.zshrc.
587
588 For information regarding zsh start at http://grml.org/zsh/
589
590 Take a look at grml's zsh refcard:
591 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
592
593 Check out the main zsh refcard:
594 % $BROWSER http://www.bash2zsh.com/zsh_refcard/refcard.pdf
595
596 And of course visit the zsh-lovers:
597 % man zsh-lovers
598
599 You can adjust some options through environment variables when
600 invoking zsh without having to edit configuration files.
601 Basically meant for bash users who are not used to the power of
602 the zsh yet. :)
603
604   \"NOCOR=1    zsh\" => deactivate automatic correction
605   \"NOMENU=1   zsh\" => do not use menu completion (note: use strg-d for completion instead!)
606   \"NOPRECMD=1 zsh\" => disable the precmd + preexec commands (set GNU screen title)
607   \"BATTERY=1  zsh\" => activate battery status (via acpi) on right side of prompt
608 $bg[white]$fg[black]
609 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
610 Enjoy your grml system with the zsh!$reset_color"
611 }
612
613 # debian stuff
614   if [ -r /etc/debian_version ] ; then
615     alias acs='apt-cache search'
616     alias acsh='apt-cache show'
617     alias acp='apt-cache policy'
618     alias adg="$SUDO apt-get dist-upgrade"
619     alias agi="$SUDO apt-get install"
620     alias ag="$SUDO apt-get upgrade"
621     alias au="$SUDO apt-get update"
622     alias dbp='dpkg-buildpackage'
623     alias ge='grep-excuses'
624
625     # debian upgrade
626     upgrade () {
627       if [ -z "$1" ] ; then
628           $SUDO apt-get update
629           $SUDO apt-get -u upgrade
630       else
631           ssh $1 $SUDO apt-get update
632           # ask before the upgrade
633           local dummy
634           ssh $1 $SUDO apt-get --no-act upgrade
635           echo -n 'Process the upgrade?'
636           read -q dummy
637           if [[ $dummy == "y" ]] ; then
638               ssh $1 $SUDO apt-get -u upgrade --yes
639           fi
640       fi
641     }
642
643     isgrmlcd && alias su="sudo su"          # change to user root
644     alias tlog="tail -f /var/log/syslog"    # take a look at the syslog
645     alias zshskel="source /etc/skel/.zshrc" # source skeleton zshrc
646   fi
647
648 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
649   if [ -L /usr/bin/cdrecord -o ! -x =cdrecord ] ; then
650      if [ -x =wodim ] ; then
651         alias cdrecord="echo 'cdrecord is not provided under its original name by Debian anymore.
652 See #377109 in the BTS of Debian for more details.
653
654 Please use the wodim binary instead' ; return 1"
655      fi
656   fi
657
658 # }}}
659
660 # {{{ Use hard limits, except for a smaller stack and no core dumps
661   unlimit
662   limit stack 8192
663   isgrmlcd && limit core 0 # important for a live-cd-system
664   limit -s
665 # }}}
666
667 # {{{ completion stuff
668
669 # Where to look for autoloaded function definitions
670   if [ -d /etc/zsh/completion.d ] ; then
671     local comp=/etc/zsh/completion.d
672     for func in $comp/*(N-.:t); . ${comp}/${func}
673   fi
674
675 # called later (via is4 && grmlcomp)
676 # notice: use 'zstyle' for getting current settings
677 #         press ^Xh (control-x h) for getting tags in context; ^X? (control-x ?) to run complete_debug with trace output
678 grmlcomp() {
679 ## completion system
680   zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )' # allow one error for every three characters typed in approximate completer
681   zstyle ':completion:*:complete:-command-::commands' ignored-patterns '*\~' # don't complete backup files as executables
682   zstyle ':completion:*:correct:*'       insert-unambiguous true             # start menu completion only if it could find no unambiguous initial string
683   zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}' #
684   zstyle ':completion:*:correct:*'       original true                       #
685   zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}      # activate color-completion(!)
686   zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'  # format on completion
687   zstyle ':completion:*:*:cd:*:directory-stack' menu yes select              # complete 'cd -<tab>' with menu
688   zstyle ':completion:*:expand:*'        tag-order all-expansions            # insert all expansions for expand completer
689   zstyle ':completion:*:history-words'   list false                          #
690   zstyle ':completion:*:history-words'   menu yes                            # activate menu
691   zstyle ':completion:*:history-words'   remove-all-dups yes                 # ignore duplicate entries
692   zstyle ':completion:*:history-words'   stop yes                            #
693   zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'        # match uppercase from lowercase
694   zstyle ':completion:*:matches'         group 'yes'                         # separate matches into groups
695   zstyle ':completion:*'                 group-name ''
696   if [[ -z "$NOMENU" ]] ; then
697     zstyle ':completion:*'               menu select=5                       # if there are more than 5 options allow selecting from a menu
698   else
699     setopt no_auto_menu # don't use any menus at all
700   fi
701   zstyle ':completion:*:messages'        format '%d'                         #
702   zstyle ':completion:*:options'         auto-description '%d'               #
703   zstyle ':completion:*:options'         description 'yes'                   # describe options in full
704   zstyle ':completion:*:processes'       command 'ps -au$USER'               # on processes completion complete all user processes
705   zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters        # offer indexes before parameters in subscripts
706   zstyle ':completion:*'                 verbose true                        # provide verbose completion information
707   zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d' # set format for warnings
708   zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'       # define files to ignore for zcompile
709   zstyle ':completion:correct:'          prompt 'correct to: %e'             #
710   zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'    # Ignore completion functions for commands you don't have:
711
712 # complete manual by their section
713   zstyle ':completion:*:manuals'    separate-sections true
714   zstyle ':completion:*:manuals.*'  insert-sections   true
715   zstyle ':completion:*:man:*'      menu yes select
716
717 ## correction
718 # run rehash on completion so new installed program are found automatically:
719   _force_rehash() {
720       (( CURRENT == 1 )) && rehash
721          return 1 # Because we didn't really complete anything
722     }
723 # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
724   if [[ -n "$NOCOR" ]] ; then
725     zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete
726     setopt nocorrect # do not try to correct the spelling if possible
727   else
728 #    zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _correct _approximate
729     setopt correct  # try to correct the spelling if possible
730     zstyle -e ':completion:*' completer '
731         if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]]; then
732           _last_try="$HISTNO$BUFFER$CURSOR"
733           reply=(_complete _match _prefix)
734         else
735           if [[ $words[1] = (rm|mv) ]]; then
736             reply=(_complete)
737           else
738             reply=(_oldlist _expand _force_rehash _complete _correct _approximate)
739           fi
740         fi'
741   fi
742 # zstyle ':completion:*' completer _complete _correct _approximate
743 # zstyle ':completion:*' expand prefix suffix
744
745 # automatic rehash? Credits go to Frank Terbeck
746 # function my_accept () {
747 #   local buf
748 #   [[ -z ${BUFFER} ]] && zle accept-line && return
749 #   buf=( ${(z)BUFFER}  )
750 #   [[ -z ${commands[${buf[1]}]} ]] && rehash
751 #   zle accept-line
752 # }
753 # zle -N my_accept
754 # bindkey "^M" my_accept
755
756 # command for process lists, the local web server details and host completion
757   hosts=(`hostname` grml.org)
758   zstyle '*' hosts $hosts
759   zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
760
761 # caching
762   [ -d $ZSHDIR/cache ] && zstyle ':completion:*' use-cache yes && \
763                           zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
764
765 # use ~/.ssh/known_hosts for completion [does not work with hashing of new ssh versions anymore]
766   if [ -f "$HOME/.ssh/known_hosts" ] ; then
767     hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*})
768     zstyle ':completion:*:hosts' hosts $hosts
769   fi
770
771 # use generic completion system for programs not yet defined:
772   compdef _gnu_generic tail head feh cp mv gpg df stow uname ipacsum fetchipac
773
774 # see upgrade function in this file
775   compdef _hosts upgrade
776 }
777 # }}}
778
779 # {{{ grmlstuff
780 grmlstuff() {
781 # people should use 'grml-x'!
782   function startx() {
783     if [ -e /etc/X11/xorg.conf ] ; then
784        [ -x /usr/bin/startx ] && /usr/bin/startx || /usr/X11R6/bin/startx
785     else
786       echo "Please use the script \"grml-x\" for starting the X Window System
787 because there does not exist /etc/X11/xorg.conf yet.
788 If you want to use startx anyway please call \"/usr/bin/startx\"."
789       return -1
790     fi
791   }
792
793   function xinit() {
794     if [ -e /etc/X11/xorg.conf ] ; then
795        [ -x /usr/bin/xinit ] && /usr/bin/xinit || /usr/X11R6/bin/xinit
796     else
797       echo "Please use the script \"grml-x\" for starting the X Window System.
798 because there does not exist /etc/X11/xorg.conf yet.
799 If you want to use xinit anyway please call \"/usr/bin/xinit\"."
800       return -1
801     fi
802   }
803
804   if [ -x /usr/sbin/915resolution ] ; then
805      alias 855resolution='echo -e "Please use 915resolution as resolution modify tool for Intel graphic chipset."; return -1'
806   fi
807
808   alias grml-version='cat /etc/grml_version'
809
810   if [ -x /usr/sbin/rebuildfstab ] ; then
811      alias grml-rebuildfstab='rebuildfstab -v -r -config'
812   fi
813 }
814 # }}}
815
816 # {{{ now run the functions
817   isgrml && checkhome
818   is4    && isgrml    && grmlstuff
819   is4    && grmlcomp
820 # }}}
821
822 # {{{ keephack
823   [ -r /etc/zsh/keephack ] && is4 && source /etc/zsh/keephack
824 # }}}
825
826 # {{{ wonderful idea of using "e" glob qualifier by Peter Stephenson
827 # You use it as follows:
828 # $ NTREF=/reference/file
829 # $ ls -l *(e:nt:)
830 # This lists all the files in the current directory newer than the reference file.
831 # You can also specify the reference file inline; note quotes:
832 # $ ls -l *(e:'nt ~/.zshenv':)
833   is4 && nt() {
834     if [[ -n $1 ]]; then
835       local NTREF=${~1}
836     fi
837     [[ $REPLY -nt $NTREF ]]
838   }
839 # }}}
840
841 # shell functions {{{
842   setenv()  { typeset -x "${1}${1:+=}${(@)argv[2,$#]}" }  # csh compatibility
843   freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
844
845   # fast manual access
846   if type -p qma &>/dev/null ; then
847      manzsh()  { qma zshall "$1" }
848   else
849      manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
850      # manzsh()  { /usr/bin/man zshall |  most +/"$1" ; }
851      # manzsh()  { man zshall | $MYLESS -p $1 ; }
852   fi
853
854 # use "dchange <package-name>" to view Debian's changelog of the package:
855   dchange() {
856     if [ -r /usr/share/doc/${1}/changelog.Debian.gz ] ; then
857        most /usr/share/doc/${1}/changelog.Debian.gz
858     else
859        if [ -r /usr/share/doc/${1}/changelog.gz ] ; then
860           most /usr/share/doc/${1}/changelog.gz
861        else
862           echo "No changelog for package $1 found, sorry."
863           return 1
864        fi
865     fi
866   }
867   _dchange() { _files -W /usr/share/doc -/ }
868   compdef _dchange dchange
869
870 # use "uchange <package-name>" to view upstream's changelog of the package:
871   uchange() {
872     if [ -r /usr/share/doc/${1}/changelog.gz ] ; then
873        most /usr/share/doc/${1}/changelog.gz
874     else
875        echo "No changelog for package $1 found, sorry."
876        return 1
877     fi
878   }
879   _uchange() { _files -W /usr/share/doc -/ }
880   compdef _uchange uchange
881
882 # edit alias via zle:
883   edalias() {
884     [ -z "$1" ] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
885   }
886   compdef _aliases edalias
887
888 # edit function via zle:
889   edfun() {
890     [ -z "$1" ] && { echo "Usage: edfun <function_to_edit>" ; return 1 } || zed -f "$1" ;
891   }
892   compdef _functions edfun
893
894 # use it e.g. via 'Restart apache2'
895  if [ -d /etc/init.d ] ; then
896   for i in Start Restart Stop Force-Reload Reload ; do
897     eval "$i() { $SUDO /etc/init.d/\$1 ${i:l} \$2 ; }"
898   done
899   # now the completion for this:
900   compctl -g "$(echo /etc/init.d/*(:t))" Start Restart Stop Force-Reload Reload
901  fi
902
903 # provide useful information on globbing
904   H-Glob() {
905   echo -e "
906       /      directories
907       .      plain files
908       @      symbolic links
909       =      sockets
910       p      named pipes (FIFOs)
911       *      executable plain files (0100)
912       %      device files (character or block special)
913       %b     block special files
914       %c     character special files
915       r      owner-readable files (0400)
916       w      owner-writable files (0200)
917       x      owner-executable files (0100)
918       A      group-readable files (0040)
919       I      group-writable files (0020)
920       E      group-executable files (0010)
921       R      world-readable files (0004)
922       W      world-writable files (0002)
923       X      world-executable files (0001)
924       s      setuid files (04000)
925       S      setgid files (02000)
926       t      files with the sticky bit (01000)
927
928    print *(m-1)          # Files modified up to a day ago
929    print *(a1)           # Files accessed a day ago
930    print *(@)            # Just symlinks
931    print *(Lk+50)        # Files bigger than 50 kilobytes
932    print *(Lk-50)        # Files smaller than 50 kilobytes
933    print **/*.c          # All *.c files recursively starting in \$PWD
934    print **/*.c~file.c   # Same as above, but excluding 'file.c'
935    print (foo|bar).*     # Files starting with 'foo' or 'bar'
936    print *~*.*           # All Files that do not contain a dot
937    chmod 644 *(.^x)      # make all plain non-executable files publically readable
938    print -l *(.c|.h)     # Lists *.c and *.h
939    print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
940    echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
941   }
942   alias help-zshglob=H-Glob
943
944   type -p qma &>/dev/null && alias ?='qma zshall'
945
946   # grep for running process, like: 'any vim'
947   any() {
948   if [ -z "$1" ] ; then
949      echo "any - grep for process(es) by keyword" >&2
950      echo "Usage: any <keyword>" >&2 ; return 1
951   else
952      local STRING=$1
953      local LENGTH=$(expr length $STRING)
954      local FIRSCHAR=$(echo $(expr substr $STRING 1 1))
955      local REST=$(echo $(expr substr $STRING 2 $LENGTH))
956      ps xauwww| grep [$FIRSCHAR]$REST
957   fi
958   }
959
960 # }}}
961
962 # {{{ make sure our environment is clean regarding colors
963   for color in BLUE RED GREEN CYAN WHITE ; unset $color
964 # }}}
965
966 # source another config file if present {{{
967   if [ -r /etc/zsh/zshrc.local ]; then
968    source /etc/zsh/zshrc.local
969   fi
970 # }}}
971
972 # "persistent history" {{{
973 # just write important commands you always need to ~/.important_commands
974   if [ -r ~/.important_commands ] ; then
975      fc -R ~/.important_commands
976   fi
977 # }}}
978
979 ## END OF FILE #################################################################
980 # vim:foldmethod=marker