reduce unneeded filesystem seeks
[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 # zsh profiling
106 # just execute 'ZSH_PROFILE_RC=1 zsh' and run 'zprof' to get the details
107 if [[ $ZSH_PROFILE_RC -gt 0 ]] ; then
108     zmodload zsh/zprof
109 fi
110
111 # load .zshrc.pre to give the user the chance to overwrite the defaults
112 [[ -r ${ZDOTDIR:-${HOME}}/.zshrc.pre ]] && source ${ZDOTDIR:-${HOME}}/.zshrc.pre
113
114 # check for version/system
115 # check for versions (compatibility reasons)
116 function is4 () {
117     [[ $ZSH_VERSION == <4->* ]] && return 0
118     return 1
119 }
120
121 function is41 () {
122     [[ $ZSH_VERSION == 4.<1->* || $ZSH_VERSION == <5->* ]] && return 0
123     return 1
124 }
125
126 function is42 () {
127     [[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
128     return 1
129 }
130
131 function is425 () {
132     [[ $ZSH_VERSION == 4.2.<5->* || $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
133     return 1
134 }
135
136 function is43 () {
137     [[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
138     return 1
139 }
140
141 function is433 () {
142     [[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == 4.<4->* \
143                                  || $ZSH_VERSION == <5->* ]] && return 0
144     return 1
145 }
146
147 function is437 () {
148     [[ $ZSH_VERSION == 4.3.<7->* || $ZSH_VERSION == 4.<4->* \
149                                  || $ZSH_VERSION == <5->* ]] && return 0
150     return 1
151 }
152
153 function is439 () {
154     [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* \
155                                  || $ZSH_VERSION == <5->* ]] && return 0
156     return 1
157 }
158
159 #f1# Checks whether or not you're running grml
160 function isgrml () {
161     [[ -f /etc/grml_version ]] && return 0
162     return 1
163 }
164
165 #f1# Checks whether or not you're running a grml cd
166 function isgrmlcd () {
167     [[ -f /etc/grml_cd ]] && return 0
168     return 1
169 }
170
171 if isgrml ; then
172 #f1# Checks whether or not you're running grml-small
173     function isgrmlsmall () {
174         if [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]]; then
175             return 0
176         fi
177         return 1
178     }
179 else
180     function isgrmlsmall () { return 1 }
181 fi
182
183 GRML_OSTYPE=$(uname -s)
184
185 function islinux () {
186     [[ $GRML_OSTYPE == "Linux" ]]
187 }
188
189 function isdarwin () {
190     [[ $GRML_OSTYPE == "Darwin" ]]
191 }
192
193 function isfreebsd () {
194     [[ $GRML_OSTYPE == "FreeBSD" ]]
195 }
196
197 function isopenbsd () {
198     [[ $GRML_OSTYPE == "OpenBSD" ]]
199 }
200
201 function issolaris () {
202     [[ $GRML_OSTYPE == "SunOS" ]]
203 }
204
205 #f1# are we running within an utf environment?
206 function isutfenv () {
207     case "$LANG $CHARSET $LANGUAGE" in
208         *utf*) return 0 ;;
209         *UTF*) return 0 ;;
210         *)     return 1 ;;
211     esac
212 }
213
214 # check for user, if not running as root set $SUDO to sudo
215 (( EUID != 0 )) && SUDO='sudo' || SUDO=''
216
217 # change directory to home on first invocation of zsh
218 # important for rungetty -> autologin
219 # Thanks go to Bart Schaefer!
220 isgrml && function checkhome () {
221     if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
222         export ALREADY_DID_CD_HOME=$HOME
223         cd
224     fi
225 }
226
227 # check for zsh v3.1.7+
228
229 if ! [[ ${ZSH_VERSION} == 3.1.<7->*      \
230      || ${ZSH_VERSION} == 3.<2->.<->*    \
231      || ${ZSH_VERSION} == <4->.<->*   ]] ; then
232
233     printf '-!-\n'
234     printf '-!- In this configuration we try to make use of features, that only\n'
235     printf '-!- require version 3.1.7 of the shell; That way this setup can be\n'
236     printf '-!- used with a wide range of zsh versions, while using fairly\n'
237     printf '-!- advanced features in all supported versions.\n'
238     printf '-!-\n'
239     printf '-!- However, you are running zsh version %s.\n' "$ZSH_VERSION"
240     printf '-!-\n'
241     printf '-!- While this *may* work, it might as well fail.\n'
242     printf '-!- Please consider updating to at least version 3.1.7 of zsh.\n'
243     printf '-!-\n'
244     printf '-!- DO NOT EXPECT THIS TO WORK FLAWLESSLY!\n'
245     printf '-!- If it does today, you'\''ve been lucky.\n'
246     printf '-!-\n'
247     printf '-!- Ye been warned!\n'
248     printf '-!-\n'
249
250     function zstyle () { : }
251 fi
252
253 # autoload wrapper - use this one instead of autoload directly
254 # We need to define this function as early as this, because autoloading
255 # 'is-at-least()' needs it.
256 function zrcautoload () {
257     emulate -L zsh
258     setopt extended_glob
259     local fdir ffile
260     local -i ffound
261
262     ffile=$1
263     (( ffound = 0 ))
264     for fdir in ${fpath} ; do
265         [[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
266     done
267
268     (( ffound == 0 )) && return 1
269     if [[ $ZSH_VERSION == 3.1.<6-> || $ZSH_VERSION == <4->* ]] ; then
270         autoload -U ${ffile} || return 1
271     else
272         autoload ${ffile} || return 1
273     fi
274     return 0
275 }
276
277 # The following is the â€˜add-zsh-hook’ function from zsh upstream. It is
278 # included here to make the setup work with older versions of zsh (prior to
279 # 4.3.7) in which this function had a bug that triggers annoying errors during
280 # shell startup. This is exactly upstreams code from f0068edb4888a4d8fe94def,
281 # with just a few adjustments in coding style to make the function look more
282 # compact. This definition can be removed as soon as we raise the minimum
283 # version requirement to 4.3.7 or newer.
284 function add-zsh-hook () {
285     # Add to HOOK the given FUNCTION.
286     # HOOK is one of chpwd, precmd, preexec, periodic, zshaddhistory,
287     # zshexit, zsh_directory_name (the _functions subscript is not required).
288     #
289     # With -d, remove the function from the hook instead; delete the hook
290     # variable if it is empty.
291     #
292     # -D behaves like -d, but pattern characters are active in the function
293     # name, so any matching function will be deleted from the hook.
294     #
295     # Without -d, the FUNCTION is marked for autoload; -U is passed down to
296     # autoload if that is given, as are -z and -k. (This is harmless if the
297     # function is actually defined inline.)
298     emulate -L zsh
299     local -a hooktypes
300     hooktypes=(
301         chpwd precmd preexec periodic zshaddhistory zshexit
302         zsh_directory_name
303     )
304     local usage="Usage: $0 hook function\nValid hooks are:\n  $hooktypes"
305     local opt
306     local -a autoopts
307     integer del list help
308     while getopts "dDhLUzk" opt; do
309         case $opt in
310         (d) del=1 ;;
311         (D) del=2 ;;
312         (h) help=1 ;;
313         (L) list=1 ;;
314         ([Uzk]) autoopts+=(-$opt) ;;
315         (*) return 1 ;;
316         esac
317     done
318     shift $(( OPTIND - 1 ))
319     if (( list )); then
320         typeset -mp "(${1:-${(@j:|:)hooktypes}})_functions"
321         return $?
322     elif (( help || $# != 2 || ${hooktypes[(I)$1]} == 0 )); then
323         print -u$(( 2 - help )) $usage
324         return $(( 1 - help ))
325     fi
326     local hook="${1}_functions"
327     local fn="$2"
328     if (( del )); then
329         # delete, if hook is set
330         if (( ${(P)+hook} )); then
331             if (( del == 2 )); then
332                 set -A $hook ${(P)hook:#${~fn}}
333             else
334                 set -A $hook ${(P)hook:#$fn}
335             fi
336             # unset if no remaining entries --- this can give better
337             # performance in some cases
338             if (( ! ${(P)#hook} )); then
339                 unset $hook
340             fi
341         fi
342     else
343         if (( ${(P)+hook} )); then
344             if (( ${${(P)hook}[(I)$fn]} == 0 )); then
345                 set -A $hook ${(P)hook} $fn
346             fi
347         else
348             set -A $hook $fn
349         fi
350         autoload $autoopts -- $fn
351     fi
352 }
353
354 # Load is-at-least() for more precise version checks Note that this test will
355 # *always* fail, if the is-at-least function could not be marked for
356 # autoloading.
357 zrcautoload is-at-least || function is-at-least () { return 1 }
358
359 # set some important options (as early as possible)
360
361 # append history list to the history file; this is the default but we make sure
362 # because it's required for share_history.
363 setopt append_history
364
365 # import new commands from the history file also in other zsh-session
366 is4 && setopt share_history
367
368 # save each command's beginning timestamp and the duration to the history file
369 setopt extended_history
370
371 # If a new command line being added to the history list duplicates an older
372 # one, the older command is removed from the list
373 is4 && setopt histignorealldups
374
375 # remove command lines from the history list when the first character on the
376 # line is a space
377 setopt histignorespace
378
379 # if a command is issued that can't be executed as a normal command, and the
380 # command is the name of a directory, perform the cd command to that directory.
381 setopt auto_cd
382
383 # in order to use #, ~ and ^ for filename generation grep word
384 # *~(*.gz|*.bz|*.bz2|*.zip|*.Z) -> searches for word not in compressed files
385 # don't forget to quote '^', '~' and '#'!
386 setopt extended_glob
387
388 # display PID when suspending processes as well
389 setopt longlistjobs
390
391 # report the status of backgrounds jobs immediately
392 setopt notify
393
394 # whenever a command completion is attempted, make sure the entire command path
395 # is hashed first.
396 setopt hash_list_all
397
398 # not just at the end
399 setopt completeinword
400
401 # Don't send SIGHUP to background processes when the shell exits.
402 setopt nohup
403
404 # make cd push the old directory onto the directory stack.
405 setopt auto_pushd
406
407 # avoid "beep"ing
408 setopt nobeep
409
410 # don't push the same dir twice.
411 setopt pushd_ignore_dups
412
413 # * shouldn't match dotfiles. ever.
414 setopt noglobdots
415
416 # use zsh style word splitting
417 setopt noshwordsplit
418
419 # don't error out when unset parameters are used
420 setopt unset
421
422 # setting some default values
423 NOCOR=${NOCOR:-0}
424 NOMENU=${NOMENU:-0}
425 NOPRECMD=${NOPRECMD:-0}
426 COMMAND_NOT_FOUND=${COMMAND_NOT_FOUND:-0}
427 GRML_ZSH_CNF_HANDLER=${GRML_ZSH_CNF_HANDLER:-/usr/share/command-not-found/command-not-found}
428 GRML_DISPLAY_BATTERY=${GRML_DISPLAY_BATTERY:-${BATTERY:-0}}
429 GRMLSMALL_SPECIFIC=${GRMLSMALL_SPECIFIC:-1}
430 ZSH_NO_DEFAULT_LOCALE=${ZSH_NO_DEFAULT_LOCALE:-0}
431
432 typeset -ga ls_options
433 typeset -ga grep_options
434 if ls --color=auto / >/dev/null 2>&1; then
435     ls_options+=( --color=auto )
436 elif ls -G / >/dev/null 2>&1; then
437     ls_options+=( -G )
438 fi
439 if grep --color=auto -q "a" <<< "a" >/dev/null 2>&1; then
440     grep_options+=( --color=auto )
441 fi
442
443 # utility functions
444 # this function checks if a command exists and returns either true
445 # or false. This avoids using 'which' and 'whence', which will
446 # avoid problems with aliases for which on certain weird systems. :-)
447 # Usage: check_com [-c|-g] word
448 #   -c  only checks for external commands
449 #   -g  does the usual tests and also checks for global aliases
450 function check_com () {
451     emulate -L zsh
452     local -i comonly gatoo
453     comonly=0
454     gatoo=0
455
456     if [[ $1 == '-c' ]] ; then
457         comonly=1
458         shift 1
459     elif [[ $1 == '-g' ]] ; then
460         gatoo=1
461         shift 1
462     fi
463
464     if (( ${#argv} != 1 )) ; then
465         printf 'usage: check_com [-c|-g] <command>\n' >&2
466         return 1
467     fi
468
469     if (( comonly > 0 )) ; then
470         (( ${+commands[$1]}  )) && return 0
471         return 1
472     fi
473
474     if     (( ${+commands[$1]}    )) \
475         || (( ${+functions[$1]}   )) \
476         || (( ${+aliases[$1]}     )) \
477         || (( ${+reswords[(r)$1]} )) ; then
478         return 0
479     fi
480
481     if (( gatoo > 0 )) && (( ${+galiases[$1]} )) ; then
482         return 0
483     fi
484
485     return 1
486 }
487
488 # creates an alias and precedes the command with
489 # sudo if $EUID is not zero.
490 function salias () {
491     emulate -L zsh
492     local only=0 ; local multi=0
493     local key val
494     while getopts ":hao" opt; do
495         case $opt in
496             o) only=1 ;;
497             a) multi=1 ;;
498             h)
499                 printf 'usage: salias [-hoa] <alias-expression>\n'
500                 printf '  -h      shows this help text.\n'
501                 printf '  -a      replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
502                 printf '          be careful using this option.\n'
503                 printf '  -o      only sets an alias if a preceding sudo would be needed.\n'
504                 return 0
505                 ;;
506             *) salias -h >&2; return 1 ;;
507         esac
508     done
509     shift "$((OPTIND-1))"
510
511     if (( ${#argv} > 1 )) ; then
512         printf 'Too many arguments %s\n' "${#argv}"
513         return 1
514     fi
515
516     key="${1%%\=*}" ;  val="${1#*\=}"
517     if (( EUID == 0 )) && (( only == 0 )); then
518         alias -- "${key}=${val}"
519     elif (( EUID > 0 )) ; then
520         (( multi > 0 )) && val="${val// ; / ; sudo }"
521         alias -- "${key}=sudo ${val}"
522     fi
523
524     return 0
525 }
526
527 # Check if we can read given files and source those we can.
528 function xsource () {
529     if (( ${#argv} < 1 )) ; then
530         printf 'usage: xsource FILE(s)...\n' >&2
531         return 1
532     fi
533
534     while (( ${#argv} > 0 )) ; do
535         [[ -r "$1" ]] && source "$1"
536         shift
537     done
538     return 0
539 }
540
541 # Check if we can read a given file and 'cat(1)' it.
542 function xcat () {
543     emulate -L zsh
544     if (( ${#argv} != 1 )) ; then
545         printf 'usage: xcat FILE\n' >&2
546         return 1
547     fi
548
549     [[ -r $1 ]] && cat $1
550     return 0
551 }
552
553 # Remove these functions again, they are of use only in these
554 # setup files. This should be called at the end of .zshrc.
555 function xunfunction () {
556     emulate -L zsh
557     local -a funcs
558     local func
559     funcs=(salias xcat xsource xunfunction zrcautoload zrcautozle)
560     for func in $funcs ; do
561         [[ -n ${functions[$func]} ]] \
562             && unfunction $func
563     done
564     return 0
565 }
566
567 # this allows us to stay in sync with grml's zshrc and put own
568 # modifications in ~/.zshrc.local
569 function zrclocal () {
570     xsource "/etc/zsh/zshrc.local"
571     xsource "${ZDOTDIR:-${HOME}}/.zshrc.local"
572     return 0
573 }
574
575 # locale setup
576 if (( ZSH_NO_DEFAULT_LOCALE == 0 )); then
577     xsource "/etc/default/locale"
578 fi
579
580 for var in LANG LC_ALL LC_MESSAGES ; do
581     [[ -n ${(P)var} ]] && export $var
582 done
583 builtin unset -v var
584
585 # set some variables
586 if check_com -c vim ; then
587 #v#
588     export EDITOR=${EDITOR:-vim}
589 else
590     export EDITOR=${EDITOR:-vi}
591 fi
592
593 #v#
594 export PAGER=${PAGER:-less}
595
596 #v#
597 export MAIL=${MAIL:-/var/mail/$USER}
598
599 # color setup for ls:
600 check_com -c dircolors && eval $(dircolors -b)
601 # color setup for ls on OS X / FreeBSD:
602 isdarwin && export CLICOLOR=1
603 isfreebsd && export CLICOLOR=1
604
605 # do MacPorts setup on darwin
606 if isdarwin && [[ -d /opt/local ]]; then
607     # Note: PATH gets set in /etc/zprofile on Darwin, so this can't go into
608     # zshenv.
609     PATH="/opt/local/bin:/opt/local/sbin:$PATH"
610     MANPATH="/opt/local/share/man:$MANPATH"
611 fi
612 # do Fink setup on darwin
613 isdarwin && xsource /sw/bin/init.sh
614
615 # load our function and completion directories
616 for fdir in /usr/share/grml/zsh/completion /usr/share/grml/zsh/functions; do
617     fpath=( ${fdir} ${fdir}/**/*(/N) ${fpath} )
618 done
619 unset -v fdir
620 autoload -U /usr/share/grml/zsh/functions/**/[^_]*[^~](N.:t)
621
622 # support colors in less
623 export LESS_TERMCAP_mb=$'\E[01;31m'
624 export LESS_TERMCAP_md=$'\E[01;31m'
625 export LESS_TERMCAP_me=$'\E[0m'
626 export LESS_TERMCAP_se=$'\E[0m'
627 export LESS_TERMCAP_so=$'\E[01;44;33m'
628 export LESS_TERMCAP_ue=$'\E[0m'
629 export LESS_TERMCAP_us=$'\E[01;32m'
630
631 # mailchecks
632 MAILCHECK=30
633
634 # report about cpu-/system-/user-time of command if running longer than
635 # 5 seconds
636 REPORTTIME=5
637
638 # watch for everyone but me and root
639 watch=(notme root)
640
641 # automatically remove duplicates from these arrays
642 typeset -U path PATH cdpath CDPATH fpath FPATH manpath MANPATH
643
644 # Load a few modules
645 is4 && \
646 for mod in parameter complist deltochar mathfunc ; do
647     zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
648 done && builtin unset -v mod
649
650 # autoload zsh modules when they are referenced
651 if is4 ; then
652     zmodload -a  zsh/stat    zstat
653     zmodload -a  zsh/zpty    zpty
654     zmodload -ap zsh/mapfile mapfile
655 fi
656
657 # completion system
658 COMPDUMPFILE=${COMPDUMPFILE:-${ZDOTDIR:-${HOME}}/.zcompdump}
659 if zrcautoload compinit ; then
660     compinit -d ${COMPDUMPFILE} || print 'Notice: no compinit available :('
661 else
662     print 'Notice: no compinit available :('
663     function compdef { }
664 fi
665
666 # completion system
667
668 # called later (via is4 && grmlcomp)
669 # note: use 'zstyle' for getting current settings
670 #         press ^xh (control-x h) for getting tags in context; ^x? (control-x ?) to run complete_debug with trace output
671 function grmlcomp () {
672     # TODO: This could use some additional information
673
674     # Make sure the completion system is initialised
675     (( ${+_comps} )) || return 1
676
677     # allow one error for every three characters typed in approximate completer
678     zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
679
680     # don't complete backup files as executables
681     zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
682
683     # start menu completion only if it could find no unambiguous initial string
684     zstyle ':completion:*:correct:*'       insert-unambiguous true
685     zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
686     zstyle ':completion:*:correct:*'       original true
687
688     # activate color-completion
689     zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}
690
691     # format on completion
692     zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
693
694     # automatically complete 'cd -<tab>' and 'cd -<ctrl-d>' with menu
695     # zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
696
697     # insert all expansions for expand completer
698     zstyle ':completion:*:expand:*'        tag-order all-expansions
699     zstyle ':completion:*:history-words'   list false
700
701     # activate menu
702     zstyle ':completion:*:history-words'   menu yes
703
704     # ignore duplicate entries
705     zstyle ':completion:*:history-words'   remove-all-dups yes
706     zstyle ':completion:*:history-words'   stop yes
707
708     # match uppercase from lowercase
709     zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'
710
711     # separate matches into groups
712     zstyle ':completion:*:matches'         group 'yes'
713     zstyle ':completion:*'                 group-name ''
714
715     if [[ "$NOMENU" -eq 0 ]] ; then
716         # if there are more than 5 options allow selecting from a menu
717         zstyle ':completion:*'               menu select=5
718     else
719         # don't use any menus at all
720         setopt no_auto_menu
721     fi
722
723     zstyle ':completion:*:messages'        format '%d'
724     zstyle ':completion:*:options'         auto-description '%d'
725
726     # describe options in full
727     zstyle ':completion:*:options'         description 'yes'
728
729     # on processes completion complete all user processes
730     zstyle ':completion:*:processes'       command 'ps -au$USER'
731
732     # offer indexes before parameters in subscripts
733     zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
734
735     # provide verbose completion information
736     zstyle ':completion:*'                 verbose true
737
738     # recent (as of Dec 2007) zsh versions are able to provide descriptions
739     # for commands (read: 1st word in the line) that it will list for the user
740     # to choose from. The following disables that, because it's not exactly fast.
741     zstyle ':completion:*:-command-:*:'    verbose false
742
743     # set format for warnings
744     zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
745
746     # define files to ignore for zcompile
747     zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
748     zstyle ':completion:correct:'          prompt 'correct to: %e'
749
750     # Ignore completion functions for commands you don't have:
751     zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
752
753     # Provide more processes in completion of programs like killall:
754     zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'
755
756     # complete manual by their section
757     zstyle ':completion:*:manuals'    separate-sections true
758     zstyle ':completion:*:manuals.*'  insert-sections   true
759     zstyle ':completion:*:man:*'      menu yes select
760
761     # Search path for sudo completion
762     zstyle ':completion:*:sudo:*' command-path /usr/local/sbin \
763                                                /usr/local/bin  \
764                                                /usr/sbin       \
765                                                /usr/bin        \
766                                                /sbin           \
767                                                /bin            \
768                                                /usr/X11R6/bin
769
770     # provide .. as a completion
771     zstyle ':completion:*' special-dirs ..
772
773     # run rehash on completion so new installed program are found automatically:
774     function _force_rehash () {
775         (( CURRENT == 1 )) && rehash
776         return 1
777     }
778
779     ## correction
780     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
781     if [[ "$NOCOR" -gt 0 ]] ; then
782         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
783         setopt nocorrect
784     else
785         # try to be smart about when to use what completer...
786         setopt correct
787         zstyle -e ':completion:*' completer '
788             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
789                 _last_try="$HISTNO$BUFFER$CURSOR"
790                 reply=(_complete _match _ignored _prefix _files)
791             else
792                 if [[ $words[1] == (rm|mv) ]] ; then
793                     reply=(_complete _files)
794                 else
795                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
796                 fi
797             fi'
798     fi
799
800     # command for process lists, the local web server details and host completion
801     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
802
803     # Some functions, like _apt and _dpkg, are very slow. We can use a cache in
804     # order to speed things up
805     if [[ ${GRML_COMP_CACHING:-yes} == yes ]]; then
806         GRML_COMP_CACHE_DIR=${GRML_COMP_CACHE_DIR:-${ZDOTDIR:-$HOME}/.cache}
807         if [[ ! -d ${GRML_COMP_CACHE_DIR} ]]; then
808             command mkdir -p "${GRML_COMP_CACHE_DIR}"
809         fi
810         zstyle ':completion:*' use-cache  yes
811         zstyle ':completion:*:complete:*' cache-path "${GRML_COMP_CACHE_DIR}"
812     fi
813
814     # host completion
815     if is42 ; then
816         [[ -r ~/.ssh/config ]] && _ssh_config_hosts=(${${(s: :)${(ps:\t:)${${(@M)${(f)"$(<$HOME/.ssh/config)"}:#Host *}#Host }}}:#*[*?]*}) || _ssh_config_hosts=()
817         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
818         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
819     else
820         _ssh_config_hosts=()
821         _ssh_hosts=()
822         _etc_hosts=()
823     fi
824     hosts=(
825         $(hostname)
826         "$_ssh_config_hosts[@]"
827         "$_ssh_hosts[@]"
828         "$_etc_hosts[@]"
829         localhost
830     )
831     zstyle ':completion:*:hosts' hosts $hosts
832     # TODO: so, why is this here?
833     #  zstyle '*' hosts $hosts
834
835     # use generic completion system for programs not yet defined; (_gnu_generic works
836     # with commands that provide a --help option with "standard" gnu-like output.)
837     for compcom in cp deborphan df feh fetchipac gpasswd head hnb ipacsum mv \
838                    pal stow uname ; do
839         [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
840     done; unset compcom
841
842     # see upgrade function in this file
843     compdef _hosts upgrade
844 }
845
846 # Keyboard setup: The following is based on the same code, we wrote for
847 # debian's setup. It ensures the terminal is in the right mode, when zle is
848 # active, so the values from $terminfo are valid. Therefore, this setup should
849 # work on all systems, that have support for `terminfo'. It also requires the
850 # zsh in use to have the `zsh/terminfo' module built.
851 #
852 # If you are customising your `zle-line-init()' or `zle-line-finish()'
853 # functions, make sure you call the following utility functions in there:
854 #
855 #     - zle-line-init():      zle-smkx
856 #     - zle-line-finish():    zle-rmkx
857
858 # Use emacs-like key bindings by default:
859 bindkey -e
860
861 # Custom widgets:
862
863 ## beginning-of-line OR beginning-of-buffer OR beginning of history
864 ## by: Bart Schaefer <schaefer@brasslantern.com>, Bernhard Tittelbach
865 function beginning-or-end-of-somewhere () {
866     local hno=$HISTNO
867     if [[ ( "${LBUFFER[-1]}" == $'\n' && "${WIDGET}" == beginning-of* ) || \
868       ( "${RBUFFER[1]}" == $'\n' && "${WIDGET}" == end-of* ) ]]; then
869         zle .${WIDGET:s/somewhere/buffer-or-history/} "$@"
870     else
871         zle .${WIDGET:s/somewhere/line-hist/} "$@"
872         if (( HISTNO != hno )); then
873             zle .${WIDGET:s/somewhere/buffer-or-history/} "$@"
874         fi
875     fi
876 }
877 zle -N beginning-of-somewhere beginning-or-end-of-somewhere
878 zle -N end-of-somewhere beginning-or-end-of-somewhere
879
880 # add a command line to the shells history without executing it
881 function commit-to-history () {
882     print -s ${(z)BUFFER}
883     zle send-break
884 }
885 zle -N commit-to-history
886
887 # only slash should be considered as a word separator:
888 function slash-backward-kill-word () {
889     local WORDCHARS="${WORDCHARS:s@/@}"
890     # zle backward-word
891     zle backward-kill-word
892 }
893 zle -N slash-backward-kill-word
894
895 # a generic accept-line wrapper
896
897 # This widget can prevent unwanted autocorrections from command-name
898 # to _command-name, rehash automatically on enter and call any number
899 # of builtin and user-defined widgets in different contexts.
900 #
901 # For a broader description, see:
902 # <http://bewatermyfriend.org/posts/2007/12-26.11-50-38-tooltime.html>
903 #
904 # The code is imported from the file 'zsh/functions/accept-line' from
905 # <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>, which
906 # distributed under the same terms as zsh itself.
907
908 # A newly added command will may not be found or will cause false
909 # correction attempts, if you got auto-correction set. By setting the
910 # following style, we force accept-line() to rehash, if it cannot
911 # find the first word on the command line in the $command[] hash.
912 zstyle ':acceptline:*' rehash true
913
914 function Accept-Line () {
915     setopt localoptions noksharrays
916     local -a subs
917     local -xi aldone
918     local sub
919     local alcontext=${1:-$alcontext}
920
921     zstyle -a ":acceptline:${alcontext}" actions subs
922
923     (( ${#subs} < 1 )) && return 0
924
925     (( aldone = 0 ))
926     for sub in ${subs} ; do
927         [[ ${sub} == 'accept-line' ]] && sub='.accept-line'
928         zle ${sub}
929
930         (( aldone > 0 )) && break
931     done
932 }
933
934 function Accept-Line-getdefault () {
935     emulate -L zsh
936     local default_action
937
938     zstyle -s ":acceptline:${alcontext}" default_action default_action
939     case ${default_action} in
940         ((accept-line|))
941             printf ".accept-line"
942             ;;
943         (*)
944             printf ${default_action}
945             ;;
946     esac
947 }
948
949 function Accept-Line-HandleContext () {
950     zle Accept-Line
951
952     default_action=$(Accept-Line-getdefault)
953     zstyle -T ":acceptline:${alcontext}" call_default \
954         && zle ${default_action}
955 }
956
957 function accept-line () {
958     setopt localoptions noksharrays
959     local -a cmdline
960     local -x alcontext
961     local buf com fname format msg default_action
962
963     alcontext='default'
964     buf="${BUFFER}"
965     cmdline=(${(z)BUFFER})
966     com="${cmdline[1]}"
967     fname="_${com}"
968
969     Accept-Line 'preprocess'
970
971     zstyle -t ":acceptline:${alcontext}" rehash \
972         && [[ -z ${commands[$com]} ]]           \
973         && rehash
974
975     if    [[ -n ${com}               ]] \
976        && [[ -n ${reswords[(r)$com]} ]] \
977        || [[ -n ${aliases[$com]}     ]] \
978        || [[ -n ${functions[$com]}   ]] \
979        || [[ -n ${builtins[$com]}    ]] \
980        || [[ -n ${commands[$com]}    ]] ; then
981
982         # there is something sensible to execute, just do it.
983         alcontext='normal'
984         Accept-Line-HandleContext
985
986         return
987     fi
988
989     if    [[ -o correct              ]] \
990        || [[ -o correctall           ]] \
991        && [[ -n ${functions[$fname]} ]] ; then
992
993         # nothing there to execute but there is a function called
994         # _command_name; a completion widget. Makes no sense to
995         # call it on the commandline, but the correct{,all} options
996         # will ask for it nevertheless, so warn the user.
997         if [[ ${LASTWIDGET} == 'accept-line' ]] ; then
998             # Okay, we warned the user before, he called us again,
999             # so have it his way.
1000             alcontext='force'
1001             Accept-Line-HandleContext
1002
1003             return
1004         fi
1005
1006         if zstyle -t ":acceptline:${alcontext}" nocompwarn ; then
1007             alcontext='normal'
1008             Accept-Line-HandleContext
1009         else
1010             # prepare warning message for the user, configurable via zstyle.
1011             zstyle -s ":acceptline:${alcontext}" compwarnfmt msg
1012
1013             if [[ -z ${msg} ]] ; then
1014                 msg="%c will not execute and completion %f exists."
1015             fi
1016
1017             zformat -f msg "${msg}" "c:${com}" "f:${fname}"
1018
1019             zle -M -- "${msg}"
1020         fi
1021         return
1022     elif [[ -n ${buf//[$' \t\n']##/} ]] ; then
1023         # If we are here, the commandline contains something that is not
1024         # executable, which is neither subject to _command_name correction
1025         # and is not empty. might be a variable assignment
1026         alcontext='misc'
1027         Accept-Line-HandleContext
1028
1029         return
1030     fi
1031
1032     # If we got this far, the commandline only contains whitespace, or is empty.
1033     alcontext='empty'
1034     Accept-Line-HandleContext
1035 }
1036
1037 zle -N accept-line
1038 zle -N Accept-Line
1039 zle -N Accept-Line-HandleContext
1040
1041 # power completion / abbreviation expansion / buffer expansion
1042 # see http://zshwiki.org/home/examples/zleiab for details
1043 # less risky than the global aliases but powerful as well
1044 # just type the abbreviation key and afterwards 'ctrl-x .' to expand it
1045 declare -A abk
1046 setopt extendedglob
1047 setopt interactivecomments
1048 abk=(
1049 #   key   # value                  (#d additional doc string)
1050 #A# start
1051     '...'  '../..'
1052     '....' '../../..'
1053     'BG'   '& exit'
1054     'C'    '| wc -l'
1055     'G'    '|& grep '${grep_options:+"${grep_options[*]}"}
1056     'H'    '| head'
1057     'Hl'   ' --help |& less -r'    #d (Display help in pager)
1058     'L'    '| less'
1059     'LL'   '|& less -r'
1060     'M'    '| most'
1061     'N'    '&>/dev/null'           #d (No Output)
1062     'R'    '| tr A-z N-za-m'       #d (ROT13)
1063     'SL'   '| sort | less'
1064     'S'    '| sort -u'
1065     'T'    '| tail'
1066     'V'    '|& vim -'
1067 #A# end
1068     'co'   './configure && make && sudo make install'
1069 )
1070
1071 function zleiab () {
1072     emulate -L zsh
1073     setopt extendedglob
1074     local MATCH
1075
1076     LBUFFER=${LBUFFER%%(#m)[.\-+:|_a-zA-Z0-9]#}
1077     LBUFFER+=${abk[$MATCH]:-$MATCH}
1078 }
1079
1080 zle -N zleiab
1081
1082 function help-show-abk () {
1083   zle -M "$(print "Available abbreviations for expansion:"; print -a -C 2 ${(kv)abk})"
1084 }
1085
1086 zle -N help-show-abk
1087
1088 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
1089 function insert-datestamp () { LBUFFER+=${(%):-'%D{%Y-%m-%d}'}; }
1090 zle -N insert-datestamp
1091
1092 # press esc-m for inserting last typed word again (thanks to caphuso!)
1093 function insert-last-typed-word () { zle insert-last-word -- 0 -1 };
1094 zle -N insert-last-typed-word;
1095
1096 function grml-zsh-fg () {
1097   if (( ${#jobstates} )); then
1098     zle .push-input
1099     [[ -o hist_ignore_space ]] && BUFFER=' ' || BUFFER=''
1100     BUFFER="${BUFFER}fg"
1101     zle .accept-line
1102   else
1103     zle -M 'No background jobs. Doing nothing.'
1104   fi
1105 }
1106 zle -N grml-zsh-fg
1107
1108 # run command line as user root via sudo:
1109 function sudo-command-line () {
1110     [[ -z $BUFFER ]] && zle up-history
1111     if [[ $BUFFER != sudo\ * ]]; then
1112         BUFFER="sudo $BUFFER"
1113         CURSOR=$(( CURSOR+5 ))
1114     fi
1115 }
1116 zle -N sudo-command-line
1117
1118 ### jump behind the first word on the cmdline.
1119 ### useful to add options.
1120 function jump_after_first_word () {
1121     local words
1122     words=(${(z)BUFFER})
1123
1124     if (( ${#words} <= 1 )) ; then
1125         CURSOR=${#BUFFER}
1126     else
1127         CURSOR=${#${words[1]}}
1128     fi
1129 }
1130 zle -N jump_after_first_word
1131
1132 #f5# Create directory under cursor or the selected area
1133 function inplaceMkDirs () {
1134     # Press ctrl-xM to create the directory under the cursor or the selected area.
1135     # To select an area press ctrl-@ or ctrl-space and use the cursor.
1136     # Use case: you type "mv abc ~/testa/testb/testc/" and remember that the
1137     # directory does not exist yet -> press ctrl-XM and problem solved
1138     local PATHTOMKDIR
1139     if ((REGION_ACTIVE==1)); then
1140         local F=$MARK T=$CURSOR
1141         if [[ $F -gt $T ]]; then
1142             F=${CURSOR}
1143             T=${MARK}
1144         fi
1145         # get marked area from buffer and eliminate whitespace
1146         PATHTOMKDIR=${BUFFER[F+1,T]%%[[:space:]]##}
1147         PATHTOMKDIR=${PATHTOMKDIR##[[:space:]]##}
1148     else
1149         local bufwords iword
1150         bufwords=(${(z)LBUFFER})
1151         iword=${#bufwords}
1152         bufwords=(${(z)BUFFER})
1153         PATHTOMKDIR="${(Q)bufwords[iword]}"
1154     fi
1155     [[ -z "${PATHTOMKDIR}" ]] && return 1
1156     PATHTOMKDIR=${~PATHTOMKDIR}
1157     if [[ -e "${PATHTOMKDIR}" ]]; then
1158         zle -M " path already exists, doing nothing"
1159     else
1160         zle -M "$(mkdir -p -v "${PATHTOMKDIR}")"
1161         zle end-of-line
1162     fi
1163 }
1164
1165 zle -N inplaceMkDirs
1166
1167 #v1# set number of lines to display per page
1168 HELP_LINES_PER_PAGE=20
1169 #v1# set location of help-zle cache file
1170 HELP_ZLE_CACHE_FILE=~/.cache/zsh_help_zle_lines.zsh
1171 # helper function for help-zle, actually generates the help text
1172 function help_zle_parse_keybindings () {
1173     emulate -L zsh
1174     setopt extendedglob
1175     unsetopt ksharrays  #indexing starts at 1
1176
1177     #v1# choose files that help-zle will parse for keybindings
1178     ((${+HELPZLE_KEYBINDING_FILES})) || HELPZLE_KEYBINDING_FILES=( /etc/zsh/zshrc ~/.zshrc.pre ~/.zshrc ~/.zshrc.local )
1179
1180     if [[ -r $HELP_ZLE_CACHE_FILE ]]; then
1181         local load_cache=0
1182         local f
1183         for f ($HELPZLE_KEYBINDING_FILES) [[ $f -nt $HELP_ZLE_CACHE_FILE ]] && load_cache=1
1184         [[ $load_cache -eq 0 ]] && . $HELP_ZLE_CACHE_FILE && return
1185     fi
1186
1187     #fill with default keybindings, possibly to be overwriten in a file later
1188     #Note that due to zsh inconsistency on escaping assoc array keys, we encase the key in '' which we will remove later
1189     local -A help_zle_keybindings
1190     help_zle_keybindings['<Ctrl>@']="set MARK"
1191     help_zle_keybindings['<Ctrl>x<Ctrl>j']="vi-join lines"
1192     help_zle_keybindings['<Ctrl>x<Ctrl>b']="jump to matching brace"
1193     help_zle_keybindings['<Ctrl>x<Ctrl>u']="undo"
1194     help_zle_keybindings['<Ctrl>_']="undo"
1195     help_zle_keybindings['<Ctrl>x<Ctrl>f<c>']="find <c> in cmdline"
1196     help_zle_keybindings['<Ctrl>a']="goto beginning of line"
1197     help_zle_keybindings['<Ctrl>e']="goto end of line"
1198     help_zle_keybindings['<Ctrl>t']="transpose charaters"
1199     help_zle_keybindings['<Alt>t']="transpose words"
1200     help_zle_keybindings['<Alt>s']="spellcheck word"
1201     help_zle_keybindings['<Ctrl>k']="backward kill buffer"
1202     help_zle_keybindings['<Ctrl>u']="forward kill buffer"
1203     help_zle_keybindings['<Ctrl>y']="insert previously killed word/string"
1204     help_zle_keybindings["<Alt>'"]="quote line"
1205     help_zle_keybindings['<Alt>"']="quote from mark to cursor"
1206     help_zle_keybindings['<Alt><arg>']="repeat next cmd/char <arg> times (<Alt>-<Alt>1<Alt>0a -> -10 times 'a')"
1207     help_zle_keybindings['<Alt>u']="make next word Uppercase"
1208     help_zle_keybindings['<Alt>l']="make next word lowercase"
1209     help_zle_keybindings['<Ctrl>xd']="preview expansion under cursor"
1210     help_zle_keybindings['<Alt>q']="push current CL into background, freeing it. Restore on next CL"
1211     help_zle_keybindings['<Alt>.']="insert (and interate through) last word from prev CLs"
1212     help_zle_keybindings['<Alt>,']="complete word from newer history (consecutive hits)"
1213     help_zle_keybindings['<Alt>m']="repeat last typed word on current CL"
1214     help_zle_keybindings['<Ctrl>v']="insert next keypress symbol literally (e.g. for bindkey)"
1215     help_zle_keybindings['!!:n*<Tab>']="insert last n arguments of last command"
1216     help_zle_keybindings['!!:n-<Tab>']="insert arguments n..N-2 of last command (e.g. mv s s d)"
1217     help_zle_keybindings['<Alt>h']="show help/manpage for current command"
1218
1219     #init global variables
1220     unset help_zle_lines help_zle_sln
1221     typeset -g -a help_zle_lines
1222     typeset -g help_zle_sln=1
1223
1224     local k v f cline
1225     local lastkeybind_desc contents     #last description starting with #k# that we found
1226     local num_lines_elapsed=0            #number of lines between last description and keybinding
1227     #search config files in the order they a called (and thus the order in which they overwrite keybindings)
1228     for f in $HELPZLE_KEYBINDING_FILES; do
1229         [[ -r "$f" ]] || continue   #not readable ? skip it
1230         contents="$(<$f)"
1231         for cline in "${(f)contents}"; do
1232             #zsh pattern: matches lines like: #k# ..............
1233             if [[ "$cline" == (#s)[[:space:]]#\#k\#[[:space:]]##(#b)(*)[[:space:]]#(#e) ]]; then
1234                 lastkeybind_desc="$match[*]"
1235                 num_lines_elapsed=0
1236             #zsh pattern: matches lines that set a keybinding using bind2map, bindkey or compdef -k
1237             #             ignores lines that are commentend out
1238             #             grabs first in '' or "" enclosed string with length between 1 and 6 characters
1239             elif [[ "$cline" == [^#]#(bind2maps[[:space:]](*)-s|bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*)  ]]; then
1240                 #description prevously found ? description not more than 2 lines away ? keybinding not empty ?
1241                 if [[ -n $lastkeybind_desc && $num_lines_elapsed -lt 2 && -n $match[1] ]]; then
1242                     #substitute keybinding string with something readable
1243                     k=${${${${${${${match[1]/\\e\^h/<Alt><BS>}/\\e\^\?/<Alt><BS>}/\\e\[5~/<PageUp>}/\\e\[6~/<PageDown>}//(\\e|\^\[)/<Alt>}//\^/<Ctrl>}/3~/<Alt><Del>}
1244                     #put keybinding in assoc array, possibly overwriting defaults or stuff found in earlier files
1245                     #Note that we are extracting the keybinding-string including the quotes (see Note at beginning)
1246                     help_zle_keybindings[${k}]=$lastkeybind_desc
1247                 fi
1248                 lastkeybind_desc=""
1249             else
1250               ((num_lines_elapsed++))
1251             fi
1252         done
1253     done
1254     unset contents
1255     #calculate length of keybinding column
1256     local kstrlen=0
1257     for k (${(k)help_zle_keybindings[@]}) ((kstrlen < ${#k})) && kstrlen=${#k}
1258     #convert the assoc array into preformated lines, which we are able to sort
1259     for k v in ${(kv)help_zle_keybindings[@]}; do
1260         #pad keybinding-string to kstrlen chars and remove outermost characters (i.e. the quotes)
1261         help_zle_lines+=("${(r:kstrlen:)k[2,-2]}${v}")
1262     done
1263     #sort lines alphabetically
1264     help_zle_lines=("${(i)help_zle_lines[@]}")
1265     [[ -d ${HELP_ZLE_CACHE_FILE:h} ]] || mkdir -p "${HELP_ZLE_CACHE_FILE:h}"
1266     echo "help_zle_lines=(${(q)help_zle_lines[@]})" >| $HELP_ZLE_CACHE_FILE
1267     zcompile $HELP_ZLE_CACHE_FILE
1268 }
1269 typeset -g help_zle_sln
1270 typeset -g -a help_zle_lines
1271
1272 # Provides (partially autogenerated) help on keybindings and the zsh line editor
1273 function help-zle () {
1274     emulate -L zsh
1275     unsetopt ksharrays  #indexing starts at 1
1276     #help lines already generated ? no ? then do it
1277     [[ ${+functions[help_zle_parse_keybindings]} -eq 1 ]] && {help_zle_parse_keybindings && unfunction help_zle_parse_keybindings}
1278     #already displayed all lines ? go back to the start
1279     [[ $help_zle_sln -gt ${#help_zle_lines} ]] && help_zle_sln=1
1280     local sln=$help_zle_sln
1281     #note that help_zle_sln is a global var, meaning we remember the last page we viewed
1282     help_zle_sln=$((help_zle_sln + HELP_LINES_PER_PAGE))
1283     zle -M "${(F)help_zle_lines[sln,help_zle_sln-1]}"
1284 }
1285 zle -N help-zle
1286
1287 ## complete word from currently visible Screen or Tmux buffer.
1288 if check_com -c screen || check_com -c tmux; then
1289     function _complete_screen_display () {
1290         [[ "$TERM" != "screen" ]] && return 1
1291
1292         local TMPFILE=$(mktemp)
1293         local -U -a _screen_display_wordlist
1294         trap "rm -f $TMPFILE" EXIT
1295
1296         # fill array with contents from screen hardcopy
1297         if ((${+TMUX})); then
1298             #works, but crashes tmux below version 1.4
1299             #luckily tmux -V option to ask for version, was also added in 1.4
1300             tmux -V &>/dev/null || return
1301             tmux -q capture-pane \; save-buffer -b 0 $TMPFILE \; delete-buffer -b 0
1302         else
1303             screen -X hardcopy $TMPFILE
1304             # screen sucks, it dumps in latin1, apparently always. so recode it
1305             # to system charset
1306             check_com recode && recode latin1 $TMPFILE
1307         fi
1308         _screen_display_wordlist=( ${(QQ)$(<$TMPFILE)} )
1309         # remove PREFIX to be completed from that array
1310         _screen_display_wordlist[${_screen_display_wordlist[(i)$PREFIX]}]=""
1311         compadd -a _screen_display_wordlist
1312     }
1313     #m# k CTRL-x\,\,\,S Complete word from GNU screen buffer
1314     bindkey -r "^xS"
1315     compdef -k _complete_screen_display complete-word '^xS'
1316 fi
1317
1318 # Load a few more functions and tie them to widgets, so they can be bound:
1319
1320 function zrcautozle () {
1321     emulate -L zsh
1322     local fnc=$1
1323     zrcautoload $fnc && zle -N $fnc
1324 }
1325
1326 function zrcgotwidget () {
1327     (( ${+widgets[$1]} ))
1328 }
1329
1330 function zrcgotkeymap () {
1331     [[ -n ${(M)keymaps:#$1} ]]
1332 }
1333
1334 zrcautozle insert-files
1335 zrcautozle edit-command-line
1336 zrcautozle insert-unicode-char
1337 if zrcautoload history-search-end; then
1338     zle -N history-beginning-search-backward-end history-search-end
1339     zle -N history-beginning-search-forward-end  history-search-end
1340 fi
1341 zle -C hist-complete complete-word _generic
1342 zstyle ':completion:hist-complete:*' completer _history
1343
1344 # The actual terminal setup hooks and bindkey-calls:
1345
1346 # An array to note missing features to ease diagnosis in case of problems.
1347 typeset -ga grml_missing_features
1348
1349 function zrcbindkey () {
1350     if (( ARGC )) && zrcgotwidget ${argv[-1]}; then
1351         bindkey "$@"
1352     fi
1353 }
1354
1355 function bind2maps () {
1356     local i sequence widget
1357     local -a maps
1358
1359     while [[ "$1" != "--" ]]; do
1360         maps+=( "$1" )
1361         shift
1362     done
1363     shift
1364
1365     if [[ "$1" == "-s" ]]; then
1366         shift
1367         sequence="$1"
1368     else
1369         sequence="${key[$1]}"
1370     fi
1371     widget="$2"
1372
1373     [[ -z "$sequence" ]] && return 1
1374
1375     for i in "${maps[@]}"; do
1376         zrcbindkey -M "$i" "$sequence" "$widget"
1377     done
1378 }
1379
1380 if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
1381     function zle-smkx () {
1382         emulate -L zsh
1383         printf '%s' ${terminfo[smkx]}
1384     }
1385     function zle-rmkx () {
1386         emulate -L zsh
1387         printf '%s' ${terminfo[rmkx]}
1388     }
1389     function zle-line-init () {
1390         zle-smkx
1391     }
1392     function zle-line-finish () {
1393         zle-rmkx
1394     }
1395     zle -N zle-line-init
1396     zle -N zle-line-finish
1397 else
1398     for i in {s,r}mkx; do
1399         (( ${+terminfo[$i]} )) || grml_missing_features+=($i)
1400     done
1401     unset i
1402 fi
1403
1404 typeset -A key
1405 key=(
1406     Home     "${terminfo[khome]}"
1407     End      "${terminfo[kend]}"
1408     Insert   "${terminfo[kich1]}"
1409     Delete   "${terminfo[kdch1]}"
1410     Up       "${terminfo[kcuu1]}"
1411     Down     "${terminfo[kcud1]}"
1412     Left     "${terminfo[kcub1]}"
1413     Right    "${terminfo[kcuf1]}"
1414     PageUp   "${terminfo[kpp]}"
1415     PageDown "${terminfo[knp]}"
1416     BackTab  "${terminfo[kcbt]}"
1417 )
1418
1419 # Guidelines for adding key bindings:
1420 #
1421 #   - Do not add hardcoded escape sequences, to enable non standard key
1422 #     combinations such as Ctrl-Meta-Left-Cursor. They are not easily portable.
1423 #
1424 #   - Adding Ctrl characters, such as '^b' is okay; note that '^b' and '^B' are
1425 #     the same key.
1426 #
1427 #   - All keys from the $key[] mapping are obviously okay.
1428 #
1429 #   - Most terminals send "ESC x" when Meta-x is pressed. Thus, sequences like
1430 #     '\ex' are allowed in here as well.
1431
1432 bind2maps emacs             -- Home   beginning-of-somewhere
1433 bind2maps       viins vicmd -- Home   vi-beginning-of-line
1434 bind2maps emacs             -- End    end-of-somewhere
1435 bind2maps       viins vicmd -- End    vi-end-of-line
1436 bind2maps emacs viins       -- Insert overwrite-mode
1437 bind2maps             vicmd -- Insert vi-insert
1438 bind2maps emacs             -- Delete delete-char
1439 bind2maps       viins vicmd -- Delete vi-delete-char
1440 bind2maps emacs viins vicmd -- Up     up-line-or-search
1441 bind2maps emacs viins vicmd -- Down   down-line-or-search
1442 bind2maps emacs             -- Left   backward-char
1443 bind2maps       viins vicmd -- Left   vi-backward-char
1444 bind2maps emacs             -- Right  forward-char
1445 bind2maps       viins vicmd -- Right  vi-forward-char
1446 #k# Perform abbreviation expansion
1447 bind2maps emacs viins       -- -s '^x.' zleiab
1448 #k# Display list of abbreviations that would expand
1449 bind2maps emacs viins       -- -s '^xb' help-show-abk
1450 #k# mkdir -p <dir> from string under cursor or marked area
1451 bind2maps emacs viins       -- -s '^xM' inplaceMkDirs
1452 #k# display help for keybindings and ZLE
1453 bind2maps emacs viins       -- -s '^xz' help-zle
1454 #k# Insert files and test globbing
1455 bind2maps emacs viins       -- -s "^xf" insert-files
1456 #k# Edit the current line in \kbd{\$EDITOR}
1457 bind2maps emacs viins       -- -s '\ee' edit-command-line
1458 #k# search history backward for entry beginning with typed text
1459 bind2maps emacs viins       -- -s '^xp' history-beginning-search-backward-end
1460 #k# search history forward for entry beginning with typed text
1461 bind2maps emacs viins       -- -s '^xP' history-beginning-search-forward-end
1462 #k# search history backward for entry beginning with typed text
1463 bind2maps emacs viins       -- PageUp history-beginning-search-backward-end
1464 #k# search history forward for entry beginning with typed text
1465 bind2maps emacs viins       -- PageDown history-beginning-search-forward-end
1466 bind2maps emacs viins       -- -s "^x^h" commit-to-history
1467 #k# Kill left-side word or everything up to next slash
1468 bind2maps emacs viins       -- -s '\ev' slash-backward-kill-word
1469 #k# Kill left-side word or everything up to next slash
1470 bind2maps emacs viins       -- -s '\e^h' slash-backward-kill-word
1471 #k# Kill left-side word or everything up to next slash
1472 bind2maps emacs viins       -- -s '\e^?' slash-backward-kill-word
1473 # Do history expansion on space:
1474 bind2maps emacs viins       -- -s ' ' magic-space
1475 #k# Trigger menu-complete
1476 bind2maps emacs viins       -- -s '\ei' menu-complete  # menu completion via esc-i
1477 #k# Insert a timestamp on the command line (yyyy-mm-dd)
1478 bind2maps emacs viins       -- -s '^ed' insert-datestamp
1479 #k# Insert last typed word
1480 bind2maps emacs viins       -- -s "\em" insert-last-typed-word
1481 #k# A smart shortcut for \kbd{fg<enter>}
1482 bind2maps emacs viins       -- -s '^z' grml-zsh-fg
1483 #k# prepend the current command with "sudo"
1484 bind2maps emacs viins       -- -s "^os" sudo-command-line
1485 #k# jump to after first word (for adding options)
1486 bind2maps emacs viins       -- -s '^x1' jump_after_first_word
1487 #k# complete word from history with menu
1488 bind2maps emacs viins       -- -s "^x^x" hist-complete
1489
1490 # insert unicode character
1491 # usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an Â§
1492 # See for example http://unicode.org/charts/ for unicode characters code
1493 #k# Insert Unicode character
1494 bind2maps emacs viins       -- -s '^xi' insert-unicode-char
1495
1496 # use the new *-pattern-* widgets for incremental history search
1497 if zrcgotwidget history-incremental-pattern-search-backward; then
1498     for seq wid in '^r' history-incremental-pattern-search-backward \
1499                    '^s' history-incremental-pattern-search-forward
1500     do
1501         bind2maps emacs viins vicmd -- -s $seq $wid
1502     done
1503     builtin unset -v seq wid
1504 fi
1505
1506 if zrcgotkeymap menuselect; then
1507     #m# k Shift-tab Perform backwards menu completion
1508     bind2maps menuselect -- BackTab reverse-menu-complete
1509
1510     #k# menu selection: pick item but stay in the menu
1511     bind2maps menuselect -- -s '\e^M' accept-and-menu-complete
1512     # also use + and INSERT since it's easier to press repeatedly
1513     bind2maps menuselect -- -s '+' accept-and-menu-complete
1514     bind2maps menuselect -- Insert accept-and-menu-complete
1515
1516     # accept a completion and try to complete again by using menu
1517     # completion; very useful with completing directories
1518     # by using 'undo' one's got a simple file browser
1519     bind2maps menuselect -- -s '^o' accept-and-infer-next-history
1520 fi
1521
1522 # Finally, here are still a few hardcoded escape sequences; Special sequences
1523 # like Ctrl-<Cursor-key> etc do suck a fair bit, because they are not
1524 # standardised and most of the time are not available in a terminals terminfo
1525 # entry.
1526 #
1527 # While we do not encourage adding bindings like these, we will keep these for
1528 # backward compatibility.
1529
1530 ## use Ctrl-left-arrow and Ctrl-right-arrow for jumping to word-beginnings on
1531 ## the command line.
1532 # URxvt sequences:
1533 bind2maps emacs viins vicmd -- -s '\eOc' forward-word
1534 bind2maps emacs viins vicmd -- -s '\eOd' backward-word
1535 # These are for xterm:
1536 bind2maps emacs viins vicmd -- -s '\e[1;5C' forward-word
1537 bind2maps emacs viins vicmd -- -s '\e[1;5D' backward-word
1538 ## the same for alt-left-arrow and alt-right-arrow
1539 # URxvt again:
1540 bind2maps emacs viins vicmd -- -s '\e\e[C' forward-word
1541 bind2maps emacs viins vicmd -- -s '\e\e[D' backward-word
1542 # Xterm again:
1543 bind2maps emacs viins vicmd -- -s '^[[1;3C' forward-word
1544 bind2maps emacs viins vicmd -- -s '^[[1;3D' backward-word
1545 # Also try ESC Left/Right:
1546 bind2maps emacs viins vicmd -- -s '\e'${key[Right]} forward-word
1547 bind2maps emacs viins vicmd -- -s '\e'${key[Left]}  backward-word
1548
1549 # autoloading
1550
1551 zrcautoload zmv
1552 zrcautoload zed
1553
1554 # we don't want to quote/espace URLs on our own...
1555 # if autoload -U url-quote-magic ; then
1556 #    zle -N self-insert url-quote-magic
1557 #    zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}='
1558 # else
1559 #    print 'Notice: no url-quote-magic available :('
1560 # fi
1561 alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic'
1562
1563 #m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
1564 alias run-help >&/dev/null && unalias run-help
1565 for rh in run-help{,-git,-ip,-openssl,-p4,-sudo,-svk,-svn}; do
1566     zrcautoload $rh
1567 done; unset rh
1568
1569 # command not found handling
1570
1571 (( ${COMMAND_NOT_FOUND} == 1 )) &&
1572 function command_not_found_handler () {
1573     emulate -L zsh
1574     if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then
1575         ${GRML_ZSH_CNF_HANDLER} $1
1576     fi
1577     return 1
1578 }
1579
1580 # history
1581
1582 #v#
1583 HISTFILE=${ZDOTDIR:-${HOME}}/.zsh_history
1584 isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
1585 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
1586
1587 # dirstack handling
1588
1589 DIRSTACKSIZE=${DIRSTACKSIZE:-20}
1590 DIRSTACKFILE=${DIRSTACKFILE:-${ZDOTDIR:-${HOME}}/.zdirs}
1591
1592 if zstyle -T ':grml:chpwd:dirstack' enable; then
1593     typeset -gaU GRML_PERSISTENT_DIRSTACK
1594     function grml_dirstack_filter () {
1595         local -a exclude
1596         local filter entry
1597         if zstyle -s ':grml:chpwd:dirstack' filter filter; then
1598             $filter $1 && return 0
1599         fi
1600         if zstyle -a ':grml:chpwd:dirstack' exclude exclude; then
1601             for entry in "${exclude[@]}"; do
1602                 [[ $1 == ${~entry} ]] && return 0
1603             done
1604         fi
1605         return 1
1606     }
1607
1608     function chpwd () {
1609         (( ZSH_SUBSHELL )) && return
1610         (( $DIRSTACKSIZE <= 0 )) && return
1611         [[ -z $DIRSTACKFILE ]] && return
1612         grml_dirstack_filter $PWD && return
1613         GRML_PERSISTENT_DIRSTACK=(
1614             $PWD "${(@)GRML_PERSISTENT_DIRSTACK[1,$DIRSTACKSIZE]}"
1615         )
1616         builtin print -l ${GRML_PERSISTENT_DIRSTACK} >! ${DIRSTACKFILE}
1617     }
1618
1619     if [[ -f ${DIRSTACKFILE} ]]; then
1620         # Enabling NULL_GLOB via (N) weeds out any non-existing
1621         # directories from the saved dir-stack file.
1622         dirstack=( ${(f)"$(< $DIRSTACKFILE)"}(N) )
1623         # "cd -" won't work after login by just setting $OLDPWD, so
1624         [[ -d $dirstack[1] ]] && cd -q $dirstack[1] && cd -q $OLDPWD
1625     fi
1626
1627     if zstyle -t ':grml:chpwd:dirstack' filter-on-load; then
1628         for i in "${dirstack[@]}"; do
1629             if ! grml_dirstack_filter "$i"; then
1630                 GRML_PERSISTENT_DIRSTACK=(
1631                     "${GRML_PERSISTENT_DIRSTACK[@]}"
1632                     $i
1633                 )
1634             fi
1635         done
1636     else
1637         GRML_PERSISTENT_DIRSTACK=( "${dirstack[@]}" )
1638     fi
1639 fi
1640
1641 # directory based profiles
1642
1643 if is433 ; then
1644
1645 # chpwd_profiles(): Directory Profiles, Quickstart:
1646 #
1647 # In .zshrc.local:
1648 #
1649 #   zstyle ':chpwd:profiles:/usr/src/grml(|/|/*)'   profile grml
1650 #   zstyle ':chpwd:profiles:/usr/src/debian(|/|/*)' profile debian
1651 #   chpwd_profiles
1652 #
1653 # For details see the `grmlzshrc.5' manual page.
1654 function chpwd_profiles () {
1655     local profile context
1656     local -i reexecute
1657
1658     context=":chpwd:profiles:$PWD"
1659     zstyle -s "$context" profile profile || profile='default'
1660     zstyle -T "$context" re-execute && reexecute=1 || reexecute=0
1661
1662     if (( ${+parameters[CHPWD_PROFILE]} == 0 )); then
1663         typeset -g CHPWD_PROFILE
1664         local CHPWD_PROFILES_INIT=1
1665         (( ${+functions[chpwd_profiles_init]} )) && chpwd_profiles_init
1666     elif [[ $profile != $CHPWD_PROFILE ]]; then
1667         (( ${+functions[chpwd_leave_profile_$CHPWD_PROFILE]} )) \
1668             && chpwd_leave_profile_${CHPWD_PROFILE}
1669     fi
1670     if (( reexecute )) || [[ $profile != $CHPWD_PROFILE ]]; then
1671         (( ${+functions[chpwd_profile_$profile]} )) && chpwd_profile_${profile}
1672     fi
1673
1674     CHPWD_PROFILE="${profile}"
1675     return 0
1676 }
1677
1678 chpwd_functions=( ${chpwd_functions} chpwd_profiles )
1679
1680 fi # is433
1681
1682 # Prompt setup for grml:
1683
1684 # set colors for use in prompts (modern zshs allow for the use of %F{red}foo%f
1685 # in prompts to get a red "foo" embedded, but it's good to keep these for
1686 # backwards compatibility).
1687 if is437; then
1688     BLUE="%F{blue}"
1689     RED="%F{red}"
1690     GREEN="%F{green}"
1691     CYAN="%F{cyan}"
1692     MAGENTA="%F{magenta}"
1693     YELLOW="%F{yellow}"
1694     WHITE="%F{white}"
1695     NO_COLOR="%f"
1696 elif zrcautoload colors && colors 2>/dev/null ; then
1697     BLUE="%{${fg[blue]}%}"
1698     RED="%{${fg_bold[red]}%}"
1699     GREEN="%{${fg[green]}%}"
1700     CYAN="%{${fg[cyan]}%}"
1701     MAGENTA="%{${fg[magenta]}%}"
1702     YELLOW="%{${fg[yellow]}%}"
1703     WHITE="%{${fg[white]}%}"
1704     NO_COLOR="%{${reset_color}%}"
1705 else
1706     BLUE=$'%{\e[1;34m%}'
1707     RED=$'%{\e[1;31m%}'
1708     GREEN=$'%{\e[1;32m%}'
1709     CYAN=$'%{\e[1;36m%}'
1710     WHITE=$'%{\e[1;37m%}'
1711     MAGENTA=$'%{\e[1;35m%}'
1712     YELLOW=$'%{\e[1;33m%}'
1713     NO_COLOR=$'%{\e[0m%}'
1714 fi
1715
1716 # First, the easy ones: PS2..4:
1717
1718 # secondary prompt, printed when the shell needs more information to complete a
1719 # command.
1720 PS2='\`%_> '
1721 # selection prompt used within a select loop.
1722 PS3='?# '
1723 # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
1724 PS4='+%N:%i:%_> '
1725
1726 # Some additional features to use with our prompt:
1727 #
1728 #    - battery status
1729 #    - debian_chroot
1730 #    - vcs_info setup and version specific fixes
1731
1732 # display battery status on right side of prompt using 'GRML_DISPLAY_BATTERY=1' in .zshrc.pre
1733
1734 function battery () {
1735 if [[ $GRML_DISPLAY_BATTERY -gt 0 ]] ; then
1736     if islinux ; then
1737         batterylinux
1738     elif isopenbsd ; then
1739         batteryopenbsd
1740     elif isfreebsd ; then
1741         batteryfreebsd
1742     elif isdarwin ; then
1743         batterydarwin
1744     else
1745         #not yet supported
1746         GRML_DISPLAY_BATTERY=0
1747     fi
1748 fi
1749 }
1750
1751 function batterylinux () {
1752 GRML_BATTERY_LEVEL=''
1753 local batteries bat capacity
1754 batteries=( /sys/class/power_supply/BAT*(N) )
1755 if (( $#batteries > 0 )) ; then
1756     for bat in $batteries ; do
1757         if [[ -e $bat/capacity ]]; then
1758             capacity=$(< $bat/capacity)
1759         else
1760             typeset -F energy_full=$(< $bat/energy_full)
1761             typeset -F energy_now=$(< $bat/energy_now)
1762             typeset -i capacity=$(( 100 * $energy_now / $energy_full))
1763         fi
1764         case $(< $bat/status) in
1765         Charging)
1766             GRML_BATTERY_LEVEL+=" ^"
1767             ;;
1768         Discharging)
1769             if (( capacity < 20 )) ; then
1770                 GRML_BATTERY_LEVEL+=" !v"
1771             else
1772                 GRML_BATTERY_LEVEL+=" v"
1773             fi
1774             ;;
1775         *) # Full, Unknown
1776             GRML_BATTERY_LEVEL+=" ="
1777             ;;
1778         esac
1779         GRML_BATTERY_LEVEL+="${capacity}%%"
1780     done
1781 fi
1782 }
1783
1784 function batteryopenbsd () {
1785 GRML_BATTERY_LEVEL=''
1786 local bat batfull batwarn batnow num
1787 for num in 0 1 ; do
1788     bat=$(sysctl -n hw.sensors.acpibat${num} 2>/dev/null)
1789     if [[ -n $bat ]]; then
1790         batfull=${"$(sysctl -n hw.sensors.acpibat${num}.amphour0)"%% *}
1791         batwarn=${"$(sysctl -n hw.sensors.acpibat${num}.amphour1)"%% *}
1792         batnow=${"$(sysctl -n hw.sensors.acpibat${num}.amphour3)"%% *}
1793         case "$(sysctl -n hw.sensors.acpibat${num}.raw0)" in
1794             *" discharging"*)
1795                 if (( batnow < batwarn )) ; then
1796                     GRML_BATTERY_LEVEL+=" !v"
1797                 else
1798                     GRML_BATTERY_LEVEL+=" v"
1799                 fi
1800                 ;;
1801             *" charging"*)
1802                 GRML_BATTERY_LEVEL+=" ^"
1803                 ;;
1804             *)
1805                 GRML_BATTERY_LEVEL+=" ="
1806                 ;;
1807         esac
1808         GRML_BATTERY_LEVEL+="${$(( 100 * batnow / batfull ))%%.*}%%"
1809     fi
1810 done
1811 }
1812
1813 function batteryfreebsd () {
1814 GRML_BATTERY_LEVEL=''
1815 local num
1816 local -A table
1817 for num in 0 1 ; do
1818     table=( ${=${${${${${(M)${(f)"$(acpiconf -i $num 2>&1)"}:#(State|Remaining capacity):*}%%( ##|%)}//:[ $'\t']##/@}// /-}//@/ }} )
1819     if [[ -n $table ]] && [[ $table[State] != "not-present" ]] ; then
1820         case $table[State] in
1821             *discharging*)
1822                 if (( $table[Remaining-capacity] < 20 )) ; then
1823                     GRML_BATTERY_LEVEL+=" !v"
1824                 else
1825                     GRML_BATTERY_LEVEL+=" v"
1826                 fi
1827                 ;;
1828             *charging*)
1829                 GRML_BATTERY_LEVEL+=" ^"
1830                 ;;
1831             *)
1832                 GRML_BATTERY_LEVEL+=" ="
1833                 ;;
1834         esac
1835         GRML_BATTERY_LEVEL+="$table[Remaining-capacity]%%"
1836     fi
1837 done
1838 }
1839
1840 function batterydarwin () {
1841 GRML_BATTERY_LEVEL=''
1842 local -a table
1843 table=( ${$(pmset -g ps)[(w)7,8]%%(\%|);} )
1844 if [[ -n $table[2] ]] ; then
1845     case $table[2] in
1846         charging)
1847             GRML_BATTERY_LEVEL+=" ^"
1848             ;;
1849         discharging)
1850             if (( $table[1] < 20 )) ; then
1851                 GRML_BATTERY_LEVEL+=" !v"
1852             else
1853                 GRML_BATTERY_LEVEL+=" v"
1854             fi
1855             ;;
1856         *)
1857             GRML_BATTERY_LEVEL+=" ="
1858             ;;
1859     esac
1860     GRML_BATTERY_LEVEL+="$table[1]%%"
1861 fi
1862 }
1863
1864 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
1865 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
1866     debian_chroot=$(</etc/debian_chroot)
1867 fi
1868
1869 # gather version control information for inclusion in a prompt
1870
1871 if zrcautoload vcs_info; then
1872     # `vcs_info' in zsh versions 4.3.10 and below have a broken `_realpath'
1873     # function, which can cause a lot of trouble with our directory-based
1874     # profiles. So:
1875     if [[ ${ZSH_VERSION} == 4.3.<-10> ]] ; then
1876         function VCS_INFO_realpath () {
1877             setopt localoptions NO_shwordsplit chaselinks
1878             ( builtin cd -q $1 2> /dev/null && pwd; )
1879         }
1880     fi
1881
1882     zstyle ':vcs_info:*' max-exports 2
1883
1884     if [[ -o restricted ]]; then
1885         zstyle ':vcs_info:*' enable NONE
1886     fi
1887 fi
1888
1889 typeset -A grml_vcs_coloured_formats
1890 typeset -A grml_vcs_plain_formats
1891
1892 grml_vcs_plain_formats=(
1893     format "(%s%)-[%b] "    "zsh: %r"
1894     actionformat "(%s%)-[%b|%a] " "zsh: %r"
1895     rev-branchformat "%b:%r"
1896 )
1897
1898 grml_vcs_coloured_formats=(
1899     format "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOR} "
1900     actionformat "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOR} "
1901     rev-branchformat "%b${RED}:${YELLOW}%r"
1902 )
1903
1904 typeset GRML_VCS_COLOUR_MODE=xxx
1905
1906 function grml_vcs_info_toggle_colour () {
1907     emulate -L zsh
1908     if [[ $GRML_VCS_COLOUR_MODE == plain ]]; then
1909         grml_vcs_info_set_formats coloured
1910     else
1911         grml_vcs_info_set_formats plain
1912     fi
1913     return 0
1914 }
1915
1916 function grml_vcs_info_set_formats () {
1917     emulate -L zsh
1918     #setopt localoptions xtrace
1919     local mode=$1 AF F BF
1920     if [[ $mode == coloured ]]; then
1921         AF=${grml_vcs_coloured_formats[actionformat]}
1922         F=${grml_vcs_coloured_formats[format]}
1923         BF=${grml_vcs_coloured_formats[rev-branchformat]}
1924         GRML_VCS_COLOUR_MODE=coloured
1925     else
1926         AF=${grml_vcs_plain_formats[actionformat]}
1927         F=${grml_vcs_plain_formats[format]}
1928         BF=${grml_vcs_plain_formats[rev-branchformat]}
1929         GRML_VCS_COLOUR_MODE=plain
1930     fi
1931
1932     zstyle ':vcs_info:*'              actionformats "$AF" "zsh: %r"
1933     zstyle ':vcs_info:*'              formats       "$F"  "zsh: %r"
1934     zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat  "$BF"
1935     return 0
1936 }
1937
1938 # Change vcs_info formats for the grml prompt. The 2nd format sets up
1939 # $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title.
1940 if [[ "$TERM" == dumb ]] ; then
1941     grml_vcs_info_set_formats plain
1942 else
1943     grml_vcs_info_set_formats coloured
1944 fi
1945
1946 # Now for the fun part: The grml prompt themes in `promptsys' mode of operation
1947
1948 # This actually defines three prompts:
1949 #
1950 #    - grml
1951 #    - grml-large
1952 #    - grml-chroot
1953 #
1954 # They all share the same code and only differ with respect to which items they
1955 # contain. The main source of documentation is the `prompt_grml_help' function
1956 # below, which gets called when the user does this: prompt -h grml
1957
1958 function prompt_grml_help () {
1959     <<__EOF0__
1960   prompt grml
1961
1962     This is the prompt as used by the grml-live system <http://grml.org>. It is
1963     a rather simple one-line prompt, that by default looks something like this:
1964
1965         <user>@<host> <current-working-directory>[ <vcs_info-data>]%
1966
1967     The prompt itself integrates with zsh's prompt themes system (as you are
1968     witnessing right now) and is configurable to a certain degree. In
1969     particular, these aspects are customisable:
1970
1971         - The items used in the prompt (e.g. you can remove \`user' from
1972           the list of activated items, which will cause the user name to
1973           be omitted from the prompt string).
1974
1975         - The attributes used with the items are customisable via strings
1976           used before and after the actual item.
1977
1978     The available items are: at, battery, change-root, date, grml-chroot,
1979     history, host, jobs, newline, path, percent, rc, rc-always, sad-smiley,
1980     shell-level, time, user, vcs
1981
1982     The actual configuration is done via zsh's \`zstyle' mechanism. The
1983     context, that is used while looking up styles is:
1984
1985         ':prompt:grml:<left-or-right>:<subcontext>'
1986
1987     Here <left-or-right> is either \`left' or \`right', signifying whether the
1988     style should affect the left or the right prompt. <subcontext> is either
1989     \`setup' or 'items:<item>', where \`<item>' is one of the available items.
1990
1991     The styles:
1992
1993         - use-rprompt (boolean): If \`true' (the default), print a sad smiley
1994           in $RPROMPT if the last command a returned non-successful error code.
1995           (This in only valid if <left-or-right> is "right"; ignored otherwise)
1996
1997         - items (list): The list of items used in the prompt. If \`vcs' is
1998           present in the list, the theme's code invokes \`vcs_info'
1999           accordingly. Default (left): rc change-root user at host path vcs
2000           percent; Default (right): sad-smiley
2001
2002     Available styles in 'items:<item>' are: pre, post. These are strings that
2003     are inserted before (pre) and after (post) the item in question. Thus, the
2004     following would cause the user name to be printed in red instead of the
2005     default blue:
2006
2007         zstyle ':prompt:grml:*:items:user' pre '%F{red}'
2008
2009     Note, that the \`post' style may remain at its default value, because its
2010     default value is '%f', which turns the foreground text attribute off (which
2011     is exactly, what is still required with the new \`pre' value).
2012 __EOF0__
2013 }
2014
2015 function prompt_grml-chroot_help () {
2016     <<__EOF0__
2017   prompt grml-chroot
2018
2019     This is a variation of the grml prompt, see: prompt -h grml
2020
2021     The main difference is the default value of the \`items' style. The rest
2022     behaves exactly the same. Here are the defaults for \`grml-chroot':
2023
2024         - left: grml-chroot user at host path percent
2025         - right: (empty list)
2026 __EOF0__
2027 }
2028
2029 function prompt_grml-large_help () {
2030     <<__EOF0__
2031   prompt grml-large
2032
2033     This is a variation of the grml prompt, see: prompt -h grml
2034
2035     The main difference is the default value of the \`items' style. In
2036     particular, this theme uses _two_ lines instead of one with the plain
2037     \`grml' theme. The rest behaves exactly the same. Here are the defaults
2038     for \`grml-large':
2039
2040         - left: rc jobs history shell-level change-root time date newline user
2041                 at host path vcs percent
2042         - right: sad-smiley
2043 __EOF0__
2044 }
2045
2046 function grml_prompt_setup () {
2047     emulate -L zsh
2048     autoload -Uz vcs_info
2049     # The following autoload is disabled for now, since this setup includes a
2050     # static version of the â€˜add-zsh-hook’ function above. It needs to be
2051     # reenabled as soon as that static definition is removed again.
2052     #autoload -Uz add-zsh-hook
2053     add-zsh-hook precmd prompt_$1_precmd
2054 }
2055
2056 function prompt_grml_setup () {
2057     grml_prompt_setup grml
2058 }
2059
2060 function prompt_grml-chroot_setup () {
2061     grml_prompt_setup grml-chroot
2062 }
2063
2064 function prompt_grml-large_setup () {
2065     grml_prompt_setup grml-large
2066 }
2067
2068 # These maps define default tokens and pre-/post-decoration for items to be
2069 # used within the themes. All defaults may be customised in a context sensitive
2070 # matter by using zsh's `zstyle' mechanism.
2071 typeset -gA grml_prompt_pre_default \
2072             grml_prompt_post_default \
2073             grml_prompt_token_default \
2074             grml_prompt_token_function
2075
2076 grml_prompt_pre_default=(
2077     at                ''
2078     battery           ' '
2079     change-root       ''
2080     date              '%F{blue}'
2081     grml-chroot       '%F{red}'
2082     history           '%F{green}'
2083     host              ''
2084     jobs              '%F{cyan}'
2085     newline           ''
2086     path              '%B'
2087     percent           ''
2088     rc                '%B%F{red}'
2089     rc-always         ''
2090     sad-smiley        ''
2091     shell-level       '%F{red}'
2092     time              '%F{blue}'
2093     user              '%B%F{blue}'
2094     vcs               ''
2095 )
2096
2097 grml_prompt_post_default=(
2098     at                ''
2099     battery           ''
2100     change-root       ''
2101     date              '%f'
2102     grml-chroot       '%f '
2103     history           '%f'
2104     host              ''
2105     jobs              '%f'
2106     newline           ''
2107     path              '%b'
2108     percent           ''
2109     rc                '%f%b'
2110     rc-always         ''
2111     sad-smiley        ''
2112     shell-level       '%f'
2113     time              '%f'
2114     user              '%f%b'
2115     vcs               ''
2116 )
2117
2118 grml_prompt_token_default=(
2119     at                '@'
2120     battery           'GRML_BATTERY_LEVEL'
2121     change-root       'debian_chroot'
2122     date              '%D{%Y-%m-%d}'
2123     grml-chroot       'GRML_CHROOT'
2124     history           '{history#%!} '
2125     host              '%m '
2126     jobs              '[%j running job(s)] '
2127     newline           $'\n'
2128     path              '%40<..<%~%<< '
2129     percent           '%# '
2130     rc                '%(?..%? )'
2131     rc-always         '%?'
2132     sad-smiley        '%(?..:()'
2133     shell-level       '%(3L.+ .)'
2134     time              '%D{%H:%M:%S} '
2135     user              '%n'
2136     vcs               '0'
2137 )
2138
2139 function grml_theme_has_token () {
2140     if (( ARGC != 1 )); then
2141         printf 'usage: grml_theme_has_token <name>\n'
2142         return 1
2143     fi
2144     (( ${+grml_prompt_token_default[$1]} ))
2145 }
2146
2147 function GRML_theme_add_token_usage () {
2148     <<__EOF0__
2149   Usage: grml_theme_add_token <name> [-f|-i] <token/function> [<pre> <post>]
2150
2151     <name> is the name for the newly added token. If the \`-f' or \`-i' options
2152     are used, <token/function> is the name of the function (see below for
2153     details). Otherwise it is the literal token string to be used. <pre> and
2154     <post> are optional.
2155
2156   Options:
2157
2158     -f <function>   Use a function named \`<function>' each time the token
2159                     is to be expanded.
2160
2161     -i <function>   Use a function named \`<function>' to initialise the
2162                     value of the token _once_ at runtime.
2163
2164     The functions are called with one argument: the token's new name. The
2165     return value is expected in the \$REPLY parameter. The use of these
2166     options is mutually exclusive.
2167
2168     There is a utility function \`grml_theme_has_token', which you can use
2169     to test if a token exists before trying to add it. This can be a guard
2170     for situations in which a \`grml_theme_add_token' call may happen more
2171     than once.
2172
2173   Example:
2174
2175     To add a new token \`day' that expands to the current weekday in the
2176     current locale in green foreground colour, use this:
2177
2178       grml_theme_add_token day '%D{%A}' '%F{green}' '%f'
2179
2180     Another example would be support for \$VIRTUAL_ENV:
2181
2182       function virtual_env_prompt () {
2183         REPLY=\${VIRTUAL_ENV+\${VIRTUAL_ENV:t} }
2184       }
2185       grml_theme_add_token virtual-env -f virtual_env_prompt
2186
2187     After that, you will be able to use a changed \`items' style to
2188     assemble your prompt.
2189 __EOF0__
2190 }
2191
2192 function grml_theme_add_token () {
2193     emulate -L zsh
2194     local name token pre post
2195     local -i init funcall
2196
2197     if (( ARGC == 0 )); then
2198         GRML_theme_add_token_usage
2199         return 0
2200     fi
2201
2202     init=0
2203     funcall=0
2204     pre=''
2205     post=''
2206     name=$1
2207     shift
2208     if [[ $1 == '-f' ]]; then
2209         funcall=1
2210         shift
2211     elif [[ $1 == '-i' ]]; then
2212         init=1
2213         shift
2214     fi
2215
2216     if (( ARGC == 0 )); then
2217         printf '
2218 grml_theme_add_token: No token-string/function-name provided!\n\n'
2219         GRML_theme_add_token_usage
2220         return 1
2221     fi
2222     token=$1
2223     shift
2224     if (( ARGC != 0 && ARGC != 2 )); then
2225         printf '
2226 grml_theme_add_token: <pre> and <post> need to by specified _both_!\n\n'
2227         GRML_theme_add_token_usage
2228         return 1
2229     fi
2230     if (( ARGC )); then
2231         pre=$1
2232         post=$2
2233         shift 2
2234     fi
2235
2236     if grml_theme_has_token $name; then
2237         printf '
2238 grml_theme_add_token: Token `%s'\'' exists! Giving up!\n\n' $name
2239         GRML_theme_add_token_usage
2240         return 2
2241     fi
2242     if (( init )); then
2243         $token $name
2244         token=$REPLY
2245     fi
2246     grml_prompt_pre_default[$name]=$pre
2247     grml_prompt_post_default[$name]=$post
2248     if (( funcall )); then
2249         grml_prompt_token_function[$name]=$token
2250         grml_prompt_token_default[$name]=23
2251     else
2252         grml_prompt_token_default[$name]=$token
2253     fi
2254 }
2255
2256 function grml_typeset_and_wrap () {
2257     emulate -L zsh
2258     local target="$1"
2259     local new="$2"
2260     local left="$3"
2261     local right="$4"
2262
2263     if (( ${+parameters[$new]} )); then
2264         typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
2265     fi
2266 }
2267
2268 function grml_prompt_addto () {
2269     emulate -L zsh
2270     local target="$1"
2271     local lr it apre apost new v
2272     local -a items
2273     shift
2274
2275     [[ $target == PS1 ]] && lr=left || lr=right
2276     zstyle -a ":prompt:${grmltheme}:${lr}:setup" items items || items=( "$@" )
2277     typeset -g "${target}="
2278     for it in "${items[@]}"; do
2279         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" pre apre \
2280             || apre=${grml_prompt_pre_default[$it]}
2281         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" post apost \
2282             || apost=${grml_prompt_post_default[$it]}
2283         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
2284             || new=${grml_prompt_token_default[$it]}
2285         typeset -g "${target}=${(P)target}${apre}"
2286         if (( ${+grml_prompt_token_function[$it]} )); then
2287             ${grml_prompt_token_function[$it]} $it
2288             typeset -g "${target}=${(P)target}${REPLY}"
2289         else
2290             case $it in
2291             battery)
2292                 grml_typeset_and_wrap $target $new '' ''
2293                 ;;
2294             change-root)
2295                 grml_typeset_and_wrap $target $new '(' ')'
2296                 ;;
2297             grml-chroot)
2298                 if [[ -n ${(P)new} ]]; then
2299                     typeset -g "${target}=${(P)target}(CHROOT)"
2300                 fi
2301                 ;;
2302             vcs)
2303                 v="vcs_info_msg_${new}_"
2304                 if (( ! vcscalled )); then
2305                     vcs_info
2306                     vcscalled=1
2307                 fi
2308                 if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
2309                     typeset -g "${target}=${(P)target}${(P)v}"
2310                 fi
2311                 ;;
2312             *) typeset -g "${target}=${(P)target}${new}" ;;
2313             esac
2314         fi
2315         typeset -g "${target}=${(P)target}${apost}"
2316     done
2317 }
2318
2319 function prompt_grml_precmd () {
2320     emulate -L zsh
2321     local grmltheme=grml
2322     local -a left_items right_items
2323     left_items=(rc change-root user at host path vcs percent)
2324     right_items=(sad-smiley)
2325
2326     prompt_grml_precmd_worker
2327 }
2328
2329 function prompt_grml-chroot_precmd () {
2330     emulate -L zsh
2331     local grmltheme=grml-chroot
2332     local -a left_items right_items
2333     left_items=(grml-chroot user at host path percent)
2334     right_items=()
2335
2336     prompt_grml_precmd_worker
2337 }
2338
2339 function prompt_grml-large_precmd () {
2340     emulate -L zsh
2341     local grmltheme=grml-large
2342     local -a left_items right_items
2343     left_items=(rc jobs history shell-level change-root time date newline
2344                 user at host path vcs percent)
2345     right_items=(sad-smiley)
2346
2347     prompt_grml_precmd_worker
2348 }
2349
2350 function prompt_grml_precmd_worker () {
2351     emulate -L zsh
2352     local -i vcscalled=0
2353
2354     grml_prompt_addto PS1 "${left_items[@]}"
2355     if zstyle -T ":prompt:${grmltheme}:right:setup" use-rprompt; then
2356         grml_prompt_addto RPS1 "${right_items[@]}"
2357     fi
2358 }
2359
2360 function grml_prompt_fallback () {
2361     setopt prompt_subst
2362     local p0 p1
2363
2364     p0="${RED}%(?..%? )${WHITE}${debian_chroot:+($debian_chroot)}"
2365     p1="${BLUE}%n${NO_COLOR}@%m %40<...<%B%~%b%<< "'${vcs_info_msg_0_}'"%# "
2366     if (( EUID == 0 )); then
2367         PROMPT="${BLUE}${p0}${RED}${p1}"
2368     else
2369         PROMPT="${RED}${p0}${BLUE}${p1}"
2370     fi
2371 }
2372
2373 if zrcautoload promptinit && promptinit 2>/dev/null ; then
2374     # Since we define the required functions in here and not in files in
2375     # $fpath, we need to stick the theme's name into `$prompt_themes'
2376     # ourselves, since promptinit does not pick them up otherwise.
2377     prompt_themes+=( grml grml-chroot grml-large )
2378     # Also, keep the array sorted...
2379     prompt_themes=( "${(@on)prompt_themes}" )
2380 else
2381     print 'Notice: no promptinit available :('
2382     grml_prompt_fallback
2383     function precmd () { (( ${+functions[vcs_info]} )) && vcs_info; }
2384 fi
2385
2386 if is437; then
2387     # The prompt themes use modern features of zsh, that require at least
2388     # version 4.3.7 of the shell. Use the fallback otherwise.
2389     if [[ $GRML_DISPLAY_BATTERY -gt 0 ]]; then
2390         zstyle ':prompt:grml:right:setup' items sad-smiley battery
2391         add-zsh-hook precmd battery
2392     fi
2393     if [[ "$TERM" == dumb ]] ; then
2394         zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" pre ''
2395         zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" post ' '
2396         for i in rc user path jobs history date time shell-level; do
2397             zstyle ":prompt:grml(|-large|-chroot):*:items:$i" pre ''
2398             zstyle ":prompt:grml(|-large|-chroot):*:items:$i" post ''
2399         done
2400         unset i
2401         zstyle ':prompt:grml(|-large|-chroot):right:setup' use-rprompt false
2402     elif (( EUID == 0 )); then
2403         zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%B%F{red}'
2404     fi
2405
2406     # Finally enable one of the prompts.
2407     if [[ -n $GRML_CHROOT ]]; then
2408         prompt grml-chroot
2409     elif [[ $GRMLPROMPT -gt 0 ]]; then
2410         prompt grml-large
2411     else
2412         prompt grml
2413     fi
2414 else
2415     grml_prompt_fallback
2416     function precmd () { (( ${+functions[vcs_info]} )) && vcs_info; }
2417 fi
2418
2419 # Terminal-title wizardry
2420
2421 function ESC_print () {
2422     info_print $'\ek' $'\e\\' "$@"
2423 }
2424 function set_title () {
2425     info_print  $'\e]0;' $'\a' "$@"
2426 }
2427
2428 function info_print () {
2429     local esc_begin esc_end
2430     esc_begin="$1"
2431     esc_end="$2"
2432     shift 2
2433     printf '%s' ${esc_begin}
2434     printf '%s' "$*"
2435     printf '%s' "${esc_end}"
2436 }
2437
2438 function grml_reset_screen_title () {
2439     # adjust title of xterm
2440     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
2441     [[ ${NOTITLE:-} -gt 0 ]] && return 0
2442     case $TERM in
2443         (xterm*|rxvt*)
2444             set_title ${(%):-"%n@%m: %~"}
2445             ;;
2446     esac
2447 }
2448
2449 function grml_vcs_to_screen_title () {
2450     if [[ $TERM == screen* ]] ; then
2451         if [[ -n ${vcs_info_msg_1_} ]] ; then
2452             ESC_print ${vcs_info_msg_1_}
2453         else
2454             ESC_print "zsh"
2455         fi
2456     fi
2457 }
2458
2459 function grml_maintain_name () {
2460     # set hostname if not running on host with name 'grml'
2461     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
2462        NAME="@$HOSTNAME"
2463     fi
2464 }
2465
2466 function grml_cmd_to_screen_title () {
2467     # get the name of the program currently running and hostname of local
2468     # machine set screen window title if running in a screen
2469     if [[ "$TERM" == screen* ]] ; then
2470         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME"
2471         ESC_print ${CMD}
2472     fi
2473 }
2474
2475 function grml_control_xterm_title () {
2476     case $TERM in
2477         (xterm*|rxvt*)
2478             set_title "${(%):-"%n@%m:"}" "$1"
2479             ;;
2480     esac
2481 }
2482
2483 # The following autoload is disabled for now, since this setup includes a
2484 # static version of the â€˜add-zsh-hook’ function above. It needs to be
2485 # reenabled as soon as that static definition is removed again.
2486 #zrcautoload add-zsh-hook || add-zsh-hook () { :; }
2487 if [[ $NOPRECMD -eq 0 ]]; then
2488     add-zsh-hook precmd grml_reset_screen_title
2489     add-zsh-hook precmd grml_vcs_to_screen_title
2490     add-zsh-hook preexec grml_maintain_name
2491     add-zsh-hook preexec grml_cmd_to_screen_title
2492     if [[ $NOTITLE -eq 0 ]]; then
2493         add-zsh-hook preexec grml_control_xterm_title
2494     fi
2495 fi
2496
2497 # 'hash' some often used directories
2498 #d# start
2499 hash -d deb=/var/cache/apt/archives
2500 hash -d doc=/usr/share/doc
2501 hash -d linux=/lib/modules/$(command uname -r)/build/
2502 hash -d log=/var/log
2503 hash -d slog=/var/log/syslog
2504 hash -d src=/usr/src
2505 hash -d www=/var/www
2506 #d# end
2507
2508 # some aliases
2509 if check_com -c screen ; then
2510     if [[ $UID -eq 0 ]] ; then
2511         if [[ -r /etc/grml/screenrc ]]; then
2512             alias screen='screen -c /etc/grml/screenrc'
2513         fi
2514     elif [[ ! -r $HOME/.screenrc ]] ; then
2515         if [[ -r /etc/grml/screenrc_grml ]]; then
2516             alias screen='screen -c /etc/grml/screenrc_grml'
2517         else
2518             if [[ -r /etc/grml/screenrc ]]; then
2519                 alias screen='screen -c /etc/grml/screenrc'
2520             fi
2521         fi
2522     fi
2523 fi
2524
2525 # do we have GNU ls with color-support?
2526 if [[ "$TERM" != dumb ]]; then
2527     #a1# List files with colors (\kbd{ls \ldots})
2528     alias ls="command ls ${ls_options:+${ls_options[*]}}"
2529     #a1# List all files, with colors (\kbd{ls -la \ldots})
2530     alias la="command ls -la ${ls_options:+${ls_options[*]}}"
2531     #a1# List files with long colored list, without dotfiles (\kbd{ls -l \ldots})
2532     alias ll="command ls -l ${ls_options:+${ls_options[*]}}"
2533     #a1# List files with long colored list, human readable sizes (\kbd{ls -hAl \ldots})
2534     alias lh="command ls -hAl ${ls_options:+${ls_options[*]}}"
2535     #a1# List files with long colored list, append qualifier to filenames (\kbd{ls -l \ldots})\\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
2536     alias l="command ls -l ${ls_options:+${ls_options[*]}}"
2537 else
2538     alias la='command ls -la'
2539     alias ll='command ls -l'
2540     alias lh='command ls -hAl'
2541     alias l='command ls -l'
2542 fi
2543
2544 if [[ -r /proc/mdstat ]]; then
2545     alias mdstat='cat /proc/mdstat'
2546 fi
2547
2548 alias ...='cd ../../'
2549
2550 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
2551 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
2552     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
2553 fi
2554
2555 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
2556 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
2557 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
2558
2559 # make sure it is not assigned yet
2560 [[ -n ${aliases[utf2iso]} ]] && unalias utf2iso
2561 function utf2iso () {
2562     if isutfenv ; then
2563         local ENV
2564         for ENV in $(env | command grep -i '.utf') ; do
2565             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
2566         done
2567     fi
2568 }
2569
2570 # make sure it is not assigned yet
2571 [[ -n ${aliases[iso2utf]} ]] && unalias iso2utf
2572 function iso2utf () {
2573     if ! isutfenv ; then
2574         local ENV
2575         for ENV in $(env | command grep -i '\.iso') ; do
2576             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
2577         done
2578     fi
2579 }
2580
2581 # especially for roadwarriors using GNU screen and ssh:
2582 if ! check_com asc &>/dev/null ; then
2583   function asc () { autossh -t "$@" 'screen -RdU' }
2584   compdef asc=ssh
2585 fi
2586
2587 #f1# Hints for the use of zsh on grml
2588 function zsh-help () {
2589     print "$bg[white]$fg[black]
2590 zsh-help - hints for use of zsh on grml
2591 =======================================$reset_color"
2592
2593     print '
2594 Main configuration of zsh happens in /etc/zsh/zshrc.
2595 That file is part of the package grml-etc-core, if you want to
2596 use them on a non-grml-system just get the tar.gz from
2597 http://deb.grml.org/ or (preferably) get it from the git repository:
2598
2599   http://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
2600
2601 This version of grml'\''s zsh setup does not use skel/.zshrc anymore.
2602 The file is still there, but it is empty for backwards compatibility.
2603
2604 For your own changes use these two files:
2605     $HOME/.zshrc.pre
2606     $HOME/.zshrc.local
2607
2608 The former is sourced very early in our zshrc, the latter is sourced
2609 very lately.
2610
2611 System wide configuration without touching configuration files of grml
2612 can take place in /etc/zsh/zshrc.local.
2613
2614 For information regarding zsh start at http://grml.org/zsh/
2615
2616 Take a look at grml'\''s zsh refcard:
2617 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
2618
2619 Check out the main zsh refcard:
2620 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
2621
2622 And of course visit the zsh-lovers:
2623 % man zsh-lovers
2624
2625 You can adjust some options through environment variables when
2626 invoking zsh without having to edit configuration files.
2627 Basically meant for bash users who are not used to the power of
2628 the zsh yet. :)
2629
2630   "NOCOR=1    zsh" => deactivate automatic correction
2631   "NOMENU=1   zsh" => do not use auto menu completion
2632                       (note: use ctrl-d for completion instead!)
2633   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
2634   "NOTITLE=1  zsh" => disable setting the title of xterms without disabling
2635                       preexec() and precmd() completely
2636   "GRML_DISPLAY_BATTERY=1  zsh"
2637                    => activate battery status on right side of prompt (WIP)
2638   "COMMAND_NOT_FOUND=1 zsh"
2639                    => Enable a handler if an external command was not found
2640                       The command called in the handler can be altered by setting
2641                       the GRML_ZSH_CNF_HANDLER variable, the default is:
2642                       "/usr/share/command-not-found/command-not-found"
2643
2644 A value greater than 0 is enables a feature; a value equal to zero
2645 disables it. If you like one or the other of these settings, you can
2646 add them to ~/.zshrc.pre to ensure they are set when sourcing grml'\''s
2647 zshrc.'
2648
2649     print "
2650 $bg[white]$fg[black]
2651 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
2652 Enjoy your grml system with the zsh!$reset_color"
2653 }
2654
2655 # debian stuff
2656 if [[ -r /etc/debian_version ]] ; then
2657     if [[ -z "$GRML_NO_APT_ALIASES" ]]; then
2658         #a3# Execute \kbd{apt-cache search}
2659         alias acs='apt-cache search'
2660         #a3# Execute \kbd{apt-cache show}
2661         alias acsh='apt-cache show'
2662         #a3# Execute \kbd{apt-cache policy}
2663         alias acp='apt-cache policy'
2664         #a3# Execute \kbd{apt-get dist-upgrade}
2665         salias adg="apt-get dist-upgrade"
2666         #a3# Execute \kbd{apt-get install}
2667         salias agi="apt-get install"
2668         #a3# Execute \kbd{aptitude install}
2669         salias ati="aptitude install"
2670         #a3# Execute \kbd{apt-get upgrade}
2671         salias ag="apt-get upgrade"
2672         #a3# Execute \kbd{apt-get update}
2673         salias au="apt-get update"
2674         #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
2675         salias -a up="aptitude update ; aptitude safe-upgrade"
2676         #a3# Execute \kbd{dpkg-buildpackage}
2677         alias dbp='dpkg-buildpackage'
2678         #a3# Execute \kbd{grep-excuses}
2679         alias ge='grep-excuses'
2680     fi
2681
2682     # get a root shell as normal user in live-cd mode:
2683     if isgrmlcd && [[ $UID -ne 0 ]] ; then
2684        alias su="sudo su"
2685     fi
2686
2687 fi
2688
2689 # use /var/log/syslog iff present, fallback to journalctl otherwise
2690 if [ -e /var/log/syslog ] ; then
2691   #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog || journalctl}
2692   salias llog="$PAGER /var/log/syslog"     # take a look at the syslog
2693   #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog || journalctl}
2694   salias tlog="tail -f /var/log/syslog"    # follow the syslog
2695 elif check_com -c journalctl ; then
2696   salias llog="journalctl"
2697   salias tlog="journalctl -f"
2698 fi
2699
2700 # sort installed Debian-packages by size
2701 if check_com -c dpkg-query ; then
2702     #a3# List installed Debian-packages sorted by size
2703     alias debs-by-size="dpkg-query -Wf 'x \${Installed-Size} \${Package} \${Status}\n' | sed -ne '/^x  /d' -e '/^x \(.*\) install ok installed$/s//\1/p' | sort -nr"
2704 fi
2705
2706 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
2707 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord; then
2708     if check_com -c wodim; then
2709         function cdrecord () {
2710             <<__EOF0__
2711 cdrecord is not provided under its original name by Debian anymore.
2712 See #377109 in the BTS of Debian for more details.
2713
2714 Please use the wodim binary instead
2715 __EOF0__
2716             return 1
2717         }
2718     fi
2719 fi
2720
2721 if isgrmlcd; then
2722     # No core dumps: important for a live-cd-system
2723     limit -s core 0
2724 fi
2725
2726 # grmlstuff
2727 function grmlstuff () {
2728 # people should use 'grml-x'!
2729     if check_com -c 915resolution; then
2730         function 855resolution () {
2731             echo "Please use 915resolution as resolution modifying tool for Intel \
2732 graphic chipset."
2733             return -1
2734         }
2735     fi
2736
2737     #a1# Output version of running grml
2738     alias grml-version='cat /etc/grml_version'
2739
2740     if check_com -c grml-debootstrap ; then
2741         function debian2hd () {
2742             echo "Installing debian to harddisk is possible by using grml-debootstrap."
2743             return 1
2744         }
2745     fi
2746 }
2747
2748 # now run the functions
2749 isgrml && checkhome
2750 is4    && isgrml    && grmlstuff
2751 is4    && grmlcomp
2752
2753 # keephack
2754 is4 && xsource "/etc/zsh/keephack"
2755
2756 # wonderful idea of using "e" glob qualifier by Peter Stephenson
2757 # You use it as follows:
2758 # $ NTREF=/reference/file
2759 # $ ls -l *(e:nt:)
2760 # This lists all the files in the current directory newer than the reference file.
2761 # You can also specify the reference file inline; note quotes:
2762 # $ ls -l *(e:'nt ~/.zshenv':)
2763 is4 && function nt () {
2764     if [[ -n $1 ]] ; then
2765         local NTREF=${~1}
2766     fi
2767     [[ $REPLY -nt $NTREF ]]
2768 }
2769
2770 # shell functions
2771
2772 #f1# Reload an autoloadable function
2773 function freload () { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2774 compdef _functions freload
2775
2776 #
2777 # Usage:
2778 #
2779 #      e.g.:   a -> b -> c -> d  ....
2780 #
2781 #      sll a
2782 #
2783 #
2784 #      if parameter is given with leading '=', lookup $PATH for parameter and resolve that
2785 #
2786 #      sll =java
2787 #
2788 #      Note: limit for recursive symlinks on linux:
2789 #            http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/namei.c?id=refs/heads/master#l808
2790 #            This limits recursive symlink follows to 8,
2791 #            while limiting consecutive symlinks to 40.
2792 #
2793 #      When resolving and displaying information about symlinks, no check is made
2794 #      that the displayed information does make any sense on your OS.
2795 #      We leave that decission to the user.
2796 #
2797 #      The zstat module is used to detect symlink loops. zstat is available since zsh4.
2798 #      With an older zsh you will need to abort with <C-c> in that case.
2799 #      When a symlink loop is detected, a warning ist printed and further processing is stopped.
2800 #
2801 #      Module zstat is loaded by default in grml zshrc, no extra action needed for that.
2802 #
2803 #      Known bugs:
2804 #      If you happen to come accross a symlink that points to a destination on an other partition
2805 #      with the same inode number, that will be marked as symlink loop though it is not.
2806 #      Two hints for this situation:
2807 #      I)  Play lottery the same day, as you seem to be rather lucky right now.
2808 #      II) Send patches.
2809 #
2810 #      return status:
2811 #      0 upon success
2812 #      1 file/dir not accesible
2813 #      2 symlink loop detected
2814 #
2815 #f1# List symlinks in detail (more detailed version of 'readlink -f', 'whence -s' and 'namei -l')
2816 function sll () {
2817     if [[ -z ${1} ]] ; then
2818         printf 'Usage: %s <symlink(s)>\n' "${0}"
2819         return 1
2820     fi
2821
2822     local file jumpd curdir
2823     local -i 10 RTN LINODE i
2824     local -a    SEENINODES
2825     curdir="${PWD}"
2826     RTN=0
2827
2828     for file in "${@}" ; do
2829         SEENINODES=()
2830         ls -l "${file:a}"   || RTN=1
2831
2832         while [[ -h "$file" ]] ; do
2833             if is4 ; then
2834                 LINODE=$(zstat -L +inode "${file}")
2835                 for i in ${SEENINODES} ; do
2836                     if (( ${i} == ${LINODE} )) ; then
2837                         builtin cd -q "${curdir}"
2838                         print 'link loop detected, aborting!'
2839                         return 2
2840                     fi
2841                 done
2842                 SEENINODES+=${LINODE}
2843             fi
2844             jumpd="${file:h}"
2845             file="${file:t}"
2846
2847             if [[ -d ${jumpd} ]] ; then
2848                 builtin cd -q "${jumpd}"  || RTN=1
2849             fi
2850             file=$(readlink "$file")
2851
2852             jumpd="${file:h}"
2853             file="${file:t}"
2854
2855             if [[ -d ${jumpd} ]] ; then
2856                 builtin cd -q "${jumpd}"  || RTN=1
2857             fi
2858
2859             ls -l "${PWD}/${file}"     || RTN=1
2860         done
2861         shift 1
2862         if (( ${#} >= 1 )) ; then
2863             print ""
2864         fi
2865         builtin cd -q "${curdir}"
2866     done
2867     return ${RTN}
2868 }
2869
2870 # TODO: Is it supported to use pager settings like this?
2871 #   PAGER='less -Mr' - If so, the use of $PAGER here needs fixing
2872 # with respect to wordsplitting. (ie. ${=PAGER})
2873 if check_com -c $PAGER ; then
2874     #f3# View Debian's changelog of given package(s)
2875     function dchange () {
2876         emulate -L zsh
2877         [[ -z "$1" ]] && printf 'Usage: %s <package_name(s)>\n' "$0" && return 1
2878
2879         local package
2880         for package in "$@" ; do
2881             if [[ -r /usr/share/doc/${package}/changelog.Debian.gz ]] ; then
2882                 $PAGER /usr/share/doc/${package}/changelog.Debian.gz
2883             elif [[ -r /usr/share/doc/${package}/changelog.gz ]] ; then
2884                 $PAGER /usr/share/doc/${package}/changelog.gz
2885             elif [[ -r /usr/share/doc/${package}/changelog ]] ; then
2886                 $PAGER /usr/share/doc/${package}/changelog
2887             else
2888                 if check_com -c aptitude ; then
2889                     echo "No changelog for package $package found, using aptitude to retrieve it."
2890                     aptitude changelog "$package"
2891                 elif check_com -c apt-get ; then
2892                     echo "No changelog for package $package found, using apt-get to retrieve it."
2893                     apt-get changelog "$package"
2894                 else
2895                     echo "No changelog for package $package found, sorry."
2896                 fi
2897             fi
2898         done
2899     }
2900     function _dchange () { _files -W /usr/share/doc -/ }
2901     compdef _dchange dchange
2902
2903     #f3# View Debian's NEWS of a given package
2904     function dnews () {
2905         emulate -L zsh
2906         if [[ -r /usr/share/doc/$1/NEWS.Debian.gz ]] ; then
2907             $PAGER /usr/share/doc/$1/NEWS.Debian.gz
2908         else
2909             if [[ -r /usr/share/doc/$1/NEWS.gz ]] ; then
2910                 $PAGER /usr/share/doc/$1/NEWS.gz
2911             else
2912                 echo "No NEWS file for package $1 found, sorry."
2913                 return 1
2914             fi
2915         fi
2916     }
2917     function _dnews () { _files -W /usr/share/doc -/ }
2918     compdef _dnews dnews
2919
2920     #f3# View Debian's copyright of a given package
2921     function dcopyright () {
2922         emulate -L zsh
2923         if [[ -r /usr/share/doc/$1/copyright ]] ; then
2924             $PAGER /usr/share/doc/$1/copyright
2925         else
2926             echo "No copyright file for package $1 found, sorry."
2927             return 1
2928         fi
2929     }
2930     function _dcopyright () { _files -W /usr/share/doc -/ }
2931     compdef _dcopyright dcopyright
2932
2933     #f3# View upstream's changelog of a given package
2934     function uchange () {
2935         emulate -L zsh
2936         if [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
2937             $PAGER /usr/share/doc/$1/changelog.gz
2938         else
2939             echo "No changelog for package $1 found, sorry."
2940             return 1
2941         fi
2942     }
2943     function _uchange () { _files -W /usr/share/doc -/ }
2944     compdef _uchange uchange
2945 fi
2946
2947 # zsh profiling
2948 function profile () {
2949     ZSH_PROFILE_RC=1 zsh "$@"
2950 }
2951
2952 #f1# Edit an alias via zle
2953 function edalias () {
2954     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
2955 }
2956 compdef _aliases edalias
2957
2958 #f1# Edit a function via zle
2959 function edfunc () {
2960     [[ -z "$1" ]] && { echo "Usage: edfunc <function_to_edit>" ; return 1 } || zed -f "$1" ;
2961 }
2962 compdef _functions edfunc
2963
2964 # use it e.g. via 'Restart apache2'
2965 #m# f6 Start() \kbd{service \em{process}}\quad\kbd{start}
2966 #m# f6 Restart() \kbd{service \em{process}}\quad\kbd{restart}
2967 #m# f6 Stop() \kbd{service \em{process}}\quad\kbd{stop}
2968 #m# f6 Reload() \kbd{service \em{process}}\quad\kbd{reload}
2969 #m# f6 Force-Reload() \kbd{service \em{process}}\quad\kbd{force-reload}
2970 #m# f6 Status() \kbd{service \em{process}}\quad\kbd{status}
2971 if [[ -d /etc/init.d || -d /etc/service ]] ; then
2972     function __start_stop () {
2973         local action_="${1:l}"  # e.g Start/Stop/Restart
2974         local service_="$2"
2975         local param_="$3"
2976
2977         local service_target_="$(readlink /etc/init.d/$service_)"
2978         if [[ $service_target_ == "/usr/bin/sv" ]]; then
2979             # runit
2980             case "${action_}" in
2981                 start) if [[ ! -e /etc/service/$service_ ]]; then
2982                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
2983                        else
2984                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2985                        fi ;;
2986                 # there is no reload in runits sysv emulation
2987                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
2988                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
2989             esac
2990         else
2991             # sysv/sysvinit-utils, upstart
2992             if check_com -c service ; then
2993               $SUDO service "$service_" "${action_}" "$param_"
2994             else
2995               $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2996             fi
2997         fi
2998     }
2999
3000     function _grmlinitd () {
3001         local -a scripts
3002         scripts=( /etc/init.d/*(x:t) )
3003         _describe "service startup script" scripts
3004     }
3005
3006     for i in Start Restart Stop Force-Reload Reload Status ; do
3007         eval "function $i () { __start_stop $i \"\$1\" \"\$2\" ; }"
3008         compdef _grmlinitd $i
3009     done
3010     builtin unset -v i
3011 fi
3012
3013 #f1# Provides useful information on globbing
3014 function H-Glob () {
3015     echo -e "
3016     /      directories
3017     .      plain files
3018     @      symbolic links
3019     =      sockets
3020     p      named pipes (FIFOs)
3021     *      executable plain files (0100)
3022     %      device files (character or block special)
3023     %b     block special files
3024     %c     character special files
3025     r      owner-readable files (0400)
3026     w      owner-writable files (0200)
3027     x      owner-executable files (0100)
3028     A      group-readable files (0040)
3029     I      group-writable files (0020)
3030     E      group-executable files (0010)
3031     R      world-readable files (0004)
3032     W      world-writable files (0002)
3033     X      world-executable files (0001)
3034     s      setuid files (04000)
3035     S      setgid files (02000)
3036     t      files with the sticky bit (01000)
3037
3038   print *(m-1)          # Files modified up to a day ago
3039   print *(a1)           # Files accessed a day ago
3040   print *(@)            # Just symlinks
3041   print *(Lk+50)        # Files bigger than 50 kilobytes
3042   print *(Lk-50)        # Files smaller than 50 kilobytes
3043   print **/*.c          # All *.c files recursively starting in \$PWD
3044   print **/*.c~file.c   # Same as above, but excluding 'file.c'
3045   print (foo|bar).*     # Files starting with 'foo' or 'bar'
3046   print *~*.*           # All Files that do not contain a dot
3047   chmod 644 *(.^x)      # make all plain non-executable files publically readable
3048   print -l *(.c|.h)     # Lists *.c and *.h
3049   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
3050   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
3051 }
3052 alias help-zshglob=H-Glob
3053
3054 # grep for running process, like: 'any vim'
3055 function any () {
3056     emulate -L zsh
3057     unsetopt KSH_ARRAYS
3058     if [[ -z "$1" ]] ; then
3059         echo "any - grep for process(es) by keyword" >&2
3060         echo "Usage: any <keyword>" >&2 ; return 1
3061     else
3062         ps xauwww | grep -i "${grep_options[@]}" "[${1[1]}]${1[2,-1]}"
3063     fi
3064 }
3065
3066
3067 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
3068 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
3069 [[ -r /proc/1/maps ]] && \
3070 function deswap () {
3071     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
3072     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
3073     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
3074 }
3075
3076 # a wrapper for vim, that deals with title setting
3077 #   VIM_OPTIONS
3078 #       set this array to a set of options to vim you always want
3079 #       to have set when calling vim (in .zshrc.local), like:
3080 #           VIM_OPTIONS=( -p )
3081 #       This will cause vim to send every file given on the
3082 #       commandline to be send to it's own tab (needs vim7).
3083 if check_com vim; then
3084     function vim () {
3085         VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
3086     }
3087 fi
3088
3089 ssl_hashes=( sha512 sha256 sha1 md5 )
3090
3091 for sh in ${ssl_hashes}; do
3092     eval 'ssl-cert-'${sh}'() {
3093         emulate -L zsh
3094         if [[ -z $1 ]] ; then
3095             printf '\''usage: %s <file>\n'\'' "ssh-cert-'${sh}'"
3096             return 1
3097         fi
3098         openssl x509 -noout -fingerprint -'${sh}' -in $1
3099     }'
3100 done; unset sh
3101
3102 function ssl-cert-fingerprints () {
3103     emulate -L zsh
3104     local i
3105     if [[ -z $1 ]] ; then
3106         printf 'usage: ssl-cert-fingerprints <file>\n'
3107         return 1
3108     fi
3109     for i in ${ssl_hashes}
3110         do ssl-cert-$i $1;
3111     done
3112 }
3113
3114 function ssl-cert-info () {
3115     emulate -L zsh
3116     if [[ -z $1 ]] ; then
3117         printf 'usage: ssl-cert-info <file>\n'
3118         return 1
3119     fi
3120     openssl x509 -noout -text -in $1
3121     ssl-cert-fingerprints $1
3122 }
3123
3124 # make sure our environment is clean regarding colors
3125 builtin unset -v BLUE RED GREEN CYAN YELLOW MAGENTA WHITE NO_COLOR
3126
3127 # "persistent history"
3128 # just write important commands you always need to $GRML_IMPORTANT_COMMANDS
3129 # defaults for backward compatibility to ~/.important_commands
3130 if [[ -r ~/.important_commands ]] ; then
3131     GRML_IMPORTANT_COMMANDS=~/.important_commands
3132 else
3133     GRML_IMPORTANT_COMMANDS=${GRML_IMPORTANT_COMMANDS:-${ZDOTDIR:-${HOME}}/.important_commands}
3134 fi
3135 [[ -r ${GRML_IMPORTANT_COMMANDS} ]] && builtin fc -R ${GRML_IMPORTANT_COMMANDS}
3136
3137 # load the lookup subsystem if it's available on the system
3138 zrcautoload lookupinit && lookupinit
3139
3140 # variables
3141
3142 # set terminal property (used e.g. by msgid-chooser)
3143 export COLORTERM="yes"
3144
3145 # aliases
3146
3147 # general
3148 #a2# Execute \kbd{du -sch}
3149 [[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias da='du -sch'
3150
3151 # listing stuff
3152 #a2# Execute \kbd{ls -lSrah}
3153 alias dir="command ls -lSrah"
3154 #a2# Only show dot-directories
3155 alias lad='command ls -d .*(/)'
3156 #a2# Only show dot-files
3157 alias lsa='command ls -a .*(.)'
3158 #a2# Only files with setgid/setuid/sticky flag
3159 alias lss='command ls -l *(s,S,t)'
3160 #a2# Only show symlinks
3161 alias lsl='command ls -l *(@)'
3162 #a2# Display only executables
3163 alias lsx='command ls -l *(*)'
3164 #a2# Display world-{readable,writable,executable} files
3165 alias lsw='command ls -ld *(R,W,X.^ND/)'
3166 #a2# Display the ten biggest files
3167 alias lsbig="command ls -flh *(.OL[1,10])"
3168 #a2# Only show directories
3169 alias lsd='command ls -d *(/)'
3170 #a2# Only show empty directories
3171 alias lse='command ls -d *(/^F)'
3172 #a2# Display the ten newest files
3173 alias lsnew="command ls -rtlh *(D.om[1,10])"
3174 #a2# Display the ten oldest files
3175 alias lsold="command ls -rtlh *(D.Om[1,10])"
3176 #a2# Display the ten smallest files
3177 alias lssmall="command ls -Srl *(.oL[1,10])"
3178 #a2# Display the ten newest directories and ten newest .directories
3179 alias lsnewdir="command ls -rthdl *(/om[1,10]) .*(D/om[1,10])"
3180 #a2# Display the ten oldest directories and ten oldest .directories
3181 alias lsolddir="command ls -rthdl *(/Om[1,10]) .*(D/Om[1,10])"
3182
3183 # some useful aliases
3184 #a2# Remove current empty directory. Execute \kbd{cd ..; rmdir \$OLDCWD}
3185 alias rmcdir='cd ..; rmdir $OLDPWD || cd $OLDPWD'
3186
3187 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3188 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3189 #a2# scp with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3190 alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3191
3192 # work around non utf8 capable software in utf environment via $LANG and luit
3193 if check_com isutfenv && check_com luit ; then
3194     if check_com -c mrxvt ; then
3195         isutfenv && [[ -n "$LANG" ]] && \
3196             alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
3197     fi
3198
3199     if check_com -c aterm ; then
3200         isutfenv && [[ -n "$LANG" ]] && \
3201             alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
3202     fi
3203
3204     if check_com -c centericq ; then
3205         isutfenv && [[ -n "$LANG" ]] && \
3206             alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
3207     fi
3208 fi
3209
3210 # useful functions
3211
3212 #f5# Backup \kbd{file_or_folder {\rm to} file_or_folder\_timestamp}
3213 function bk () {
3214     emulate -L zsh
3215     local current_date=$(date -u "+%Y-%m-%dT%H:%M:%SZ")
3216     local clean keep move verbose result all to_bk
3217     setopt extended_glob
3218     keep=1
3219     while getopts ":hacmrv" opt; do
3220         case $opt in
3221             a) (( all++ ));;
3222             c) unset move clean && (( ++keep ));;
3223             m) unset keep clean && (( ++move ));;
3224             r) unset move keep && (( ++clean ));;
3225             v) verbose="-v";;
3226             h) <<__EOF0__
3227 bk [-hcmv] FILE [FILE ...]
3228 bk -r [-av] [FILE [FILE ...]]
3229 Backup a file or folder in place and append the timestamp
3230 Remove backups of a file or folder, or all backups in the current directory
3231
3232 Usage:
3233 -h    Display this help text
3234 -c    Keep the file/folder as is, create a copy backup using cp(1) (default)
3235 -m    Move the file/folder, using mv(1)
3236 -r    Remove backups of the specified file or directory, using rm(1). If none
3237       is provided, remove all backups in the current directory.
3238 -a    Remove all (even hidden) backups.
3239 -v    Verbose
3240
3241 The -c, -r and -m options are mutually exclusive. If specified at the same time,
3242 the last one is used.
3243
3244 The return code is the sum of all cp/mv/rm return codes.
3245 __EOF0__
3246 return 0;;
3247             \?) bk -h >&2; return 1;;
3248         esac
3249     done
3250     shift "$((OPTIND-1))"
3251     if (( keep > 0 )); then
3252         if islinux || isfreebsd; then
3253             for to_bk in "$@"; do
3254                 cp $verbose -a "${to_bk%/}" "${to_bk%/}_$current_date"
3255                 (( result += $? ))
3256             done
3257         else
3258             for to_bk in "$@"; do
3259                 cp $verbose -pR "${to_bk%/}" "${to_bk%/}_$current_date"
3260                 (( result += $? ))
3261             done
3262         fi
3263     elif (( move > 0 )); then
3264         while (( $# > 0 )); do
3265             mv $verbose "${1%/}" "${1%/}_$current_date"
3266             (( result += $? ))
3267             shift
3268         done
3269     elif (( clean > 0 )); then
3270         if (( $# > 0 )); then
3271             for to_bk in "$@"; do
3272                 rm $verbose -rf "${to_bk%/}"_[0-9](#c4,)-(0[0-9]|1[0-2])-([0-2][0-9]|3[0-1])T([0-1][0-9]|2[0-3])(:[0-5][0-9])(#c2)Z
3273                 (( result += $? ))
3274             done
3275         else
3276             if (( all > 0 )); then
3277                 rm $verbose -rf *_[0-9](#c4,)-(0[0-9]|1[0-2])-([0-2][0-9]|3[0-1])T([0-1][0-9]|2[0-3])(:[0-5][0-9])(#c2)Z(D)
3278             else
3279                 rm $verbose -rf *_[0-9](#c4,)-(0[0-9]|1[0-2])-([0-2][0-9]|3[0-1])T([0-1][0-9]|2[0-3])(:[0-5][0-9])(#c2)Z
3280             fi
3281             (( result += $? ))
3282         fi
3283     fi
3284     return $result
3285 }
3286
3287 #f5# cd to directoy and list files
3288 function cl () {
3289     emulate -L zsh
3290     cd $1 && ls -a
3291 }
3292
3293 # smart cd function, allows switching to /etc when running 'cd /etc/fstab'
3294 function cd () {
3295     if (( ${#argv} == 1 )) && [[ -f ${1} ]]; then
3296         [[ ! -e ${1:h} ]] && return 1
3297         print "Correcting ${1} to ${1:h}"
3298         builtin cd ${1:h}
3299     else
3300         builtin cd "$@"
3301     fi
3302 }
3303
3304 #f5# Create Directoy and \kbd{cd} to it
3305 function mkcd () {
3306     if (( ARGC != 1 )); then
3307         printf 'usage: mkcd <new-directory>\n'
3308         return 1;
3309     fi
3310     if [[ ! -d "$1" ]]; then
3311         command mkdir -p "$1"
3312     else
3313         printf '`%s'\'' already exists: cd-ing.\n' "$1"
3314     fi
3315     builtin cd "$1"
3316 }
3317
3318 #f5# Create temporary directory and \kbd{cd} to it
3319 function cdt () {
3320     builtin cd "$(mktemp -d)"
3321     builtin pwd
3322 }
3323
3324 #f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
3325 function accessed () {
3326     emulate -L zsh
3327     print -l -- *(a-${1:-1})
3328 }
3329
3330 #f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
3331 function changed () {
3332     emulate -L zsh
3333     print -l -- *(c-${1:-1})
3334 }
3335
3336 #f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
3337 function modified () {
3338     emulate -L zsh
3339     print -l -- *(m-${1:-1})
3340 }
3341 # modified() was named new() in earlier versions, add an alias for backwards compatibility
3342 check_com new || alias new=modified
3343
3344 # use colors when GNU grep with color-support
3345 if (( $#grep_options > 0 )); then
3346     o=${grep_options:+"${grep_options[*]}"}
3347     #a2# Execute \kbd{grep -{}-color=auto}
3348     alias grep='grep '$o
3349     alias egrep='egrep '$o
3350     unset o
3351 fi
3352
3353 # Translate DE<=>EN
3354 # 'translate' looks up a word in a file with language-to-language
3355 # translations (field separator should be " : "). A typical wordlist looks
3356 # like the following:
3357 #  | english-word : german-translation
3358 # It's also only possible to translate english to german but not reciprocal.
3359 # Use the following oneliner to reverse the sort order:
3360 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
3361 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
3362 #f5# Translates a word
3363 function trans () {
3364     emulate -L zsh
3365     case "$1" in
3366         -[dD]*)
3367             translate -l de-en $2
3368             ;;
3369         -[eE]*)
3370             translate -l en-de $2
3371             ;;
3372         *)
3373             echo "Usage: $0 { -D | -E }"
3374             echo "         -D == German to English"
3375             echo "         -E == English to German"
3376     esac
3377 }
3378
3379 # Usage: simple-extract <file>
3380 # Using option -d deletes the original archive file.
3381 #f5# Smart archive extractor
3382 function simple-extract () {
3383     emulate -L zsh
3384     setopt extended_glob noclobber
3385     local ARCHIVE DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
3386     local RC=0
3387     zparseopts -D -E "d=DELETE_ORIGINAL"
3388     for ARCHIVE in "${@}"; do
3389         case $ARCHIVE in
3390             *(tar.bz2|tbz2|tbz))
3391                 DECOMP_CMD="tar -xvjf -"
3392                 USES_STDIN=true
3393                 USES_STDOUT=false
3394                 ;;
3395             *(tar.gz|tgz))
3396                 DECOMP_CMD="tar -xvzf -"
3397                 USES_STDIN=true
3398                 USES_STDOUT=false
3399                 ;;
3400             *(tar.xz|txz|tar.lzma))
3401                 DECOMP_CMD="tar -xvJf -"
3402                 USES_STDIN=true
3403                 USES_STDOUT=false
3404                 ;;
3405             *tar)
3406                 DECOMP_CMD="tar -xvf -"
3407                 USES_STDIN=true
3408                 USES_STDOUT=false
3409                 ;;
3410             *rar)
3411                 DECOMP_CMD="unrar x"
3412                 USES_STDIN=false
3413                 USES_STDOUT=false
3414                 ;;
3415             *lzh)
3416                 DECOMP_CMD="lha x"
3417                 USES_STDIN=false
3418                 USES_STDOUT=false
3419                 ;;
3420             *7z)
3421                 DECOMP_CMD="7z x"
3422                 USES_STDIN=false
3423                 USES_STDOUT=false
3424                 ;;
3425             *(zip|jar))
3426                 DECOMP_CMD="unzip"
3427                 USES_STDIN=false
3428                 USES_STDOUT=false
3429                 ;;
3430             *deb)
3431                 DECOMP_CMD="ar -x"
3432                 USES_STDIN=false
3433                 USES_STDOUT=false
3434                 ;;
3435             *bz2)
3436                 DECOMP_CMD="bzip2 -d -c -"
3437                 USES_STDIN=true
3438                 USES_STDOUT=true
3439                 ;;
3440             *(gz|Z))
3441                 DECOMP_CMD="gzip -d -c -"
3442                 USES_STDIN=true
3443                 USES_STDOUT=true
3444                 ;;
3445             *(xz|lzma))
3446                 DECOMP_CMD="xz -d -c -"
3447                 USES_STDIN=true
3448                 USES_STDOUT=true
3449                 ;;
3450             *)
3451                 print "ERROR: '$ARCHIVE' has unrecognized archive type." >&2
3452                 RC=$((RC+1))
3453                 continue
3454                 ;;
3455         esac
3456
3457         if ! check_com ${DECOMP_CMD[(w)1]}; then
3458             echo "ERROR: ${DECOMP_CMD[(w)1]} not installed." >&2
3459             RC=$((RC+2))
3460             continue
3461         fi
3462
3463         GZTARGET="${ARCHIVE:t:r}"
3464         if [[ -f $ARCHIVE ]] ; then
3465
3466             print "Extracting '$ARCHIVE' ..."
3467             if $USES_STDIN; then
3468                 if $USES_STDOUT; then
3469                     ${=DECOMP_CMD} < "$ARCHIVE" > $GZTARGET
3470                 else
3471                     ${=DECOMP_CMD} < "$ARCHIVE"
3472                 fi
3473             else
3474                 if $USES_STDOUT; then
3475                     ${=DECOMP_CMD} "$ARCHIVE" > $GZTARGET
3476                 else
3477                     ${=DECOMP_CMD} "$ARCHIVE"
3478                 fi
3479             fi
3480             [[ $? -eq 0 && -n "$DELETE_ORIGINAL" ]] && rm -f "$ARCHIVE"
3481
3482         elif [[ "$ARCHIVE" == (#s)(https|http|ftp)://* ]] ; then
3483             if check_com curl; then
3484                 WGET_CMD="curl -L -s -o -"
3485             elif check_com wget; then
3486                 WGET_CMD="wget -q -O -"
3487             elif check_com fetch; then
3488                 WGET_CMD="fetch -q -o -"
3489             else
3490                 print "ERROR: neither wget, curl nor fetch is installed" >&2
3491                 RC=$((RC+4))
3492                 continue
3493             fi
3494             print "Downloading and Extracting '$ARCHIVE' ..."
3495             if $USES_STDIN; then
3496                 if $USES_STDOUT; then
3497                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD} > $GZTARGET
3498                     RC=$((RC+$?))
3499                 else
3500                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD}
3501                     RC=$((RC+$?))
3502                 fi
3503             else
3504                 if $USES_STDOUT; then
3505                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE") > $GZTARGET
3506                 else
3507                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE")
3508                 fi
3509             fi
3510
3511         else
3512             print "ERROR: '$ARCHIVE' is neither a valid file nor a supported URI." >&2
3513             RC=$((RC+8))
3514         fi
3515     done
3516     return $RC
3517 }
3518
3519 function __archive_or_uri () {
3520     _alternative \
3521         'files:Archives:_files -g "*.(#l)(tar.bz2|tbz2|tbz|tar.gz|tgz|tar.xz|txz|tar.lzma|tar|rar|lzh|7z|zip|jar|deb|bz2|gz|Z|xz|lzma)"' \
3522         '_urls:Remote Archives:_urls'
3523 }
3524
3525 function _simple_extract () {
3526     _arguments \
3527         '-d[delete original archivefile after extraction]' \
3528         '*:Archive Or Uri:__archive_or_uri'
3529 }
3530 compdef _simple_extract simple-extract
3531 [[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias se=simple-extract
3532
3533 #f5# Change the xterm title from within GNU-screen
3534 function xtrename () {
3535     emulate -L zsh
3536     if [[ $1 != "-f" ]] ; then
3537         if [[ -z ${DISPLAY} ]] ; then
3538             printf 'xtrename only makes sense in X11.\n'
3539             return 1
3540         fi
3541     else
3542         shift
3543     fi
3544     if [[ -z $1 ]] ; then
3545         printf 'usage: xtrename [-f] "title for xterm"\n'
3546         printf '  renames the title of xterm from _within_ screen.\n'
3547         printf '  also works without screen.\n'
3548         printf '  will not work if DISPLAY is unset, use -f to override.\n'
3549         return 0
3550     fi
3551     print -n "\eP\e]0;${1}\C-G\e\\"
3552     return 0
3553 }
3554
3555 # Create small urls via http://goo.gl using curl(1).
3556 # API reference: https://code.google.com/apis/urlshortener/
3557 function zurl () {
3558     emulate -L zsh
3559     setopt extended_glob
3560
3561     if [[ -z $1 ]]; then
3562         print "USAGE: zurl <URL>"
3563         return 1
3564     fi
3565
3566     local PN url prog api json contenttype item
3567     local -a data
3568     PN=$0
3569     url=$1
3570
3571     # Prepend 'http://' to given URL where necessary for later output.
3572     if [[ ${url} != http(s|)://* ]]; then
3573         url='http://'${url}
3574     fi
3575
3576     if check_com -c curl; then
3577         prog=curl
3578     else
3579         print "curl is not available, but mandatory for ${PN}. Aborting."
3580         return 1
3581     fi
3582     api='https://www.googleapis.com/urlshortener/v1/url'
3583     contenttype="Content-Type: application/json"
3584     json="{\"longUrl\": \"${url}\"}"
3585     data=(${(f)"$($prog --silent -H ${contenttype} -d ${json} $api)"})
3586     # Parse the response
3587     for item in "${data[@]}"; do
3588         case "$item" in
3589             ' '#'"id":'*)
3590                 item=${item#*: \"}
3591                 item=${item%\",*}
3592                 printf '%s\n' "$item"
3593                 return 0
3594                 ;;
3595         esac
3596     done
3597     return 1
3598 }
3599
3600 #f2# Find history events by search pattern and list them by date.
3601 function whatwhen () {
3602     emulate -L zsh
3603     local usage help ident format_l format_s first_char remain first last
3604     usage='USAGE: whatwhen [options] <searchstring> <search range>'
3605     help='Use `whatwhen -h'\'' for further explanations.'
3606     ident=${(l,${#${:-Usage: }},, ,)}
3607     format_l="${ident}%s\t\t\t%s\n"
3608     format_s="${format_l//(\\t)##/\\t}"
3609     # Make the first char of the word to search for case
3610     # insensitive; e.g. [aA]
3611     first_char=[${(L)1[1]}${(U)1[1]}]
3612     remain=${1[2,-1]}
3613     # Default search range is `-100'.
3614     first=${2:-\-100}
3615     # Optional, just used for `<first> <last>' given.
3616     last=$3
3617     case $1 in
3618         ("")
3619             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
3620             printf '%s\n%s\n\n' ${usage} ${help} && return 1
3621         ;;
3622         (-h)
3623             printf '%s\n\n' ${usage}
3624             print 'OPTIONS:'
3625             printf $format_l '-h' 'show help text'
3626             print '\f'
3627             print 'SEARCH RANGE:'
3628             printf $format_l "'0'" 'the whole history,'
3629             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
3630             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
3631             printf '\n%s\n' 'EXAMPLES:'
3632             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
3633             printf $format_l 'whatwhen zsh -250'
3634             printf $format_l 'whatwhen foo 1 99'
3635         ;;
3636         (\?)
3637             printf '%s\n%s\n\n' ${usage} ${help} && return 1
3638         ;;
3639         (*)
3640             # -l list results on stout rather than invoking $EDITOR.
3641             # -i Print dates as in YYYY-MM-DD.
3642             # -m Search for a - quoted - pattern within the history.
3643             fc -li -m "*${first_char}${remain}*" $first $last
3644         ;;
3645     esac
3646 }
3647
3648 # mercurial related stuff
3649 if check_com -c hg ; then
3650     # gnu like diff for mercurial
3651     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
3652     #f5# GNU like diff for mercurial
3653     function hgdi () {
3654         emulate -L zsh
3655         local i
3656         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
3657     }
3658
3659     # build debian package
3660     #a2# Alias for \kbd{hg-buildpackage}
3661     alias hbp='hg-buildpackage'
3662
3663     # execute commands on the versioned patch-queue from the current repos
3664     [[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
3665
3666     # diffstat for specific version of a mercurial repository
3667     #   hgstat      => display diffstat between last revision and tip
3668     #   hgstat 1234 => display diffstat between revision 1234 and tip
3669     #f5# Diffstat for specific version of a mercurial repos
3670     function hgstat () {
3671         emulate -L zsh
3672         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
3673     }
3674
3675 fi # end of check whether we have the 'hg'-executable
3676
3677 # grml-small cleanups
3678
3679 # The following is used to remove zsh-config-items that do not work
3680 # in grml-small by default.
3681 # If you do not want these adjustments (for whatever reason), set
3682 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
3683 # sources if it is there).
3684
3685 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
3686
3687     unset abk[V]
3688     unalias    'V'      &> /dev/null
3689     unfunction vman     &> /dev/null
3690     unfunction viless   &> /dev/null
3691     unfunction 2html    &> /dev/null
3692
3693     # manpages are not in grmlsmall
3694     unfunction manzsh   &> /dev/null
3695     unfunction man2     &> /dev/null
3696
3697 fi
3698
3699 zrclocal
3700
3701 ## genrefcard.pl settings
3702
3703 ### doc strings for external functions from files
3704 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
3705
3706 ### example: split functions-search 8,16,24,32
3707 #@# split functions-search 8
3708
3709 ## END OF FILE #################################################################
3710 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
3711 # Local variables:
3712 # mode: sh
3713 # End: