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