zshrc: fix typo in top10
[grml-etc-core.git] / etc / zsh / zshrc
1 # Filename:      /etc/zsh/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 ################################################################################
7 # This file is sourced only for interactive shells. It
8 # should contain commands to set up aliases, functions,
9 # options, key bindings, etc.
10 #
11 # Global Order: zshenv, zprofile, zshrc, zlogin
12 ################################################################################
13
14 # USAGE
15 # If you are using this file as your ~/.zshrc file, please use ~/.zshrc.pre
16 # and ~/.zshrc.local for your own customisations. The former file is read
17 # before ~/.zshrc, the latter is read after it. Also, consider reading the
18 # refcard and the reference manual for this setup, both available from:
19 #     <http://grml.org/zsh/>
20
21 # Contributing:
22 # If you want to help to improve grml's zsh setup, clone the grml-etc-core
23 # repository from git.grml.org:
24 #   git clone git://git.grml.org/grml-etc-core.git
25 #
26 # Make your changes, commit them; use 'git format-patch' to create a series
27 # of patches and send those to the following address via 'git send-email':
28 #   grml-etc-core@grml.org
29 #
30 # Doing so makes sure the right people get your patches for review and
31 # possibly inclusion.
32
33 # zsh-refcard-tag documentation: {{{
34 #   You may notice strange looking comments in this file.
35 #   These are there for a purpose. grml's zsh-refcard can now be
36 #   automatically generated from the contents of the actual configuration
37 #   file. However, we need a little extra information on which comments
38 #   and what lines of code to take into account (and for what purpose).
39 #
40 # Here is what they mean:
41 #
42 # List of tags (comment types) used:
43 #   #a#     Next line contains an important alias, that should
44 #           be included in the grml-zsh-refcard.
45 #           (placement tag: @@INSERT-aliases@@)
46 #   #f#     Next line contains the beginning of an important function.
47 #           (placement tag: @@INSERT-functions@@)
48 #   #v#     Next line contains an important variable.
49 #           (placement tag: @@INSERT-variables@@)
50 #   #k#     Next line contains an important keybinding.
51 #           (placement tag: @@INSERT-keybindings@@)
52 #   #d#     Hashed directories list generation:
53 #               start   denotes the start of a list of 'hash -d'
54 #                       definitions.
55 #               end     denotes its end.
56 #           (placement tag: @@INSERT-hasheddirs@@)
57 #   #A#     Abbreviation expansion list generation:
58 #               start   denotes the beginning of abbreviations.
59 #               end     denotes their end.
60 #           Lines within this section that end in '#d .*' provide
61 #           extra documentation to be included in the refcard.
62 #           (placement tag: @@INSERT-abbrev@@)
63 #   #m#     This tag allows you to manually generate refcard entries
64 #           for code lines that are hard/impossible to parse.
65 #               Example:
66 #                   #m# k ESC-h Call the run-help function
67 #               That would add a refcard entry in the keybindings table
68 #               for 'ESC-h' with the given comment.
69 #           So the syntax is: #m# <section> <argument> <comment>
70 #   #o#     This tag lets you insert entries to the 'other' hash.
71 #           Generally, this should not be used. It is there for
72 #           things that cannot be done easily in another way.
73 #           (placement tag: @@INSERT-other-foobar@@)
74 #
75 #   All of these tags (except for m and o) take two arguments, the first
76 #   within the tag, the other after the tag:
77 #
78 #   #<tag><section># <comment>
79 #
80 #   Where <section> is really just a number, which are defined by the
81 #   @secmap array on top of 'genrefcard.pl'. The reason for numbers
82 #   instead of names is, that for the reader, the tag should not differ
83 #   much from a regular comment. For zsh, it is a regular comment indeed.
84 #   The numbers have got the following meanings:
85 #         0 -> "default"
86 #         1 -> "system"
87 #         2 -> "user"
88 #         3 -> "debian"
89 #         4 -> "search"
90 #         5 -> "shortcuts"
91 #         6 -> "services"
92 #
93 #   So, the following will add an entry to the 'functions' table in the
94 #   'system' section, with a (hopefully) descriptive comment:
95 #       #f1# Edit an alias via zle
96 #       edalias() {
97 #
98 #   It will then show up in the @@INSERT-aliases-system@@ replacement tag
99 #   that can be found in 'grml-zsh-refcard.tex.in'.
100 #   If the section number is omitted, the 'default' section is assumed.
101 #   Furthermore, in 'grml-zsh-refcard.tex.in' @@INSERT-aliases@@ is
102 #   exactly the same as @@INSERT-aliases-default@@. If you want a list of
103 #   *all* aliases, for example, use @@INSERT-aliases-all@@.
104 #}}}
105
106 # zsh profiling {{{
107 # just execute 'ZSH_PROFILE_RC=1 zsh' and run 'zprof' to get the details
108 if [[ $ZSH_PROFILE_RC -gt 0 ]] ; then
109     zmodload zsh/zprof
110 fi
111 # }}}
112
113 # load .zshrc.pre to give the user the chance to overwrite the defaults
114 [[ -r ${HOME}/.zshrc.pre ]] && source ${HOME}/.zshrc.pre
115
116 # {{{ check for version/system
117 # check for versions (compatibility reasons)
118 is4(){
119     [[ $ZSH_VERSION == <4->* ]] && return 0
120     return 1
121 }
122
123 is41(){
124     [[ $ZSH_VERSION == 4.<1->* || $ZSH_VERSION == <5->* ]] && return 0
125     return 1
126 }
127
128 is42(){
129     [[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
130     return 1
131 }
132
133 is425(){
134     [[ $ZSH_VERSION == 4.2.<5->* || $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
135     return 1
136 }
137
138 is43(){
139     [[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
140     return 1
141 }
142
143 is433(){
144     [[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == 4.<4->* || $ZSH_VERSION == <5->* ]] && return 0
145     return 1
146 }
147
148 is439(){
149     [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* || $ZSH_VERSION == <5->* ]] && return 0
150     return 1
151 }
152
153 #f1# Checks whether or not you're running grml
154 isgrml(){
155     [[ -f /etc/grml_version ]] && return 0
156     return 1
157 }
158
159 #f1# Checks whether or not you're running a grml cd
160 isgrmlcd(){
161     [[ -f /etc/grml_cd ]] && return 0
162     return 1
163 }
164
165 if isgrml ; then
166 #f1# Checks whether or not you're running grml-small
167     isgrmlsmall() {
168         [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
169     }
170 else
171     isgrmlsmall() { return 1 }
172 fi
173
174 isdarwin(){
175     [[ $OSTYPE == darwin* ]] && return 0
176     return 1
177 }
178
179 #f1# are we running within an utf environment?
180 isutfenv() {
181     case "$LANG $CHARSET $LANGUAGE" in
182         *utf*) return 0 ;;
183         *UTF*) return 0 ;;
184         *)     return 1 ;;
185     esac
186 }
187
188 # check for user, if not running as root set $SUDO to sudo
189 (( EUID != 0 )) && SUDO='sudo' || SUDO=''
190
191 # change directory to home on first invocation of zsh
192 # important for rungetty -> autologin
193 # Thanks go to Bart Schaefer!
194 isgrml && checkhome() {
195     if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
196         export ALREADY_DID_CD_HOME=$HOME
197         cd
198     fi
199 }
200
201 # check for zsh v3.1.7+
202
203 if ! [[ ${ZSH_VERSION} == 3.1.<7->*      \
204      || ${ZSH_VERSION} == 3.<2->.<->*    \
205      || ${ZSH_VERSION} == <4->.<->*   ]] ; then
206
207     printf '-!-\n'
208     printf '-!- In this configuration we try to make use of features, that only\n'
209     printf '-!- require version 3.1.7 of the shell; That way this setup can be\n'
210     printf '-!- used with a wide range of zsh versions, while using fairly\n'
211     printf '-!- advanced features in all supported versions.\n'
212     printf '-!-\n'
213     printf '-!- However, you are running zsh version %s.\n' "$ZSH_VERSION"
214     printf '-!-\n'
215     printf '-!- While this *may* work, it might as well fail.\n'
216     printf '-!- Please consider updating to at least version 3.1.7 of zsh.\n'
217     printf '-!-\n'
218     printf '-!- DO NOT EXPECT THIS TO WORK FLAWLESSLY!\n'
219     printf '-!- If it does today, you'\''ve been lucky.\n'
220     printf '-!-\n'
221     printf '-!- Ye been warned!\n'
222     printf '-!-\n'
223
224     function zstyle() { : }
225 fi
226
227 # autoload wrapper - use this one instead of autoload directly
228 # We need to define this function as early as this, because autoloading
229 # 'is-at-least()' needs it.
230 function zrcautoload() {
231     emulate -L zsh
232     setopt extended_glob
233     local fdir ffile
234     local -i ffound
235
236     ffile=$1
237     (( found = 0 ))
238     for fdir in ${fpath} ; do
239         [[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
240     done
241
242     (( ffound == 0 )) && return 1
243     if [[ $ZSH_VERSION == 3.1.<6-> || $ZSH_VERSION == <4->* ]] ; then
244         autoload -U ${ffile} || return 1
245     else
246         autoload ${ffile} || return 1
247     fi
248     return 0
249 }
250
251 # Load is-at-least() for more precise version checks
252 # Note that this test will *always* fail, if the is-at-least
253 # function could not be marked for autoloading.
254 zrcautoload is-at-least || is-at-least() { return 1 }
255
256 # }}}
257
258 # {{{ set some important options (as early as possible)
259 setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
260 is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
261 setopt extended_history     # save each command's beginning timestamp and the duration to the history file
262 is4 && setopt histignorealldups # If  a  new  command  line being added to the history
263                             # list duplicates an older one, the older command is removed from the list
264 setopt histignorespace      # remove command lines from the history list when
265                             # the first character on the line is a space
266 setopt auto_cd              # if a command is issued that can't be executed as a normal command,
267                             # and the command is the name of a directory, perform the cd command to that directory
268 setopt extended_glob        # in order to use #, ~ and ^ for filename generation
269                             # grep word *~(*.gz|*.bz|*.bz2|*.zip|*.Z) ->
270                             # -> searches for word not in compressed files
271                             # don't forget to quote '^', '~' and '#'!
272 setopt longlistjobs         # display PID when suspending processes as well
273 setopt notify               # report the status of backgrounds jobs immediately
274 setopt hash_list_all        # Whenever a command completion is attempted, make sure \
275                             # the entire command path is hashed first.
276 setopt completeinword       # not just at the end
277 setopt nohup                # and don't kill them, either
278 setopt auto_pushd           # make cd push the old directory onto the directory stack.
279 setopt nonomatch            # try to avoid the 'zsh: no matches found...'
280 setopt nobeep               # avoid "beep"ing
281 setopt pushd_ignore_dups    # don't push the same dir twice.
282 setopt noglobdots           # * shouldn't match dotfiles. ever.
283 setopt noshwordsplit        # use zsh style word splitting
284 setopt unset                # don't error out when unset parameters are used
285
286 # }}}
287
288 # setting some default values {{{
289
290 NOCOR=${NOCOR:-0}
291 NOMENU=${NOMENU:-0}
292 NOPRECMD=${NOPRECMD:-0}
293 COMMAND_NOT_FOUND=${COMMAND_NOT_FOUND:-0}
294 GRML_ZSH_CNF_HANDLER=${GRML_ZSH_CNF_HANDLER:-/usr/share/command-not-found/command-not-found}
295 BATTERY=${BATTERY:-0}
296 GRMLSMALL_SPECIFIC=${GRMLSMALL_SPECIFIC:-1}
297 GRML_ALWAYS_LOAD_ALL=${GRML_ALWAYS_LOAD_ALL:-0}
298 ZSH_NO_DEFAULT_LOCALE=${ZSH_NO_DEFAULT_LOCALE:-0}
299
300 # }}}
301
302 # utility functions {{{
303 # this function checks if a command exists and returns either true
304 # or false. This avoids using 'which' and 'whence', which will
305 # avoid problems with aliases for which on certain weird systems. :-)
306 # Usage: check_com [-c|-g] word
307 #   -c  only checks for external commands
308 #   -g  does the usual tests and also checks for global aliases
309 check_com() {
310     emulate -L zsh
311     local -i comonly gatoo
312
313     if [[ $1 == '-c' ]] ; then
314         (( comonly = 1 ))
315         shift
316     elif [[ $1 == '-g' ]] ; then
317         (( gatoo = 1 ))
318     else
319         (( comonly = 0 ))
320         (( gatoo = 0 ))
321     fi
322
323     if (( ${#argv} != 1 )) ; then
324         printf 'usage: check_com [-c] <command>\n' >&2
325         return 1
326     fi
327
328     if (( comonly > 0 )) ; then
329         [[ -n ${commands[$1]}  ]] && return 0
330         return 1
331     fi
332
333     if   [[ -n ${commands[$1]}    ]] \
334       || [[ -n ${functions[$1]}   ]] \
335       || [[ -n ${aliases[$1]}     ]] \
336       || [[ -n ${reswords[(r)$1]} ]] ; then
337
338         return 0
339     fi
340
341     if (( gatoo > 0 )) && [[ -n ${galiases[$1]} ]] ; then
342         return 0
343     fi
344
345     return 1
346 }
347
348 # creates an alias and precedes the command with
349 # sudo if $EUID is not zero.
350 salias() {
351     emulate -L zsh
352     local only=0 ; local multi=0
353     while [[ $1 == -* ]] ; do
354         case $1 in
355             (-o) only=1 ;;
356             (-a) multi=1 ;;
357             (--) shift ; break ;;
358             (-h)
359                 printf 'usage: salias [-h|-o|-a] <alias-expression>\n'
360                 printf '  -h      shows this help text.\n'
361                 printf '  -a      replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
362                 printf '          be careful using this option.\n'
363                 printf '  -o      only sets an alias if a preceding sudo would be needed.\n'
364                 return 0
365                 ;;
366             (*) printf "unkown option: '%s'\n" "$1" ; return 1 ;;
367         esac
368         shift
369     done
370
371     if (( ${#argv} > 1 )) ; then
372         printf 'Too many arguments %s\n' "${#argv}"
373         return 1
374     fi
375
376     key="${1%%\=*}" ;  val="${1#*\=}"
377     if (( EUID == 0 )) && (( only == 0 )); then
378         alias -- "${key}=${val}"
379     elif (( EUID > 0 )) ; then
380         (( multi > 0 )) && val="${val// ; / ; sudo }"
381         alias -- "${key}=sudo ${val}"
382     fi
383
384     return 0
385 }
386
387 # a "print -l ${(u)foo}"-workaround for pre-4.2.0 shells
388 # usage: uprint foo
389 #   Where foo is the *name* of the parameter you want printed.
390 #   Note that foo is no typo; $foo would be wrong here!
391 if ! is42 ; then
392     uprint () {
393         emulate -L zsh
394         local -a u
395         local w
396         local parameter=$1
397
398         if [[ -z ${parameter} ]] ; then
399             printf 'usage: uprint <parameter>\n'
400             return 1
401         fi
402
403         for w in ${(P)parameter} ; do
404             [[ -z ${(M)u:#$w} ]] && u=( $u $w )
405         done
406
407         builtin print -l $u
408     }
409 fi
410
411 # Check if we can read given files and source those we can.
412 xsource() {
413     if (( ${#argv} < 1 )) ; then
414         printf 'usage: xsource FILE(s)...\n' >&2
415         return 1
416     fi
417
418     while (( ${#argv} > 0 )) ; do
419         [[ -r "$1" ]] && source "$1"
420         shift
421     done
422     return 0
423 }
424
425 # Check if we can read a given file and 'cat(1)' it.
426 xcat() {
427     emulate -L zsh
428     if (( ${#argv} != 1 )) ; then
429         printf 'usage: xcat FILE\n' >&2
430         return 1
431     fi
432
433     [[ -r $1 ]] && cat $1
434     return 0
435 }
436
437 # Remove these functions again, they are of use only in these
438 # setup files. This should be called at the end of .zshrc.
439 xunfunction() {
440     emulate -L zsh
441     local -a funcs
442     funcs=(salias xcat xsource xunfunction zrcautoload)
443
444     for func in $funcs ; do
445         [[ -n ${functions[$func]} ]] \
446             && unfunction $func
447     done
448     return 0
449 }
450
451 # this allows us to stay in sync with grml's zshrc and put own
452 # modifications in ~/.zshrc.local
453 zrclocal() {
454     xsource "/etc/zsh/zshrc.local"
455     xsource "${HOME}/.zshrc.local"
456     return 0
457 }
458
459 #}}}
460
461 # locale setup {{{
462 if (( ZSH_NO_DEFAULT_LOCALE == 0 )); then
463     xsource "/etc/default/locale"
464 fi
465
466 for var in LANG LC_ALL LC_MESSAGES ; do
467     [[ -n ${(P)var} ]] && export $var
468 done
469
470 xsource "/etc/sysconfig/keyboard"
471
472 TZ=$(xcat /etc/timezone)
473 # }}}
474
475 # {{{ set some variables
476 if check_com -c vim ; then
477 #v#
478     export EDITOR=${EDITOR:-vim}
479 else
480     export EDITOR=${EDITOR:-vi}
481 fi
482
483 #v#
484 export PAGER=${PAGER:-less}
485
486 #v#
487 export MAIL=${MAIL:-/var/mail/$USER}
488
489 # if we don't set $SHELL then aterm, rxvt,.. will use /bin/sh or /bin/bash :-/
490 export SHELL='/bin/zsh'
491
492 # color setup for ls:
493 check_com -c dircolors && eval $(dircolors -b)
494 # color setup for ls on OS X:
495 isdarwin && export CLICOLOR=1
496
497 # do MacPorts setup on darwin
498 if isdarwin && [[ -d /opt/local ]]; then
499     # Note: PATH gets set in /etc/zprofile on Darwin, so this can't go into
500     # zshenv.
501     PATH="/opt/local/bin:/opt/local/sbin:$PATH"
502     MANPATH="/opt/local/share/man:$MANPATH"
503 fi
504 # do Fink setup on darwin
505 isdarwin && xsource /sw/bin/init.sh
506
507 # load our function and completion directories
508 for fdir in /usr/share/grml/zsh/completion /usr/share/grml/zsh/functions; do
509     fpath=( ${fdir} ${fdir}/**/*(/N) ${fpath} )
510     if [[ ${fpath} == '/usr/share/grml/zsh/functions' ]] ; then
511         for func in ${fdir}/**/[^_]*[^~](N.) ; do
512             zrcautoload ${func:t}
513         done
514     fi
515 done
516 unset fdir func
517
518 # support colors in less
519 export LESS_TERMCAP_mb=$'\E[01;31m'
520 export LESS_TERMCAP_md=$'\E[01;31m'
521 export LESS_TERMCAP_me=$'\E[0m'
522 export LESS_TERMCAP_se=$'\E[0m'
523 export LESS_TERMCAP_so=$'\E[01;44;33m'
524 export LESS_TERMCAP_ue=$'\E[0m'
525 export LESS_TERMCAP_us=$'\E[01;32m'
526
527 MAILCHECK=30       # mailchecks
528 REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 seconds
529 watch=(notme root) # watch for everyone but me and root
530
531 # automatically remove duplicates from these arrays
532 typeset -U path cdpath fpath manpath
533 # }}}
534
535 # {{{ keybindings
536 if [[ "$TERM" != emacs ]] ; then
537     [[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
538     [[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
539     [[ -z "$terminfo[kend]"  ]] || bindkey -M emacs "$terminfo[kend]"  end-of-line
540     [[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
541     [[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
542     [[ -z "$terminfo[kend]"  ]] || bindkey -M vicmd "$terminfo[kend]"  vi-end-of-line
543     [[ -z "$terminfo[cuu1]"  ]] || bindkey -M viins "$terminfo[cuu1]"  vi-up-line-or-history
544     [[ -z "$terminfo[cuf1]"  ]] || bindkey -M viins "$terminfo[cuf1]"  vi-forward-char
545     [[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
546     [[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
547     [[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
548     [[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char
549     # ncurses stuff:
550     [[ "$terminfo[kcuu1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
551     [[ "$terminfo[kcud1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
552     [[ "$terminfo[kcuf1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
553     [[ "$terminfo[kcub1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
554     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
555     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M viins "${terminfo[kend]/O/[}"  end-of-line
556     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
557     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M emacs "${terminfo[kend]/O/[}"  end-of-line
558 fi
559
560 ## keybindings (run 'bindkeys' for details, more details via man zshzle)
561 # use emacs style per default:
562 bindkey -e
563 # use vi style:
564 # bindkey -v
565
566 #if [[ "$TERM" == screen ]] ; then
567 bindkey '\e[1~' beginning-of-line       # home
568 bindkey '\e[4~' end-of-line             # end
569 bindkey '\e[A'  up-line-or-search       # cursor up
570 bindkey '\e[B'  down-line-or-search     # <ESC>-
571
572 bindkey '^xp'   history-beginning-search-backward
573 bindkey '^xP'   history-beginning-search-forward
574 # bindkey -s '^L' "|less\n"             # ctrl-L pipes to less
575 # bindkey -s '^B' " &\n"                # ctrl-B runs it in the background
576 # if terminal type is set to 'rxvt':
577 bindkey '\e[7~' beginning-of-line       # home
578 bindkey '\e[8~' end-of-line             # end
579 #fi
580
581 # insert unicode character
582 # usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an Â§
583 # See for example http://unicode.org/charts/ for unicode characters code
584 zrcautoload insert-unicode-char
585 zle -N insert-unicode-char
586 #k# Insert Unicode character
587 bindkey '^Xi' insert-unicode-char
588
589 #m# k Shift-tab Perform backwards menu completion
590 if [[ -n "$terminfo[kcbt]" ]]; then
591     bindkey "$terminfo[kcbt]" reverse-menu-complete
592 elif [[ -n "$terminfo[cbt]" ]]; then # required for GNU screen
593     bindkey "$terminfo[cbt]"  reverse-menu-complete
594 fi
595
596 ## toggle the ,. abbreviation feature on/off
597 # NOABBREVIATION: default abbreviation-state
598 #                 0 - enabled (default)
599 #                 1 - disabled
600 NOABBREVIATION=${NOABBREVIATION:-0}
601
602 grml_toggle_abbrev() {
603     if (( ${NOABBREVIATION} > 0 )) ; then
604         NOABBREVIATION=0
605     else
606         NOABBREVIATION=1
607     fi
608 }
609
610 zle -N grml_toggle_abbrev
611 bindkey '^xA' grml_toggle_abbrev
612
613 # add a command line to the shells history without executing it
614 commit-to-history() {
615     print -s ${(z)BUFFER}
616     zle send-break
617 }
618 zle -N commit-to-history
619 bindkey "^x^h" commit-to-history
620
621 # only slash should be considered as a word separator:
622 slash-backward-kill-word() {
623     local WORDCHARS="${WORDCHARS:s@/@}"
624     # zle backward-word
625     zle backward-kill-word
626 }
627 zle -N slash-backward-kill-word
628
629 #k# Kill everything in a word up to its last \kbd{/}
630 bindkey '\ev' slash-backward-kill-word
631 #k# Kill everything in a word up to its last \kbd{/}
632 bindkey '\e^h' slash-backward-kill-word
633 #k# Kill everything in a word up to its last \kbd{/}
634 bindkey '\e^?' slash-backward-kill-word
635
636 # use the new *-pattern-* widgets for incremental history search
637 if is439 ; then
638     bindkey '^r' history-incremental-pattern-search-backward
639     bindkey '^s' history-incremental-pattern-search-forward
640 fi
641 # }}}
642
643 # a generic accept-line wrapper {{{
644
645 # This widget can prevent unwanted autocorrections from command-name
646 # to _command-name, rehash automatically on enter and call any number
647 # of builtin and user-defined widgets in different contexts.
648 #
649 # For a broader description, see:
650 # <http://bewatermyfriend.org/posts/2007/12-26.11-50-38-tooltime.html>
651 #
652 # The code is imported from the file 'zsh/functions/accept-line' from
653 # <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>, which
654 # distributed under the same terms as zsh itself.
655
656 # A newly added command will may not be found or will cause false
657 # correction attempts, if you got auto-correction set. By setting the
658 # following style, we force accept-line() to rehash, if it cannot
659 # find the first word on the command line in the $command[] hash.
660 zstyle ':acceptline:*' rehash true
661
662 function Accept-Line() {
663     emulate -L zsh
664     local -a subs
665     local -xi aldone
666     local sub
667
668     zstyle -a ":acceptline:${alcontext}" actions subs
669
670     (( ${#subs} < 1 )) && return 0
671
672     (( aldone = 0 ))
673     for sub in ${subs} ; do
674         [[ ${sub} == 'accept-line' ]] && sub='.accept-line'
675         zle ${sub}
676
677         (( aldone > 0 )) && break
678     done
679 }
680
681 function Accept-Line-getdefault() {
682     emulate -L zsh
683     local default_action
684
685     zstyle -s ":acceptline:${alcontext}" default_action default_action
686     case ${default_action} in
687         ((accept-line|))
688             printf ".accept-line"
689             ;;
690         (*)
691             printf ${default_action}
692             ;;
693     esac
694 }
695
696 function accept-line() {
697     emulate -L zsh
698     local -a cmdline
699     local -x alcontext
700     local buf com fname format msg default_action
701
702     alcontext='default'
703     buf="${BUFFER}"
704     cmdline=(${(z)BUFFER})
705     com="${cmdline[1]}"
706     fname="_${com}"
707
708     zstyle -t ":acceptline:${alcontext}" rehash \
709         && [[ -z ${commands[$com]} ]]           \
710         && rehash
711
712     if    [[ -n ${reswords[(r)$com]} ]] \
713        || [[ -n ${aliases[$com]}     ]] \
714        || [[ -n ${functions[$com]}   ]] \
715        || [[ -n ${builtins[$com]}    ]] \
716        || [[ -n ${commands[$com]}    ]] ; then
717
718         # there is something sensible to execute, just do it.
719         alcontext='normal'
720         zle Accept-Line
721
722         default_action=$(Accept-Line-getdefault)
723         zstyle -T ":acceptline:${alcontext}" call_default \
724             && zle ${default_action}
725         return
726     fi
727
728     if    [[ -o correct              ]] \
729        || [[ -o correctall           ]] \
730        && [[ -n ${functions[$fname]} ]] ; then
731
732         # nothing there to execute but there is a function called
733         # _command_name; a completion widget. Makes no sense to
734         # call it on the commandline, but the correct{,all} options
735         # will ask for it nevertheless, so warn the user.
736         if [[ ${LASTWIDGET} == 'accept-line' ]] ; then
737             # Okay, we warned the user before, he called us again,
738             # so have it his way.
739             alcontext='force'
740             zle Accept-Line
741
742             default_action=$(Accept-Line-getdefault)
743             zstyle -T ":acceptline:${alcontext}" call_default \
744                 && zle ${default_action}
745             return
746         fi
747
748         # prepare warning message for the user, configurable via zstyle.
749         zstyle -s ":acceptline:${alcontext}" compwarnfmt msg
750
751         if [[ -z ${msg} ]] ; then
752             msg="%c will not execute and completion %f exists."
753         fi
754
755         zformat -f msg "${msg}" "c:${com}" "f:${fname}"
756
757         zle -M -- "${msg}"
758         return
759     elif [[ -n ${buf//[$' \t\n']##/} ]] ; then
760         # If we are here, the commandline contains something that is not
761         # executable, which is neither subject to _command_name correction
762         # and is not empty. might be a variable assignment
763         alcontext='misc'
764         zle Accept-Line
765
766         default_action=$(Accept-Line-getdefault)
767         zstyle -T ":acceptline:${alcontext}" call_default \
768             && zle ${default_action}
769         return
770     fi
771
772     # If we got this far, the commandline only contains whitespace, or is empty.
773     alcontext='empty'
774     zle Accept-Line
775
776     default_action=$(Accept-Line-getdefault)
777     zstyle -T ":acceptline:${alcontext}" call_default \
778         && zle ${default_action}
779 }
780
781 zle -N accept-line
782 zle -N Accept-Line
783
784 # }}}
785
786 # power completion - abbreviation expansion {{{
787 # power completion / abbreviation expansion / buffer expansion
788 # see http://zshwiki.org/home/examples/zleiab for details
789 # less risky than the global aliases but powerful as well
790 # just type the abbreviation key and afterwards ',.' to expand it
791 declare -A abk
792 setopt extendedglob
793 setopt interactivecomments
794 abk=(
795 #   key   # value                  (#d additional doc string)
796 #A# start
797     '...'  '../..'
798     '....' '../../..'
799     'BG'   '& exit'
800     'C'    '| wc -l'
801     'G'    '|& grep --color=auto '
802     'H'    '| head'
803     'Hl'   ' --help |& less -r'    #d (Display help in pager)
804     'L'    '| less'
805     'LL'   '|& less -r'
806     'M'    '| most'
807     'N'    '&>/dev/null'           #d (No Output)
808     'R'    '| tr A-z N-za-m'       #d (ROT13)
809     'SL'   '| sort | less'
810     'S'    '| sort -u'
811     'T'    '| tail'
812     'V'    '|& vim -'
813 #A# end
814     'co'   './configure && make && sudo make install'
815 )
816
817 globalias() {
818     emulate -L zsh
819     setopt extendedglob
820     local MATCH
821
822     if (( NOABBREVIATION > 0 )) ; then
823         LBUFFER="${LBUFFER},."
824         return 0
825     fi
826
827     matched_chars='[.-|_a-zA-Z0-9]#'
828     LBUFFER=${LBUFFER%%(#m)[.-|_a-zA-Z0-9]#}
829     LBUFFER+=${abk[$MATCH]:-$MATCH}
830 }
831
832 zle -N globalias
833 bindkey ",." globalias
834 # }}}
835
836 # {{{ autoloading
837 zrcautoload zmv    # who needs mmv or rename?
838 zrcautoload history-search-end
839
840 # we don't want to quote/espace URLs on our own...
841 # if autoload -U url-quote-magic ; then
842 #    zle -N self-insert url-quote-magic
843 #    zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}='
844 # else
845 #    print 'Notice: no url-quote-magic available :('
846 # fi
847 alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic'
848
849 #m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
850 alias run-help >&/dev/null && unalias run-help
851 for rh in run-help{,-git,-svk,-svn}; do
852     zrcautoload $rh
853 done; unset rh
854
855 # completion system
856 if zrcautoload compinit ; then
857     compinit || print 'Notice: no compinit available :('
858 else
859     print 'Notice: no compinit available :('
860     function zstyle { }
861     function compdef { }
862 fi
863
864 is4 && zrcautoload zed # use ZLE editor to edit a file or function
865
866 is4 && \
867 for mod in complist deltochar mathfunc ; do
868     zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
869 done
870
871 # autoload zsh modules when they are referenced
872 if is4 ; then
873     zmodload -a  zsh/stat    zstat
874     zmodload -a  zsh/zpty    zpty
875     zmodload -ap zsh/mapfile mapfile
876 fi
877
878 if is4 && zrcautoload insert-files && zle -N insert-files ; then
879     #k# Insert files
880     bindkey "^Xf" insert-files # C-x-f
881 fi
882
883 bindkey ' '   magic-space    # also do history expansion on space
884 #k# Trigger menu-complete
885 bindkey '\ei' menu-complete  # menu completion via esc-i
886
887 # press esc-e for editing command line in $EDITOR or $VISUAL
888 if is4 && zrcautoload edit-command-line && zle -N edit-command-line ; then
889     #k# Edit the current line in \kbd{\$EDITOR}
890     bindkey '\ee' edit-command-line
891 fi
892
893 if is4 && [[ -n ${(k)modules[zsh/complist]} ]] ; then
894     #k# menu selection: pick item but stay in the menu
895     bindkey -M menuselect '\e^M' accept-and-menu-complete
896
897     # accept a completion and try to complete again by using menu
898     # completion; very useful with completing directories
899     # by using 'undo' one's got a simple file browser
900     bindkey -M menuselect '^o' accept-and-infer-next-history
901 fi
902
903 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
904 insert-datestamp() { LBUFFER+=${(%):-'%D{%Y-%m-%d}'}; }
905 zle -N insert-datestamp
906
907 #k# Insert a timestamp on the command line (yyyy-mm-dd)
908 bindkey '^Ed' insert-datestamp
909
910 # press esc-m for inserting last typed word again (thanks to caphuso!)
911 insert-last-typed-word() { zle insert-last-word -- 0 -1 };
912 zle -N insert-last-typed-word;
913
914 #k# Insert last typed word
915 bindkey "\em" insert-last-typed-word
916
917 function grml-zsh-fg() {
918   if (( ${#jobstates} )); then
919     zle .push-input
920     [[ -o hist_ignore_space ]] && BUFFER=' ' || BUFFER=''
921     BUFFER="${BUFFER}fg"
922     zle .accept-line
923   else
924     zle -M 'No background jobs. Doing nothing.'
925   fi
926 }
927 zle -N grml-zsh-fg
928 #k# A smart shortcut for \kbd{fg<enter>}
929 bindkey '^z' grml-zsh-fg
930
931 # run command line as user root via sudo:
932 sudo-command-line() {
933     [[ -z $BUFFER ]] && zle up-history
934     if [[ $BUFFER != sudo\ * ]]; then
935         BUFFER="sudo $BUFFER"
936         CURSOR=$(( CURSOR+5 ))
937     fi
938 }
939 zle -N sudo-command-line
940
941 #k# Put the current command line into a \kbd{sudo} call
942 bindkey "^Os" sudo-command-line
943
944 ### jump behind the first word on the cmdline.
945 ### useful to add options.
946 function jump_after_first_word() {
947     local words
948     words=(${(z)BUFFER})
949
950     if (( ${#words} <= 1 )) ; then
951         CURSOR=${#BUFFER}
952     else
953         CURSOR=${#${words[1]}}
954     fi
955 }
956 zle -N jump_after_first_word
957
958 bindkey '^x1' jump_after_first_word
959
960 # }}}
961
962 # {{{ history
963
964 ZSHDIR=$HOME/.zsh
965
966 #v#
967 HISTFILE=$HOME/.zsh_history
968 isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
969 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
970
971 # }}}
972
973 # dirstack handling {{{
974
975 DIRSTACKSIZE=${DIRSTACKSIZE:-20}
976 DIRSTACKFILE=${DIRSTACKFILE:-${HOME}/.zdirs}
977
978 if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
979     dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
980     # "cd -" won't work after login by just setting $OLDPWD, so
981     [[ -d $dirstack[0] ]] && cd $dirstack[0] && cd $OLDPWD
982 fi
983
984 chpwd() {
985     local -ax my_stack
986     my_stack=( ${PWD} ${dirstack} )
987     if is42 ; then
988         builtin print -l ${(u)my_stack} >! ${DIRSTACKFILE}
989     else
990         uprint my_stack >! ${DIRSTACKFILE}
991     fi
992 }
993
994 # }}}
995
996 # directory based profiles {{{
997
998 if is433 ; then
999
1000 CHPWD_PROFILE='default'
1001 function chpwd_profiles() {
1002     # Say you want certain settings to be active in certain directories.
1003     # This is what you want.
1004     #
1005     # zstyle ':chpwd:profiles:/usr/src/grml(|/|/*)'   profile grml
1006     # zstyle ':chpwd:profiles:/usr/src/debian(|/|/*)' profile debian
1007     #
1008     # When that's done and you enter a directory that matches the pattern
1009     # in the third part of the context, a function called chpwd_profile_grml,
1010     # for example, is called (if it exists).
1011     #
1012     # If no pattern matches (read: no profile is detected) the profile is
1013     # set to 'default', which means chpwd_profile_default is attempted to
1014     # be called.
1015     #
1016     # A word about the context (the ':chpwd:profiles:*' stuff in the zstyle
1017     # command) which is used: The third part in the context is matched against
1018     # ${PWD}. That's why using a pattern such as /foo/bar(|/|/*) makes sense.
1019     # Because that way the profile is detected for all these values of ${PWD}:
1020     #   /foo/bar
1021     #   /foo/bar/
1022     #   /foo/bar/baz
1023     # So, if you want to make double damn sure a profile works in /foo/bar
1024     # and everywhere deeper in that tree, just use (|/|/*) and be happy.
1025     #
1026     # The name of the detected profile will be available in a variable called
1027     # 'profile' in your functions. You don't need to do anything, it'll just
1028     # be there.
1029     #
1030     # Then there is the parameter $CHPWD_PROFILE is set to the profile, that
1031     # was is currently active. That way you can avoid running code for a
1032     # profile that is already active, by running code such as the following
1033     # at the start of your function:
1034     #
1035     # function chpwd_profile_grml() {
1036     #     [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
1037     #   ...
1038     # }
1039     #
1040     # The initial value for $CHPWD_PROFILE is 'default'.
1041     #
1042     # Version requirement:
1043     #   This feature requires zsh 4.3.3 or newer.
1044     #   If you use this feature and need to know whether it is active in your
1045     #   current shell, there are several ways to do that. Here are two simple
1046     #   ways:
1047     #
1048     #   a) If knowing if the profiles feature is active when zsh starts is
1049     #      good enough for you, you can put the following snippet into your
1050     #      .zshrc.local:
1051     #
1052     #   (( ${+functions[chpwd_profiles]} )) && print "directory profiles active"
1053     #
1054     #   b) If that is not good enough, and you would prefer to be notified
1055     #      whenever a profile changes, you can solve that by making sure you
1056     #      start *every* profile function you create like this:
1057     #
1058     #   function chpwd_profile_myprofilename() {
1059     #       [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
1060     #       print "chpwd(): Switching to profile: $profile"
1061     #     ...
1062     #   }
1063     #
1064     #      That makes sure you only get notified if a profile is *changed*,
1065     #      not everytime you change directory, which would probably piss
1066     #      you off fairly quickly. :-)
1067     #
1068     # There you go. Now have fun with that.
1069     local -x profile
1070
1071     zstyle -s ":chpwd:profiles:${PWD}" profile profile || profile='default'
1072     if (( ${+functions[chpwd_profile_$profile]} )) ; then
1073         chpwd_profile_${profile}
1074     fi
1075
1076     CHPWD_PROFILE="${profile}"
1077     return 0
1078 }
1079 chpwd_functions=( ${chpwd_functions} chpwd_profiles )
1080
1081 fi # is433
1082
1083 # }}}
1084
1085 # {{{ display battery status on right side of prompt via running 'BATTERY=1 zsh'
1086 if [[ $BATTERY -gt 0 ]] ; then
1087     if ! check_com -c acpi ; then
1088         BATTERY=0
1089     fi
1090 fi
1091
1092 battery() {
1093 if [[ $BATTERY -gt 0 ]] ; then
1094     PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]#Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
1095     if [[ -z "$PERCENT" ]] ; then
1096         PERCENT='acpi not present'
1097     else
1098         if [[ "$PERCENT" -lt 20 ]] ; then
1099             PERCENT="warning: ${PERCENT}%%"
1100         else
1101             PERCENT="${PERCENT}%%"
1102         fi
1103     fi
1104 fi
1105 }
1106 # }}}
1107
1108 # set colors for use in prompts {{{
1109 if zrcautoload colors && colors 2>/dev/null ; then
1110     BLUE="%{${fg[blue]}%}"
1111     RED="%{${fg_bold[red]}%}"
1112     GREEN="%{${fg[green]}%}"
1113     CYAN="%{${fg[cyan]}%}"
1114     MAGENTA="%{${fg[magenta]}%}"
1115     YELLOW="%{${fg[yellow]}%}"
1116     WHITE="%{${fg[white]}%}"
1117     NO_COLOUR="%{${reset_color}%}"
1118 else
1119     BLUE=$'%{\e[1;34m%}'
1120     RED=$'%{\e[1;31m%}'
1121     GREEN=$'%{\e[1;32m%}'
1122     CYAN=$'%{\e[1;36m%}'
1123     WHITE=$'%{\e[1;37m%}'
1124     MAGENTA=$'%{\e[1;35m%}'
1125     YELLOW=$'%{\e[1;33m%}'
1126     NO_COLOUR=$'%{\e[0m%}'
1127 fi
1128
1129 # }}}
1130
1131 # gather version control information for inclusion in a prompt {{{
1132
1133 if ! is41 ; then
1134     # Be quiet about version problems in grml's zshrc as the user cannot disable
1135     # loading vcs_info() as it is *in* the zshrc - as you can see. :-)
1136     # Just unset most probable variables and disable vcs_info altogether.
1137     local -i i
1138     for i in {0..9} ; do
1139         unset VCS_INFO_message_${i}_
1140     done
1141     zstyle ':vcs_info:*' enable false
1142 fi
1143
1144 if zrcautoload vcs_info; then
1145     GRML_VCS_INFO=0
1146     # `vcs_info' in zsh versions 4.3.10 and below have a broken `_realpath'
1147     # function, which can cause a lot of trouble with our directory-based
1148     # profiles. So:
1149     if [[ ${ZSH_VERSION} == 4.3.<-10> ]] ; then
1150         function VCS_INFO_realpath () {
1151             setopt localoptions NO_shwordsplit chaselinks
1152             ( builtin cd -q $1 2> /dev/null && pwd; )
1153         }
1154     fi
1155 else
1156 # I'm not reindenting the whole code below.
1157 GRML_VCS_INFO=1
1158
1159 # The following code is imported from the file 'zsh/functions/vcs_info'
1160 # from <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>,
1161 # which distributed under the same terms as zsh itself.
1162
1163 # we will be using two variables, so let the code know now.
1164 zstyle ':vcs_info:*' max-exports 2
1165
1166 # vcs_info() documentation:
1167 #{{{
1168 # REQUIREMENTS:
1169 #{{{
1170 #     This functionality requires zsh version >= 4.1.*.
1171 #}}}
1172 #
1173 # LOADING:
1174 #{{{
1175 # To load vcs_info(), copy this file to your $fpath[] and do:
1176 #   % autoload -Uz vcs_info && vcs_info
1177 #
1178 # To work, vcs_info() needs 'setopt prompt_subst' in your setup.
1179 #}}}
1180 #
1181 # QUICKSTART:
1182 #{{{
1183 # To get vcs_info() working quickly (including colors), you can do the
1184 # following (assuming, you loaded vcs_info() properly - see above):
1185 #
1186 # % RED=$'%{\e[31m%}'
1187 # % GR=$'%{\e[32m%}'
1188 # % MA=$'%{\e[35m%}'
1189 # % YE=$'%{\e[33m%}'
1190 # % NC=$'%{\e[0m%}'
1191 #
1192 # % zstyle ':vcs_info:*' actionformats \
1193 #       "${MA}(${NC}%s${MA})${YE}-${MA}[${GR}%b${YE}|${RED}%a${MA}]${NC} "
1194 #
1195 # % zstyle ':vcs_info:*' formats       \
1196 #       "${MA}(${NC}%s${MA})${Y}-${MA}[${GR}%b${MA}]${NC}%} "
1197 #
1198 # % zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YE}%r"
1199 #
1200 # % precmd () { vcs_info }
1201 # % PS1='${MA}[${GR}%n${MA}] ${MA}(${RED}%!${MA}) ${YE}%3~ ${VCS_INFO_message_0_}${NC}%# '
1202 #
1203 # Obviously, the las two lines are there for demonstration: You need to
1204 # call vcs_info() from your precmd() function (see 'SPECIAL FUNCTIONS' in
1205 # 'man zshmisc'). Once that is done you need a *single* quoted
1206 # '${VCS_INFO_message_0_}' in your prompt.
1207 #
1208 # Now call the 'vcs_info_printsys' utility from the command line:
1209 #
1210 # % vcs_info_printsys
1211 # # list of supported version control backends:
1212 # # disabled systems are prefixed by a hash sign (#)
1213 # git
1214 # hg
1215 # bzr
1216 # darcs
1217 # svk
1218 # mtn
1219 # svn
1220 # cvs
1221 # cdv
1222 # tla
1223 # # flavours (cannot be used in the disable style; they
1224 # # are disabled with their master [git-svn -> git]):
1225 # git-p4
1226 # git-svn
1227 #
1228 # Ten version control backends as you can see. You may not want all
1229 # of these. Because there is no point in running the code to detect
1230 # systems you do not use. ever. So, there is a way to disable some
1231 # backends altogether:
1232 #
1233 # % zstyle ':vcs_info:*' disable bzr cdv darcs mtn svk tla
1234 #
1235 # If you rerun 'vcs_info_printsys' now, you will see the backends listed
1236 # in the 'disable' style marked as diabled by a hash sign. That means the
1237 # detection of these systems is skipped *completely*. No wasted time there.
1238 #
1239 # For more control, read the reference below.
1240 #}}}
1241 #
1242 # CONFIGURATION:
1243 #{{{
1244 # The vcs_info() feature can be configured via zstyle.
1245 #
1246 # First, the context in which we are working:
1247 #       :vcs_info:<vcs-string>:<user-context>
1248 #
1249 # ...where <vcs-string> is one of:
1250 #   - git, git-svn, git-p4, hg, darcs, bzr, cdv, mtn, svn, cvs, svk or tla.
1251 #
1252 # ...and <user-context> is a freely configurable string, assignable by the
1253 # user as the first argument to vcs_info() (see its description below).
1254 #
1255 # There is are three special values for <vcs-string>: The first is named
1256 # 'init', that is in effect as long as there was no decision what vcs
1257 # backend to use. The second is 'preinit; it is used *before* vcs_info()
1258 # is run, when initializing the data exporting variables. The third
1259 # special value is 'formats' and is used by the 'vcs_info_lastmsg' for
1260 # looking up its styles.
1261 #
1262 # There are two pre-defined values for <user-context>:
1263 #   default  - the one used if none is specified
1264 #   command  - used by vcs_info_lastmsg to lookup its styles.
1265 #
1266 # You may *not* use 'print_systems_' as a user-context string, because it
1267 # is used internally.
1268 #
1269 # You can of course use ':vcs_info:*' to match all VCSs in all
1270 # user-contexts at once.
1271 #
1272 # Another special context is 'formats', which is used by the
1273 # vcs_info_lastmsg() utility function (see below).
1274 #
1275 #
1276 # This is a description of all styles, that are looked up:
1277 #   formats             - A list of formats, used when actionformats is not
1278 #                         used (which is most of the time).
1279 #   actionformats       - A list of formats, used if a there is a special
1280 #                         action going on in your current repository;
1281 #                         (like an interactive rebase or a merge conflict)
1282 #   branchformat        - Some backends replace %b in the formats and
1283 #                         actionformats styles above, not only by a branch
1284 #                         name but also by a revision number. This style
1285 #                         let's you modify how that string should look like.
1286 #   nvcsformats         - These "formats" are exported, when we didn't detect
1287 #                         a version control system for the current directory.
1288 #                         This is useful, if you want vcs_info() to completely
1289 #                         take over the generation of your prompt.
1290 #                         You would do something like
1291 #                           PS1='${VCS_INFO_message_0_}'
1292 #                         to accomplish that.
1293 #   max-exports         - Defines the maximum number if VCS_INFO_message_*_
1294 #                         variables vcs_info() will export.
1295 #   enable              - Checked in the 'init' context. If set to false,
1296 #                         vcs_info() will do nothing.
1297 #   disable             - Provide a list of systems, you don't want
1298 #                         the vcs_info() to check for repositories
1299 #                         (checked in the 'init' context, too).
1300 #   disable-patterns    - A list of patterns that are checked against $PWD.
1301 #                         If the pattern matches, vcs_info will be disabled.
1302 #                         Say, ~/.zsh is a directory under version control,
1303 #                         in which you do not want vcs_info to be active, do:
1304 #                         zstyle ':vcs_info:*' disable-patterns "$HOME/.zsh+(|/*)"
1305 #   use-simple          - If there are two different ways of gathering
1306 #                         information, you can select the simpler one
1307 #                         by setting this style to true; the default
1308 #                         is to use the not-that-simple code, which is
1309 #                         potentially a lot slower but might be more
1310 #                         accurate in all possible cases.
1311 #   use-prompt-escapes  - determines if we assume that the assembled
1312 #                         string from vcs_info() includes prompt escapes.
1313 #                         (Used by vcs_info_lastmsg().
1314 #
1315 # The use-simple style is only available for the bzr backend.
1316 #
1317 # The default values for these in all contexts are:
1318 #   formats             " (%s)-[%b|%a]-"
1319 #   actionformats       " (%s)-[%b]-"
1320 #   branchformat        "%b:%r" (for bzr, svn and svk)
1321 #   nvcsformats         ""
1322 #   max-exports         2
1323 #   enable              true
1324 #   disable             (empty list)
1325 #   disable-patterns    (empty list)
1326 #   use-simple          false
1327 #   use-prompt-escapes  true
1328 #
1329 #
1330 # In normal formats and actionformats, the following replacements
1331 # are done:
1332 #   %s  - The vcs in use (git, hg, svn etc.)
1333 #   %b  - Information about the current branch.
1334 #   %a  - An identifier, that describes the action.
1335 #         Only makes sense in actionformats.
1336 #   %R  - base directory of the repository.
1337 #   %r  - repository name
1338 #         If %R is '/foo/bar/repoXY', %r is 'repoXY'.
1339 #   %S  - subdirectory within a repository. if $PWD is
1340 #         '/foo/bar/reposXY/beer/tasty', %S is 'beer/tasty'.
1341 #
1342 #
1343 # In branchformat these replacements are done:
1344 #   %b  - the branch name
1345 #   %r  - the current revision number
1346 #
1347 # Not all vcs backends have to support all replacements.
1348 # nvcsformat does not perform *any* replacements. It is just a string.
1349 #}}}
1350 #
1351 # ODDITIES:
1352 #{{{
1353 # If you want to use the %b (bold off) prompt expansion in 'formats', which
1354 # expands %b itself, use %%b. That will cause the vcs_info() expansion to
1355 # replace %%b with %b. So zsh's prompt expansion mechanism can handle it.
1356 # Similarly, to hand down %b from branchformat, use %%%%b. Sorry for this
1357 # inconvenience, but it cannot be easily avoided. Luckily we do not clash
1358 # with a lot of prompt expansions and this only needs to be done for those.
1359 # See 'man zshmisc' for details about EXPANSION OF PROMPT SEQUENCES.
1360 #}}}
1361 #
1362 # FUNCTION DESCRIPTIONS (public API):
1363 #{{{
1364 #   vcs_info()
1365 #       The main function, that runs all backends and assembles
1366 #       all data into ${VCS_INFO_message_*_}. This is the function
1367 #       you want to call from precmd() if you want to include
1368 #       up-to-date information in your prompt (see VARIABLE
1369 #       DESCRIPTION below).
1370 #
1371 #   vcs_info_printsys()
1372 #       Prints a list of all supported version control systems.
1373 #       Useful to find out possible contexts (and which of them are enabled)
1374 #       or values for the 'disable' style.
1375 #
1376 #   vcs_info_lastmsg()
1377 #       Outputs the last ${VCS_INFO_message_*_} value. Takes into account
1378 #       the value of the use-prompt-escapes style in ':vcs_info:formats'.
1379 #       It also only prints max-exports values.
1380 #
1381 # All functions named VCS_INFO_* are for internal use only.
1382 #}}}
1383 #
1384 # VARIABLE DESCRIPTION:
1385 #{{{
1386 #   ${VCS_INFO_message_N_}    (Note the trailing underscore)
1387 #       Where 'N' is an integer, eg: VCS_INFO_message_0_
1388 #       These variables are the storage for the informational message the
1389 #       last vcs_info() call has assembled. These are strongly connected
1390 #       to the formats, actionformats and nvcsformats styles described
1391 #       above. Those styles are lists. the first member of that list gets
1392 #       expanded into ${VCS_INFO_message_0_}, the second into
1393 #       ${VCS_INFO_message_1_} and the Nth into ${VCS_INFO_message_N-1_}.
1394 #       These parameters are exported into the environment.
1395 #       (See the max-exports style above.)
1396 #}}}
1397 #
1398 # EXAMPLES:
1399 #{{{
1400 #   Don't use vcs_info at all (even though it's in your prompt):
1401 #   % zstyle ':vcs_info:*' enable false
1402 #
1403 #   Disable the backends for bzr and svk:
1404 #   % zstyle ':vcs_info:*' disable bzr svk
1405 #
1406 #   Provide a special formats for git:
1407 #   % zstyle ':vcs_info:git:*' formats       ' GIT, BABY! [%b]'
1408 #   % zstyle ':vcs_info:git:*' actionformats ' GIT ACTION! [%b|%a]'
1409 #
1410 #   Use the quicker bzr backend (if you do, please report if it does
1411 #   the-right-thing[tm] - thanks):
1412 #   % zstyle ':vcs_info:bzr:*' use-simple true
1413 #
1414 #   Display the revision number in yellow for bzr and svn:
1415 #   % zstyle ':vcs_info:(svn|bzr):*' branchformat '%b%{'${fg[yellow]}'%}:%r'
1416 #
1417 # If you want colors, make sure you enclose the color codes in %{...%},
1418 # if you want to use the string provided by vcs_info() in prompts.
1419 #
1420 # Here is how to print the vcs infomation as a command:
1421 #   % alias vcsi='vcs_info command; vcs_info_lastmsg'
1422 #
1423 #   This way, you can even define different formats for output via
1424 #   vcs_info_lastmsg() in the ':vcs_info:command:*' namespace.
1425 #}}}
1426 #}}}
1427 # utilities
1428 VCS_INFO_adjust () { #{{{
1429     [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
1430     return 0
1431 }
1432 # }}}
1433 VCS_INFO_check_com () { #{{{
1434     (( ${+commands[$1]} )) && [[ -x ${commands[$1]} ]] && return 0
1435     return 1
1436 }
1437 # }}}
1438 VCS_INFO_formats () { # {{{
1439     setopt localoptions noksharrays
1440     local action=$1 branch=$2 base=$3
1441     local msg
1442     local -i i
1443
1444     if [[ -n ${action} ]] ; then
1445         zstyle -a ":vcs_info:${vcs}:${usercontext}" actionformats msgs
1446         (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b|%a]-'
1447     else
1448         zstyle -a ":vcs_info:${vcs}:${usercontext}" formats msgs
1449         (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b]-'
1450     fi
1451
1452     (( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=()
1453     for i in {1..${#msgs}} ; do
1454         zformat -f msg ${msgs[$i]}                      \
1455                         a:${action}                     \
1456                         b:${branch}                     \
1457                         r:${base:t}                     \
1458                         s:${vcs}                        \
1459                         R:${base}                       \
1460                         S:"$(VCS_INFO_reposub ${base})"
1461         msgs[$i]=${msg}
1462     done
1463     return 0
1464 }
1465 # }}}
1466 VCS_INFO_maxexports () { #{{{
1467     zstyle -s ":vcs_info:${vcs}:${usercontext}" "max-exports" maxexports || maxexports=2
1468     if [[ ${maxexports} != <-> ]] || (( maxexports < 1 )); then
1469         printf 'vcs_info(): expecting numeric arg >= 1 for max-exports (got %s).\n' ${maxexports}
1470         printf 'Defaulting to 2.\n'
1471         maxexports=2
1472     fi
1473 }
1474 # }}}
1475 VCS_INFO_nvcsformats () { #{{{
1476     setopt localoptions noksharrays
1477     local c v
1478
1479     if [[ $1 == 'preinit' ]] ; then
1480         c=default
1481         v=preinit
1482     fi
1483     zstyle -a ":vcs_info:${v:-$vcs}:${c:-$usercontext}" nvcsformats msgs
1484     (( ${#msgs} > maxexports )) && msgs[${maxexports},-1]=()
1485 }
1486 # }}}
1487 VCS_INFO_realpath () { #{{{
1488     # a portable 'readlink -f'
1489     # forcing a subshell, to ensure chpwd() is not removed
1490     # from the calling shell (if VCS_INFO_realpath() is called
1491     # manually).
1492     (
1493         (( ${+functions[chpwd]} )) && unfunction chpwd
1494         setopt chaselinks
1495         cd $1 2>/dev/null && pwd
1496     )
1497 }
1498 # }}}
1499 VCS_INFO_reposub () { #{{{
1500     setopt localoptions extendedglob
1501     local base=${1%%/##}
1502
1503     [[ ${PWD} == ${base}/* ]] || {
1504         printf '.'
1505         return 1
1506     }
1507     printf '%s' ${PWD#$base/}
1508     return 0
1509 }
1510 # }}}
1511 VCS_INFO_set () { #{{{
1512     setopt localoptions noksharrays
1513     local -i i j
1514
1515     if [[ $1 == '--clear' ]] ; then
1516         for i in {0..9} ; do
1517             unset VCS_INFO_message_${i}_
1518         done
1519     fi
1520     if [[ $1 == '--nvcs' ]] ; then
1521         [[ $2 == 'preinit' ]] && (( maxexports == 0 )) && (( maxexports = 1 ))
1522         for i in {0..$((maxexports - 1))} ; do
1523             typeset -gx VCS_INFO_message_${i}_=
1524         done
1525         VCS_INFO_nvcsformats $2
1526     fi
1527
1528     (( ${#msgs} - 1 < 0 )) && return 0
1529     for i in {0..$(( ${#msgs} - 1 ))} ; do
1530         (( j = i + 1 ))
1531         typeset -gx VCS_INFO_message_${i}_=${msgs[$j]}
1532     done
1533     return 0
1534 }
1535 # }}}
1536 # information gathering
1537 VCS_INFO_bzr_get_data () { # {{{
1538     setopt localoptions noksharrays
1539     local bzrbase bzrbr
1540     local -a bzrinfo
1541
1542     if zstyle -t ":vcs_info:${vcs}:${usercontext}" "use-simple" ; then
1543         bzrbase=${vcs_comm[basedir]}
1544         bzrinfo[2]=${bzrbase:t}
1545         if [[ -f ${bzrbase}/.bzr/branch/last-revision ]] ; then
1546             bzrinfo[1]=$(< ${bzrbase}/.bzr/branch/last-revision)
1547             bzrinfo[1]=${${bzrinfo[1]}%% *}
1548         fi
1549     else
1550         bzrbase=${${(M)${(f)"$( bzr info )"}:# ##branch\ root:*}/*: ##/}
1551         bzrinfo=( ${${${(M)${(f)"$( bzr version-info )"}:#(#s)(revno|branch-nick)*}/*: /}/*\//} )
1552         bzrbase="$(VCS_INFO_realpath ${bzrbase})"
1553     fi
1554
1555     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat bzrbr || bzrbr="%b:%r"
1556     zformat -f bzrbr "${bzrbr}" "b:${bzrinfo[2]}" "r:${bzrinfo[1]}"
1557     VCS_INFO_formats '' "${bzrbr}" "${bzrbase}"
1558     return 0
1559 }
1560 # }}}
1561 VCS_INFO_cdv_get_data () { # {{{
1562     local cdvbase
1563
1564     cdvbase=${vcs_comm[basedir]}
1565     VCS_INFO_formats '' "${cdvbase:t}" "${cdvbase}"
1566     return 0
1567 }
1568 # }}}
1569 VCS_INFO_cvs_get_data () { # {{{
1570     local cvsbranch cvsbase basename
1571
1572     cvsbase="."
1573     while [[ -d "${cvsbase}/../CVS" ]]; do
1574         cvsbase="${cvsbase}/.."
1575     done
1576     cvsbase="$(VCS_INFO_realpath ${cvsbase})"
1577     cvsbranch=$(< ./CVS/Repository)
1578     basename=${cvsbase:t}
1579     cvsbranch=${cvsbranch##${basename}/}
1580     [[ -z ${cvsbranch} ]] && cvsbranch=${basename}
1581     VCS_INFO_formats '' "${cvsbranch}" "${cvsbase}"
1582     return 0
1583 }
1584 # }}}
1585 VCS_INFO_darcs_get_data () { # {{{
1586     local darcsbase
1587
1588     darcsbase=${vcs_comm[basedir]}
1589     VCS_INFO_formats '' "${darcsbase:t}" "${darcsbase}"
1590     return 0
1591 }
1592 # }}}
1593 VCS_INFO_git_getaction () { #{{{
1594     local gitaction='' gitdir=$1
1595     local tmp
1596
1597     for tmp in "${gitdir}/rebase-apply" \
1598                "${gitdir}/rebase"       \
1599                "${gitdir}/../.dotest" ; do
1600         if [[ -d ${tmp} ]] ; then
1601             if   [[ -f "${tmp}/rebasing" ]] ; then
1602                 gitaction="rebase"
1603             elif [[ -f "${tmp}/applying" ]] ; then
1604                 gitaction="am"
1605             else
1606                 gitaction="am/rebase"
1607             fi
1608             printf '%s' ${gitaction}
1609             return 0
1610         fi
1611     done
1612
1613     for tmp in "${gitdir}/rebase-merge/interactive" \
1614                "${gitdir}/.dotest-merge/interactive" ; do
1615         if [[ -f "${tmp}" ]] ; then
1616             printf '%s' "rebase-i"
1617             return 0
1618         fi
1619     done
1620
1621     for tmp in "${gitdir}/rebase-merge" \
1622                "${gitdir}/.dotest-merge" ; do
1623         if [[ -d "${tmp}" ]] ; then
1624             printf '%s' "rebase-m"
1625             return 0
1626         fi
1627     done
1628
1629     if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1630         printf '%s' "merge"
1631         return 0
1632     fi
1633
1634     if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
1635         printf '%s' "bisect"
1636         return 0
1637     fi
1638     return 1
1639 }
1640 # }}}
1641 VCS_INFO_git_getbranch () { #{{{
1642     local gitbranch gitdir=$1 tmp actiondir
1643     local gitsymref='git symbolic-ref HEAD'
1644
1645     actiondir=''
1646     for tmp in "${gitdir}/rebase-apply" \
1647                "${gitdir}/rebase"       \
1648                "${gitdir}/../.dotest"; do
1649         if [[ -d ${tmp} ]]; then
1650             actiondir=${tmp}
1651             break
1652         fi
1653     done
1654     if [[ -n ${actiondir} ]]; then
1655         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1656         [[ -z ${gitbranch} ]] && [[ -r ${actiondir}/head-name ]] \
1657             && gitbranch="$(< ${actiondir}/head-name)"
1658
1659     elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1660         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1661         [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/MERGE_HEAD)"
1662
1663     elif [[ -d "${gitdir}/rebase-merge" ]] ; then
1664         gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
1665
1666     elif [[ -d "${gitdir}/.dotest-merge" ]] ; then
1667         gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
1668
1669     else
1670         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1671
1672         if [[ $? -ne 0 ]] ; then
1673             gitbranch="refs/tags/$(git describe --exact-match HEAD 2>/dev/null)"
1674
1675             if [[ $? -ne 0 ]] ; then
1676                 gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
1677             fi
1678         fi
1679     fi
1680
1681     printf '%s' "${gitbranch##refs/[^/]##/}"
1682     return 0
1683 }
1684 # }}}
1685 VCS_INFO_git_get_data () { # {{{
1686     setopt localoptions extendedglob
1687     local gitdir gitbase gitbranch gitaction
1688
1689     gitdir=${vcs_comm[gitdir]}
1690     gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"
1691
1692     if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
1693         return 1
1694     fi
1695
1696     VCS_INFO_adjust
1697     gitaction="$(VCS_INFO_git_getaction ${gitdir})"
1698     gitbase=${PWD%/${$( git rev-parse --show-prefix )%/##}}
1699     VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}"
1700     return 0
1701 }
1702 # }}}
1703 VCS_INFO_hg_get_data () { # {{{
1704     local hgbranch hgbase file
1705
1706     hgbase=${vcs_comm[basedir]}
1707
1708     file="${hgbase}/.hg/branch"
1709     if [[ -r ${file} ]] ; then
1710         hgbranch=$(< ${file})
1711     else
1712         hgbranch='default'
1713     fi
1714
1715     VCS_INFO_formats '' "${hgbranch}" "${hgbase}"
1716     return 0
1717 }
1718 # }}}
1719 VCS_INFO_mtn_get_data () { # {{{
1720     local mtnbranch mtnbase
1721
1722     mtnbase=${vcs_comm[basedir]}
1723     mtnbranch=${${(M)${(f)"$( mtn status )"}:#(#s)Current branch:*}/*: /}
1724     VCS_INFO_formats '' "${mtnbranch}" "${mtnbase}"
1725     return 0
1726 }
1727 # }}}
1728 VCS_INFO_svk_get_data () { # {{{
1729     local svkbranch svkbase
1730
1731     svkbase=${vcs_comm[basedir]}
1732     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat svkbranch || svkbranch="%b:%r"
1733     zformat -f svkbranch "${svkbranch}" "b:${vcs_comm[branch]}" "r:${vcs_comm[revision]}"
1734     VCS_INFO_formats '' "${svkbranch}" "${svkbase}"
1735     return 0
1736 }
1737 # }}}
1738 VCS_INFO_svn_get_data () { # {{{
1739     setopt localoptions noksharrays
1740     local svnbase svnbranch
1741     local -a svninfo
1742
1743     svnbase="."
1744     while [[ -d "${svnbase}/../.svn" ]]; do
1745         svnbase="${svnbase}/.."
1746     done
1747     svnbase="$(VCS_INFO_realpath ${svnbase})"
1748     svninfo=( ${${${(M)${(f)"$( svn info )"}:#(#s)(URL|Revision)*}/*: /}/*\//} )
1749
1750     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat svnbranch || svnbranch="%b:%r"
1751     zformat -f svnbranch "${svnbranch}" "b:${svninfo[1]}" "r:${svninfo[2]}"
1752     VCS_INFO_formats '' "${svnbranch}" "${svnbase}"
1753     return 0
1754 }
1755 # }}}
1756 VCS_INFO_tla_get_data () { # {{{
1757     local tlabase tlabranch
1758
1759     tlabase="$(VCS_INFO_realpath ${vcs_comm[basedir]})"
1760     # tree-id gives us something like 'foo@example.com/demo--1.0--patch-4', so:
1761     tlabranch=${${"$( tla tree-id )"}/*\//}
1762     VCS_INFO_formats '' "${tlabranch}" "${tlabase}"
1763     return 0
1764 }
1765 # }}}
1766 # detection
1767 VCS_INFO_detect_by_dir() { #{{{
1768     local dirname=$1
1769     local basedir="." realbasedir
1770
1771     realbasedir="$(VCS_INFO_realpath ${basedir})"
1772     while [[ ${realbasedir} != '/' ]]; do
1773         [[ -r ${realbasedir} ]] || return 1
1774         if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
1775             [[ -d ${basedir}/${dirname} ]] && \
1776             [[ -e ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
1777                 break
1778         else
1779             [[ -d ${basedir}/${dirname} ]] && break
1780         fi
1781
1782         basedir=${basedir}/..
1783         realbasedir="$(VCS_INFO_realpath ${basedir})"
1784     done
1785
1786     [[ ${realbasedir} == "/" ]] && return 1
1787     vcs_comm[basedir]=${realbasedir}
1788     return 0
1789 }
1790 # }}}
1791 VCS_INFO_bzr_detect() { #{{{
1792     VCS_INFO_check_com bzr || return 1
1793     vcs_comm[detect_need_file]=branch/format
1794     VCS_INFO_detect_by_dir '.bzr'
1795     return $?
1796 }
1797 # }}}
1798 VCS_INFO_cdv_detect() { #{{{
1799     VCS_INFO_check_com cdv || return 1
1800     vcs_comm[detect_need_file]=format
1801     VCS_INFO_detect_by_dir '.cdv'
1802     return $?
1803 }
1804 # }}}
1805 VCS_INFO_cvs_detect() { #{{{
1806     VCS_INFO_check_com cvs || return 1
1807     [[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
1808     return 1
1809 }
1810 # }}}
1811 VCS_INFO_darcs_detect() { #{{{
1812     VCS_INFO_check_com darcs || return 1
1813     vcs_comm[detect_need_file]=format
1814     VCS_INFO_detect_by_dir '_darcs'
1815     return $?
1816 }
1817 # }}}
1818 VCS_INFO_git_detect() { #{{{
1819     if VCS_INFO_check_com git && git rev-parse --is-inside-work-tree &> /dev/null ; then
1820         vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
1821         if   [[ -d ${vcs_comm[gitdir]}/svn ]]             ; then vcs_comm[overwrite_name]='git-svn'
1822         elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
1823         return 0
1824     fi
1825     return 1
1826 }
1827 # }}}
1828 VCS_INFO_hg_detect() { #{{{
1829     VCS_INFO_check_com hg || return 1
1830     vcs_comm[detect_need_file]=store
1831     VCS_INFO_detect_by_dir '.hg'
1832     return $?
1833 }
1834 # }}}
1835 VCS_INFO_mtn_detect() { #{{{
1836     VCS_INFO_check_com mtn || return 1
1837     vcs_comm[detect_need_file]=revision
1838     VCS_INFO_detect_by_dir '_MTN'
1839     return $?
1840 }
1841 # }}}
1842 VCS_INFO_svk_detect() { #{{{
1843     setopt localoptions noksharrays extendedglob
1844     local -a info
1845     local -i fhash
1846     fhash=0
1847
1848     VCS_INFO_check_com svk || return 1
1849     [[ -f ~/.svk/config ]] || return 1
1850
1851     # This detection function is a bit different from the others.
1852     # We need to read svk's config file to detect a svk repository
1853     # in the first place. Therefore, we'll just proceed and read
1854     # the other information, too. This is more then any of the
1855     # other detections do but this takes only one file open for
1856     # svk at most. VCS_INFO_svk_get_data() get simpler, too. :-)
1857     while IFS= read -r line ; do
1858         if [[ -n ${vcs_comm[basedir]} ]] ; then
1859             line=${line## ##}
1860             [[ ${line} == depotpath:* ]] && vcs_comm[branch]=${line##*/}
1861             [[ ${line} == revision:* ]] && vcs_comm[revision]=${line##*[[:space:]]##}
1862             [[ -n ${vcs_comm[branch]} ]] && [[ -n ${vcs_comm[revision]} ]] && break
1863             continue
1864         fi
1865         (( fhash > 0 )) && [[ ${line} == '  '[^[:space:]]*:* ]] && break
1866         [[ ${line} == '  hash:'* ]] && fhash=1 && continue
1867         (( fhash == 0 )) && continue
1868         [[ ${PWD}/ == ${${line## ##}%:*}/* ]] && vcs_comm[basedir]=${${line## ##}%:*}
1869     done < ~/.svk/config
1870
1871     [[ -n ${vcs_comm[basedir]} ]]  && \
1872     [[ -n ${vcs_comm[branch]} ]]   && \
1873     [[ -n ${vcs_comm[revision]} ]] && return 0
1874     return 1
1875 }
1876 # }}}
1877 VCS_INFO_svn_detect() { #{{{
1878     VCS_INFO_check_com svn || return 1
1879     [[ -d ".svn" ]] && return 0
1880     return 1
1881 }
1882 # }}}
1883 VCS_INFO_tla_detect() { #{{{
1884     VCS_INFO_check_com tla || return 1
1885     vcs_comm[basedir]="$(tla tree-root 2> /dev/null)" && return 0
1886     return 1
1887 }
1888 # }}}
1889 # public API
1890 vcs_info_printsys () { # {{{
1891     vcs_info print_systems_
1892 }
1893 # }}}
1894 vcs_info_lastmsg () { # {{{
1895     emulate -L zsh
1896     local -i i
1897
1898     VCS_INFO_maxexports
1899     for i in {0..$((maxexports - 1))} ; do
1900         printf '$VCS_INFO_message_%d_: "' $i
1901         if zstyle -T ':vcs_info:formats:command' use-prompt-escapes ; then
1902             print -nP ${(P)${:-VCS_INFO_message_${i}_}}
1903         else
1904             print -n ${(P)${:-VCS_INFO_message_${i}_}}
1905         fi
1906         printf '"\n'
1907     done
1908 }
1909 # }}}
1910 vcs_info () { # {{{
1911     emulate -L zsh
1912     setopt extendedglob
1913
1914     [[ -r . ]] || return 1
1915
1916     local pat
1917     local -i found
1918     local -a VCSs disabled dps
1919     local -x vcs usercontext
1920     local -ix maxexports
1921     local -ax msgs
1922     local -Ax vcs_comm
1923
1924     vcs="init"
1925     VCSs=(git hg bzr darcs svk mtn svn cvs cdv tla)
1926     case $1 in
1927         (print_systems_)
1928             zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable" disabled
1929             print -l '# list of supported version control backends:' \
1930                      '# disabled systems are prefixed by a hash sign (#)'
1931             for vcs in ${VCSs} ; do
1932                 [[ -n ${(M)disabled:#${vcs}} ]] && printf '#'
1933                 printf '%s\n' ${vcs}
1934             done
1935             print -l '# flavours (cannot be used in the disable style; they' \
1936                      '# are disabled with their master [git-svn -> git]):'   \
1937                      git-{p4,svn}
1938             return 0
1939             ;;
1940         ('')
1941             [[ -z ${usercontext} ]] && usercontext=default
1942             ;;
1943         (*) [[ -z ${usercontext} ]] && usercontext=$1
1944             ;;
1945     esac
1946
1947     zstyle -T ":vcs_info:${vcs}:${usercontext}" "enable" || {
1948         [[ -n ${VCS_INFO_message_0_} ]] && VCS_INFO_set --clear
1949         return 0
1950     }
1951     zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable" disabled
1952
1953     zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable-patterns" dps
1954     for pat in ${dps} ; do
1955         if [[ ${PWD} == ${~pat} ]] ; then
1956             [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --clear
1957             return 0
1958         fi
1959     done
1960
1961     VCS_INFO_maxexports
1962
1963     (( found = 0 ))
1964     for vcs in ${VCSs} ; do
1965         [[ -n ${(M)disabled:#${vcs}} ]] && continue
1966         vcs_comm=()
1967         VCS_INFO_${vcs}_detect && (( found = 1 )) && break
1968     done
1969
1970     (( found == 0 )) && {
1971         VCS_INFO_set --nvcs
1972         return 0
1973     }
1974
1975     VCS_INFO_${vcs}_get_data || {
1976         VCS_INFO_set --nvcs
1977         return 1
1978     }
1979
1980     VCS_INFO_set
1981     return 0
1982 }
1983
1984 VCS_INFO_set --nvcs preinit
1985 # }}}
1986
1987 fi
1988
1989 # Change vcs_info formats for the grml prompt. The 2nd format sets up
1990 # $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title.
1991 # TODO: The included vcs_info() version still uses $VCS_INFO_message_N_.
1992 #       That needs to be the use of $VCS_INFO_message_N_ needs to be changed
1993 #       to $vcs_info_msg_N_ as soon as we use the included version.
1994 if [[ "$TERM" == dumb ]] ; then
1995     zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] " "zsh: %r"
1996     zstyle ':vcs_info:*' formats       "(%s%)-[%b] "    "zsh: %r"
1997 else
1998     # these are the same, just with a lot of colours:
1999     zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOUR} " \
2000                                        "zsh: %r"
2001     zstyle ':vcs_info:*' formats       "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOUR}%} " \
2002                                        "zsh: %r"
2003     zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r"
2004 fi
2005
2006 if [[ -o restricted ]]; then
2007     zstyle ':vcs_info:*' enable false
2008 fi
2009
2010 # }}}
2011
2012 # command not found handling {{{
2013
2014 (( ${COMMAND_NOT_FOUND} == 1 )) &&
2015 function command_not_found_handler() {
2016     emulate -L zsh
2017     if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then
2018         ${GRML_ZSH_CNF_HANDLER} $1
2019     fi
2020     return 1
2021 }
2022
2023 # }}}
2024
2025 # {{{ set prompt
2026 if zrcautoload promptinit && promptinit 2>/dev/null ; then
2027     promptinit # people should be able to use their favourite prompt
2028 else
2029     print 'Notice: no promptinit available :('
2030 fi
2031
2032 setopt prompt_subst
2033
2034 # make sure to use right prompt only when not running a command
2035 is41 && setopt transient_rprompt
2036
2037
2038 function ESC_print () {
2039     info_print $'\ek' $'\e\\' "$@"
2040 }
2041 function set_title () {
2042     info_print  $'\e]0;' $'\a' "$@"
2043 }
2044
2045 function info_print () {
2046     local esc_begin esc_end
2047     esc_begin="$1"
2048     esc_end="$2"
2049     shift 2
2050     printf '%s' ${esc_begin}
2051     printf '%s' "$*"
2052     printf '%s' "${esc_end}"
2053 }
2054
2055 # TODO: revise all these NO* variables and especially their documentation
2056 #       in zsh-help() below.
2057 is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
2058     [[ $NOPRECMD -gt 0 ]] && return 0
2059     # update VCS information
2060     vcs_info
2061
2062     if [[ $TERM == screen* ]] ; then
2063         if [[ -n ${VCS_INFO_message_1_} ]] ; then
2064             ESC_print ${VCS_INFO_message_1_}
2065         elif [[ -n ${vcs_info_msg_1_} ]] ; then
2066             ESC_print ${vcs_info_msg_1_}
2067         else
2068             ESC_print "zsh"
2069         fi
2070     fi
2071     # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
2072     if [[ $DONTSETRPROMPT -eq 0 ]] ; then
2073         if [[ $BATTERY -gt 0 ]] ; then
2074             # update battery (dropped into $PERCENT) information
2075             battery
2076             RPROMPT="%(?..:() ${PERCENT}"
2077         else
2078             RPROMPT="%(?..:() "
2079         fi
2080     fi
2081     # adjust title of xterm
2082     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
2083     [[ ${NOTITLE} -gt 0 ]] && return 0
2084     case $TERM in
2085         (xterm*|rxvt*)
2086             set_title ${(%):-"%n@%m: %~"}
2087             ;;
2088     esac
2089 }
2090
2091 # preexec() => a function running before every command
2092 is4 && [[ $NOPRECMD -eq 0 ]] && \
2093 preexec () {
2094     [[ $NOPRECMD -gt 0 ]] && return 0
2095 # set hostname if not running on host with name 'grml'
2096     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
2097        NAME="@$HOSTNAME"
2098     fi
2099 # get the name of the program currently running and hostname of local machine
2100 # set screen window title if running in a screen
2101     if [[ "$TERM" == screen* ]] ; then
2102         # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]}       # don't use hostname
2103         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname
2104         ESC_print ${CMD}
2105     fi
2106 # adjust title of xterm
2107     [[ ${NOTITLE} -gt 0 ]] && return 0
2108     case $TERM in
2109         (xterm*|rxvt*)
2110             set_title "${(%):-"%n@%m:"}" "$1"
2111             ;;
2112     esac
2113 }
2114
2115 EXITCODE="%(?..%?%1v )"
2116 PS2='\`%_> '      # secondary prompt, printed when the shell needs more information to complete a command.
2117 PS3='?# '         # selection prompt used within a select loop.
2118 PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
2119
2120 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
2121 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
2122     debian_chroot=$(cat /etc/debian_chroot)
2123 fi
2124
2125 # don't use colors on dumb terminals (like emacs):
2126 if [[ "$TERM" == dumb ]] ; then
2127     PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< "
2128 else
2129     # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt
2130     # set variable identifying the chroot you work in (used in the prompt below)
2131     if [[ $GRMLPROMPT -gt 0 ]] ; then
2132         PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D
2133 ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "
2134     else
2135         # This assembles the primary prompt string
2136         if (( EUID != 0 )); then
2137             PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "
2138         else
2139             PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "
2140         fi
2141     fi
2142 fi
2143
2144 if (( GRML_VCS_INFO )); then
2145     PROMPT="${PROMPT}"'${VCS_INFO_message_0_}'"%# "
2146 else
2147     PROMPT="${PROMPT}"'${vcs_info_msg_0_}'"%# "
2148 fi
2149
2150 # if we are inside a grml-chroot set a specific prompt theme
2151 if [[ -n "$GRML_CHROOT" ]] ; then
2152     PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# "
2153 fi
2154 # }}}
2155
2156 # {{{ 'hash' some often used directories
2157 #d# start
2158 hash -d deb=/var/cache/apt/archives
2159 hash -d doc=/usr/share/doc
2160 hash -d linux=/lib/modules/$(command uname -r)/build/
2161 hash -d log=/var/log
2162 hash -d slog=/var/log/syslog
2163 hash -d src=/usr/src
2164 hash -d templ=/usr/share/doc/grml-templates
2165 hash -d tt=/usr/share/doc/texttools-doc
2166 hash -d www=/var/www
2167 #d# end
2168 # }}}
2169
2170 # {{{ some aliases
2171 if check_com -c screen ; then
2172     if [[ $UID -eq 0 ]] ; then
2173         [[ -r /etc/grml/screenrc ]] && alias screen="${commands[screen]} -c /etc/grml/screenrc"
2174     elif [[ -r $HOME/.screenrc ]] ; then
2175         alias screen="${commands[screen]} -c $HOME/.screenrc"
2176     else
2177         if [[ -r /etc/grml/screenrc_grml ]]; then
2178             alias screen="${commands[screen]} -c /etc/grml/screenrc_grml"
2179         else
2180             [[ -r /etc/grml/screenrc ]] && alias screen="${commands[screen]} -c /etc/grml/screenrc"
2181         fi
2182     fi
2183 fi
2184
2185 # do we have GNU ls with color-support?
2186 if ls --help 2>/dev/null | grep -- --color= >/dev/null && [[ "$TERM" != dumb ]] ; then
2187     #a1# execute \kbd{@a@}:\quad ls with colors
2188     alias ls='ls -b -CF --color=auto'
2189     #a1# execute \kbd{@a@}:\quad list all files, with colors
2190     alias la='ls -la --color=auto'
2191     #a1# long colored list, without dotfiles (@a@)
2192     alias ll='ls -l --color=auto'
2193     #a1# long colored list, human readable sizes (@a@)
2194     alias lh='ls -hAl --color=auto'
2195     #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
2196     alias l='ls -lF --color=auto'
2197 else
2198     alias ls='ls -b -CF'
2199     alias la='ls -la'
2200     alias ll='ls -l'
2201     alias lh='ls -hAl'
2202     alias l='ls -lF'
2203 fi
2204
2205 alias mdstat='cat /proc/mdstat'
2206 alias ...='cd ../../'
2207
2208 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
2209 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
2210     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
2211 fi
2212
2213 alias cp='nocorrect cp'         # no spelling correction on cp
2214 alias mkdir='nocorrect mkdir'   # no spelling correction on mkdir
2215 alias mv='nocorrect mv'         # no spelling correction on mv
2216 alias rm='nocorrect rm'         # no spelling correction on rm
2217
2218 #a1# Execute \kbd{rmdir}
2219 alias rd='rmdir'
2220 #a1# Execute \kbd{mkdir}
2221 alias md='mkdir'
2222
2223 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
2224 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
2225 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
2226
2227 # make sure it is not assigned yet
2228 [[ -n ${aliases[utf2iso]} ]] && unalias utf2iso
2229 utf2iso() {
2230     if isutfenv ; then
2231         for ENV in $(env | command grep -i '.utf') ; do
2232             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
2233         done
2234     fi
2235 }
2236
2237 # make sure it is not assigned yet
2238 [[ -n ${aliases[iso2utf]} ]] && unalias iso2utf
2239 iso2utf() {
2240     if ! isutfenv ; then
2241         for ENV in $(env | command grep -i '\.iso') ; do
2242             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
2243         done
2244     fi
2245 }
2246
2247 # set up software synthesizer via speakup
2248 swspeak() {
2249     if [ -x /usr/sbin/swspeak-setup ] ; then
2250        setopt singlelinezle
2251        unsetopt prompt_cr
2252        export PS1="%m%# "
2253        /usr/sbin/swspeak-setup $@
2254      else # old version:
2255         if ! [[ -r /dev/softsynth ]] ; then
2256             flite -o play -t "Sorry, software synthesizer not available. Did you boot with swspeak bootoption?"
2257             return 1
2258         else
2259            setopt singlelinezle
2260            unsetopt prompt_cr
2261            export PS1="%m%# "
2262             nice -n -20 speechd-up
2263             sleep 2
2264             flite -o play -t "Finished setting up software synthesizer"
2265         fi
2266      fi
2267 }
2268
2269 # I like clean prompt, so provide simple way to get that
2270 check_com 0 || alias 0='return 0'
2271
2272 # for really lazy people like mika:
2273 check_com S &>/dev/null || alias S='screen'
2274 check_com s &>/dev/null || alias s='ssh'
2275
2276 # especially for roadwarriors using GNU screen and ssh:
2277 if ! check_com asc &>/dev/null ; then
2278   asc() { autossh -t "$@" 'screen -RdU' }
2279   compdef asc=ssh
2280 fi
2281
2282 # get top 10 shell commands:
2283 alias top10='print -l ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
2284
2285 # truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i'
2286 if check_com -c truecrypt ; then
2287     if isutfenv ; then
2288         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" '
2289     else
2290         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" '
2291     fi
2292 fi
2293
2294 #f1# Hints for the use of zsh on grml
2295 zsh-help() {
2296     print "$bg[white]$fg[black]
2297 zsh-help - hints for use of zsh on grml
2298 =======================================$reset_color"
2299
2300     print '
2301 Main configuration of zsh happens in /etc/zsh/zshrc.
2302 That file is part of the package grml-etc-core, if you want to
2303 use them on a non-grml-system just get the tar.gz from
2304 http://deb.grml.org/ or (preferably) get it from the git repository:
2305
2306   http://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
2307
2308 This version of grml'\''s zsh setup does not use skel/.zshrc anymore.
2309 The file is still there, but it is empty for backwards compatibility.
2310
2311 For your own changes use these two files:
2312     $HOME/.zshrc.pre
2313     $HOME/.zshrc.local
2314
2315 The former is sourced very early in our zshrc, the latter is sourced
2316 very lately.
2317
2318 System wide configuration without touching configuration files of grml
2319 can take place in /etc/zsh/zshrc.local.
2320
2321 Normally, the root user (EUID == 0) does not get the whole grml setup.
2322 If you want to force the whole setup for that user, too, set
2323 GRML_ALWAYS_LOAD_ALL=1 in .zshrc.pre in root'\''s home directory.
2324
2325 For information regarding zsh start at http://grml.org/zsh/
2326
2327 Take a look at grml'\''s zsh refcard:
2328 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
2329
2330 Check out the main zsh refcard:
2331 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
2332
2333 And of course visit the zsh-lovers:
2334 % man zsh-lovers
2335
2336 You can adjust some options through environment variables when
2337 invoking zsh without having to edit configuration files.
2338 Basically meant for bash users who are not used to the power of
2339 the zsh yet. :)
2340
2341   "NOCOR=1    zsh" => deactivate automatic correction
2342   "NOMENU=1   zsh" => do not use auto menu completion (note: use ctrl-d for completion instead!)
2343   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
2344   "NOTITLE=1  zsh" => disable setting the title of xterms without disabling
2345                       preexec() and precmd() completely
2346   "BATTERY=1  zsh" => activate battery status (via acpi) on right side of prompt
2347   "COMMAND_NOT_FOUND=1 zsh"
2348                    => Enable a handler if an external command was not found
2349                       The command called in the handler can be altered by setting
2350                       the GRML_ZSH_CNF_HANDLER variable, the default is:
2351                       "/usr/share/command-not-found/command-not-found"
2352
2353 A value greater than 0 is enables a feature; a value equal to zero
2354 disables it. If you like one or the other of these settings, you can
2355 add them to ~/.zshrc.pre to ensure they are set when sourcing grml'\''s
2356 zshrc.'
2357
2358     print "
2359 $bg[white]$fg[black]
2360 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
2361 Enjoy your grml system with the zsh!$reset_color"
2362 }
2363
2364 # debian stuff
2365 if [[ -r /etc/debian_version ]] ; then
2366     #a3# Execute \kbd{apt-cache search}
2367     alias acs='apt-cache search'
2368     #a3# Execute \kbd{apt-cache show}
2369     alias acsh='apt-cache show'
2370     #a3# Execute \kbd{apt-cache policy}
2371     alias acp='apt-cache policy'
2372     #a3# Execute \kbd{apt-get dist-upgrade}
2373     salias adg="apt-get dist-upgrade"
2374     #a3# Execute \kbd{apt-get install}
2375     salias agi="apt-get install"
2376     #a3# Execute \kbd{aptitude install}
2377     salias ati="aptitude install"
2378     #a3# Execute \kbd{apt-get upgrade}
2379     salias ag="apt-get upgrade"
2380     #a3# Execute \kbd{apt-get update}
2381     salias au="apt-get update"
2382     #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
2383     salias -a up="aptitude update ; aptitude safe-upgrade"
2384     #a3# Execute \kbd{dpkg-buildpackage}
2385     alias dbp='dpkg-buildpackage'
2386     #a3# Execute \kbd{grep-excuses}
2387     alias ge='grep-excuses'
2388
2389     # debian upgrade
2390     #f3# Execute \kbd{apt-get update \&\& }\\&\quad \kbd{apt-get dist-upgrade}
2391     upgrade() {
2392         emulate -L zsh
2393         if [[ -z $1 ]] ; then
2394             $SUDO apt-get update
2395             $SUDO apt-get -u upgrade
2396         else
2397             ssh $1 $SUDO apt-get update
2398             # ask before the upgrade
2399             local dummy
2400             ssh $1 $SUDO apt-get --no-act upgrade
2401             echo -n 'Process the upgrade?'
2402             read -q dummy
2403             if [[ $dummy == "y" ]] ; then
2404                 ssh $1 $SUDO apt-get -u upgrade --yes
2405             fi
2406         fi
2407     }
2408
2409     # get a root shell as normal user in live-cd mode:
2410     if isgrmlcd && [[ $UID -ne 0 ]] ; then
2411        alias su="sudo su"
2412      fi
2413
2414     #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
2415     salias llog="$PAGER /var/log/syslog"     # take a look at the syslog
2416     #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
2417     salias tlog="tail -f /var/log/syslog"    # follow the syslog
2418 fi
2419
2420 # sort installed Debian-packages by size
2421 if check_com -c grep-status ; then
2422     #a3# List installed Debian-packages sorted by size
2423     alias debs-by-size='grep-status -FStatus -sInstalled-Size,Package -n "install ok installed" | paste -sd "  \n" | sort -rn'
2424 fi
2425
2426 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
2427 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord; then
2428     if check_com -c wodim; then
2429         cdrecord() {
2430             cat <<EOMESS
2431 cdrecord is not provided under its original name by Debian anymore.
2432 See #377109 in the BTS of Debian for more details.
2433
2434 Please use the wodim binary instead
2435 EOMESS
2436             return 1
2437         }
2438     fi
2439 fi
2440
2441 # get_tw_cli has been renamed into get_3ware
2442 if check_com -c get_3ware ; then
2443     get_tw_cli() {
2444         echo 'Warning: get_tw_cli has been renamed into get_3ware. Invoking get_3ware for you.'>&2
2445         get_3ware
2446     }
2447 fi
2448
2449 # I hate lacking backward compatibility, so provide an alternative therefore
2450 if ! check_com -c apache2-ssl-certificate ; then
2451
2452     apache2-ssl-certificate() {
2453
2454     print 'Debian does not ship apache2-ssl-certificate anymore (see #398520). :('
2455     print 'You might want to take a look at Debian the package ssl-cert as well.'
2456     print 'To generate a certificate for use with apache2 follow the instructions:'
2457
2458     echo '
2459
2460 export RANDFILE=/dev/random
2461 mkdir /etc/apache2/ssl/
2462 openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem
2463 chmod 600 /etc/apache2/ssl/apache.pem
2464
2465 Run "grml-tips ssl-certificate" if you need further instructions.
2466 '
2467     }
2468 fi
2469 # }}}
2470
2471 # {{{ Use hard limits, except for a smaller stack and no core dumps
2472 unlimit
2473 is425 && limit stack 8192
2474 isgrmlcd && limit core 0 # important for a live-cd-system
2475 limit -s
2476 # }}}
2477
2478 # {{{ completion system
2479
2480 # called later (via is4 && grmlcomp)
2481 # note: use 'zstyle' for getting current settings
2482 #         press ^Xh (control-x h) for getting tags in context; ^X? (control-x ?) to run complete_debug with trace output
2483 grmlcomp() {
2484     # TODO: This could use some additional information
2485
2486     # allow one error for every three characters typed in approximate completer
2487     zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
2488
2489     # don't complete backup files as executables
2490     zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
2491
2492     # start menu completion only if it could find no unambiguous initial string
2493     zstyle ':completion:*:correct:*'       insert-unambiguous true
2494     zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
2495     zstyle ':completion:*:correct:*'       original true
2496
2497     # activate color-completion
2498     zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}
2499
2500     # format on completion
2501     zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
2502
2503     # automatically complete 'cd -<tab>' and 'cd -<ctrl-d>' with menu
2504     # zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
2505
2506     # insert all expansions for expand completer
2507     zstyle ':completion:*:expand:*'        tag-order all-expansions
2508     zstyle ':completion:*:history-words'   list false
2509
2510     # activate menu
2511     zstyle ':completion:*:history-words'   menu yes
2512
2513     # ignore duplicate entries
2514     zstyle ':completion:*:history-words'   remove-all-dups yes
2515     zstyle ':completion:*:history-words'   stop yes
2516
2517     # match uppercase from lowercase
2518     zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'
2519
2520     # separate matches into groups
2521     zstyle ':completion:*:matches'         group 'yes'
2522     zstyle ':completion:*'                 group-name ''
2523
2524     if [[ "$NOMENU" -eq 0 ]] ; then
2525         # if there are more than 5 options allow selecting from a menu
2526         zstyle ':completion:*'               menu select=5
2527     else
2528         # don't use any menus at all
2529         setopt no_auto_menu
2530     fi
2531
2532     zstyle ':completion:*:messages'        format '%d'
2533     zstyle ':completion:*:options'         auto-description '%d'
2534
2535     # describe options in full
2536     zstyle ':completion:*:options'         description 'yes'
2537
2538     # on processes completion complete all user processes
2539     zstyle ':completion:*:processes'       command 'ps -au$USER'
2540
2541     # offer indexes before parameters in subscripts
2542     zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
2543
2544     # provide verbose completion information
2545     zstyle ':completion:*'                 verbose true
2546
2547     # recent (as of Dec 2007) zsh versions are able to provide descriptions
2548     # for commands (read: 1st word in the line) that it will list for the user
2549     # to choose from. The following disables that, because it's not exactly fast.
2550     zstyle ':completion:*:-command-:*:'    verbose false
2551
2552     # set format for warnings
2553     zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
2554
2555     # define files to ignore for zcompile
2556     zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
2557     zstyle ':completion:correct:'          prompt 'correct to: %e'
2558
2559     # Ignore completion functions for commands you don't have:
2560     zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
2561
2562     # Provide more processes in completion of programs like killall:
2563     zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'
2564
2565     # complete manual by their section
2566     zstyle ':completion:*:manuals'    separate-sections true
2567     zstyle ':completion:*:manuals.*'  insert-sections   true
2568     zstyle ':completion:*:man:*'      menu yes select
2569
2570     # provide .. as a completion
2571     zstyle ':completion:*' special-dirs ..
2572
2573     # run rehash on completion so new installed program are found automatically:
2574     _force_rehash() {
2575         (( CURRENT == 1 )) && rehash
2576         return 1
2577     }
2578
2579     ## correction
2580     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
2581     if [[ "$NOCOR" -gt 0 ]] ; then
2582         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
2583         setopt nocorrect
2584     else
2585         # try to be smart about when to use what completer...
2586         setopt correct
2587         zstyle -e ':completion:*' completer '
2588             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
2589                 _last_try="$HISTNO$BUFFER$CURSOR"
2590                 reply=(_complete _match _ignored _prefix _files)
2591             else
2592                 if [[ $words[1] == (rm|mv) ]] ; then
2593                     reply=(_complete _files)
2594                 else
2595                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
2596                 fi
2597             fi'
2598     fi
2599
2600     # command for process lists, the local web server details and host completion
2601     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
2602
2603     # caching
2604     [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
2605                             zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
2606
2607     # host completion /* add brackets as vim can't parse zsh's complex cmdlines 8-) {{{ */
2608     if is42 ; then
2609         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
2610         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
2611     else
2612         _ssh_hosts=()
2613         _etc_hosts=()
2614     fi
2615     hosts=(
2616         $(hostname)
2617         "$_ssh_hosts[@]"
2618         "$_etc_hosts[@]"
2619         grml.org
2620         localhost
2621     )
2622     zstyle ':completion:*:hosts' hosts $hosts
2623     # TODO: so, why is this here?
2624     #  zstyle '*' hosts $hosts
2625
2626     # use generic completion system for programs not yet defined; (_gnu_generic works
2627     # with commands that provide a --help option with "standard" gnu-like output.)
2628     for compcom in cp deborphan df feh fetchipac head hnb ipacsum mv \
2629                    pal stow tail uname ; do
2630         [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
2631     done; unset compcom
2632
2633     # see upgrade function in this file
2634     compdef _hosts upgrade
2635 }
2636 # }}}
2637
2638 # {{{ grmlstuff
2639 grmlstuff() {
2640 # people should use 'grml-x'!
2641     if check_com -c 915resolution; then
2642         855resolution() {
2643             echo "Please use 915resolution as resolution modifying tool for Intel \
2644 graphic chipset."
2645             return -1
2646         }
2647     fi
2648
2649     #a1# Output version of running grml
2650     alias grml-version='cat /etc/grml_version'
2651
2652     if check_com -c rebuildfstab ; then
2653         #a1# Rebuild /etc/fstab
2654         alias grml-rebuildfstab='rebuildfstab -v -r -config'
2655     fi
2656
2657     if check_com -c grml-debootstrap ; then
2658         debian2hd() {
2659             echo "Installing debian to harddisk is possible by using grml-debootstrap."
2660             return 1
2661         }
2662     fi
2663 }
2664 # }}}
2665
2666 # {{{ now run the functions
2667 isgrml && checkhome
2668 is4    && isgrml    && grmlstuff
2669 is4    && grmlcomp
2670 # }}}
2671
2672 # {{{ keephack
2673 is4 && xsource "/etc/zsh/keephack"
2674 # }}}
2675
2676 # {{{ wonderful idea of using "e" glob qualifier by Peter Stephenson
2677 # You use it as follows:
2678 # $ NTREF=/reference/file
2679 # $ ls -l *(e:nt:)
2680 # This lists all the files in the current directory newer than the reference file.
2681 # You can also specify the reference file inline; note quotes:
2682 # $ ls -l *(e:'nt ~/.zshenv':)
2683 is4 && nt() {
2684     if [[ -n $1 ]] ; then
2685         local NTREF=${~1}
2686     fi
2687     [[ $REPLY -nt $NTREF ]]
2688 }
2689 # }}}
2690
2691 # shell functions {{{
2692
2693 #f1# Provide csh compatibility
2694 setenv()  { typeset -x "${1}${1:+=}${(@)argv[2,$#]}" }  # csh compatibility
2695
2696 #f1# Reload an autoloadable function
2697 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2698 compdef _functions freload
2699
2700 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
2701 sll() {
2702     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
2703     for file in "$@" ; do
2704         while [[ -h "$file" ]] ; do
2705             ls -l $file
2706             file=$(readlink "$file")
2707         done
2708     done
2709 }
2710
2711 # fast manual access
2712 if check_com qma ; then
2713     #f1# View the zsh manual
2714     manzsh()  { qma zshall "$1" }
2715     compdef _man qma
2716 else
2717     manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
2718 fi
2719
2720 # TODO: Is it supported to use pager settings like this?
2721 #   PAGER='less -Mr' - If so, the use of $PAGER here needs fixing
2722 # with respect to wordsplitting. (ie. ${=PAGER})
2723 if check_com -c $PAGER ; then
2724     #f1# View Debian's changelog of a given package
2725     dchange() {
2726         emulate -L zsh
2727         if [[ -r /usr/share/doc/$1/changelog.Debian.gz ]] ; then
2728             $PAGER /usr/share/doc/$1/changelog.Debian.gz
2729         elif [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
2730             $PAGER /usr/share/doc/$1/changelog.gz
2731         else
2732             if check_com -c aptitude ; then
2733                 echo "No changelog for package $1 found, using aptitude to retrieve it."
2734                 if isgrml ; then
2735                     aptitude -t unstable changelog $1
2736                 else
2737                     aptitude changelog $1
2738                 fi
2739             else
2740                 echo "No changelog for package $1 found, sorry."
2741                 return 1
2742             fi
2743         fi
2744     }
2745     _dchange() { _files -W /usr/share/doc -/ }
2746     compdef _dchange dchange
2747
2748     #f1# View Debian's NEWS of a given package
2749     dnews() {
2750         emulate -L zsh
2751         if [[ -r /usr/share/doc/$1/NEWS.Debian.gz ]] ; then
2752             $PAGER /usr/share/doc/$1/NEWS.Debian.gz
2753         else
2754             if [[ -r /usr/share/doc/$1/NEWS.gz ]] ; then
2755                 $PAGER /usr/share/doc/$1/NEWS.gz
2756             else
2757                 echo "No NEWS file for package $1 found, sorry."
2758                 return 1
2759             fi
2760         fi
2761     }
2762     _dnews() { _files -W /usr/share/doc -/ }
2763     compdef _dnews dnews
2764
2765     #f1# View upstream's changelog of a given package
2766     uchange() {
2767         emulate -L zsh
2768         if [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
2769             $PAGER /usr/share/doc/$1/changelog.gz
2770         else
2771             echo "No changelog for package $1 found, sorry."
2772             return 1
2773         fi
2774     }
2775     _uchange() { _files -W /usr/share/doc -/ }
2776     compdef _uchange uchange
2777 fi
2778
2779 # zsh profiling
2780 profile() {
2781     ZSH_PROFILE_RC=1 $SHELL "$@"
2782 }
2783
2784 #f1# Edit an alias via zle
2785 edalias() {
2786     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
2787 }
2788 compdef _aliases edalias
2789
2790 #f1# Edit a function via zle
2791 edfunc() {
2792     [[ -z "$1" ]] && { echo "Usage: edfun <function_to_edit>" ; return 1 } || zed -f "$1" ;
2793 }
2794 compdef _functions edfunc
2795
2796 # use it e.g. via 'Restart apache2'
2797 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
2798 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
2799 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
2800 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
2801 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
2802 if [[ -d /etc/init.d || -d /etc/service ]] ; then
2803     __start_stop() {
2804         local action_="${1:l}"  # e.g Start/Stop/Restart
2805         local service_="$2"
2806         local param_="$3"
2807
2808         local service_target_="$(readlink /etc/init.d/$service_)"
2809         if [[ $service_target_ == "/usr/bin/sv" ]]; then
2810             # runit
2811             case "${action_}" in
2812                 start) if [[ ! -e /etc/service/$service_ ]]; then
2813                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
2814                        else
2815                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2816                        fi ;;
2817                 # there is no reload in runits sysv emulation
2818                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
2819                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
2820             esac
2821         else
2822             # sysvinit
2823             $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2824         fi
2825     }
2826
2827     for i in Start Restart Stop Force-Reload Reload ; do
2828         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
2829     done
2830 fi
2831
2832 #f1# Provides useful information on globbing
2833 H-Glob() {
2834     echo -e "
2835     /      directories
2836     .      plain files
2837     @      symbolic links
2838     =      sockets
2839     p      named pipes (FIFOs)
2840     *      executable plain files (0100)
2841     %      device files (character or block special)
2842     %b     block special files
2843     %c     character special files
2844     r      owner-readable files (0400)
2845     w      owner-writable files (0200)
2846     x      owner-executable files (0100)
2847     A      group-readable files (0040)
2848     I      group-writable files (0020)
2849     E      group-executable files (0010)
2850     R      world-readable files (0004)
2851     W      world-writable files (0002)
2852     X      world-executable files (0001)
2853     s      setuid files (04000)
2854     S      setgid files (02000)
2855     t      files with the sticky bit (01000)
2856
2857   print *(m-1)          # Files modified up to a day ago
2858   print *(a1)           # Files accessed a day ago
2859   print *(@)            # Just symlinks
2860   print *(Lk+50)        # Files bigger than 50 kilobytes
2861   print *(Lk-50)        # Files smaller than 50 kilobytes
2862   print **/*.c          # All *.c files recursively starting in \$PWD
2863   print **/*.c~file.c   # Same as above, but excluding 'file.c'
2864   print (foo|bar).*     # Files starting with 'foo' or 'bar'
2865   print *~*.*           # All Files that do not contain a dot
2866   chmod 644 *(.^x)      # make all plain non-executable files publically readable
2867   print -l *(.c|.h)     # Lists *.c and *.h
2868   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
2869   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
2870 }
2871 alias help-zshglob=H-Glob
2872
2873 check_com -c qma && alias ?='qma zshall'
2874
2875 # grep for running process, like: 'any vim'
2876 any() {
2877     emulate -L zsh
2878     if [[ -z "$1" ]] ; then
2879         echo "any - grep for process(es) by keyword" >&2
2880         echo "Usage: any <keyword>" >&2 ; return 1
2881     else
2882         local STRING=$1
2883         local LENGTH=$(expr length $STRING)
2884         local FIRSCHAR=$(echo $(expr substr $STRING 1 1))
2885         local REST=$(echo $(expr substr $STRING 2 $LENGTH))
2886         ps xauwww| grep "[$FIRSCHAR]$REST"
2887     fi
2888 }
2889
2890 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
2891 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
2892 [[ -r /proc/1/maps ]] && \
2893 deswap() {
2894     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
2895     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
2896     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
2897 }
2898
2899 # print hex value of a number
2900 hex() {
2901     emulate -L zsh
2902     [[ -n "$1" ]] && printf "%x\n" $1 || { print 'Usage: hex <number-to-convert>' ; return 1 }
2903 }
2904
2905 # calculate (or eval at all ;-)) with perl => p[erl-]eval
2906 # hint: also take a look at zcalc -> 'autoload zcalc' -> 'man zshmodules | less -p MATHFUNC'
2907 peval() {
2908     [[ -n "$1" ]] && CALC="$*" || print "Usage: calc [expression]"
2909     perl -e "print eval($CALC),\"\n\";"
2910 }
2911 functions peval &>/dev/null && alias calc=peval
2912
2913 # brltty seems to have problems with utf8 environment and/or font Uni3-Terminus16 under
2914 # certain circumstances, so work around it, no matter which environment we have
2915 brltty() {
2916     if [[ -z "$DISPLAY" ]] ; then
2917         consolechars -f /usr/share/consolefonts/default8x16.psf.gz
2918         command brltty "$@"
2919     else
2920         command brltty "$@"
2921     fi
2922 }
2923
2924 # just press 'asdf' keys to toggle between dvorak and us keyboard layout
2925 aoeu() {
2926     echo -n 'Switching to us keyboard layout: '
2927     [[ -z "$DISPLAY" ]] && $SUDO loadkeys us &>/dev/null || setxkbmap us &>/dev/null
2928     echo 'Done'
2929 }
2930 asdf() {
2931     echo -n 'Switching to dvorak keyboard layout: '
2932     [[ -z "$DISPLAY" ]] && $SUDO loadkeys dvorak &>/dev/null || setxkbmap dvorak &>/dev/null
2933     echo 'Done'
2934 }
2935 # just press 'asdf' key to toggle from neon layout to us keyboard layout
2936 uiae() {
2937     echo -n 'Switching to us keyboard layout: '
2938     setxkbmap us && echo 'Done' || echo 'Failed'
2939 }
2940
2941 # set up an ipv6 tunnel
2942 ipv6-tunnel() {
2943     emulate -L zsh
2944     case $1 in
2945         start)
2946             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2947                 print 'ipv6 tunnel already set up, nothing to be done.'
2948                 print 'execute: "ifconfig sit1 down ; ifconfig sit0 down" to remove ipv6-tunnel.' ; return 1
2949             else
2950                 [[ -n "$PUBLIC_IP" ]] || \
2951                     local PUBLIC_IP=$(ifconfig $(route -n | awk '/^0\.0\.0\.0/{print $8; exit}') | \
2952                                       awk '/inet addr:/ {print $2}' | tr -d 'addr:')
2953
2954                 [[ -n "$PUBLIC_IP" ]] || { print 'No $PUBLIC_IP set and could not determine default one.' ; return 1 }
2955                 local IPV6ADDR=$(printf "2002:%02x%02x:%02x%02x:1::1" $(print ${PUBLIC_IP//./ }))
2956                 print -n "Setting up ipv6 tunnel $IPV6ADDR via ${PUBLIC_IP}: "
2957                 ifconfig sit0 tunnel ::192.88.99.1 up
2958                 ifconfig sit1 add "$IPV6ADDR" && print done || print failed
2959             fi
2960             ;;
2961         status)
2962             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2963                 print 'ipv6 tunnel available' ; return 0
2964             else
2965                 print 'ipv6 tunnel not available' ; return 1
2966             fi
2967             ;;
2968         stop)
2969             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2970                 print -n 'Stopping ipv6 tunnel (sit0 + sit1): '
2971                 ifconfig sit1 down ; ifconfig sit0 down && print done || print failed
2972             else
2973                 print 'No ipv6 tunnel found, nothing to be done.' ; return 1
2974             fi
2975             ;;
2976         *)
2977             print "Usage: ipv6-tunnel [start|stop|status]">&2 ; return 1
2978             ;;
2979     esac
2980 }
2981
2982 # run dhclient for wireless device
2983 iwclient() {
2984     sudo dhclient "$(wavemon -d | awk '/device/{print $3}')"
2985 }
2986
2987 # spawn a minimally set up mksh - useful if you want to umount /usr/.
2988 minimal-shell() {
2989     emulate -L zsh
2990     local shell="/bin/mksh"
2991
2992     if [[ ! -x ${shell} ]]; then
2993         printf '`%s'\'' not available, giving up.\n' ${shell} >&2
2994         return 1
2995     fi
2996
2997     exec env -i ENV="/etc/minimal-shellrc" HOME="$HOME" TERM="$TERM" ${shell}
2998 }
2999
3000 # a wrapper for vim, that deals with title setting
3001 #   VIM_OPTIONS
3002 #       set this array to a set of options to vim you always want
3003 #       to have set when calling vim (in .zshrc.local), like:
3004 #           VIM_OPTIONS=( -p )
3005 #       This will cause vim to send every file given on the
3006 #       commandline to be send to it's own tab (needs vim7).
3007 vim() {
3008     VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
3009 }
3010
3011 # make a backup of a file
3012 bk() {
3013     cp -a "$1" "${1}_$(date --iso-8601=seconds)"
3014 }
3015
3016 #f1# grep for patterns in grml's zsh setup
3017 zg() {
3018 #{{{
3019     LANG=C perl -e '
3020
3021 sub usage {
3022     print "usage: zg -[anr] <pattern>\n";
3023     print " Search for patterns in grml'\''s zshrc.\n";
3024     print " zg takes no or exactly one option plus a non empty pattern.\n\n";
3025     print "   options:\n";
3026     print "     --  no options (use if your pattern starts in with a dash.\n";
3027     print "     -a  search for the pattern in all code regions\n";
3028     print "     -n  search for the pattern in non-root code only\n";
3029     print "     -r  search in code for everyone (also root) only\n\n";
3030     print "   The default is -a for non-root users and -r for root.\n\n";
3031     print " If you installed the zshrc to a non-default locations (ie *NOT*\n";
3032     print " in /etc/zsh/zshrc) do: export GRML_ZSHRC=\$HOME/.zshrc\n";
3033     print " ...in case you copied the file to that location.\n\n";
3034     exit 1;
3035 }
3036
3037 if ($ENV{GRML_ZSHRC} ne "") {
3038     $RC = $ENV{GRML_ZSHRC};
3039 } else {
3040     $RC = "/etc/zsh/zshrc";
3041 }
3042
3043 usage if ($#ARGV < 0 || $#ARGV > 1);
3044 if ($> == 0) { $mode = "allonly"; }
3045 else { $mode = "all"; }
3046
3047 $opt = $ARGV[0];
3048 if ($opt eq "--")     { shift; }
3049 elsif ($opt eq "-a")  { $mode = "all"; shift; }
3050 elsif ($opt eq "-n")  { $mode = "nonroot"; shift; }
3051 elsif ($opt eq "-r" ) { $mode = "allonly"; shift; }
3052 elsif ($opt =~ m/^-/ || $#ARGV > 0) { usage(); }
3053
3054 $pattern = $ARGV[0];
3055 usage() if ($pattern eq "");
3056
3057 open FH, "<$RC" or die "zg: Could not open $RC: $!\n";
3058 while ($line = <FH>) {
3059     chomp $line;
3060     if ($line =~ m/^#:grep:marker:for:mika:/) { $markerfound = 1; next; }
3061     next if ($mode eq "nonroot" && markerfound == 0);
3062     break if ($mode eq "allonly" && markerfound == 1);
3063     print $line, "\n" if ($line =~ /$pattern/);
3064 }
3065 close FH;
3066 exit 0;
3067
3068     ' -- "$@"
3069 #}}}
3070     return $?
3071 }
3072
3073 ssl_hashes=( sha512 sha256 sha1 md5 )
3074
3075 for sh in ${ssl_hashes}; do
3076     eval 'ssl-cert-'${sh}'() {
3077         emulate -L zsh
3078         if [[ -z $1 ]] ; then
3079             printf '\''usage: %s <file>\n'\'' "ssh-cert-'${sh}'"
3080             return 1
3081         fi
3082         openssl x509 -noout -fingerprint -'${sh}' -in $1
3083     }'
3084 done; unset sh
3085
3086 ssl-cert-fingerprints() {
3087     emulate -L zsh
3088     local i
3089     if [[ -z $1 ]] ; then
3090         printf 'usage: ssl-cert-fingerprints <file>\n'
3091         return 1
3092     fi
3093     for i in ${ssl_hashes}
3094         do ssl-cert-$i $1;
3095     done
3096 }
3097
3098 ssl-cert-info() {
3099     emulate -L zsh
3100     if [[ -z $1 ]] ; then
3101         printf 'usage: ssl-cert-info <file>\n'
3102         return 1
3103     fi
3104     openssl x509 -noout -text -in $1
3105     ssl-cert-fingerprints $1
3106 }
3107
3108 # }}}
3109
3110 # {{{ make sure our environment is clean regarding colors
3111 for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
3112 # }}}
3113
3114 # "persistent history" {{{
3115 # just write important commands you always need to ~/.important_commands
3116 if [[ -r ~/.important_commands ]] ; then
3117     fc -R ~/.important_commands
3118 fi
3119 # }}}
3120
3121 # load the lookup subsystem if it's available on the system
3122 zrcautoload lookupinit && lookupinit
3123
3124 #:grep:marker:for:mika: :-)
3125 ### non-root (EUID != 0) code below
3126 ###
3127
3128 if (( GRML_ALWAYS_LOAD_ALL == 0 )) && (( $EUID == 0 )) ; then
3129     zrclocal
3130     return 0
3131 fi
3132
3133 # variables {{{
3134
3135 # set terminal property (used e.g. by msgid-chooser)
3136 export COLORTERM="yes"
3137
3138 # set default browser
3139 if [[ -z "$BROWSER" ]] ; then
3140     if [[ -n "$DISPLAY" ]] ; then
3141         #v# If X11 is running
3142         check_com -c firefox && export BROWSER=firefox
3143     else
3144         #v# If no X11 is running
3145         check_com -c w3m && export BROWSER=w3m
3146     fi
3147 fi
3148
3149 #m# v QTDIR \kbd{/usr/share/qt[34]}\quad [for non-root only]
3150 [[ -d /usr/share/qt3 ]] && export QTDIR=/usr/share/qt3
3151 [[ -d /usr/share/qt4 ]] && export QTDIR=/usr/share/qt4
3152
3153 # support running 'jikes *.java && jamvm HelloWorld' OOTB:
3154 #v# [for non-root only]
3155 [[ -f /usr/share/classpath/glibj.zip ]] && export JIKESPATH=/usr/share/classpath/glibj.zip
3156 # }}}
3157
3158 # aliases {{{
3159
3160 # Xterm resizing-fu.
3161 # Based on http://svn.kitenet.net/trunk/home-full/.zshrc?rev=11710&view=log (by Joey Hess)
3162 alias hide='echo -en "\033]50;nil2\007"'
3163 alias tiny='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"'
3164 alias small='echo -en "\033]50;6x10\007"'
3165 alias medium='echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"'
3166 alias default='echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"'
3167 alias large='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"'
3168 alias huge='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"'
3169 alias smartfont='echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"'
3170 alias semifont='echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"'
3171
3172 # general
3173 #a2# Execute \kbd{du -sch}
3174 alias da='du -sch'
3175 #a2# Execute \kbd{jobs -l}
3176 alias j='jobs -l'
3177
3178 # compile stuff
3179 #a2# Execute \kbd{./configure}
3180 alias CO="./configure"
3181 #a2# Execute \kbd{./configure --help}
3182 alias CH="./configure --help"
3183
3184 # listing stuff
3185 #a2# Execute \kbd{ls -lSrah}
3186 alias dir="ls -lSrah"
3187 #a2# Only show dot-directories
3188 alias lad='ls -d .*(/)'                # only show dot-directories
3189 #a2# Only show dot-files
3190 alias lsa='ls -a .*(.)'                # only show dot-files
3191 #a2# Only files with setgid/setuid/sticky flag
3192 alias lss='ls -l *(s,S,t)'             # only files with setgid/setuid/sticky flag
3193 #a2# Only show 1st ten symlinks
3194 alias lsl='ls -l *(@)'                 # only symlinks
3195 #a2# Display only executables
3196 alias lsx='ls -l *(*)'                 # only executables
3197 #a2# Display world-{readable,writable,executable} files
3198 alias lsw='ls -ld *(R,W,X.^ND/)'       # world-{readable,writable,executable} files
3199 #a2# Display the ten biggest files
3200 alias lsbig="ls -flh *(.OL[1,10])"     # display the biggest files
3201 #a2# Only show directories
3202 alias lsd='ls -d *(/)'                 # only show directories
3203 #a2# Only show empty directories
3204 alias lse='ls -d *(/^F)'               # only show empty directories
3205 #a2# Display the ten newest files
3206 alias lsnew="ls -rtlh *(D.om[1,10])"   # display the newest files
3207 #a2# Display the ten oldest files
3208 alias lsold="ls -rtlh *(D.Om[1,10])"   # display the oldest files
3209 #a2# Display the ten smallest files
3210 alias lssmall="ls -Srl *(.oL[1,10])"   # display the smallest files
3211
3212 # chmod
3213 #a2# Execute \kbd{chmod 600}
3214 alias rw-='chmod 600'
3215 #a2# Execute \kbd{chmod 700}
3216 alias rwx='chmod 700'
3217 #m# a2 r-{}- Execute \kbd{chmod 644}
3218 alias r--='chmod 644'
3219 #a2# Execute \kbd{chmod 755}
3220 alias r-x='chmod 755'
3221
3222 # some useful aliases
3223 #a2# Execute \kbd{mkdir -o}
3224 alias md='mkdir -p'
3225
3226 # console stuff
3227 #a2# Execute \kbd{mplayer -vo fbdev}
3228 alias cmplayer='mplayer -vo fbdev'
3229 #a2# Execute \kbd{mplayer -vo fbdev -fs -zoom}
3230 alias fbmplayer='mplayer -vo fbdev -fs -zoom'
3231 #a2# Execute \kbd{links2 -driver fb}
3232 alias fblinks='links2 -driver fb'
3233
3234 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3235 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3236 alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3237
3238 # simple webserver
3239 check_com -c python && alias http="python -m SimpleHTTPServer"
3240
3241 # Use 'g' instead of 'git':
3242 check_com g || alias g='git'
3243
3244 # work around non utf8 capable software in utf environment via $LANG and luit
3245 if check_com isutfenv && check_com luit ; then
3246     if check_com -c mrxvt ; then
3247         isutfenv && [[ -n "$LANG" ]] && \
3248             alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
3249     fi
3250
3251     if check_com -c aterm ; then
3252         isutfenv && [[ -n "$LANG" ]] && \
3253             alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
3254     fi
3255
3256     if check_com -c centericq ; then
3257         isutfenv && [[ -n "$LANG" ]] && \
3258             alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
3259     fi
3260 fi
3261 # }}}
3262
3263 # useful functions {{{
3264
3265 # searching
3266 #f4# Search for newspostings from authors
3267 agoogle() { ${=BROWSER} "http://groups.google.com/groups?as_uauthors=$*" ; }
3268 #f4# Search Debian Bug Tracking System
3269 debbug()  {
3270     emulate -L zsh
3271     setopt extendedglob
3272     if [[ $# -eq 1 ]]; then
3273         case "$1" in
3274             ([0-9]##)
3275             ${=BROWSER} "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=$1"
3276             ;;
3277             (*@*)
3278             ${=BROWSER} "http://bugs.debian.org/cgi-bin/pkgreport.cgi?submitter=$1"
3279             ;;
3280             (*)
3281             ${=BROWSER} "http://bugs.debian.org/$*"
3282             ;;
3283         esac
3284     else
3285         print "$0 needs one argument"
3286         return 1
3287     fi
3288 }
3289 #f4# Search Debian Bug Tracking System in mbox format
3290 debbugm() {
3291     emulate -L zsh
3292     bts show --mbox $1
3293 }
3294 #f4# Search DMOZ
3295 dmoz()    {
3296     emulate -L zsh
3297     ${=BROWSER} http://search.dmoz.org/cgi-bin/search\?search=${1// /_}
3298 }
3299 #f4# Search German   Wiktionary
3300 dwicti()  {
3301     emulate -L zsh
3302     ${=BROWSER} http://de.wiktionary.org/wiki/${(C)1// /_}
3303 }
3304 #f4# Search English  Wiktionary
3305 ewicti()  {
3306     emulate -L zsh
3307     ${=BROWSER} http://en.wiktionary.org/wiki/${(C)1// /_}
3308 }
3309 #f4# Search Google Groups
3310 ggogle()  {
3311     emulate -L zsh
3312     ${=BROWSER} "http://groups.google.com/groups?q=$*"
3313 }
3314 #f4# Search Google
3315 google()  {
3316     emulate -L zsh
3317     ${=BROWSER} "http://www.google.com/search?&num=100&q=$*"
3318 }
3319 #f4# Search Google Groups for MsgID
3320 mggogle() {
3321     emulate -L zsh
3322     ${=BROWSER} "http://groups.google.com/groups?selm=$*"
3323 }
3324 #f4# Search Netcraft
3325 netcraft(){
3326     emulate -L zsh
3327     ${=BROWSER} "http://toolbar.netcraft.com/site_report?url=$1"
3328 }
3329 #f4# Use German Wikipedia's full text search
3330 swiki()   {
3331     emulate -L zsh
3332     ${=BROWSER} http://de.wikipedia.org/wiki/Spezial:Search/${(C)1}
3333 }
3334 #f4# search \kbd{dict.leo.org}
3335 oleo()    {
3336     emulate -L zsh
3337     ${=BROWSER} "http://dict.leo.org/?search=$*"
3338 }
3339 #f4# Search German   Wikipedia
3340 wikide()  {
3341     emulate -L zsh
3342     ${=BROWSER} http://de.wikipedia.org/wiki/"${(C)*}"
3343 }
3344 #f4# Search English  Wikipedia
3345 wikien()  {
3346     emulate -L zsh
3347     ${=BROWSER} http://en.wikipedia.org/wiki/"${(C)*}"
3348 }
3349 #f4# Search official debs
3350 wodeb()   {
3351     emulate -L zsh
3352     ${=BROWSER} "http://packages.debian.org/search?keywords=$1&searchon=contents&suite=${2:=unstable}&section=all"
3353 }
3354
3355 #m# f4 gex() Exact search via Google
3356 check_com google && gex () {
3357     google "\"[ $1]\" $*"
3358 }
3359
3360 # misc
3361 #f5# Backup \kbd{file {\rm to} file\_timestamp}
3362 bk() {
3363     emulate -L zsh
3364     cp -b $1 $1_`date --iso-8601=m`
3365 }
3366 #f5# Copied diff
3367 cdiff() {
3368     emulate -L zsh
3369     diff -crd "$@" | egrep -v "^Only in |^Binary files "
3370 }
3371 #f5# cd to directoy and list files
3372 cl() {
3373     emulate -L zsh
3374     cd $1 && ls -a
3375 }
3376 #f5# Cvs add
3377 cvsa() {
3378     emulate -L zsh
3379     cvs add $* && cvs com -m 'initial checkin' $*
3380 }
3381 #f5# Cvs diff
3382 cvsd() {
3383     emulate -L zsh
3384     cvs diff -N $* |& $PAGER
3385 }
3386 #f5# Cvs log
3387 cvsl() {
3388     emulate -L zsh
3389     cvs log $* |& $PAGER
3390 }
3391 #f5# Cvs update
3392 cvsq() {
3393     emulate -L zsh
3394     cvs -nq update
3395 }
3396 #f5# Rcs2log
3397 cvsr() {
3398     emulate -L zsh
3399     rcs2log $* | $PAGER
3400 }
3401 #f5# Cvs status
3402 cvss() {
3403     emulate -L zsh
3404     cvs status -v $*
3405 }
3406 #f5# Disassemble source files using gcc and as
3407 disassemble(){
3408     emulate -L zsh
3409     gcc -pipe -S -o - -O -g $* | as -aldh -o /dev/null
3410 }
3411 #f5# Firefox remote control - open given URL
3412 fir() {
3413     if [ -e /etc/debian_version ]; then
3414         firefox -a iceweasel -remote "openURL($1)" || firefox ${1}&
3415     else
3416         firefox -a firefox -remote "openURL($1)" || firefox ${1}&
3417     fi
3418 }
3419 #f5# Create Directoy and \kbd{cd} to it
3420 mcd() {
3421     mkdir -p "$@" && cd "$@"
3422 }
3423 #f5# Unified diff to timestamped outputfile
3424 mdiff() {
3425     diff -udrP "$1" "$2" > diff.`date "+%Y-%m-%d"`."$1"
3426 }
3427 #f5# Memory overview
3428 memusage() {
3429     ps aux | awk '{if (NR > 1) print $5; if (NR > 2) print "+"} END { print "p" }' | dc
3430 }
3431 #f5# Show contents of gzipped tar file
3432 shtar() {
3433     emulate -L zsh
3434     gunzip -c $1 | tar -tf - -- | $PAGER
3435 }
3436 #f5# Show contents of zip file
3437 shzip() {
3438     emulate -L zsh
3439     unzip -l $1 | $PAGER
3440 }
3441 #f5# Unified diff
3442 udiff() {
3443     emulate -L zsh
3444     diff -urd $* | egrep -v "^Only in |^Binary files "
3445 }
3446 #f5# (Mis)use \kbd{vim} as \kbd{less}
3447 viless() {
3448     emulate -L zsh
3449     vim --cmd 'let no_plugin_maps = 1' -c "so \$VIMRUNTIME/macros/less.vim" "${@:--}"
3450 }
3451
3452 # Function Usage: uopen $URL/$file
3453 #f5# Download a file and display it locally
3454 uopen() {
3455     emulate -L zsh
3456     if ! [[ -n "$1" ]] ; then
3457         print "Usage: uopen \$URL/\$file">&2
3458         return 1
3459     else
3460         FILE=$1
3461         MIME=$(curl --head $FILE | grep Content-Type | cut -d ' ' -f 2 | cut -d\; -f 1)
3462         MIME=${MIME%$'\r'}
3463         curl $FILE | see ${MIME}:-
3464     fi
3465 }
3466
3467 # Function Usage: doc packagename
3468 #f5# \kbd{cd} to /usr/share/doc/\textit{package}
3469 doc() {
3470     emulate -L zsh
3471     cd /usr/share/doc/$1 && ls
3472 }
3473 _doc() { _files -W /usr/share/doc -/ }
3474 check_com compdef && compdef _doc doc
3475
3476 #f5# Make screenshot
3477 sshot() {
3478     [[ ! -d ~/shots  ]] && mkdir ~/shots
3479     #cd ~/shots ; sleep 5 ; import -window root -depth 8 -quality 80 `date "+%Y-%m-%d--%H:%M:%S"`.png
3480     cd ~/shots ; sleep 5; import -window root shot_`date --iso-8601=m`.jpg
3481 }
3482
3483 # list images only
3484 limg() {
3485     local -a images
3486     images=( *.{jpg,gif,png}(.N) )
3487
3488     if [[ $#images -eq 0 ]] ; then
3489         print "No image files found"
3490     else
3491         ls "$images[@]"
3492     fi
3493 }
3494
3495 #f5# Create PDF file from source code
3496 makereadable() {
3497     emulate -L zsh
3498     output=$1
3499     shift
3500     a2ps --medium A4dj -E -o $output $*
3501     ps2pdf $output
3502 }
3503
3504 # zsh with perl-regex - use it e.g. via:
3505 # regcheck '\s\d\.\d{3}\.\d{3} Euro' ' 1.000.000 Euro'
3506 #f5# Checks whether a regex matches or not.\\&\quad Example: \kbd{regcheck '.\{3\} EUR' '500 EUR'}
3507 regcheck() {
3508     emulate -L zsh
3509     zmodload -i zsh/pcre
3510     pcre_compile $1 && \
3511     pcre_match $2 && echo "regex matches" || echo "regex does not match"
3512 }
3513
3514 #f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
3515 accessed() {
3516     emulate -L zsh
3517     print -l -- *(a-${1:-1})
3518 }
3519
3520 #f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
3521 changed() {
3522     emulate -L zsh
3523     print -l -- *(c-${1:-1})
3524 }
3525
3526 #f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
3527 modified() {
3528     emulate -L zsh
3529     print -l -- *(m-${1:-1})
3530 }
3531 # modified() was named new() in earlier versions, add an alias for backwards compatibility
3532 check_com new || alias new=modified
3533
3534 #f5# Grep in history
3535 greph() {
3536     emulate -L zsh
3537     history 0 | grep $1
3538 }
3539 # use colors when GNU grep with color-support
3540 #a2# Execute \kbd{grep -{}-color=auto}
3541 (grep --help 2>/dev/null |grep -- --color) >/dev/null && alias grep='grep --color=auto'
3542 #a2# Execute \kbd{grep -i -{}-color=auto}
3543 alias GREP='grep -i --color=auto'
3544
3545 #f5# Watch manpages in a stretched style
3546 man2() { PAGER='dash -c "sed G | /usr/bin/less"' command man "$@" ; }
3547
3548 # usage example: 'lcheck strcpy'
3549 #f5# Find out which libs define a symbol
3550 lcheck() {
3551     if [[ -n "$1" ]] ; then
3552         nm -go /usr/lib/lib*.a 2>/dev/null | grep ":[[:xdigit:]]\{8\} . .*$1"
3553     else
3554         echo "Usage: lcheck <function>" >&2
3555     fi
3556 }
3557
3558 #f5# Clean up directory - remove well known tempfiles
3559 purge() {
3560     FILES=(*~(N) .*~(N) \#*\#(N) *.o(N) a.out(N) *.core(N) *.cmo(N) *.cmi(N) .*.swp(N))
3561     NBFILES=${#FILES}
3562     if [[ $NBFILES > 0 ]] ; then
3563         print $FILES
3564         local ans
3565         echo -n "Remove these files? [y/n] "
3566         read -q ans
3567         if [[ $ans == "y" ]] ; then
3568             rm ${FILES}
3569             echo ">> $PWD purged, $NBFILES files removed"
3570         else
3571             echo "Ok. .. then not.."
3572         fi
3573     fi
3574 }
3575
3576 #f5# show labels and uuids of disk devices
3577 if is439 && [[ -d /dev/disk/by-id/ ]]; then
3578     lsdisk() {
3579         emulate -L zsh
3580         setopt extendedglob
3581         local -a -U disks
3582         disks=( /dev/disk/by-id/*(@:A) )
3583         for dev in "$disks[@]"; do
3584             print ${fg_bold[red]}${dev}${reset_color} /dev/disk/by-label/*(@e/'[[ ${REPLY:A} == $dev ]] && REPLY=${fg[blue]}LABEL=${REPLY:t}${reset_color}'/N) /dev/disk/by-uuid/*(@e/'[[ ${REPLY:A} == $dev ]] && REPLY=${fg[green]}UUID=${REPLY:t}${reset_color}'/N)
3585             print -f "  %s\n" /dev/disk/by-id/*(@e/'[[ ${REPLY:A} == $dev ]]'/N:t)
3586         done
3587     }
3588 fi
3589
3590 # Translate DE<=>EN
3591 # 'translate' looks up fot a word in a file with language-to-language
3592 # translations (field separator should be " : "). A typical wordlist looks
3593 # like at follows:
3594 #  | english-word : german-transmission
3595 # It's also only possible to translate english to german but not reciprocal.
3596 # Use the following oneliner to turn back the sort order:
3597 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
3598 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
3599 #f5# Translates a word
3600 trans() {
3601     emulate -L zsh
3602     case "$1" in
3603         -[dD]*)
3604             translate -l de-en $2
3605             ;;
3606         -[eE]*)
3607             translate -l en-de $2
3608             ;;
3609         *)
3610             echo "Usage: $0 { -D | -E }"
3611             echo "         -D == German to English"
3612             echo "         -E == English to German"
3613     esac
3614 }
3615
3616 #f5# List all occurrences of programm in current PATH
3617 plap() {
3618     emulate -L zsh
3619     if [[ $# = 0 ]] ; then
3620         echo "Usage:    $0 program"
3621         echo "Example:  $0 zsh"
3622         echo "Lists all occurrences of program in the current PATH."
3623     else
3624         ls -l ${^path}/*$1*(*N)
3625     fi
3626 }
3627
3628 # Found in the mailinglistarchive from Zsh (IIRC ~1996)
3629 #f5# Select items for specific command(s) from history
3630 selhist() {
3631     emulate -L zsh
3632     local TAB=$'\t';
3633     (( $# < 1 )) && {
3634         echo "Usage: $0 command"
3635         return 1
3636     };
3637     cmd=(${(f)"$(grep -w $1 $HISTFILE | sort | uniq | pr -tn)"})
3638     print -l $cmd | less -F
3639     echo -n "enter number of desired command [1 - $(( ${#cmd[@]} - 1 ))]: "
3640     local answer
3641     read answer
3642     print -z "${cmd[$answer]#*$TAB}"
3643 }
3644
3645 # Use vim to convert plaintext to HTML
3646 #f5# Transform files to html with highlighting
3647 2html() {
3648     emulate -L zsh
3649     vim -u NONE -n -c ':syntax on' -c ':so $VIMRUNTIME/syntax/2html.vim' -c ':wqa' $1 &>/dev/null
3650 }
3651
3652 # Usage: simple-extract <file>
3653 #f5# Smart archive extractor
3654 simple-extract () {
3655     emulate -L zsh
3656     if [[ -f $1 ]] ; then
3657         case $1 in
3658             *.tar.bz2)  bzip2 -v -d $1      ;;
3659             *.tar.gz)   tar -xvzf $1        ;;
3660             *.rar)      unrar $1            ;;
3661             *.deb)      ar -x $1            ;;
3662             *.bz2)      bzip2 -d $1         ;;
3663             *.lzh)      lha x $1            ;;
3664             *.gz)       gunzip -d $1        ;;
3665             *.tar)      tar -xvf $1         ;;
3666             *.tgz)      gunzip -d $1        ;;
3667             *.tbz2)     tar -jxvf $1        ;;
3668             *.zip)      unzip $1            ;;
3669             *.Z)        uncompress $1       ;;
3670             *)          echo "'$1' Error. Please go away" ;;
3671         esac
3672     else
3673         echo "'$1' is not a valid file"
3674     fi
3675 }
3676
3677 # Usage: smartcompress <file> (<type>)
3678 #f5# Smart archive creator
3679 smartcompress() {
3680     emulate -L zsh
3681     if [[ -n $2 ]] ; then
3682         case $2 in
3683             tgz | tar.gz)   tar -zcvf$1.$2 $1 ;;
3684             tbz2 | tar.bz2) tar -jcvf$1.$2 $1 ;;
3685             tar.Z)          tar -Zcvf$1.$2 $1 ;;
3686             tar)            tar -cvf$1.$2  $1 ;;
3687             gz | gzip)      gzip           $1 ;;
3688             bz2 | bzip2)    bzip2          $1 ;;
3689             *)
3690                 echo "Error: $2 is not a valid compression type"
3691                 ;;
3692         esac
3693     else
3694         smartcompress $1 tar.gz
3695     fi
3696 }
3697
3698 # Usage: show-archive <archive>
3699 #f5# List an archive's content
3700 show-archive() {
3701     emulate -L zsh
3702     if [[ -f $1 ]] ; then
3703         case $1 in
3704             *.tar.gz)      gunzip -c $1 | tar -tf - -- ;;
3705             *.tar)         tar -tf $1 ;;
3706             *.tgz)         tar -ztf $1 ;;
3707             *.zip)         unzip -l $1 ;;
3708             *.bz2)         bzless $1 ;;
3709             *.deb)         dpkg-deb --fsys-tarfile $1 | tar -tf - -- ;;
3710             *)             echo "'$1' Error. Please go away" ;;
3711         esac
3712     else
3713         echo "'$1' is not a valid archive"
3714     fi
3715 }
3716
3717 # It's shameless stolen from <http://www.vim.org/tips/tip.php?tip_id=167>
3718 #f5# Use \kbd{vim} as your manpage reader
3719 vman() {
3720     emulate -L zsh
3721     if (( ${#argv} == 0 )); then
3722         printf 'usage: vman <topic>\n'
3723         return 1
3724     fi
3725     man "$@" | col -b | view -c 'set ft=man nomod nolist' -
3726 }
3727
3728 # function readme() { $PAGER -- (#ia3)readme* }
3729 #f5# View all README-like files in current directory in pager
3730 readme() {
3731     emulate -L zsh
3732     local files
3733     files=(./(#i)*(read*me|lue*m(in|)ut)*(ND))
3734     if (($#files)) ; then
3735         $PAGER $files
3736     else
3737         print 'No README files.'
3738     fi
3739 }
3740
3741 # function ansi-colors()
3742 #f5# Display ANSI colors
3743 ansi-colors() {
3744     typeset esc="\033[" line1 line2
3745     echo " _ _ _40 _ _ _41_ _ _ _42 _ _ 43_ _ _ 44_ _ _45 _ _ _ 46_ _ _ 47_ _ _ 49_ _"
3746     for fore in 30 31 32 33 34 35 36 37; do
3747         line1="$fore "
3748         line2="   "
3749         for back in 40 41 42 43 44 45 46 47 49; do
3750             line1="${line1}${esc}${back};${fore}m Normal ${esc}0m"
3751             line2="${line2}${esc}${back};${fore};1m Bold   ${esc}0m"
3752         done
3753         echo -e "$line1\n$line2"
3754     done
3755 }
3756
3757 #f5# Find all files in \$PATH with setuid bit set
3758 suidfind() { ls -latg $path | grep '^...s' }
3759
3760 # TODO: So, this is the third incarnation of this function!?
3761 #f5# Reload given functions
3762 refunc() {
3763     for func in $argv ; do
3764         unfunction $func
3765         autoload $func
3766     done
3767 }
3768
3769 # a small check to see which DIR is located on which server/partition.
3770 # stolen and modified from Sven's zshrc.forall
3771 #f5# Report diskusage of a directory
3772 dirspace() {
3773     emulate -L zsh
3774     if [[ -n "$1" ]] ; then
3775         for dir in "$@" ; do
3776             if [[ -d "$dir" ]] ; then
3777                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3778             else
3779                 echo "warning: $dir does not exist" >&2
3780             fi
3781         done
3782     else
3783         for dir in $path; do
3784             if [[ -d "$dir" ]] ; then
3785                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3786             else
3787                 echo "warning: $dir does not exist" >&2
3788             fi
3789         done
3790     fi
3791 }
3792
3793 # % slow_print `cat /etc/passwd`
3794 #f5# Slowly print out parameters
3795 slow_print() {
3796     for argument in "$@" ; do
3797         for ((i = 1; i <= ${#1} ;i++)) ; do
3798             print -n "${argument[i]}"
3799             sleep 0.08
3800         done
3801         print -n " "
3802     done
3803     print ""
3804 }
3805
3806 #f5# Show some status info
3807 status() {
3808     print
3809     print "Date..: "$(date "+%Y-%m-%d %H:%M:%S")
3810     print "Shell.: Zsh $ZSH_VERSION (PID = $$, $SHLVL nests)"
3811     print "Term..: $TTY ($TERM), ${BAUD:+$BAUD bauds, }$COLUMNS x $LINES chars"
3812     print "Login.: $LOGNAME (UID = $EUID) on $HOST"
3813     print "System: $(cat /etc/[A-Za-z]*[_-][rv]e[lr]*)"
3814     print "Uptime:$(uptime)"
3815     print
3816 }
3817
3818 # Rip an audio CD
3819 #f5# Rip an audio CD
3820 audiorip() {
3821     mkdir -p ~/ripps
3822     cd ~/ripps
3823     cdrdao read-cd --device $DEVICE --driver generic-mmc audiocd.toc
3824     cdrdao read-cddb --device $DEVICE --driver generic-mmc audiocd.toc
3825     echo " * Would you like to burn the cd now? (yes/no)"
3826     read input
3827     if [[ "$input" = "yes" ]] ; then
3828         echo " ! Burning Audio CD"
3829         audioburn
3830         echo " * done."
3831     else
3832         echo " ! Invalid response."
3833     fi
3834 }
3835
3836 # and burn it
3837 #f5# Burn an audio CD (in combination with audiorip)
3838 audioburn() {
3839     cd ~/ripps
3840     cdrdao write --device $DEVICE --driver generic-mmc audiocd.toc
3841     echo " * Should I remove the temporary files? (yes/no)"
3842     read input
3843     if [[ "$input" = "yes" ]] ; then
3844         echo " ! Removing Temporary Files."
3845         cd ~
3846         rm -rf ~/ripps
3847         echo " * done."
3848     else
3849         echo " ! Invalid response."
3850     fi
3851 }
3852
3853 #f5# Make an audio CD from all mp3 files
3854 mkaudiocd() {
3855     # TODO: do the renaming more zshish, possibly with zmv()
3856     emulate -L zsh
3857     cd ~/ripps
3858     for i in *.[Mm][Pp]3; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done
3859     for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`; done
3860     for i in *.mp3; do mpg123 -w `basename $i .mp3`.wav $i; done
3861     normalize -m *.wav
3862     for i in *.wav; do sox $i.wav -r 44100 $i.wav resample; done
3863 }
3864
3865 #f5# Create an ISO image. You are prompted for\\&\quad volume name, filename and directory
3866 mkiso() {
3867     emulate -L zsh
3868     echo " * Volume name "
3869     read volume
3870     echo " * ISO Name (ie. tmp.iso)"
3871     read iso
3872     echo " * Directory or File"
3873     read files
3874     mkisofs -o ~/$iso -A $volume -allow-multidot -J -R -iso-level 3 -V $volume -R $files
3875 }
3876
3877 #f5# Simple thumbnails generator
3878 genthumbs() {
3879     rm -rf thumb-* index.html
3880     echo "
3881 <html>
3882   <head>
3883     <title>Images</title>
3884   </head>
3885   <body>" > index.html
3886     for f in *.(gif|jpeg|jpg|png) ; do
3887         convert -size 100x200 "$f" -resize 100x200 thumb-"$f"
3888         echo "    <a href=\"$f\"><img src=\"thumb-$f\"></a>" >> index.html
3889     done
3890     echo "
3891   </body>
3892 </html>" >> index.html
3893 }
3894
3895 #f5# Set all ulimit parameters to \kbd{unlimited}
3896 allulimit() {
3897     ulimit -c unlimited
3898     ulimit -d unlimited
3899     ulimit -f unlimited
3900     ulimit -l unlimited
3901     ulimit -n unlimited
3902     ulimit -s unlimited
3903     ulimit -t unlimited
3904 }
3905
3906 # ogg2mp3 with bitrate of 192
3907 ogg2mp3_192() {
3908     emulate -L zsh
3909     oggdec -o - $1 | lame -b 192 - ${1:r}.mp3
3910 }
3911
3912 #f5# RFC 2396 URL encoding in Z-Shell
3913 urlencode() {
3914     emulate -L zsh
3915     setopt extendedglob
3916     input=( ${(s::)1} )
3917     print ${(j::)input/(#b)([^A-Za-z0-9_.!~*\'\(\)-])/%${(l:2::0:)$(([##16]#match))}}
3918 }
3919
3920 # http://strcat.de/blog/index.php?/archives/335-Software-sauber-deinstallieren...html
3921 #f5# Log 'make install' output
3922 mmake() {
3923     emulate -L zsh
3924     [[ ! -d ~/.errorlogs ]] && mkdir ~/.errorlogs
3925     make -n install > ~/.errorlogs/${PWD##*/}-makelog
3926 }
3927
3928 #f5# Indent source code
3929 smart-indent() {
3930     indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs "$@"
3931 }
3932
3933 # highlight important stuff in diff output, usage example: hg diff | hidiff
3934 #m# a2 hidiff \kbd{histring} oneliner for diffs
3935 check_com -c histring && \
3936     alias hidiff="histring -fE '^Comparing files .*|^diff .*' | histring -c yellow -fE '^\-.*' | histring -c green -fE '^\+.*'"
3937
3938 # rename pictures based on information found in exif headers
3939 #f5# Rename pictures based on information found in exif headers
3940 exirename() {
3941     emulate -L zsh
3942     if [[ $# -lt 1 ]] ; then
3943         echo 'Usage: jpgrename $FILES' >& 2
3944         return 1
3945     else
3946         echo -n 'Checking for jhead with version newer than 1.9: '
3947         jhead_version=`jhead -h | grep 'used by most Digital Cameras.  v.*' | awk '{print $6}' | tr -d v`
3948         if [[ $jhead_version > '1.9' ]]; then
3949             echo 'success - now running jhead.'
3950             jhead -n%Y-%m-%d_%Hh%M_%f $*
3951         else
3952             echo 'failed - exiting.'
3953         fi
3954     fi
3955 }
3956
3957 # get_ic() - queries imap servers for capabilities; real simple. no imaps
3958 ic_get() {
3959     emulate -L zsh
3960     local port
3961     if [[ ! -z $1 ]] ; then
3962         port=${2:-143}
3963         print "querying imap server on $1:${port}...\n";
3964         print "a1 capability\na2 logout\n" | nc $1 ${port}
3965     else
3966         print "usage:\n  $0 <imap-server> [port]"
3967     fi
3968 }
3969
3970 # creates a Maildir/ with its {new,cur,tmp} subdirs
3971 mkmaildir() {
3972     emulate -L zsh
3973     local root subdir
3974     root=${MAILDIR_ROOT:-${HOME}/Mail}
3975     if [[ -z ${1} ]] ; then print "Usage:\n $0 <dirname>" ; return 1 ; fi
3976     subdir=${1}
3977     mkdir -p ${root}/${subdir}/{cur,new,tmp}
3978 }
3979
3980 #f5# Change the xterm title from within GNU-screen
3981 xtrename() {
3982     emulate -L zsh
3983     if [[ $1 != "-f" ]] ; then
3984         if [[ -z ${DISPLAY} ]] ; then
3985             printf 'xtrename only makes sense in X11.\n'
3986             return 1
3987         fi
3988     else
3989         shift
3990     fi
3991     if [[ -z $1 ]] ; then
3992         printf 'usage: xtrename [-f] "title for xterm"\n'
3993         printf '  renames the title of xterm from _within_ screen.\n'
3994         printf '  also works without screen.\n'
3995         printf '  will not work if DISPLAY is unset, use -f to override.\n'
3996         return 0
3997     fi
3998     print -n "\eP\e]0;${1}\C-G\e\\"
3999     return 0
4000 }
4001
4002 # hl() highlighted less
4003 # http://ft.bewatermyfriend.org/comp/data/zsh/zfunct.html
4004 if check_com -c highlight ; then
4005     function hl() {
4006     emulate -L zsh
4007         local theme lang
4008         theme=${HL_THEME:-""}
4009         case ${1} in
4010             (-l|--list)
4011                 ( printf 'available languages (syntax parameter):\n\n' ;
4012                     highlight --list-langs ; ) | less -SMr
4013                 ;;
4014             (-t|--themes)
4015                 ( printf 'available themes (style parameter):\n\n' ;
4016                     highlight --list-themes ; ) | less -SMr
4017                 ;;
4018             (-h|--help)
4019                 printf 'usage: hl <syntax[:theme]> <file>\n'
4020                 printf '    available options: --list (-l), --themes (-t), --help (-h)\n\n'
4021                 printf '  Example: hl c main.c\n'
4022                 ;;
4023             (*)
4024                 if [[ -z ${2} ]] || (( ${#argv} > 2 )) ; then
4025                     printf 'usage: hl <syntax[:theme]> <file>\n'
4026                     printf '    available options: --list (-l), --themes (-t), --help (-h)\n'
4027                     (( ${#argv} > 2 )) && printf '  Too many arguments.\n'
4028                     return 1
4029                 fi
4030                 lang=${1%:*}
4031                 [[ ${1} == *:* ]] && [[ -n ${1#*:} ]] && theme=${1#*:}
4032                 if [[ -n ${theme} ]] ; then
4033                     highlight --xterm256 --syntax ${lang} --style ${theme} ${2} | less -SMr
4034                 else
4035                     highlight --ansi --syntax ${lang} ${2} | less -SMr
4036                 fi
4037                 ;;
4038         esac
4039         return 0
4040     }
4041     # ... and a proper completion for hl()
4042     # needs 'highlight' as well, so it fits fine in here.
4043     function _hl_genarg()  {
4044         local expl
4045         if [[ -prefix 1 *: ]] ; then
4046             local themes
4047             themes=(${${${(f)"$(LC_ALL=C highlight --list-themes)"}/ #/}:#*(Installed|Use name)*})
4048             compset -P 1 '*:'
4049             _wanted -C list themes expl theme compadd ${themes}
4050         else
4051             local langs
4052             langs=(${${${(f)"$(LC_ALL=C highlight --list-langs)"}/ #/}:#*(Installed|Use name)*})
4053             _wanted -C list languages expl languages compadd -S ':' -q ${langs}
4054         fi
4055     }
4056     function _hl_complete() {
4057         _arguments -s '1: :_hl_genarg' '2:files:_path_files'
4058     }
4059     compdef _hl_complete hl
4060 fi
4061
4062 # TODO:
4063 # Rewrite this by either using tinyurl.com's API
4064 # or using another shortening service to comply with
4065 # tinyurl.com's policy.
4066 #
4067 # Create small urls via http://tinyurl.com using wget(1).
4068 #function zurl() {
4069 #    emulate -L zsh
4070 #    [[ -z $1 ]] && { print "USAGE: zurl <URL>" ; return 1 }
4071 #
4072 #    local PN url tiny grabber search result preview
4073 #    PN=$0
4074 #    url=$1
4075 ##   Check existence of given URL with the help of ping(1).
4076 ##   N.B. ping(1) only works without an eventual given protocol.
4077 #    ping -c 1 ${${url#(ftp|http)://}%%/*} >& /dev/null || \
4078 #        read -q "?Given host ${${url#http://*/}%/*} is not reachable by pinging. Proceed anyway? [y|n] "
4079 #
4080 #    if (( $? == 0 )) ; then
4081 ##           Prepend 'http://' to given URL where necessary for later output.
4082 #            [[ ${url} != http(s|)://* ]] && url='http://'${url}
4083 #            tiny='http://tinyurl.com/create.php?url='
4084 #            if check_com -c wget ; then
4085 #                grabber='wget -O- -o/dev/null'
4086 #            else
4087 #                print "wget is not available, but mandatory for ${PN}. Aborting."
4088 #            fi
4089 ##           Looking for i.e.`copy('http://tinyurl.com/7efkze')' in TinyURL's HTML code.
4090 #            search='copy\(?http://tinyurl.com/[[:alnum:]]##*'
4091 #            result=${(M)${${${(f)"$(${=grabber} ${tiny}${url})"}[(fr)${search}*]}//[()\';]/}%%http:*}
4092 ##           TinyURL provides the rather new feature preview for more confidence. <http://tinyurl.com/preview.php>
4093 #            preview='http://preview.'${result#http://}
4094 #
4095 #            printf '%s\n\n' "${PN} - Shrinking long URLs via webservice TinyURL <http://tinyurl.com>."
4096 #            printf '%s\t%s\n\n' 'Given URL:' ${url}
4097 #            printf '%s\t%s\n\t\t%s\n' 'TinyURL:' ${result} ${preview}
4098 #    else
4099 #        return 1
4100 #    fi
4101 #}
4102
4103 #f2# Print a specific line of file(s).
4104 linenr () {
4105 # {{{
4106     emulate -L zsh
4107     if [ $# -lt 2 ] ; then
4108        print "Usage: linenr <number>[,<number>] <file>" ; return 1
4109     elif [ $# -eq 2 ] ; then
4110          local number=$1
4111          local file=$2
4112          command ed -s $file <<< "${number}n"
4113     else
4114          local number=$1
4115          shift
4116          for file in "$@" ; do
4117              if [ ! -d $file ] ; then
4118                 echo "${file}:"
4119                 command ed -s $file <<< "${number}n" 2> /dev/null
4120              else
4121                 continue
4122              fi
4123          done | less
4124     fi
4125 # }}}
4126 }
4127
4128 #f2# Find history events by search pattern and list them by date.
4129 whatwhen()  {
4130 # {{{
4131     emulate -L zsh
4132     local usage help ident format_l format_s first_char remain first last
4133     usage='USAGE: whatwhen [options] <searchstring> <search range>'
4134     help='Use `whatwhen -h'\'' for further explanations.'
4135     ident=${(l,${#${:-Usage: }},, ,)}
4136     format_l="${ident}%s\t\t\t%s\n"
4137     format_s="${format_l//(\\t)##/\\t}"
4138     # Make the first char of the word to search for case
4139     # insensitive; e.g. [aA]
4140     first_char=[${(L)1[1]}${(U)1[1]}]
4141     remain=${1[2,-1]}
4142     # Default search range is `-100'.
4143     first=${2:-\-100}
4144     # Optional, just used for `<first> <last>' given.
4145     last=$3
4146     case $1 in
4147         ("")
4148             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
4149             printf '%s\n%s\n\n' ${usage} ${help} && return 1
4150         ;;
4151         (-h)
4152             printf '%s\n\n' ${usage}
4153             print 'OPTIONS:'
4154             printf $format_l '-h' 'show help text'
4155             print '\f'
4156             print 'SEARCH RANGE:'
4157             printf $format_l "'0'" 'the whole history,'
4158             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
4159             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
4160             printf '\n%s\n' 'EXAMPLES:'
4161             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
4162             printf $format_l 'whatwhen zsh -250'
4163             printf $format_l 'whatwhen foo 1 99'
4164         ;;
4165         (\?)
4166             printf '%s\n%s\n\n' ${usage} ${help} && return 1
4167         ;;
4168         (*)
4169             # -l list results on stout rather than invoking $EDITOR.
4170             # -i Print dates as in YYYY-MM-DD.
4171             # -m Search for a - quoted - pattern within the history.
4172             fc -li -m "*${first_char}${remain}*" $first $last
4173         ;;
4174     esac
4175 # }}}
4176 }
4177
4178 # change fluxbox keys from 'Alt-#' to 'Alt-F#' and vice versa
4179 fluxkey-change() {
4180     emulate -L zsh
4181     [[ -n "$FLUXKEYS" ]] || local FLUXKEYS="$HOME/.fluxbox/keys"
4182     if ! [[ -r "$FLUXKEYS" ]] ; then
4183         echo "Sorry, \$FLUXKEYS file $FLUXKEYS could not be read - nothing to be done."
4184         return 1
4185     else
4186         if grep -q 'Mod1 F[0-9] :Workspace [0-9]' $FLUXKEYS ; then
4187             echo -n 'Switching to Alt-# mode in ~/.fluxbox/keys: '
4188             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)F\([0-9]\+[: space :]\+:Workspace.*\)|\1\2|' $FLUXKEYS && echo done || echo failed
4189         elif grep -q 'Mod1 [0-9] :Workspace [0-9]' $FLUXKEYS ; then
4190             echo -n 'Switching to Alt-F# mode in ~/.fluxbox/keys: '
4191             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)\([0-9]\+[: space :]\+:Workspace.*\)|\1F\2|' $FLUXKEYS && echo done || echo failed
4192         else
4193             echo 'Sorry, do not know what to do.'
4194             return 1
4195         fi
4196     fi
4197 }
4198
4199 # retrieve weather information on the console
4200 # Usage example: 'weather LOWG'
4201 weather() {
4202     emulate -L zsh
4203     [[ -n "$1" ]] || {
4204         print 'Usage: weather <station_id>' >&2
4205         print 'List of stations: http://en.wikipedia.org/wiki/List_of_airports_by_ICAO_code'>&2
4206         return 1
4207     }
4208
4209     local VERBOSE="yes"    # TODO: Make this a command line switch
4210
4211     local ODIR=`pwd`
4212     local PLACE="${1:u}"
4213     local DIR="${HOME}/.weather"
4214     local LOG="${DIR}/log"
4215
4216     [[ -d ${DIR} ]] || {
4217         print -n "Creating ${DIR}: "
4218         mkdir ${DIR}
4219         print 'done'
4220     }
4221
4222     print "Retrieving information for ${PLACE}:"
4223     print
4224     cd ${DIR} && wget -T 10 --no-verbose --output-file=$LOG --timestamping http://weather.noaa.gov/pub/data/observations/metar/decoded/$PLACE.TXT
4225
4226     if [[ $? -eq 0 ]] ; then
4227         if [[ -n "$VERBOSE" ]] ; then
4228             cat ${PLACE}.TXT
4229         else
4230             DATE=$(grep 'UTC' ${PLACE}.TXT | sed 's#.* /##')
4231             TEMPERATURE=$(awk '/Temperature/ { print $4" degree Celcius / " $2" degree Fahrenheit" }' ${PLACE}.TXT | tr -d '(')
4232             echo "date: $DATE"
4233             echo "temp:  $TEMPERATURE"
4234         fi
4235     else
4236         print "There was an error retrieving the weather information for $PLACE" >&2
4237         cat $LOG
4238         cd $ODIR
4239         return 1
4240     fi
4241     cd $ODIR
4242 }
4243 # }}}
4244
4245 # mercurial related stuff {{{
4246 if check_com -c hg ; then
4247     # gnu like diff for mercurial
4248     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
4249     #f5# GNU like diff for mercurial
4250     hgdi() {
4251         emulate -L zsh
4252         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
4253     }
4254
4255     # build debian package
4256     #a2# Alias for \kbd{hg-buildpackage}
4257     alias hbp='hg-buildpackage'
4258
4259     # execute commands on the versioned patch-queue from the current repos
4260     alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
4261
4262     # diffstat for specific version of a mercurial repository
4263     #   hgstat      => display diffstat between last revision and tip
4264     #   hgstat 1234 => display diffstat between revision 1234 and tip
4265     #f5# Diffstat for specific version of a mercurial repos
4266     hgstat() {
4267         emulate -L zsh
4268         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
4269     }
4270
4271 fi # end of check whether we have the 'hg'-executable
4272
4273 # }}}
4274
4275 # some useful commands often hard to remember - let's grep for them {{{
4276 # actually use our zg() function now. :)
4277
4278 # Work around ion/xterm resize bug.
4279 #if [[ "$SHLVL" -eq 1 ]]; then
4280 #       if check_com -c resize ; then
4281 #               eval `resize </dev/null`
4282 #       fi
4283 #fi
4284
4285 # enable jackd:
4286 #  /usr/bin/jackd -dalsa -dhw:0 -r48000 -p1024 -n2
4287 # now play audio file:
4288 #  alsaplayer -o jack foobar.mp3
4289
4290 # send files via netcat
4291 # on sending side:
4292 #  send() {j=$*; tar cpz ${j/%${!#}/}|nc -w 1 ${!#} 51330;}
4293 #  send dir* $HOST
4294 #  alias receive='nc -vlp 51330 | tar xzvp'
4295
4296 # debian stuff:
4297 # dh_make -e foo@localhost -f $1
4298 # dpkg-buildpackage -rfakeroot
4299 # lintian *.deb
4300 # dpkg-scanpackages ./ /dev/null | gzip > Packages.gz
4301 # dpkg-scansources . | gzip > Sources.gz
4302 # grep-dctrl --field Maintainer $* /var/lib/apt/lists/*
4303
4304 # other stuff:
4305 # convert -geometry 200x200 -interlace LINE -verbose
4306 # ldapsearch -x -b "OU=Bedienstete,O=tug" -h ldap.tugraz.at sn=$1
4307 # ps -ao user,pcpu,start,command
4308 # gpg --keyserver blackhole.pca.dfn.de --recv-keys
4309 # xterm -bg black -fg yellow -fn -misc-fixed-medium-r-normal--14-140-75-75-c-90-iso8859-15 -ah
4310 # nc -vz $1 1-1024   # portscan via netcat
4311 # wget --mirror --no-parent --convert-links
4312 # pal -d `date +%d`
4313 # autoload -U tetris; zle -N tetris; bindkey '...' ; echo "press ... for playing tennis"
4314 #
4315 # modify console cursor
4316 # see http://www.tldp.org/HOWTO/Framebuffer-HOWTO-5.html
4317 # print $'\e[?96;0;64c'
4318 # }}}
4319
4320 # grml-small cleanups {{{
4321
4322 # The following is used to remove zsh-config-items that do not work
4323 # in grml-small by default.
4324 # If you do not want these adjustments (for whatever reason), set
4325 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
4326 # sources if it is there).
4327
4328 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
4329
4330     unset abk[V]
4331     unalias    'V'      &> /dev/null
4332     unfunction vman     &> /dev/null
4333     unfunction viless   &> /dev/null
4334     unfunction 2html    &> /dev/null
4335
4336     # manpages are not in grmlsmall
4337     unfunction manzsh   &> /dev/null
4338     unfunction man2     &> /dev/null
4339
4340 fi
4341
4342 #}}}
4343
4344 zrclocal
4345
4346 ## genrefcard.pl settings {{{
4347
4348 ### doc strings for external functions from files
4349 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
4350
4351 ### example: split functions-search 8,16,24,32
4352 #@# split functions-search 8
4353
4354 ## }}}
4355
4356 ## END OF FILE #################################################################
4357 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
4358 # Local variables:
4359 # mode: sh
4360 # End: