zshrc: Adjustments for abbreviation expansion
[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 zrcautoload colors && colors 2>/dev/null ; then
1601     BLUE="%{${fg[blue]}%}"
1602     RED="%{${fg_bold[red]}%}"
1603     GREEN="%{${fg[green]}%}"
1604     CYAN="%{${fg[cyan]}%}"
1605     MAGENTA="%{${fg[magenta]}%}"
1606     YELLOW="%{${fg[yellow]}%}"
1607     WHITE="%{${fg[white]}%}"
1608     NO_COLOR="%{${reset_color}%}"
1609 else
1610     BLUE=$'%{\e[1;34m%}'
1611     RED=$'%{\e[1;31m%}'
1612     GREEN=$'%{\e[1;32m%}'
1613     CYAN=$'%{\e[1;36m%}'
1614     WHITE=$'%{\e[1;37m%}'
1615     MAGENTA=$'%{\e[1;35m%}'
1616     YELLOW=$'%{\e[1;33m%}'
1617     NO_COLOR=$'%{\e[0m%}'
1618 fi
1619
1620 # First, the easy ones: PS2..4:
1621
1622 # secondary prompt, printed when the shell needs more information to complete a
1623 # command.
1624 PS2='\`%_> '
1625 # selection prompt used within a select loop.
1626 PS3='?# '
1627 # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
1628 PS4='+%N:%i:%_> '
1629
1630 # Some additional features to use with our prompt:
1631 #
1632 #    - battery status
1633 #    - debian_chroot
1634 #    - vcs_info setup and version specific fixes
1635
1636 # display battery status on right side of prompt via running 'BATTERY=1 zsh'
1637 if [[ $BATTERY -gt 0 ]] ; then
1638     if ! check_com -c acpi ; then
1639         BATTERY=0
1640     fi
1641 fi
1642
1643 battery() {
1644 if [[ $BATTERY -gt 0 ]] ; then
1645     PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]#Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
1646     if [[ -z "$PERCENT" ]] ; then
1647         PERCENT='acpi not present'
1648     else
1649         if [[ "$PERCENT" -lt 20 ]] ; then
1650             PERCENT="warning: ${PERCENT}%%"
1651         else
1652             PERCENT="${PERCENT}%%"
1653         fi
1654     fi
1655 fi
1656 }
1657
1658 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
1659 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
1660     debian_chroot=$(</etc/debian_chroot)
1661 fi
1662
1663 # gather version control information for inclusion in a prompt
1664
1665 if zrcautoload vcs_info; then
1666     # `vcs_info' in zsh versions 4.3.10 and below have a broken `_realpath'
1667     # function, which can cause a lot of trouble with our directory-based
1668     # profiles. So:
1669     if [[ ${ZSH_VERSION} == 4.3.<-10> ]] ; then
1670         function VCS_INFO_realpath () {
1671             setopt localoptions NO_shwordsplit chaselinks
1672             ( builtin cd -q $1 2> /dev/null && pwd; )
1673         }
1674     fi
1675
1676     zstyle ':vcs_info:*' max-exports 2
1677
1678     if [[ -o restricted ]]; then
1679         zstyle ':vcs_info:*' enable NONE
1680     fi
1681 fi
1682
1683 # Change vcs_info formats for the grml prompt. The 2nd format sets up
1684 # $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title.
1685 # TODO: The included vcs_info() version still uses $VCS_INFO_message_N_.
1686 #       That needs to be the use of $VCS_INFO_message_N_ needs to be changed
1687 #       to $vcs_info_msg_N_ as soon as we use the included version.
1688 if [[ "$TERM" == dumb ]] ; then
1689     zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] " "zsh: %r"
1690     zstyle ':vcs_info:*' formats       "(%s%)-[%b] "    "zsh: %r"
1691 else
1692     # these are the same, just with a lot of colors:
1693     zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOR} " \
1694                                        "zsh: %r"
1695     zstyle ':vcs_info:*' formats       "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOR}%} " \
1696                                        "zsh: %r"
1697     zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r"
1698 fi
1699
1700 # Now for the fun part: The grml prompt themes in `promptsys' mode of operation
1701
1702 # This actually defines three prompts:
1703 #
1704 #    - grml
1705 #    - grml-large
1706 #    - grml-chroot
1707 #
1708 # They all share the same code and only differ with respect to which items they
1709 # contain. The main source of documentation is the `prompt_grml_help' function
1710 # below, which gets called when the user does this: prompt -h grml
1711
1712 function prompt_grml_help () {
1713     cat <<__EOF0__
1714   prompt grml
1715
1716     This is the prompt as used by the grml-live system <http://grml.org>. It is
1717     a rather simple one-line prompt, that by default looks something like this:
1718
1719         <user>@<host> <current-working-directory>[ <vcs_info-data>]%
1720
1721     The prompt itself integrates with zsh's prompt themes system (as you are
1722     witnessing right now) and is configurable to a certain degree. In
1723     particular, these aspects are customisable:
1724
1725         - The items used in the prompt (e.g. you can remove \`user' from
1726           the list of activated items, which will cause the user name to
1727           be omitted from the prompt string).
1728
1729         - The attributes used with the items are customisable via strings
1730           used before and after the actual item.
1731
1732     The available items are: at, battery, change-root, date, grml-chroot,
1733     history, host, jobs, newline, path, percent, rc, rc-always, sad-smiley,
1734     shell-level, time, user, vcs
1735
1736     The actual configuration is done via zsh's \`zstyle' mechanism. The
1737     context, that is used while looking up styles is:
1738
1739         ':prompt:grml:<left-or-right>:<subcontext>'
1740
1741     Here <left-or-right> is either \`left' or \`right', signifying whether the
1742     style should affect the left or the right prompt. <subcontext> is either
1743     \`setup' or 'items:<item>', where \`<item>' is one of the available items.
1744
1745     The styles:
1746
1747         - use-rprompt (boolean): If \`true' (the default), print a sad smiley
1748           in $RPROMPT if the last command a returned non-successful error code.
1749           (This in only valid if <left-or-right> is "right"; ignored otherwise)
1750
1751         - items (list): The list of items used in the prompt. If \`vcs' is
1752           present in the list, the theme's code invokes \`vcs_info'
1753           accordingly. Default (left): rc change-root user at host path vcs
1754           percent; Default (right): sad-smiley
1755
1756     Available styles in 'items:<item>' are: pre, post. These are strings that
1757     are inserted before (pre) and after (post) the item in question. Thus, the
1758     following would cause the user name to be printed in red instead of the
1759     default blue:
1760
1761         zstyle ':prompt:grml:*:items:user' pre '%F{red}'
1762
1763     Note, that the \`post' style may remain at its default value, because its
1764     default value is '%f', which turns the foreground text attribute off (which
1765     is exactly, what is still required with the new \`pre' value).
1766 __EOF0__
1767 }
1768
1769 function prompt_grml-chroot_help () {
1770     cat <<__EOF0__
1771   prompt grml-chroot
1772
1773     This is a variation of the grml prompt, see: prompt -h grml
1774
1775     The main difference is the default value of the \`items' style. The rest
1776     behaves exactly the same. Here are the defaults for \`grml-chroot':
1777
1778         - left: grml-chroot user at host path percent
1779         - right: (empty list)
1780 __EOF0__
1781 }
1782
1783 function prompt_grml-large_help () {
1784     cat <<__EOF0__
1785   prompt grml-large
1786
1787     This is a variation of the grml prompt, see: prompt -h grml
1788
1789     The main difference is the default value of the \`items' style. In
1790     particular, this theme uses _two_ lines instead of one with the plain
1791     \`grml' theme. The rest behaves exactly the same. Here are the defaults
1792     for \`grml-large':
1793
1794         - left: rc jobs history shell-level change-root time date newline user
1795                 at host path vcs percent
1796         - right: sad-smiley
1797 __EOF0__
1798 }
1799
1800 function grml_prompt_setup () {
1801     emulate -L zsh
1802     autoload -Uz vcs_info
1803     autoload -Uz add-zsh-hook
1804     add-zsh-hook precmd prompt_$1_precmd
1805 }
1806
1807 function prompt_grml_setup () {
1808     grml_prompt_setup grml
1809 }
1810
1811 function prompt_grml-chroot_setup () {
1812     grml_prompt_setup grml-chroot
1813 }
1814
1815 function prompt_grml-large_setup () {
1816     grml_prompt_setup grml-large
1817 }
1818
1819 # These maps define default tokens and pre-/post-decoration for items to be
1820 # used within the themes. All defaults may be customised in a context sensitive
1821 # matter by using zsh's `zstyle' mechanism.
1822 typeset -gA grml_prompt_pre_default \
1823             grml_prompt_post_default \
1824             grml_prompt_token_default \
1825             grml_prompt_token_function
1826
1827 grml_prompt_pre_default=(
1828     at                ''
1829     battery           ' '
1830     change-root       ''
1831     date              '%F{blue}'
1832     grml-chroot       '%F{red}'
1833     history           '%F{green}'
1834     host              ''
1835     jobs              '%F{cyan}'
1836     newline           ''
1837     path              '%B'
1838     percent           ''
1839     rc                '%B%F{red}'
1840     rc-always         ''
1841     sad-smiley        ''
1842     shell-level       '%F{red}'
1843     time              '%F{blue}'
1844     user              '%B%F{blue}'
1845     vcs               ''
1846 )
1847
1848 grml_prompt_post_default=(
1849     at                ''
1850     battery           ''
1851     change-root       ''
1852     date              '%f'
1853     grml-chroot       '%f '
1854     history           '%f'
1855     host              ''
1856     jobs              '%f'
1857     newline           ''
1858     path              '%b'
1859     percent           ''
1860     rc                '%f%b'
1861     rc-always         ''
1862     sad-smiley        ''
1863     shell-level       '%f'
1864     time              '%f'
1865     user              '%f%b'
1866     vcs               ''
1867 )
1868
1869 grml_prompt_token_default=(
1870     at                '@'
1871     battery           'PERCENT'
1872     change-root       'debian_chroot'
1873     date              '%D{%Y-%m-%d}'
1874     grml-chroot       'GRML_CHROOT'
1875     history           '{history#%!} '
1876     host              '%m '
1877     jobs              '[%j running job(s)] '
1878     newline           $'\n'
1879     path              '%40<..<%~%<< '
1880     percent           '%# '
1881     rc                '%(?..%? )'
1882     rc-always         '%?'
1883     sad-smiley        '%(?..:()'
1884     shell-level       '%(3L.+ .)'
1885     time              '%D{%H:%M:%S} '
1886     user              '%n'
1887     vcs               '0'
1888 )
1889
1890 function grml_theme_has_token () {
1891     if (( ARGC != 1 )); then
1892         printf 'usage: grml_theme_has_token <name>\n'
1893         return 1
1894     fi
1895     (( ${+grml_prompt_token_default[$1]} ))
1896 }
1897
1898 function GRML_theme_add_token_usage () {
1899     cat <<__EOF__
1900   Usage: grml_theme_add_token <name> [-f|-i] <token/function> [<pre> <post>]
1901
1902     <name> is the name for the newly added token. If the \`-f' or \`-i' options
1903     are used, <token/function> is the name of the function (see below for
1904     details). Otherwise it is the literal token string to be used. <pre> and
1905     <post> are optional.
1906
1907   Options:
1908
1909     -f <function>   Use a function named \`<function>' each time the token
1910                     is to be expanded.
1911
1912     -i <function>   Use a function named \`<function>' to initialise the
1913                     value of the token _once_ at runtime.
1914
1915     The functions are called with one argument: the token's new name. The
1916     return value is expected in the \$REPLY parameter. The use of these
1917     options is mutually exclusive.
1918
1919     There is a utility function \`grml_theme_has_token', which you can use
1920     to test if a token exists before trying to add it. This can be a guard
1921     for situations in which a \`grml_theme_add_token' call may happen more
1922     than once.
1923
1924   Example:
1925
1926     To add a new token \`day' that expands to the current weekday in the
1927     current locale in green foreground colour, use this:
1928
1929       grml_theme_add_token day '%D{%A}' '%F{green}' '%f'
1930
1931     Another example would be support for \$VIRTUAL_ENV:
1932
1933       function virtual_env_prompt () {
1934         REPLY=\${VIRTUAL_ENV+\${VIRTUAL_ENV:t} }
1935       }
1936       grml_theme_add_token virtual-env -f virtual_env_prompt
1937
1938     After that, you will be able to use a changed \`items' style to
1939     assemble your prompt.
1940 __EOF__
1941 }
1942
1943 function grml_theme_add_token () {
1944     emulate -L zsh
1945     local name token pre post
1946     local -i init funcall
1947
1948     if (( ARGC == 0 )); then
1949         GRML_theme_add_token_usage
1950         return 0
1951     fi
1952
1953     init=0
1954     funcall=0
1955     pre=''
1956     post=''
1957     name=$1
1958     shift
1959     if [[ $1 == '-f' ]]; then
1960         funcall=1
1961         shift
1962     elif [[ $1 == '-i' ]]; then
1963         init=1
1964         shift
1965     fi
1966
1967     if (( ARGC == 0 )); then
1968         printf '
1969 grml_theme_add_token: No token-string/function-name provided!\n\n'
1970         GRML_theme_add_token_usage
1971         return 1
1972     fi
1973     token=$1
1974     shift
1975     if (( ARGC != 0 && ARGC != 2 )); then
1976         printf '
1977 grml_theme_add_token: <pre> and <post> need to by specified _both_!\n\n'
1978         GRML_theme_add_token_usage
1979         return 1
1980     fi
1981     if (( ARGC )); then
1982         pre=$1
1983         post=$2
1984         shift 2
1985     fi
1986
1987     if grml_theme_has_token $name; then
1988         printf '
1989 grml_theme_add_token: Token `%s'\'' exists! Giving up!\n\n' $name
1990         GRML_theme_add_token_usage
1991         return 2
1992     fi
1993     if (( init )); then
1994         $token $name
1995         token=$REPLY
1996     fi
1997     grml_prompt_pre_default[$name]=$pre
1998     grml_prompt_post_default[$name]=$post
1999     if (( funcall )); then
2000         grml_prompt_token_function[$name]=$token
2001         grml_prompt_token_default[$name]=23
2002     else
2003         grml_prompt_token_default[$name]=$token
2004     fi
2005 }
2006
2007 function grml_typeset_and_wrap () {
2008     emulate -L zsh
2009     local target="$1"
2010     local new="$2"
2011     local left="$3"
2012     local right="$4"
2013
2014     if (( ${+parameters[$new]} )); then
2015         typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
2016     fi
2017 }
2018
2019 function grml_prompt_addto () {
2020     emulate -L zsh
2021     local target="$1"
2022     local lr it apre apost new v
2023     local -a items
2024     shift
2025
2026     [[ $target == PS1 ]] && lr=left || lr=right
2027     zstyle -a ":prompt:${grmltheme}:${lr}:setup" items items || items=( "$@" )
2028     typeset -g "${target}="
2029     for it in "${items[@]}"; do
2030         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" pre apre \
2031             || apre=${grml_prompt_pre_default[$it]}
2032         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" post apost \
2033             || apost=${grml_prompt_post_default[$it]}
2034         zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
2035             || new=${grml_prompt_token_default[$it]}
2036         typeset -g "${target}=${(P)target}${apre}"
2037         if (( ${+grml_prompt_token_function[$it]} )); then
2038             ${grml_prompt_token_function[$it]} $it
2039             typeset -g "${target}=${(P)target}${REPLY}"
2040         else
2041             case $it in
2042             battery)
2043                 grml_typeset_and_wrap $target $new '' ''
2044                 ;;
2045             change-root)
2046                 grml_typeset_and_wrap $target $new '(' ')'
2047                 ;;
2048             grml-chroot)
2049                 if [[ -n ${(P)new} ]]; then
2050                     typeset -g "${target}=${(P)target}(CHROOT)"
2051                 fi
2052                 ;;
2053             vcs)
2054                 v="vcs_info_msg_${new}_"
2055                 if (( ! vcscalled )); then
2056                     vcs_info
2057                     vcscalled=1
2058                 fi
2059                 if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
2060                     typeset -g "${target}=${(P)target}${(P)v}"
2061                 fi
2062                 ;;
2063             *) typeset -g "${target}=${(P)target}${new}" ;;
2064             esac
2065         fi
2066         typeset -g "${target}=${(P)target}${apost}"
2067     done
2068 }
2069
2070 function prompt_grml_precmd () {
2071     emulate -L zsh
2072     local grmltheme=grml
2073     local -a left_items right_items
2074     left_items=(rc change-root user at host path vcs percent)
2075     right_items=(sad-smiley)
2076
2077     prompt_grml_precmd_worker
2078 }
2079
2080 function prompt_grml-chroot_precmd () {
2081     emulate -L zsh
2082     local grmltheme=grml-chroot
2083     local -a left_items right_items
2084     left_items=(grml-chroot user at host path percent)
2085     right_items=()
2086
2087     prompt_grml_precmd_worker
2088 }
2089
2090 function prompt_grml-large_precmd () {
2091     emulate -L zsh
2092     local grmltheme=grml-large
2093     local -a left_items right_items
2094     left_items=(rc jobs history shell-level change-root time date newline
2095                 user at host path vcs percent)
2096     right_items=(sad-smiley)
2097
2098     prompt_grml_precmd_worker
2099 }
2100
2101 function prompt_grml_precmd_worker () {
2102     emulate -L zsh
2103     local -i vcscalled=0
2104
2105     grml_prompt_addto PS1 "${left_items[@]}"
2106     if zstyle -T ":prompt:${grmltheme}:right:setup" use-rprompt; then
2107         grml_prompt_addto RPS1 "${right_items[@]}"
2108     fi
2109 }
2110
2111 grml_prompt_fallback() {
2112     setopt prompt_subst
2113     precmd() {
2114         (( ${+functions[vcs_info]} )) && vcs_info
2115     }
2116
2117     p0="${RED}%(?..%? )${WHITE}${debian_chroot:+($debian_chroot)}"
2118     p1="${BLUE}%n${NO_COLOR}@%m %40<...<%B%~%b%<< "'${vcs_info_msg_0_}'"%# "
2119     if (( EUID == 0 )); then
2120         PROMPT="${BLUE}${p0}${RED}${p1}"
2121     else
2122         PROMPT="${RED}${p0}${BLUE}${p1}"
2123     fi
2124     unset p0 p1
2125 }
2126
2127 if zrcautoload promptinit && promptinit 2>/dev/null ; then
2128     # Since we define the required functions in here and not in files in
2129     # $fpath, we need to stick the theme's name into `$prompt_themes'
2130     # ourselves, since promptinit does not pick them up otherwise.
2131     prompt_themes+=( grml grml-chroot grml-large )
2132     # Also, keep the array sorted...
2133     prompt_themes=( "${(@on)prompt_themes}" )
2134 else
2135     print 'Notice: no promptinit available :('
2136     grml_prompt_fallback
2137 fi
2138
2139 if is437; then
2140     # The prompt themes use modern features of zsh, that require at least
2141     # version 4.3.7 of the shell. Use the fallback otherwise.
2142     if [[ $BATTERY -gt 0 ]]; then
2143         zstyle ':prompt:grml:right:setup' items sad-smiley battery
2144         add-zsh-hook precmd battery
2145     fi
2146     if [[ "$TERM" == dumb ]] ; then
2147         zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" pre ''
2148         zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" post ' '
2149         for i in rc user path jobs history date time shell-level; do
2150             zstyle ":prompt:grml(|-large|-chroot):*:items:$i" pre ''
2151             zstyle ":prompt:grml(|-large|-chroot):*:items:$i" post ''
2152         done
2153         unset i
2154         zstyle ':prompt:grml(|-large|-chroot):right:setup' use-rprompt false
2155     elif (( EUID == 0 )); then
2156         zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%B%F{red}'
2157     fi
2158
2159     # Finally enable one of the prompts.
2160     if [[ -n $GRML_CHROOT ]]; then
2161         prompt grml-chroot
2162     elif [[ $GRMLPROMPT -gt 0 ]]; then
2163         prompt grml-large
2164     else
2165         prompt grml
2166     fi
2167 else
2168     grml_prompt_fallback
2169 fi
2170
2171 # Terminal-title wizardry
2172
2173 function ESC_print () {
2174     info_print $'\ek' $'\e\\' "$@"
2175 }
2176 function set_title () {
2177     info_print  $'\e]0;' $'\a' "$@"
2178 }
2179
2180 function info_print () {
2181     local esc_begin esc_end
2182     esc_begin="$1"
2183     esc_end="$2"
2184     shift 2
2185     printf '%s' ${esc_begin}
2186     printf '%s' "$*"
2187     printf '%s' "${esc_end}"
2188 }
2189
2190 function grml_reset_screen_title () {
2191     # adjust title of xterm
2192     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
2193     [[ ${NOTITLE:-} -gt 0 ]] && return 0
2194     case $TERM in
2195         (xterm*|rxvt*)
2196             set_title ${(%):-"%n@%m: %~"}
2197             ;;
2198     esac
2199 }
2200
2201 function grml_vcs_to_screen_title () {
2202     if [[ $TERM == screen* ]] ; then
2203         if [[ -n ${vcs_info_msg_1_} ]] ; then
2204             ESC_print ${vcs_info_msg_1_}
2205         else
2206             ESC_print "zsh"
2207         fi
2208     fi
2209 }
2210
2211 function grml_maintain_name () {
2212     # set hostname if not running on host with name 'grml'
2213     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
2214        NAME="@$HOSTNAME"
2215     fi
2216 }
2217
2218 function grml_cmd_to_screen_title () {
2219     # get the name of the program currently running and hostname of local
2220     # machine set screen window title if running in a screen
2221     if [[ "$TERM" == screen* ]] ; then
2222         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME"
2223         ESC_print ${CMD}
2224     fi
2225 }
2226
2227 function grml_control_xterm_title () {
2228     case $TERM in
2229         (xterm*|rxvt*)
2230             set_title "${(%):-"%n@%m:"}" "$1"
2231             ;;
2232     esac
2233 }
2234
2235 zrcautoload add-zsh-hook || add-zsh-hook () { :; }
2236 if [[ $NOPRECMD -eq 0 ]]; then
2237     add-zsh-hook precmd grml_reset_screen_title
2238     add-zsh-hook precmd grml_vcs_to_screen_title
2239     add-zsh-hook preexec grml_maintain_name
2240     add-zsh-hook preexec grml_cmd_to_screen_title
2241     if [[ $NOTITLE -eq 0 ]]; then
2242         add-zsh-hook preexec grml_control_xterm_title
2243     fi
2244 fi
2245
2246 # 'hash' some often used directories
2247 #d# start
2248 hash -d deb=/var/cache/apt/archives
2249 hash -d doc=/usr/share/doc
2250 hash -d linux=/lib/modules/$(command uname -r)/build/
2251 hash -d log=/var/log
2252 hash -d slog=/var/log/syslog
2253 hash -d src=/usr/src
2254 hash -d templ=/usr/share/doc/grml-templates
2255 hash -d tt=/usr/share/doc/texttools-doc
2256 hash -d www=/var/www
2257 #d# end
2258
2259 # some aliases
2260 if check_com -c screen ; then
2261     if [[ $UID -eq 0 ]] ; then
2262         if [[ -r /etc/grml/screenrc ]]; then
2263             alias screen="${commands[screen]} -c /etc/grml/screenrc"
2264         fi
2265     elif [[ -r $HOME/.screenrc ]] ; then
2266         alias screen="${commands[screen]} -c $HOME/.screenrc"
2267     else
2268         if [[ -r /etc/grml/screenrc_grml ]]; then
2269             alias screen="${commands[screen]} -c /etc/grml/screenrc_grml"
2270         else
2271             if [[ -r /etc/grml/screenrc ]]; then
2272                 alias screen="${commands[screen]} -c /etc/grml/screenrc"
2273             fi
2274         fi
2275     fi
2276 fi
2277
2278 # do we have GNU ls with color-support?
2279 if [[ "$TERM" != dumb ]]; then
2280     #a1# List files with colors (\kbd{ls -CF \ldots})
2281     alias ls='ls -CF '${ls_options:+"${ls_options[*]}"}
2282     #a1# List all files, with colors (\kbd{ls -la \ldots})
2283     alias la='ls -la '${ls_options:+"${ls_options[*]}"}
2284     #a1# List files with long colored list, without dotfiles (\kbd{ls -l \ldots})
2285     alias ll='ls -l '${ls_options:+"${ls_options[*]}"}
2286     #a1# List files with long colored list, human readable sizes (\kbd{ls -hAl \ldots})
2287     alias lh='ls -hAl '${ls_options:+"${ls_options[*]}"}
2288     #a1# List files with long colored list, append qualifier to filenames (\kbd{ls -lF \ldots})\\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
2289     alias l='ls -lF '${ls_options:+"${ls_options[*]}"}
2290 else
2291     alias ls='ls -CF'
2292     alias la='ls -la'
2293     alias ll='ls -l'
2294     alias lh='ls -hAl'
2295     alias l='ls -lF'
2296 fi
2297
2298 alias mdstat='cat /proc/mdstat'
2299 alias ...='cd ../../'
2300
2301 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
2302 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
2303     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
2304 fi
2305
2306 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
2307 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
2308 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
2309
2310 # make sure it is not assigned yet
2311 [[ -n ${aliases[utf2iso]} ]] && unalias utf2iso
2312 utf2iso() {
2313     if isutfenv ; then
2314         for ENV in $(env | command grep -i '.utf') ; do
2315             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
2316         done
2317     fi
2318 }
2319
2320 # make sure it is not assigned yet
2321 [[ -n ${aliases[iso2utf]} ]] && unalias iso2utf
2322 iso2utf() {
2323     if ! isutfenv ; then
2324         for ENV in $(env | command grep -i '\.iso') ; do
2325             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
2326         done
2327     fi
2328 }
2329
2330 # especially for roadwarriors using GNU screen and ssh:
2331 if ! check_com asc &>/dev/null ; then
2332   asc() { autossh -t "$@" 'screen -RdU' }
2333   compdef asc=ssh
2334 fi
2335
2336 #f1# Hints for the use of zsh on grml
2337 zsh-help() {
2338     print "$bg[white]$fg[black]
2339 zsh-help - hints for use of zsh on grml
2340 =======================================$reset_color"
2341
2342     print '
2343 Main configuration of zsh happens in /etc/zsh/zshrc.
2344 That file is part of the package grml-etc-core, if you want to
2345 use them on a non-grml-system just get the tar.gz from
2346 http://deb.grml.org/ or (preferably) get it from the git repository:
2347
2348   http://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
2349
2350 This version of grml'\''s zsh setup does not use skel/.zshrc anymore.
2351 The file is still there, but it is empty for backwards compatibility.
2352
2353 For your own changes use these two files:
2354     $HOME/.zshrc.pre
2355     $HOME/.zshrc.local
2356
2357 The former is sourced very early in our zshrc, the latter is sourced
2358 very lately.
2359
2360 System wide configuration without touching configuration files of grml
2361 can take place in /etc/zsh/zshrc.local.
2362
2363 For information regarding zsh start at http://grml.org/zsh/
2364
2365 Take a look at grml'\''s zsh refcard:
2366 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
2367
2368 Check out the main zsh refcard:
2369 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
2370
2371 And of course visit the zsh-lovers:
2372 % man zsh-lovers
2373
2374 You can adjust some options through environment variables when
2375 invoking zsh without having to edit configuration files.
2376 Basically meant for bash users who are not used to the power of
2377 the zsh yet. :)
2378
2379   "NOCOR=1    zsh" => deactivate automatic correction
2380   "NOMENU=1   zsh" => do not use auto menu completion
2381                       (note: use ctrl-d for completion instead!)
2382   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
2383   "NOTITLE=1  zsh" => disable setting the title of xterms without disabling
2384                       preexec() and precmd() completely
2385   "BATTERY=1  zsh" => activate battery status (via acpi) on right side of prompt
2386   "COMMAND_NOT_FOUND=1 zsh"
2387                    => Enable a handler if an external command was not found
2388                       The command called in the handler can be altered by setting
2389                       the GRML_ZSH_CNF_HANDLER variable, the default is:
2390                       "/usr/share/command-not-found/command-not-found"
2391
2392 A value greater than 0 is enables a feature; a value equal to zero
2393 disables it. If you like one or the other of these settings, you can
2394 add them to ~/.zshrc.pre to ensure they are set when sourcing grml'\''s
2395 zshrc.'
2396
2397     print "
2398 $bg[white]$fg[black]
2399 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
2400 Enjoy your grml system with the zsh!$reset_color"
2401 }
2402
2403 # debian stuff
2404 if [[ -r /etc/debian_version ]] ; then
2405     #a3# Execute \kbd{apt-cache search}
2406     alias acs='apt-cache search'
2407     #a3# Execute \kbd{apt-cache show}
2408     alias acsh='apt-cache show'
2409     #a3# Execute \kbd{apt-cache policy}
2410     alias acp='apt-cache policy'
2411     #a3# Execute \kbd{apt-get dist-upgrade}
2412     salias adg="apt-get dist-upgrade"
2413     #a3# Execute \kbd{apt-get install}
2414     salias agi="apt-get install"
2415     #a3# Execute \kbd{aptitude install}
2416     salias ati="aptitude install"
2417     #a3# Execute \kbd{apt-get upgrade}
2418     salias ag="apt-get upgrade"
2419     #a3# Execute \kbd{apt-get update}
2420     salias au="apt-get update"
2421     #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
2422     salias -a up="aptitude update ; aptitude safe-upgrade"
2423     #a3# Execute \kbd{dpkg-buildpackage}
2424     alias dbp='dpkg-buildpackage'
2425     #a3# Execute \kbd{grep-excuses}
2426     alias ge='grep-excuses'
2427
2428     # get a root shell as normal user in live-cd mode:
2429     if isgrmlcd && [[ $UID -ne 0 ]] ; then
2430        alias su="sudo su"
2431      fi
2432
2433     #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
2434     salias llog="$PAGER /var/log/syslog"     # take a look at the syslog
2435     #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
2436     salias tlog="tail -f /var/log/syslog"    # follow the syslog
2437 fi
2438
2439 # sort installed Debian-packages by size
2440 if check_com -c dpkg-query ; then
2441     #a3# List installed Debian-packages sorted by size
2442     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"
2443 fi
2444
2445 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
2446 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord; then
2447     if check_com -c wodim; then
2448         cdrecord() {
2449             cat <<EOMESS
2450 cdrecord is not provided under its original name by Debian anymore.
2451 See #377109 in the BTS of Debian for more details.
2452
2453 Please use the wodim binary instead
2454 EOMESS
2455             return 1
2456         }
2457     fi
2458 fi
2459
2460 # Use hard limits, except for a smaller stack and no core dumps
2461 unlimit
2462 is425 && limit stack 8192
2463 isgrmlcd && limit core 0 # important for a live-cd-system
2464 limit -s
2465
2466 # grmlstuff
2467 grmlstuff() {
2468 # people should use 'grml-x'!
2469     if check_com -c 915resolution; then
2470         855resolution() {
2471             echo "Please use 915resolution as resolution modifying tool for Intel \
2472 graphic chipset."
2473             return -1
2474         }
2475     fi
2476
2477     #a1# Output version of running grml
2478     alias grml-version='cat /etc/grml_version'
2479
2480     if check_com -c grml-debootstrap ; then
2481         debian2hd() {
2482             echo "Installing debian to harddisk is possible by using grml-debootstrap."
2483             return 1
2484         }
2485     fi
2486 }
2487
2488 # now run the functions
2489 isgrml && checkhome
2490 is4    && isgrml    && grmlstuff
2491 is4    && grmlcomp
2492
2493 # keephack
2494 is4 && xsource "/etc/zsh/keephack"
2495
2496 # wonderful idea of using "e" glob qualifier by Peter Stephenson
2497 # You use it as follows:
2498 # $ NTREF=/reference/file
2499 # $ ls -l *(e:nt:)
2500 # This lists all the files in the current directory newer than the reference file.
2501 # You can also specify the reference file inline; note quotes:
2502 # $ ls -l *(e:'nt ~/.zshenv':)
2503 is4 && nt() {
2504     if [[ -n $1 ]] ; then
2505         local NTREF=${~1}
2506     fi
2507     [[ $REPLY -nt $NTREF ]]
2508 }
2509
2510 # shell functions
2511
2512 #f1# Reload an autoloadable function
2513 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2514 compdef _functions freload
2515
2516 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
2517 sll() {
2518     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
2519     local file
2520     for file in "$@" ; do
2521         while [[ -h "$file" ]] ; do
2522             ls -l $file
2523             file=$(readlink "$file")
2524         done
2525     done
2526 }
2527
2528 # TODO: Is it supported to use pager settings like this?
2529 #   PAGER='less -Mr' - If so, the use of $PAGER here needs fixing
2530 # with respect to wordsplitting. (ie. ${=PAGER})
2531 if check_com -c $PAGER ; then
2532     #f3# View Debian's changelog of given package(s)
2533     dchange() {
2534         emulate -L zsh
2535         [[ -z "$1" ]] && printf 'Usage: %s <package_name(s)>\n' "$0" && return 1
2536
2537         local package
2538         for package in "$@" ; do
2539             if [[ -r /usr/share/doc/${package}/changelog.Debian.gz ]] ; then
2540                 $PAGER /usr/share/doc/${package}/changelog.Debian.gz
2541             elif [[ -r /usr/share/doc/${package}/changelog.gz ]] ; then
2542                 $PAGER /usr/share/doc/${package}/changelog.gz
2543             elif [[ -r /usr/share/doc/${package}/changelog ]] ; then
2544                 $PAGER /usr/share/doc/${package}/changelog
2545             else
2546                 if check_com -c aptitude ; then
2547                     echo "No changelog for package $package found, using aptitude to retrieve it."
2548                     aptitude changelog "$package"
2549                 elif check_com -c apt-get ; then
2550                     echo "No changelog for package $package found, using apt-get to retrieve it."
2551                     apt-get changelog "$package"
2552                 else
2553                     echo "No changelog for package $package found, sorry."
2554                 fi
2555             fi
2556         done
2557     }
2558     _dchange() { _files -W /usr/share/doc -/ }
2559     compdef _dchange dchange
2560
2561     #f3# View Debian's NEWS of a given package
2562     dnews() {
2563         emulate -L zsh
2564         if [[ -r /usr/share/doc/$1/NEWS.Debian.gz ]] ; then
2565             $PAGER /usr/share/doc/$1/NEWS.Debian.gz
2566         else
2567             if [[ -r /usr/share/doc/$1/NEWS.gz ]] ; then
2568                 $PAGER /usr/share/doc/$1/NEWS.gz
2569             else
2570                 echo "No NEWS file for package $1 found, sorry."
2571                 return 1
2572             fi
2573         fi
2574     }
2575     _dnews() { _files -W /usr/share/doc -/ }
2576     compdef _dnews dnews
2577
2578     #f3# View Debian's copyright of a given package
2579     dcopyright() {
2580         emulate -L zsh
2581         if [[ -r /usr/share/doc/$1/copyright ]] ; then
2582             $PAGER /usr/share/doc/$1/copyright
2583         else
2584             echo "No copyright file for package $1 found, sorry."
2585             return 1
2586         fi
2587     }
2588     _dcopyright() { _files -W /usr/share/doc -/ }
2589     compdef _dcopyright dcopyright
2590
2591     #f3# View upstream's changelog of a given package
2592     uchange() {
2593         emulate -L zsh
2594         if [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
2595             $PAGER /usr/share/doc/$1/changelog.gz
2596         else
2597             echo "No changelog for package $1 found, sorry."
2598             return 1
2599         fi
2600     }
2601     _uchange() { _files -W /usr/share/doc -/ }
2602     compdef _uchange uchange
2603 fi
2604
2605 # zsh profiling
2606 profile() {
2607     ZSH_PROFILE_RC=1 $SHELL "$@"
2608 }
2609
2610 #f1# Edit an alias via zle
2611 edalias() {
2612     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
2613 }
2614 compdef _aliases edalias
2615
2616 #f1# Edit a function via zle
2617 edfunc() {
2618     [[ -z "$1" ]] && { echo "Usage: edfunc <function_to_edit>" ; return 1 } || zed -f "$1" ;
2619 }
2620 compdef _functions edfunc
2621
2622 # use it e.g. via 'Restart apache2'
2623 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
2624 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
2625 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
2626 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
2627 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
2628 #m# f6 Status() \kbd{/etc/init.d/\em{process}}\quad\kbd{status}
2629 if [[ -d /etc/init.d || -d /etc/service ]] ; then
2630     __start_stop() {
2631         local action_="${1:l}"  # e.g Start/Stop/Restart
2632         local service_="$2"
2633         local param_="$3"
2634
2635         local service_target_="$(readlink /etc/init.d/$service_)"
2636         if [[ $service_target_ == "/usr/bin/sv" ]]; then
2637             # runit
2638             case "${action_}" in
2639                 start) if [[ ! -e /etc/service/$service_ ]]; then
2640                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
2641                        else
2642                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2643                        fi ;;
2644                 # there is no reload in runits sysv emulation
2645                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
2646                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
2647             esac
2648         else
2649             # sysvinit
2650             $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2651         fi
2652     }
2653
2654     _grmlinitd() {
2655         local -a scripts
2656         scripts=( /etc/init.d/*(x:t) )
2657         _describe "service startup script" scripts
2658     }
2659
2660     for i in Start Restart Stop Force-Reload Reload Status ; do
2661         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
2662         compdef _grmlinitd $i
2663     done
2664 fi
2665
2666 #f1# Provides useful information on globbing
2667 H-Glob() {
2668     echo -e "
2669     /      directories
2670     .      plain files
2671     @      symbolic links
2672     =      sockets
2673     p      named pipes (FIFOs)
2674     *      executable plain files (0100)
2675     %      device files (character or block special)
2676     %b     block special files
2677     %c     character special files
2678     r      owner-readable files (0400)
2679     w      owner-writable files (0200)
2680     x      owner-executable files (0100)
2681     A      group-readable files (0040)
2682     I      group-writable files (0020)
2683     E      group-executable files (0010)
2684     R      world-readable files (0004)
2685     W      world-writable files (0002)
2686     X      world-executable files (0001)
2687     s      setuid files (04000)
2688     S      setgid files (02000)
2689     t      files with the sticky bit (01000)
2690
2691   print *(m-1)          # Files modified up to a day ago
2692   print *(a1)           # Files accessed a day ago
2693   print *(@)            # Just symlinks
2694   print *(Lk+50)        # Files bigger than 50 kilobytes
2695   print *(Lk-50)        # Files smaller than 50 kilobytes
2696   print **/*.c          # All *.c files recursively starting in \$PWD
2697   print **/*.c~file.c   # Same as above, but excluding 'file.c'
2698   print (foo|bar).*     # Files starting with 'foo' or 'bar'
2699   print *~*.*           # All Files that do not contain a dot
2700   chmod 644 *(.^x)      # make all plain non-executable files publically readable
2701   print -l *(.c|.h)     # Lists *.c and *.h
2702   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
2703   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
2704 }
2705 alias help-zshglob=H-Glob
2706
2707 # grep for running process, like: 'any vim'
2708 any() {
2709     emulate -L zsh
2710     unsetopt KSH_ARRAYS
2711     if [[ -z "$1" ]] ; then
2712         echo "any - grep for process(es) by keyword" >&2
2713         echo "Usage: any <keyword>" >&2 ; return 1
2714     else
2715         ps xauwww | grep -i "${grep_options[@]}" "[${1[1]}]${1[2,-1]}"
2716     fi
2717 }
2718
2719
2720 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
2721 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
2722 [[ -r /proc/1/maps ]] && \
2723 deswap() {
2724     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
2725     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
2726     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
2727 }
2728
2729 # a wrapper for vim, that deals with title setting
2730 #   VIM_OPTIONS
2731 #       set this array to a set of options to vim you always want
2732 #       to have set when calling vim (in .zshrc.local), like:
2733 #           VIM_OPTIONS=( -p )
2734 #       This will cause vim to send every file given on the
2735 #       commandline to be send to it's own tab (needs vim7).
2736 if check_com vim; then
2737     vim() {
2738         VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
2739     }
2740 fi
2741
2742 ssl_hashes=( sha512 sha256 sha1 md5 )
2743
2744 for sh in ${ssl_hashes}; do
2745     eval 'ssl-cert-'${sh}'() {
2746         emulate -L zsh
2747         if [[ -z $1 ]] ; then
2748             printf '\''usage: %s <file>\n'\'' "ssh-cert-'${sh}'"
2749             return 1
2750         fi
2751         openssl x509 -noout -fingerprint -'${sh}' -in $1
2752     }'
2753 done; unset sh
2754
2755 ssl-cert-fingerprints() {
2756     emulate -L zsh
2757     local i
2758     if [[ -z $1 ]] ; then
2759         printf 'usage: ssl-cert-fingerprints <file>\n'
2760         return 1
2761     fi
2762     for i in ${ssl_hashes}
2763         do ssl-cert-$i $1;
2764     done
2765 }
2766
2767 ssl-cert-info() {
2768     emulate -L zsh
2769     if [[ -z $1 ]] ; then
2770         printf 'usage: ssl-cert-info <file>\n'
2771         return 1
2772     fi
2773     openssl x509 -noout -text -in $1
2774     ssl-cert-fingerprints $1
2775 }
2776
2777 # make sure our environment is clean regarding colors
2778 for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
2779
2780 # "persistent history"
2781 # just write important commands you always need to ~/.important_commands
2782 if [[ -r ~/.important_commands ]] ; then
2783     fc -R ~/.important_commands
2784 fi
2785
2786 # load the lookup subsystem if it's available on the system
2787 zrcautoload lookupinit && lookupinit
2788
2789 # variables
2790
2791 # set terminal property (used e.g. by msgid-chooser)
2792 export COLORTERM="yes"
2793
2794 # aliases
2795
2796 # general
2797 #a2# Execute \kbd{du -sch}
2798 alias da='du -sch'
2799 #a2# Execute \kbd{jobs -l}
2800 alias j='jobs -l'
2801
2802 # listing stuff
2803 #a2# Execute \kbd{ls -lSrah}
2804 alias dir="ls -lSrah"
2805 #a2# Only show dot-directories
2806 alias lad='ls -d .*(/)'
2807 #a2# Only show dot-files
2808 alias lsa='ls -a .*(.)'
2809 #a2# Only files with setgid/setuid/sticky flag
2810 alias lss='ls -l *(s,S,t)'
2811 #a2# Only show symlinks
2812 alias lsl='ls -l *(@)'
2813 #a2# Display only executables
2814 alias lsx='ls -l *(*)'
2815 #a2# Display world-{readable,writable,executable} files
2816 alias lsw='ls -ld *(R,W,X.^ND/)'
2817 #a2# Display the ten biggest files
2818 alias lsbig="ls -flh *(.OL[1,10])"
2819 #a2# Only show directories
2820 alias lsd='ls -d *(/)'
2821 #a2# Only show empty directories
2822 alias lse='ls -d *(/^F)'
2823 #a2# Display the ten newest files
2824 alias lsnew="ls -rtlh *(D.om[1,10])"
2825 #a2# Display the ten oldest files
2826 alias lsold="ls -rtlh *(D.Om[1,10])"
2827 #a2# Display the ten smallest files
2828 alias lssmall="ls -Srl *(.oL[1,10])"
2829 #a2# Display the ten newest directories and ten newest .directories
2830 alias lsnewdir="ls -rthdl *(/om[1,10]) .*(D/om[1,10])"
2831 #a2# Display the ten oldest directories and ten oldest .directories
2832 alias lsolddir="ls -rthdl *(/Om[1,10]) .*(D/Om[1,10])"
2833
2834 # some useful aliases
2835 #a2# Remove current empty directory. Execute \kbd{cd ..; rmdir \$OLDCWD}
2836 alias rmcdir='cd ..; rmdir $OLDPWD || cd $OLDPWD'
2837
2838 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
2839 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
2840 #a2# scp with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
2841 alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
2842
2843 # work around non utf8 capable software in utf environment via $LANG and luit
2844 if check_com isutfenv && check_com luit ; then
2845     if check_com -c mrxvt ; then
2846         isutfenv && [[ -n "$LANG" ]] && \
2847             alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
2848     fi
2849
2850     if check_com -c aterm ; then
2851         isutfenv && [[ -n "$LANG" ]] && \
2852             alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
2853     fi
2854
2855     if check_com -c centericq ; then
2856         isutfenv && [[ -n "$LANG" ]] && \
2857             alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
2858     fi
2859 fi
2860
2861 # useful functions
2862
2863 #f5# Backup \kbd{file {\rm to} file\_timestamp}
2864 bk() {
2865     emulate -L zsh
2866     cp -b $1 $1_`date --iso-8601=m`
2867 }
2868
2869 #f5# cd to directoy and list files
2870 cl() {
2871     emulate -L zsh
2872     cd $1 && ls -a
2873 }
2874
2875 # smart cd function, allows switching to /etc when running 'cd /etc/fstab'
2876 cd() {
2877     if (( ${#argv} == 1 )) && [[ -f ${1} ]]; then
2878         [[ ! -e ${1:h} ]] && return 1
2879         print "Correcting ${1} to ${1:h}"
2880         builtin cd ${1:h}
2881     else
2882         builtin cd "$@"
2883     fi
2884 }
2885
2886 #f5# Create Directoy and \kbd{cd} to it
2887 mkcd() {
2888     if (( ARGC != 1 )); then
2889         printf 'usage: mkcd <new-directory>\n'
2890         return 1;
2891     fi
2892     if [[ ! -d "$1" ]]; then
2893         command mkdir -p "$1"
2894     else
2895         printf '`%s'\'' already exists: cd-ing.\n' "$1"
2896     fi
2897     builtin cd "$1"
2898 }
2899
2900 #f5# Create temporary directory and \kbd{cd} to it
2901 cdt() {
2902     local t
2903     t=$(mktemp -d)
2904     echo "$t"
2905     builtin cd "$t"
2906 }
2907
2908 #f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
2909 accessed() {
2910     emulate -L zsh
2911     print -l -- *(a-${1:-1})
2912 }
2913
2914 #f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
2915 changed() {
2916     emulate -L zsh
2917     print -l -- *(c-${1:-1})
2918 }
2919
2920 #f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
2921 modified() {
2922     emulate -L zsh
2923     print -l -- *(m-${1:-1})
2924 }
2925 # modified() was named new() in earlier versions, add an alias for backwards compatibility
2926 check_com new || alias new=modified
2927
2928 # use colors when GNU grep with color-support
2929 if (( $#grep_options > 0 )); then
2930     o=${grep_options:+"${grep_options[*]}"}
2931     #a2# Execute \kbd{grep -{}-color=auto}
2932     alias grep='grep '$o
2933     alias egrep='egrep '$o
2934     unset o
2935 fi
2936
2937 # Translate DE<=>EN
2938 # 'translate' looks up fot a word in a file with language-to-language
2939 # translations (field separator should be " : "). A typical wordlist looks
2940 # like at follows:
2941 #  | english-word : german-transmission
2942 # It's also only possible to translate english to german but not reciprocal.
2943 # Use the following oneliner to turn back the sort order:
2944 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
2945 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
2946 #f5# Translates a word
2947 trans() {
2948     emulate -L zsh
2949     case "$1" in
2950         -[dD]*)
2951             translate -l de-en $2
2952             ;;
2953         -[eE]*)
2954             translate -l en-de $2
2955             ;;
2956         *)
2957             echo "Usage: $0 { -D | -E }"
2958             echo "         -D == German to English"
2959             echo "         -E == English to German"
2960     esac
2961 }
2962
2963 # Usage: simple-extract <file>
2964 # Using option -d deletes the original archive file.
2965 #f5# Smart archive extractor
2966 simple-extract() {
2967     emulate -L zsh
2968     setopt extended_glob noclobber
2969     local DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
2970     local RC=0
2971     zparseopts -D -E "d=DELETE_ORIGINAL"
2972     for ARCHIVE in "${@}"; do
2973         case $ARCHIVE in
2974             *(tar.bz2|tbz2|tbz))
2975                 DECOMP_CMD="tar -xvjf -"
2976                 USES_STDIN=true
2977                 USES_STDOUT=false
2978                 ;;
2979             *(tar.gz|tgz))
2980                 DECOMP_CMD="tar -xvzf -"
2981                 USES_STDIN=true
2982                 USES_STDOUT=false
2983                 ;;
2984             *(tar.xz|txz|tar.lzma))
2985                 DECOMP_CMD="tar -xvJf -"
2986                 USES_STDIN=true
2987                 USES_STDOUT=false
2988                 ;;
2989             *tar)
2990                 DECOMP_CMD="tar -xvf -"
2991                 USES_STDIN=true
2992                 USES_STDOUT=false
2993                 ;;
2994             *rar)
2995                 DECOMP_CMD="unrar x"
2996                 USES_STDIN=false
2997                 USES_STDOUT=false
2998                 ;;
2999             *lzh)
3000                 DECOMP_CMD="lha x"
3001                 USES_STDIN=false
3002                 USES_STDOUT=false
3003                 ;;
3004             *7z)
3005                 DECOMP_CMD="7z x"
3006                 USES_STDIN=false
3007                 USES_STDOUT=false
3008                 ;;
3009             *(zip|jar))
3010                 DECOMP_CMD="unzip"
3011                 USES_STDIN=false
3012                 USES_STDOUT=false
3013                 ;;
3014             *deb)
3015                 DECOMP_CMD="ar -x"
3016                 USES_STDIN=false
3017                 USES_STDOUT=false
3018                 ;;
3019             *bz2)
3020                 DECOMP_CMD="bzip2 -d -c -"
3021                 USES_STDIN=true
3022                 USES_STDOUT=true
3023                 ;;
3024             *(gz|Z))
3025                 DECOMP_CMD="gzip -d -c -"
3026                 USES_STDIN=true
3027                 USES_STDOUT=true
3028                 ;;
3029             *(xz|lzma))
3030                 DECOMP_CMD="xz -d -c -"
3031                 USES_STDIN=true
3032                 USES_STDOUT=true
3033                 ;;
3034             *)
3035                 print "ERROR: '$ARCHIVE' has unrecognized archive type." >&2
3036                 RC=$((RC+1))
3037                 continue
3038                 ;;
3039         esac
3040
3041         if ! check_com ${DECOMP_CMD[(w)1]}; then
3042             echo "ERROR: ${DECOMP_CMD[(w)1]} not installed." >&2
3043             RC=$((RC+2))
3044             continue
3045         fi
3046
3047         GZTARGET="${ARCHIVE:t:r}"
3048         if [[ -f $ARCHIVE ]] ; then
3049
3050             print "Extracting '$ARCHIVE' ..."
3051             if $USES_STDIN; then
3052                 if $USES_STDOUT; then
3053                     ${=DECOMP_CMD} < "$ARCHIVE" > $GZTARGET
3054                 else
3055                     ${=DECOMP_CMD} < "$ARCHIVE"
3056                 fi
3057             else
3058                 if $USES_STDOUT; then
3059                     ${=DECOMP_CMD} "$ARCHIVE" > $GZTARGET
3060                 else
3061                     ${=DECOMP_CMD} "$ARCHIVE"
3062                 fi
3063             fi
3064             [[ $? -eq 0 && -n "$DELETE_ORIGINAL" ]] && rm -f "$ARCHIVE"
3065
3066         elif [[ "$ARCHIVE" == (#s)(https|http|ftp)://* ]] ; then
3067             if check_com curl; then
3068                 WGET_CMD="curl -L -k -s -o -"
3069             elif check_com wget; then
3070                 WGET_CMD="wget -q -O - --no-check-certificate"
3071             else
3072                 print "ERROR: neither wget nor curl is installed" >&2
3073                 RC=$((RC+4))
3074                 continue
3075             fi
3076             print "Downloading and Extracting '$ARCHIVE' ..."
3077             if $USES_STDIN; then
3078                 if $USES_STDOUT; then
3079                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD} > $GZTARGET
3080                     RC=$((RC+$?))
3081                 else
3082                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD}
3083                     RC=$((RC+$?))
3084                 fi
3085             else
3086                 if $USES_STDOUT; then
3087                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE") > $GZTARGET
3088                 else
3089                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE")
3090                 fi
3091             fi
3092
3093         else
3094             print "ERROR: '$ARCHIVE' is neither a valid file nor a supported URI." >&2
3095             RC=$((RC+8))
3096         fi
3097     done
3098     return $RC
3099 }
3100
3101 __archive_or_uri()
3102 {
3103     _alternative \
3104         '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)"' \
3105         '_urls:Remote Archives:_urls'
3106 }
3107
3108 _simple_extract()
3109 {
3110     _arguments \
3111         '-d[delete original archivefile after extraction]' \
3112         '*:Archive Or Uri:__archive_or_uri'
3113 }
3114 compdef _simple_extract simple-extract
3115 alias se=simple-extract
3116
3117 #f5# Set all ulimit parameters to \kbd{unlimited}
3118 allulimit() {
3119     ulimit -c unlimited
3120     ulimit -d unlimited
3121     ulimit -f unlimited
3122     ulimit -l unlimited
3123     ulimit -n unlimited
3124     ulimit -s unlimited
3125     ulimit -t unlimited
3126 }
3127
3128 #f5# Change the xterm title from within GNU-screen
3129 xtrename() {
3130     emulate -L zsh
3131     if [[ $1 != "-f" ]] ; then
3132         if [[ -z ${DISPLAY} ]] ; then
3133             printf 'xtrename only makes sense in X11.\n'
3134             return 1
3135         fi
3136     else
3137         shift
3138     fi
3139     if [[ -z $1 ]] ; then
3140         printf 'usage: xtrename [-f] "title for xterm"\n'
3141         printf '  renames the title of xterm from _within_ screen.\n'
3142         printf '  also works without screen.\n'
3143         printf '  will not work if DISPLAY is unset, use -f to override.\n'
3144         return 0
3145     fi
3146     print -n "\eP\e]0;${1}\C-G\e\\"
3147     return 0
3148 }
3149
3150 # Create small urls via http://goo.gl using curl(1).
3151 # API reference: https://code.google.com/apis/urlshortener/
3152 function zurl() {
3153     emulate -L zsh
3154     setopt extended_glob
3155
3156     if [[ -z $1 ]]; then
3157         print "USAGE: zurl <URL>"
3158         return 1
3159     fi
3160
3161     local PN url prog api json contenttype item
3162     local -a data
3163     PN=$0
3164     url=$1
3165
3166     # Prepend 'http://' to given URL where necessary for later output.
3167     if [[ ${url} != http(s|)://* ]]; then
3168         url='http://'${url}
3169     fi
3170
3171     if check_com -c curl; then
3172         prog=curl
3173     else
3174         print "curl is not available, but mandatory for ${PN}. Aborting."
3175         return 1
3176     fi
3177     api='https://www.googleapis.com/urlshortener/v1/url'
3178     contenttype="Content-Type: application/json"
3179     json="{\"longUrl\": \"${url}\"}"
3180     data=(${(f)"$($prog --silent -H ${contenttype} -d ${json} $api)"})
3181     # Parse the response
3182     for item in "${data[@]}"; do
3183         case "$item" in
3184             ' '#'"id":'*)
3185                 item=${item#*: \"}
3186                 item=${item%\",*}
3187                 printf '%s\n' "$item"
3188                 return 0
3189                 ;;
3190         esac
3191     done
3192     return 1
3193 }
3194
3195 #f2# Find history events by search pattern and list them by date.
3196 whatwhen()  {
3197     emulate -L zsh
3198     local usage help ident format_l format_s first_char remain first last
3199     usage='USAGE: whatwhen [options] <searchstring> <search range>'
3200     help='Use `whatwhen -h'\'' for further explanations.'
3201     ident=${(l,${#${:-Usage: }},, ,)}
3202     format_l="${ident}%s\t\t\t%s\n"
3203     format_s="${format_l//(\\t)##/\\t}"
3204     # Make the first char of the word to search for case
3205     # insensitive; e.g. [aA]
3206     first_char=[${(L)1[1]}${(U)1[1]}]
3207     remain=${1[2,-1]}
3208     # Default search range is `-100'.
3209     first=${2:-\-100}
3210     # Optional, just used for `<first> <last>' given.
3211     last=$3
3212     case $1 in
3213         ("")
3214             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
3215             printf '%s\n%s\n\n' ${usage} ${help} && return 1
3216         ;;
3217         (-h)
3218             printf '%s\n\n' ${usage}
3219             print 'OPTIONS:'
3220             printf $format_l '-h' 'show help text'
3221             print '\f'
3222             print 'SEARCH RANGE:'
3223             printf $format_l "'0'" 'the whole history,'
3224             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
3225             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
3226             printf '\n%s\n' 'EXAMPLES:'
3227             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
3228             printf $format_l 'whatwhen zsh -250'
3229             printf $format_l 'whatwhen foo 1 99'
3230         ;;
3231         (\?)
3232             printf '%s\n%s\n\n' ${usage} ${help} && return 1
3233         ;;
3234         (*)
3235             # -l list results on stout rather than invoking $EDITOR.
3236             # -i Print dates as in YYYY-MM-DD.
3237             # -m Search for a - quoted - pattern within the history.
3238             fc -li -m "*${first_char}${remain}*" $first $last
3239         ;;
3240     esac
3241 }
3242
3243 # mercurial related stuff
3244 if check_com -c hg ; then
3245     # gnu like diff for mercurial
3246     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
3247     #f5# GNU like diff for mercurial
3248     hgdi() {
3249         emulate -L zsh
3250         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
3251     }
3252
3253     # build debian package
3254     #a2# Alias for \kbd{hg-buildpackage}
3255     alias hbp='hg-buildpackage'
3256
3257     # execute commands on the versioned patch-queue from the current repos
3258     alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
3259
3260     # diffstat for specific version of a mercurial repository
3261     #   hgstat      => display diffstat between last revision and tip
3262     #   hgstat 1234 => display diffstat between revision 1234 and tip
3263     #f5# Diffstat for specific version of a mercurial repos
3264     hgstat() {
3265         emulate -L zsh
3266         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
3267     }
3268
3269 fi # end of check whether we have the 'hg'-executable
3270
3271 # grml-small cleanups
3272
3273 # The following is used to remove zsh-config-items that do not work
3274 # in grml-small by default.
3275 # If you do not want these adjustments (for whatever reason), set
3276 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
3277 # sources if it is there).
3278
3279 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
3280
3281     unset abk[V]
3282     unalias    'V'      &> /dev/null
3283     unfunction vman     &> /dev/null
3284     unfunction viless   &> /dev/null
3285     unfunction 2html    &> /dev/null
3286
3287     # manpages are not in grmlsmall
3288     unfunction manzsh   &> /dev/null
3289     unfunction man2     &> /dev/null
3290
3291 fi
3292
3293 zrclocal
3294
3295 ## genrefcard.pl settings
3296
3297 ### doc strings for external functions from files
3298 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
3299
3300 ### example: split functions-search 8,16,24,32
3301 #@# split functions-search 8
3302
3303 ## END OF FILE #################################################################
3304 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
3305 # Local variables:
3306 # mode: sh
3307 # End: