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