Do not disable zstyle if compsys did not load
[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 [[ ${fpath} == '/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     # provide .. as a completion
1714     zstyle ':completion:*' special-dirs ..
1715
1716     # run rehash on completion so new installed program are found automatically:
1717     _force_rehash() {
1718         (( CURRENT == 1 )) && rehash
1719         return 1
1720     }
1721
1722     ## correction
1723     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
1724     if [[ "$NOCOR" -gt 0 ]] ; then
1725         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
1726         setopt nocorrect
1727     else
1728         # try to be smart about when to use what completer...
1729         setopt correct
1730         zstyle -e ':completion:*' completer '
1731             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
1732                 _last_try="$HISTNO$BUFFER$CURSOR"
1733                 reply=(_complete _match _ignored _prefix _files)
1734             else
1735                 if [[ $words[1] == (rm|mv) ]] ; then
1736                     reply=(_complete _files)
1737                 else
1738                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
1739                 fi
1740             fi'
1741     fi
1742
1743     # command for process lists, the local web server details and host completion
1744     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
1745
1746     # caching
1747     [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
1748                             zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
1749
1750     # host completion
1751     if is42 ; then
1752         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
1753         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
1754     else
1755         _ssh_hosts=()
1756         _etc_hosts=()
1757     fi
1758     hosts=(
1759         $(hostname)
1760         "$_ssh_hosts[@]"
1761         "$_etc_hosts[@]"
1762         grml.org
1763         localhost
1764     )
1765     zstyle ':completion:*:hosts' hosts $hosts
1766     # TODO: so, why is this here?
1767     #  zstyle '*' hosts $hosts
1768
1769     # use generic completion system for programs not yet defined; (_gnu_generic works
1770     # with commands that provide a --help option with "standard" gnu-like output.)
1771     for compcom in cp deborphan df feh fetchipac head hnb ipacsum mv \
1772                    pal stow tail uname ; do
1773         [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
1774     done; unset compcom
1775
1776     # see upgrade function in this file
1777     compdef _hosts upgrade
1778 }
1779
1780 # grmlstuff
1781 grmlstuff() {
1782 # people should use 'grml-x'!
1783     if check_com -c 915resolution; then
1784         855resolution() {
1785             echo "Please use 915resolution as resolution modifying tool for Intel \
1786 graphic chipset."
1787             return -1
1788         }
1789     fi
1790
1791     #a1# Output version of running grml
1792     alias grml-version='cat /etc/grml_version'
1793
1794     if check_com -c rebuildfstab ; then
1795         #a1# Rebuild /etc/fstab
1796         alias grml-rebuildfstab='rebuildfstab -v -r -config'
1797     fi
1798
1799     if check_com -c grml-debootstrap ; then
1800         debian2hd() {
1801             echo "Installing debian to harddisk is possible by using grml-debootstrap."
1802             return 1
1803         }
1804     fi
1805 }
1806
1807 # now run the functions
1808 isgrml && checkhome
1809 is4    && isgrml    && grmlstuff
1810 is4    && grmlcomp
1811
1812 # keephack
1813 is4 && xsource "/etc/zsh/keephack"
1814
1815 # wonderful idea of using "e" glob qualifier by Peter Stephenson
1816 # You use it as follows:
1817 # $ NTREF=/reference/file
1818 # $ ls -l *(e:nt:)
1819 # This lists all the files in the current directory newer than the reference file.
1820 # You can also specify the reference file inline; note quotes:
1821 # $ ls -l *(e:'nt ~/.zshenv':)
1822 is4 && nt() {
1823     if [[ -n $1 ]] ; then
1824         local NTREF=${~1}
1825     fi
1826     [[ $REPLY -nt $NTREF ]]
1827 }
1828
1829 # shell functions
1830
1831 #f1# Reload an autoloadable function
1832 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
1833 compdef _functions freload
1834
1835 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
1836 sll() {
1837     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
1838     for file in "$@" ; do
1839         while [[ -h "$file" ]] ; do
1840             ls -l $file
1841             file=$(readlink "$file")
1842         done
1843     done
1844 }
1845
1846 # TODO: Is it supported to use pager settings like this?
1847 #   PAGER='less -Mr' - If so, the use of $PAGER here needs fixing
1848 # with respect to wordsplitting. (ie. ${=PAGER})
1849 if check_com -c $PAGER ; then
1850     #f1# View Debian's changelog of a given package
1851     dchange() {
1852         emulate -L zsh
1853         if [[ -r /usr/share/doc/$1/changelog.Debian.gz ]] ; then
1854             $PAGER /usr/share/doc/$1/changelog.Debian.gz
1855         elif [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
1856             $PAGER /usr/share/doc/$1/changelog.gz
1857         else
1858             if check_com -c aptitude ; then
1859                 echo "No changelog for package $1 found, using aptitude to retrieve it."
1860                 if isgrml ; then
1861                     aptitude -t unstable changelog $1
1862                 else
1863                     aptitude changelog $1
1864                 fi
1865             else
1866                 echo "No changelog for package $1 found, sorry."
1867                 return 1
1868             fi
1869         fi
1870     }
1871     _dchange() { _files -W /usr/share/doc -/ }
1872     compdef _dchange dchange
1873
1874     #f1# View Debian's NEWS of a given package
1875     dnews() {
1876         emulate -L zsh
1877         if [[ -r /usr/share/doc/$1/NEWS.Debian.gz ]] ; then
1878             $PAGER /usr/share/doc/$1/NEWS.Debian.gz
1879         else
1880             if [[ -r /usr/share/doc/$1/NEWS.gz ]] ; then
1881                 $PAGER /usr/share/doc/$1/NEWS.gz
1882             else
1883                 echo "No NEWS file for package $1 found, sorry."
1884                 return 1
1885             fi
1886         fi
1887     }
1888     _dnews() { _files -W /usr/share/doc -/ }
1889     compdef _dnews dnews
1890
1891     #f1# View upstream's changelog of a given package
1892     uchange() {
1893         emulate -L zsh
1894         if [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
1895             $PAGER /usr/share/doc/$1/changelog.gz
1896         else
1897             echo "No changelog for package $1 found, sorry."
1898             return 1
1899         fi
1900     }
1901     _uchange() { _files -W /usr/share/doc -/ }
1902     compdef _uchange uchange
1903 fi
1904
1905 # zsh profiling
1906 profile() {
1907     ZSH_PROFILE_RC=1 $SHELL "$@"
1908 }
1909
1910 #f1# Edit an alias via zle
1911 edalias() {
1912     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
1913 }
1914 compdef _aliases edalias
1915
1916 #f1# Edit a function via zle
1917 edfunc() {
1918     [[ -z "$1" ]] && { echo "Usage: edfunc <function_to_edit>" ; return 1 } || zed -f "$1" ;
1919 }
1920 compdef _functions edfunc
1921
1922 # use it e.g. via 'Restart apache2'
1923 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
1924 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
1925 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
1926 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
1927 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
1928 #m# f6 Status() \kbd{/etc/init.d/\em{process}}\quad\kbd{status}
1929 if [[ -d /etc/init.d || -d /etc/service ]] ; then
1930     __start_stop() {
1931         local action_="${1:l}"  # e.g Start/Stop/Restart
1932         local service_="$2"
1933         local param_="$3"
1934
1935         local service_target_="$(readlink /etc/init.d/$service_)"
1936         if [[ $service_target_ == "/usr/bin/sv" ]]; then
1937             # runit
1938             case "${action_}" in
1939                 start) if [[ ! -e /etc/service/$service_ ]]; then
1940                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
1941                        else
1942                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
1943                        fi ;;
1944                 # there is no reload in runits sysv emulation
1945                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
1946                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
1947             esac
1948         else
1949             # sysvinit
1950             $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
1951         fi
1952     }
1953
1954     _grmlinitd() {
1955         local -a scripts
1956         scripts=( /etc/init.d/*(x:t) )
1957         _describe "service startup script" scripts
1958     }
1959
1960     for i in Start Restart Stop Force-Reload Reload Status ; do
1961         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
1962         compdef _grmlinitd $i
1963     done
1964 fi
1965
1966 #f1# Provides useful information on globbing
1967 H-Glob() {
1968     echo -e "
1969     /      directories
1970     .      plain files
1971     @      symbolic links
1972     =      sockets
1973     p      named pipes (FIFOs)
1974     *      executable plain files (0100)
1975     %      device files (character or block special)
1976     %b     block special files
1977     %c     character special files
1978     r      owner-readable files (0400)
1979     w      owner-writable files (0200)
1980     x      owner-executable files (0100)
1981     A      group-readable files (0040)
1982     I      group-writable files (0020)
1983     E      group-executable files (0010)
1984     R      world-readable files (0004)
1985     W      world-writable files (0002)
1986     X      world-executable files (0001)
1987     s      setuid files (04000)
1988     S      setgid files (02000)
1989     t      files with the sticky bit (01000)
1990
1991   print *(m-1)          # Files modified up to a day ago
1992   print *(a1)           # Files accessed a day ago
1993   print *(@)            # Just symlinks
1994   print *(Lk+50)        # Files bigger than 50 kilobytes
1995   print *(Lk-50)        # Files smaller than 50 kilobytes
1996   print **/*.c          # All *.c files recursively starting in \$PWD
1997   print **/*.c~file.c   # Same as above, but excluding 'file.c'
1998   print (foo|bar).*     # Files starting with 'foo' or 'bar'
1999   print *~*.*           # All Files that do not contain a dot
2000   chmod 644 *(.^x)      # make all plain non-executable files publically readable
2001   print -l *(.c|.h)     # Lists *.c and *.h
2002   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
2003   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
2004 }
2005 alias help-zshglob=H-Glob
2006
2007 #v1# set number of lines to display per page
2008 HELP_LINES_PER_PAGE=20
2009 #v1# set location of help-zle cache file
2010 HELP_ZLE_CACHE_FILE=~/.cache/zsh_help_zle_lines.zsh
2011 #f1# helper function for help-zle, actually generates the help text
2012 help_zle_parse_keybindings()
2013 {
2014     emulate -L zsh
2015     setopt extendedglob
2016     unsetopt ksharrays  #indexing starts at 1
2017
2018     #v1# choose files that help-zle will parse for keybindings
2019     ((${+HELPZLE_KEYBINDING_FILES})) || HELPZLE_KEYBINDING_FILES=( /etc/zsh/zshrc ~/.zshrc.pre ~/.zshrc ~/.zshrc.local )
2020
2021     if [[ -r $HELP_ZLE_CACHE_FILE ]]; then
2022         local load_cache=0
2023         for f ($HELPZLE_KEYBINDING_FILES) [[ $f -nt $HELP_ZLE_CACHE_FILE ]] && load_cache=1
2024         [[ $load_cache -eq 0 ]] && . $HELP_ZLE_CACHE_FILE && return
2025     fi
2026
2027     #fill with default keybindings, possibly to be overwriten in a file later
2028     #Note that due to zsh inconsistency on escaping assoc array keys, we encase the key in '' which we will remove later
2029     local -A help_zle_keybindings
2030     help_zle_keybindings['<Ctrl>@']="set MARK"
2031     help_zle_keybindings['<Ctrl>x<Ctrl>j']="vi-join lines"
2032     help_zle_keybindings['<Ctrl>x<Ctrl>b']="jump to matching brace"
2033     help_zle_keybindings['<Ctrl>x<Ctrl>u']="undo"
2034     help_zle_keybindings['<Ctrl>_']="undo"
2035     help_zle_keybindings['<Ctrl>x<Ctrl>f<c>']="find <c> in cmdline"
2036     help_zle_keybindings['<Ctrl>a']="goto beginning of line"
2037     help_zle_keybindings['<Ctrl>e']="goto end of line"
2038     help_zle_keybindings['<Ctrl>t']="transpose charaters"
2039     help_zle_keybindings['<Alt>t']="transpose words"
2040     help_zle_keybindings['<Alt>s']="spellcheck word"
2041     help_zle_keybindings['<Ctrl>k']="backward kill buffer"
2042     help_zle_keybindings['<Ctrl>u']="forward kill buffer"
2043     help_zle_keybindings['<Ctrl>y']="insert previously killed word/string"
2044     help_zle_keybindings["<Alt>'"]="quote line"
2045     help_zle_keybindings['<Alt>"']="quote from mark to cursor"
2046     help_zle_keybindings['<Alt><arg>']="repeat next cmd/char <arg> times (<Alt>-<Alt>1<Alt>0a -> -10 times 'a')"
2047     help_zle_keybindings['<Alt>u']="make next word Uppercase"
2048     help_zle_keybindings['<Alt>l']="make next word lowercase"
2049     help_zle_keybindings['<Ctrl>xd']="preview expansion under cursor"
2050     help_zle_keybindings['<Alt>q']="push current CL into background, freeing it. Restore on next CL"
2051     help_zle_keybindings['<Alt>.']="insert (and interate through) last word from prev CLs"
2052     help_zle_keybindings['<Alt>,']="complete word from newer history (consecutive hits)"
2053     help_zle_keybindings['<Alt>m']="repeat last typed word on current CL"
2054     help_zle_keybindings['<Ctrl>v']="insert next keypress symbol literally (e.g. for bindkey)"
2055     help_zle_keybindings['!!:n*<Tab>']="insert last n arguments of last command"
2056     help_zle_keybindings['!!:n-<Tab>']="insert arguments n..N-2 of last command (e.g. mv s s d)"
2057     help_zle_keybindings['<Alt>h']="show help/manpage for current command"
2058
2059     #init global variables
2060     unset help_zle_lines help_zle_sln
2061     typeset -g -a help_zle_lines
2062     typeset -g help_zle_sln=1
2063
2064     local k v
2065     local lastkeybind_desc contents     #last description starting with #k# that we found
2066     local num_lines_elapsed=0            #number of lines between last description and keybinding
2067     #search config files in the order they a called (and thus the order in which they overwrite keybindings)
2068     for f in $HELPZLE_KEYBINDING_FILES; do
2069         [[ -r "$f" ]] || continue   #not readable ? skip it
2070         contents="$(<$f)"
2071         for cline in "${(f)contents}"; do
2072             #zsh pattern: matches lines like: #k# ..............
2073             if [[ "$cline" == (#s)[[:space:]]#\#k\#[[:space:]]##(#b)(*)[[:space:]]#(#e) ]]; then
2074                 lastkeybind_desc="$match[*]"
2075                 num_lines_elapsed=0
2076             #zsh pattern: matches lines that set a keybinding using bindkey or compdef -k
2077             #             ignores lines that are commentend out
2078             #             grabs first in '' or "" enclosed string with length between 1 and 6 characters
2079             elif [[ "$cline" == [^#]#(bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*)  ]]; then
2080                 #description prevously found ? description not more than 2 lines away ? keybinding not empty ?
2081                 if [[ -n $lastkeybind_desc && $num_lines_elapsed -lt 2 && -n $match[1] ]]; then
2082                     #substitute keybinding string with something readable
2083                     k=${${${${${${${match[1]/\\e\^h/<Alt><BS>}/\\e\^\?/<Alt><BS>}/\\e\[5~/<PageUp>}/\\e\[6~/<PageDown>}//(\\e|\^\[)/<Alt>}//\^/<Ctrl>}/3~/<Alt><Del>}
2084                     #put keybinding in assoc array, possibly overwriting defaults or stuff found in earlier files
2085                     #Note that we are extracting the keybinding-string including the quotes (see Note at beginning)
2086                     help_zle_keybindings[${k}]=$lastkeybind_desc
2087                 fi
2088                 lastkeybind_desc=""
2089             else
2090               ((num_lines_elapsed++))
2091             fi
2092         done
2093     done
2094     unset contents
2095     #calculate length of keybinding column
2096     local kstrlen=0
2097     for k (${(k)help_zle_keybindings[@]}) ((kstrlen < ${#k})) && kstrlen=${#k}
2098     #convert the assoc array into preformated lines, which we are able to sort
2099     for k v in ${(kv)help_zle_keybindings[@]}; do
2100         #pad keybinding-string to kstrlen chars and remove outermost characters (i.e. the quotes)
2101         help_zle_lines+=("${(r:kstrlen:)k[2,-2]}${v}")
2102     done
2103     #sort lines alphabetically
2104     help_zle_lines=("${(i)help_zle_lines[@]}")
2105     [[ -d ${HELP_ZLE_CACHE_FILE:h} ]] || mkdir -p "${HELP_ZLE_CACHE_FILE:h}"
2106     echo "help_zle_lines=(${(q)help_zle_lines[@]})" >| $HELP_ZLE_CACHE_FILE
2107     zcompile $HELP_ZLE_CACHE_FILE
2108 }
2109 typeset -g help_zle_sln
2110 typeset -g -a help_zle_lines
2111
2112 #f1# Provides (partially autogenerated) help on keybindings and the zsh line editor
2113 help-zle()
2114 {
2115     emulate -L zsh
2116     unsetopt ksharrays  #indexing starts at 1
2117     #help lines already generated ? no ? then do it
2118     [[ ${+functions[help_zle_parse_keybindings]} -eq 1 ]] && {help_zle_parse_keybindings && unfunction help_zle_parse_keybindings}
2119     #already displayed all lines ? go back to the start
2120     [[ $help_zle_sln -gt ${#help_zle_lines} ]] && help_zle_sln=1
2121     local sln=$help_zle_sln
2122     #note that help_zle_sln is a global var, meaning we remember the last page we viewed
2123     help_zle_sln=$((help_zle_sln + HELP_LINES_PER_PAGE))
2124     zle -M "${(F)help_zle_lines[sln,help_zle_sln-1]}"
2125 }
2126 #k# display help for keybindings and ZLE (cycle pages with consecutive use)
2127 zle -N help-zle && bindkey '^xz' help-zle
2128
2129 # grep for running process, like: 'any vim'
2130 any() {
2131     emulate -L zsh
2132     unsetopt KSH_ARRAYS
2133     if [[ -z "$1" ]] ; then
2134         echo "any - grep for process(es) by keyword" >&2
2135         echo "Usage: any <keyword>" >&2 ; return 1
2136     else
2137         ps xauwww | grep -i "${grep_options[@]}" "[${1[1]}]${1[2,-1]}"
2138     fi
2139 }
2140
2141
2142 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
2143 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
2144 [[ -r /proc/1/maps ]] && \
2145 deswap() {
2146     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
2147     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
2148     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
2149 }
2150
2151 # a wrapper for vim, that deals with title setting
2152 #   VIM_OPTIONS
2153 #       set this array to a set of options to vim you always want
2154 #       to have set when calling vim (in .zshrc.local), like:
2155 #           VIM_OPTIONS=( -p )
2156 #       This will cause vim to send every file given on the
2157 #       commandline to be send to it's own tab (needs vim7).
2158 if check_com vim; then
2159     vim() {
2160         VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
2161     }
2162 fi
2163
2164 # make a backup of a file
2165 bk() {
2166     cp -a "$1" "${1}_$(date --iso-8601=seconds)"
2167 }
2168
2169 ssl_hashes=( sha512 sha256 sha1 md5 )
2170
2171 for sh in ${ssl_hashes}; do
2172     eval 'ssl-cert-'${sh}'() {
2173         emulate -L zsh
2174         if [[ -z $1 ]] ; then
2175             printf '\''usage: %s <file>\n'\'' "ssh-cert-'${sh}'"
2176             return 1
2177         fi
2178         openssl x509 -noout -fingerprint -'${sh}' -in $1
2179     }'
2180 done; unset sh
2181
2182 ssl-cert-fingerprints() {
2183     emulate -L zsh
2184     local i
2185     if [[ -z $1 ]] ; then
2186         printf 'usage: ssl-cert-fingerprints <file>\n'
2187         return 1
2188     fi
2189     for i in ${ssl_hashes}
2190         do ssl-cert-$i $1;
2191     done
2192 }
2193
2194 ssl-cert-info() {
2195     emulate -L zsh
2196     if [[ -z $1 ]] ; then
2197         printf 'usage: ssl-cert-info <file>\n'
2198         return 1
2199     fi
2200     openssl x509 -noout -text -in $1
2201     ssl-cert-fingerprints $1
2202 }
2203
2204 # make sure our environment is clean regarding colors
2205 for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
2206
2207 # "persistent history"
2208 # just write important commands you always need to ~/.important_commands
2209 if [[ -r ~/.important_commands ]] ; then
2210     fc -R ~/.important_commands
2211 fi
2212
2213 # load the lookup subsystem if it's available on the system
2214 zrcautoload lookupinit && lookupinit
2215
2216 # variables
2217
2218 # set terminal property (used e.g. by msgid-chooser)
2219 export COLORTERM="yes"
2220
2221 # aliases
2222
2223 # general
2224 #a2# Execute \kbd{du -sch}
2225 alias da='du -sch'
2226 #a2# Execute \kbd{jobs -l}
2227 alias j='jobs -l'
2228
2229 # listing stuff
2230 #a2# Execute \kbd{ls -lSrah}
2231 alias dir="ls -lSrah"
2232 #a2# Only show dot-directories
2233 alias lad='ls -d .*(/)'
2234 #a2# Only show dot-files
2235 alias lsa='ls -a .*(.)'
2236 #a2# Only files with setgid/setuid/sticky flag
2237 alias lss='ls -l *(s,S,t)'
2238 #a2# Only show symlinks
2239 alias lsl='ls -l *(@)'
2240 #a2# Display only executables
2241 alias lsx='ls -l *(*)'
2242 #a2# Display world-{readable,writable,executable} files
2243 alias lsw='ls -ld *(R,W,X.^ND/)'
2244 #a2# Display the ten biggest files
2245 alias lsbig="ls -flh *(.OL[1,10])"
2246 #a2# Only show directories
2247 alias lsd='ls -d *(/)'
2248 #a2# Only show empty directories
2249 alias lse='ls -d *(/^F)'
2250 #a2# Display the ten newest files
2251 alias lsnew="ls -rtlh *(D.om[1,10])"
2252 #a2# Display the ten oldest files
2253 alias lsold="ls -rtlh *(D.Om[1,10])"
2254 #a2# Display the ten smallest files
2255 alias lssmall="ls -Srl *(.oL[1,10])"
2256 #a2# Display the ten newest directories and ten newest .directories
2257 alias lsnewdir="ls -rthdl *(/om[1,10]) .*(D/om[1,10])"
2258 #a2# Display the ten oldest directories and ten oldest .directories
2259 alias lsolddir="ls -rthdl *(/Om[1,10]) .*(D/Om[1,10])"
2260
2261 # some useful aliases
2262 #a2# Remove current empty directory. Execute \kbd{cd ..; rmdir $OLDCWD}
2263 alias rmcdir='cd ..; rmdir $OLDPWD || cd $OLDPWD'
2264
2265 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
2266 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
2267 alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
2268
2269 # work around non utf8 capable software in utf environment via $LANG and luit
2270 if check_com isutfenv && check_com luit ; then
2271     if check_com -c mrxvt ; then
2272         isutfenv && [[ -n "$LANG" ]] && \
2273             alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
2274     fi
2275
2276     if check_com -c aterm ; then
2277         isutfenv && [[ -n "$LANG" ]] && \
2278             alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
2279     fi
2280
2281     if check_com -c centericq ; then
2282         isutfenv && [[ -n "$LANG" ]] && \
2283             alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
2284     fi
2285 fi
2286
2287 # useful functions
2288
2289 #f5# Backup \kbd{file {\rm to} file\_timestamp}
2290 bk() {
2291     emulate -L zsh
2292     cp -b $1 $1_`date --iso-8601=m`
2293 }
2294
2295 #f5# cd to directoy and list files
2296 cl() {
2297     emulate -L zsh
2298     cd $1 && ls -a
2299 }
2300
2301 # smart cd function, allows switching to /etc when running 'cd /etc/fstab'
2302 cd() {
2303     if (( ${#argv} == 1 )) && [[ -f ${1} ]]; then
2304         [[ ! -e ${1:h} ]] && return 1
2305         print "Correcting ${1} to ${1:h}"
2306         builtin cd ${1:h}
2307     else
2308         builtin cd "$@"
2309     fi
2310 }
2311
2312 #f5# Create Directoy and \kbd{cd} to it
2313 mkcd() {
2314     if (( ARGC != 1 )); then
2315         printf 'usage: mkcd <new-directory>\n'
2316         return 1;
2317     fi
2318     if [[ ! -d "$1" ]]; then
2319         command mkdir -p "$1"
2320     else
2321         printf '`%s'\'' already exists: cd-ing.\n' "$1"
2322     fi
2323     builtin cd "$1"
2324 }
2325
2326 #f5# Create temporary directory and \kbd{cd} to it
2327 cdt() {
2328     local t
2329     t=$(mktemp -d)
2330     echo "$t"
2331     builtin cd "$t"
2332 }
2333
2334 #f5# Create directory under cursor or the selected area
2335 # Press ctrl-xM to create the directory under the cursor or the selected area.
2336 # To select an area press ctrl-@ or ctrl-space and use the cursor.
2337 # Use case: you type "mv abc ~/testa/testb/testc/" and remember that the
2338 # directory does not exist yet -> press ctrl-XM and problem solved
2339 inplaceMkDirs() {
2340     local PATHTOMKDIR
2341     if ((REGION_ACTIVE==1)); then
2342         local F=$MARK T=$CURSOR
2343         if [[ $F -gt $T ]]; then
2344             F=${CURSOR}
2345             T=${MARK}
2346         fi
2347         # get marked area from buffer and eliminate whitespace
2348         PATHTOMKDIR=${BUFFER[F+1,T]%%[[:space:]]##}
2349         PATHTOMKDIR=${PATHTOMKDIR##[[:space:]]##}
2350     else
2351         local bufwords iword
2352         bufwords=(${(z)LBUFFER})
2353         iword=${#bufwords}
2354         bufwords=(${(z)BUFFER})
2355         PATHTOMKDIR="${(Q)bufwords[iword]}"
2356     fi
2357     [[ -z "${PATHTOMKDIR}" ]] && return 1
2358     PATHTOMKDIR=${~PATHTOMKDIR}
2359     if [[ -e "${PATHTOMKDIR}" ]]; then
2360         zle -M " path already exists, doing nothing"
2361     else
2362         zle -M "$(mkdir -p -v "${PATHTOMKDIR}")"
2363         zle end-of-line
2364     fi
2365 }
2366 #k# mkdir -p <dir> from string under cursor or marked area
2367 zle -N inplaceMkDirs && bindkey '^xM' inplaceMkDirs
2368
2369 #f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
2370 accessed() {
2371     emulate -L zsh
2372     print -l -- *(a-${1:-1})
2373 }
2374
2375 #f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
2376 changed() {
2377     emulate -L zsh
2378     print -l -- *(c-${1:-1})
2379 }
2380
2381 #f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
2382 modified() {
2383     emulate -L zsh
2384     print -l -- *(m-${1:-1})
2385 }
2386 # modified() was named new() in earlier versions, add an alias for backwards compatibility
2387 check_com new || alias new=modified
2388
2389 # use colors when GNU grep with color-support
2390 #a2# Execute \kbd{grep -{}-color=auto}
2391 (( $#grep_options > 0 )) && alias grep='grep '${grep_options:+"${grep_options[*]}"}
2392
2393 # Translate DE<=>EN
2394 # 'translate' looks up fot a word in a file with language-to-language
2395 # translations (field separator should be " : "). A typical wordlist looks
2396 # like at follows:
2397 #  | english-word : german-transmission
2398 # It's also only possible to translate english to german but not reciprocal.
2399 # Use the following oneliner to turn back the sort order:
2400 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
2401 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
2402 #f5# Translates a word
2403 trans() {
2404     emulate -L zsh
2405     case "$1" in
2406         -[dD]*)
2407             translate -l de-en $2
2408             ;;
2409         -[eE]*)
2410             translate -l en-de $2
2411             ;;
2412         *)
2413             echo "Usage: $0 { -D | -E }"
2414             echo "         -D == German to English"
2415             echo "         -E == English to German"
2416     esac
2417 }
2418
2419 # Usage: simple-extract <file>
2420 # Using option -d deletes the original archive file.
2421 #f5# Smart archive extractor
2422 simple-extract() {
2423     emulate -L zsh
2424     setopt extended_glob noclobber
2425     local DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
2426     local RC=0
2427     zparseopts -D -E "d=DELETE_ORIGINAL"
2428     for ARCHIVE in "${@}"; do
2429         case $ARCHIVE in
2430             *.(tar.bz2|tbz2|tbz))
2431                 DECOMP_CMD="tar -xvjf -"
2432                 USES_STDIN=true
2433                 USES_STDOUT=false
2434                 ;;
2435             *.(tar.gz|tgz))
2436                 DECOMP_CMD="tar -xvzf -"
2437                 USES_STDIN=true
2438                 USES_STDOUT=false
2439                 ;;
2440             *.(tar.xz|txz|tar.lzma))
2441                 DECOMP_CMD="tar -xvJf -"
2442                 USES_STDIN=true
2443                 USES_STDOUT=false
2444                 ;;
2445             *.tar)
2446                 DECOMP_CMD="tar -xvf -"
2447                 USES_STDIN=true
2448                 USES_STDOUT=false
2449                 ;;
2450             *.rar)
2451                 DECOMP_CMD="unrar x"
2452                 USES_STDIN=false
2453                 USES_STDOUT=false
2454                 ;;
2455             *.lzh)
2456                 DECOMP_CMD="lha x"
2457                 USES_STDIN=false
2458                 USES_STDOUT=false
2459                 ;;
2460             *.7z)
2461                 DECOMP_CMD="7z x"
2462                 USES_STDIN=false
2463                 USES_STDOUT=false
2464                 ;;
2465             *.(zip|jar))
2466                 DECOMP_CMD="unzip"
2467                 USES_STDIN=false
2468                 USES_STDOUT=false
2469                 ;;
2470             *.deb)
2471                 DECOMP_CMD="ar -x"
2472                 USES_STDIN=false
2473                 USES_STDOUT=false
2474                 ;;
2475             *.bz2)
2476                 DECOMP_CMD="bzip2 -d -c -"
2477                 USES_STDIN=true
2478                 USES_STDOUT=true
2479                 ;;
2480             *.(gz|Z))
2481                 DECOMP_CMD="gzip -d -c -"
2482                 USES_STDIN=true
2483                 USES_STDOUT=true
2484                 ;;
2485             *.(xz|lzma))
2486                 DECOMP_CMD="xz -d -c -"
2487                 USES_STDIN=true
2488                 USES_STDOUT=true
2489                 ;;
2490             *)
2491                 print "ERROR: '$ARCHIVE' has unrecognized archive type." >&2
2492                 RC=$((RC+1))
2493                 continue
2494                 ;;
2495         esac
2496
2497         if ! check_com ${DECOMP_CMD[(w)1]}; then
2498             echo "ERROR: ${DECOMP_CMD[(w)1]} not installed." >&2
2499             RC=$((RC+2))
2500             continue
2501         fi
2502
2503         GZTARGET="${ARCHIVE:t:r}"
2504         if [[ -f $ARCHIVE ]] ; then
2505
2506             print "Extracting '$ARCHIVE' ..."
2507             if $USES_STDIN; then
2508                 if $USES_STDOUT; then
2509                     ${=DECOMP_CMD} < "$ARCHIVE" > $GZTARGET
2510                 else
2511                     ${=DECOMP_CMD} < "$ARCHIVE"
2512                 fi
2513             else
2514                 if $USES_STDOUT; then
2515                     ${=DECOMP_CMD} "$ARCHIVE" > $GZTARGET
2516                 else
2517                     ${=DECOMP_CMD} "$ARCHIVE"
2518                 fi
2519             fi
2520             [[ $? -eq 0 && -n "$DELETE_ORIGINAL" ]] && rm -f "$ARCHIVE"
2521
2522         elif [[ "$ARCHIVE" == (#s)(https|http|ftp)://* ]] ; then
2523             if check_com curl; then
2524                 WGET_CMD="curl -L -k -s -o -"
2525             elif check_com wget; then
2526                 WGET_CMD="wget -q -O - --no-check-certificate"
2527             else
2528                 print "ERROR: neither wget nor curl is installed" >&2
2529                 RC=$((RC+4))
2530                 continue
2531             fi
2532             print "Downloading and Extracting '$ARCHIVE' ..."
2533             if $USES_STDIN; then
2534                 if $USES_STDOUT; then
2535                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD} > $GZTARGET
2536                     RC=$((RC+$?))
2537                 else
2538                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD}
2539                     RC=$((RC+$?))
2540                 fi
2541             else
2542                 if $USES_STDOUT; then
2543                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE") > $GZTARGET
2544                 else
2545                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE")
2546                 fi
2547             fi
2548
2549         else
2550             print "ERROR: '$ARCHIVE' is neither a valid file nor a supported URI." >&2
2551             RC=$((RC+8))
2552         fi
2553     done
2554     return $RC
2555 }
2556
2557 __archive_or_uri()
2558 {
2559     _alternative \
2560         '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)"' \
2561         '_urls:Remote Archives:_urls'
2562 }
2563
2564 _simple_extract()
2565 {
2566     _arguments \
2567         '-d[delete original archivefile after extraction]' \
2568         '*:Archive Or Uri:__archive_or_uri'
2569 }
2570 compdef _simple_extract simple-extract
2571 alias se=simple-extract
2572
2573 #f5# Set all ulimit parameters to \kbd{unlimited}
2574 allulimit() {
2575     ulimit -c unlimited
2576     ulimit -d unlimited
2577     ulimit -f unlimited
2578     ulimit -l unlimited
2579     ulimit -n unlimited
2580     ulimit -s unlimited
2581     ulimit -t unlimited
2582 }
2583
2584 #f5# Change the xterm title from within GNU-screen
2585 xtrename() {
2586     emulate -L zsh
2587     if [[ $1 != "-f" ]] ; then
2588         if [[ -z ${DISPLAY} ]] ; then
2589             printf 'xtrename only makes sense in X11.\n'
2590             return 1
2591         fi
2592     else
2593         shift
2594     fi
2595     if [[ -z $1 ]] ; then
2596         printf 'usage: xtrename [-f] "title for xterm"\n'
2597         printf '  renames the title of xterm from _within_ screen.\n'
2598         printf '  also works without screen.\n'
2599         printf '  will not work if DISPLAY is unset, use -f to override.\n'
2600         return 0
2601     fi
2602     print -n "\eP\e]0;${1}\C-G\e\\"
2603     return 0
2604 }
2605
2606 # Create small urls via http://goo.gl using curl(1).
2607 # API reference: https://code.google.com/apis/urlshortener/
2608 function zurl() {
2609     emulate -L zsh
2610     if [[ -z $1 ]]; then
2611         print "USAGE: zurl <URL>"
2612         return 1
2613     fi
2614
2615     local PN url prog api json data
2616     PN=$0
2617     url=$1
2618
2619     # Prepend 'http://' to given URL where necessary for later output.
2620     if [[ ${url} != http(s|)://* ]]; then
2621         url='http://'${url}
2622     fi
2623
2624     if check_com -c curl; then
2625         prog=curl
2626     else
2627         print "curl is not available, but mandatory for ${PN}. Aborting."
2628         return 1
2629     fi
2630     api='https://www.googleapis.com/urlshortener/v1/url'
2631     contenttype="Content-Type: application/json"
2632     json="{\"longUrl\": \"${url}\"}"
2633     data=$($prog --silent -H ${contenttype} -d ${json} $api)
2634     # Match against a regex and print it
2635     if [[ $data =~ '"id": "(http://goo.gl/[[:alnum:]]+)"' ]]; then
2636         print $match;
2637     fi
2638 }
2639
2640 #f2# Find history events by search pattern and list them by date.
2641 whatwhen()  {
2642     emulate -L zsh
2643     local usage help ident format_l format_s first_char remain first last
2644     usage='USAGE: whatwhen [options] <searchstring> <search range>'
2645     help='Use `whatwhen -h'\'' for further explanations.'
2646     ident=${(l,${#${:-Usage: }},, ,)}
2647     format_l="${ident}%s\t\t\t%s\n"
2648     format_s="${format_l//(\\t)##/\\t}"
2649     # Make the first char of the word to search for case
2650     # insensitive; e.g. [aA]
2651     first_char=[${(L)1[1]}${(U)1[1]}]
2652     remain=${1[2,-1]}
2653     # Default search range is `-100'.
2654     first=${2:-\-100}
2655     # Optional, just used for `<first> <last>' given.
2656     last=$3
2657     case $1 in
2658         ("")
2659             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
2660             printf '%s\n%s\n\n' ${usage} ${help} && return 1
2661         ;;
2662         (-h)
2663             printf '%s\n\n' ${usage}
2664             print 'OPTIONS:'
2665             printf $format_l '-h' 'show help text'
2666             print '\f'
2667             print 'SEARCH RANGE:'
2668             printf $format_l "'0'" 'the whole history,'
2669             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
2670             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
2671             printf '\n%s\n' 'EXAMPLES:'
2672             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
2673             printf $format_l 'whatwhen zsh -250'
2674             printf $format_l 'whatwhen foo 1 99'
2675         ;;
2676         (\?)
2677             printf '%s\n%s\n\n' ${usage} ${help} && return 1
2678         ;;
2679         (*)
2680             # -l list results on stout rather than invoking $EDITOR.
2681             # -i Print dates as in YYYY-MM-DD.
2682             # -m Search for a - quoted - pattern within the history.
2683             fc -li -m "*${first_char}${remain}*" $first $last
2684         ;;
2685     esac
2686 }
2687
2688 # mercurial related stuff
2689 if check_com -c hg ; then
2690     # gnu like diff for mercurial
2691     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
2692     #f5# GNU like diff for mercurial
2693     hgdi() {
2694         emulate -L zsh
2695         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
2696     }
2697
2698     # build debian package
2699     #a2# Alias for \kbd{hg-buildpackage}
2700     alias hbp='hg-buildpackage'
2701
2702     # execute commands on the versioned patch-queue from the current repos
2703     alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
2704
2705     # diffstat for specific version of a mercurial repository
2706     #   hgstat      => display diffstat between last revision and tip
2707     #   hgstat 1234 => display diffstat between revision 1234 and tip
2708     #f5# Diffstat for specific version of a mercurial repos
2709     hgstat() {
2710         emulate -L zsh
2711         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
2712     }
2713
2714 fi # end of check whether we have the 'hg'-executable
2715
2716 # grml-small cleanups
2717
2718 # The following is used to remove zsh-config-items that do not work
2719 # in grml-small by default.
2720 # If you do not want these adjustments (for whatever reason), set
2721 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
2722 # sources if it is there).
2723
2724 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
2725
2726     unset abk[V]
2727     unalias    'V'      &> /dev/null
2728     unfunction vman     &> /dev/null
2729     unfunction viless   &> /dev/null
2730     unfunction 2html    &> /dev/null
2731
2732     # manpages are not in grmlsmall
2733     unfunction manzsh   &> /dev/null
2734     unfunction man2     &> /dev/null
2735
2736 fi
2737
2738 zrclocal
2739
2740 ## genrefcard.pl settings
2741
2742 ### doc strings for external functions from files
2743 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
2744
2745 ### example: split functions-search 8,16,24,32
2746 #@# split functions-search 8
2747
2748 ## END OF FILE #################################################################
2749 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
2750 # Local variables:
2751 # mode: sh
2752 # End: