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