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