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