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