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