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