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