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