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