zshrc: Set options a lot earlier and include no_sh_wordsplit
[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 # Contributing:
15 # If you want to help to improve grml's zsh setup, clone the grml-etc-core
16 # repository from git.grml.org:
17 #   git clone git://git.grml.org/grml-etc-core.git
18 #
19 # Make your changes, commit them; use 'git format-patch' to create a series
20 # of patches and send those to the following address via 'git send-email':
21 #   grml-etc-core@grml.org
22 #
23 # Doing so makes sure the right people get your patches for review and
24 # possibly inclusion.
25
26 # zsh-refcard-tag documentation: {{{
27 #   You may notice strange looking comments in this file.
28 #   These are there for a purpose. grml's zsh-refcard can now be
29 #   automatically generated from the contents of the actual configuration
30 #   file. However, we need a little extra information on which comments
31 #   and what lines of code to take into account (and for what purpose).
32 #
33 # Here is what they mean:
34 #
35 # List of tags (comment types) used:
36 #   #a#     Next line contains an important alias, that should
37 #           be included in the grml-zsh-refcard.
38 #           (placement tag: @@INSERT-aliases@@)
39 #   #f#     Next line contains the beginning of an important function.
40 #           (placement tag: @@INSERT-functions@@)
41 #   #v#     Next line contains an important variable.
42 #           (placement tag: @@INSERT-variables@@)
43 #   #k#     Next line contains an important keybinding.
44 #           (placement tag: @@INSERT-keybindings@@)
45 #   #d#     Hashed directories list generation:
46 #               start   denotes the start of a list of 'hash -d'
47 #                       definitions.
48 #               end     denotes its end.
49 #           (placement tag: @@INSERT-hasheddirs@@)
50 #   #A#     Abbreviation expansion list generation:
51 #               start   denotes the beginning of abbreviations.
52 #               end     denotes their end.
53 #           Lines within this section that end in '#d .*' provide
54 #           extra documentation to be included in the refcard.
55 #           (placement tag: @@INSERT-abbrev@@)
56 #   #m#     This tag allows you to manually generate refcard entries
57 #           for code lines that are hard/impossible to parse.
58 #               Example:
59 #                   #m# k ESC-h Call the run-help function
60 #               That would add a refcard entry in the keybindings table
61 #               for 'ESC-h' with the given comment.
62 #           So the syntax is: #m# <section> <argument> <comment>
63 #   #o#     This tag lets you insert entries to the 'other' hash.
64 #           Generally, this should not be used. It is there for
65 #           things that cannot be done easily in another way.
66 #           (placement tag: @@INSERT-other-foobar@@)
67 #
68 #   All of these tags (except for m and o) take two arguments, the first
69 #   within the tag, the other after the tag:
70 #
71 #   #<tag><section># <comment>
72 #
73 #   Where <section> is really just a number, which are defined by the
74 #   @secmap array on top of 'genrefcard.pl'. The reason for numbers
75 #   instead of names is, that for the reader, the tag should not differ
76 #   much from a regular comment. For zsh, it is a regular comment indeed.
77 #   The numbers have got the following meanings:
78 #         0 -> "default"
79 #         1 -> "system"
80 #         2 -> "user"
81 #         3 -> "debian"
82 #         4 -> "search"
83 #         5 -> "shortcuts"
84 #         6 -> "services"
85 #
86 #   So, the following will add an entry to the 'functions' table in the
87 #   'system' section, with a (hopefully) descriptive comment:
88 #       #f1# Edit an alias via zle
89 #       edalias() {
90 #
91 #   It will then show up in the @@INSERT-aliases-system@@ replacement tag
92 #   that can be found in 'grml-zsh-refcard.tex.in'.
93 #   If the section number is omitted, the 'default' section is assumed.
94 #   Furthermore, in 'grml-zsh-refcard.tex.in' @@INSERT-aliases@@ is
95 #   exactly the same as @@INSERT-aliases-default@@. If you want a list of
96 #   *all* aliases, for example, use @@INSERT-aliases-all@@.
97 #}}}
98
99 # zsh profiling {{{
100 # just execute 'ZSH_PROFILE_RC=1 zsh' and run 'zprof' to get the details
101 if [[ $ZSH_PROFILE_RC -gt 0 ]] ; then
102     zmodload zsh/zprof
103 fi
104 # }}}
105
106 # load .zshrc.pre to give the user the chance to overwrite the defaults
107 [[ -r ${HOME}/.zshrc.pre ]] && source ${HOME}/.zshrc.pre
108
109 # {{{ check for version/system
110 # check for versions (compatibility reasons)
111 is4(){
112     [[ $ZSH_VERSION == <4->* ]] && return 0
113     return 1
114 }
115
116 is41(){
117     [[ $ZSH_VERSION == 4.<1->* || $ZSH_VERSION == <5->* ]] && return 0
118     return 1
119 }
120
121 is42(){
122     [[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
123     return 1
124 }
125
126 is425(){
127     [[ $ZSH_VERSION == 4.2.<5->* || $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
128     return 1
129 }
130
131 is43(){
132     [[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
133     return 1
134 }
135
136 is433(){
137     [[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == <5->* ]] && return 0
138     return 1
139 }
140
141 #f1# Checks whether or not you're running grml
142 isgrml(){
143     [[ -f /etc/grml_version ]] && return 0
144     return 1
145 }
146
147 #f1# Checks whether or not you're running a grml cd
148 isgrmlcd(){
149     [[ -f /etc/grml_cd ]] && return 0
150     return 1
151 }
152
153 if isgrml ; then
154 #f1# Checks whether or not you're running grml-small
155     isgrmlsmall() {
156         [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
157     }
158 else
159     isgrmlsmall() { return 1 }
160 fi
161
162 isdarwin(){
163     [[ $OSTYPE == darwin* ]] && return 0
164     return 1
165 }
166
167 #f1# are we running within an utf environment?
168 isutfenv() {
169     case "$LANG $CHARSET $LANGUAGE" in
170         *utf*) return 0 ;;
171         *UTF*) return 0 ;;
172         *)     return 1 ;;
173     esac
174 }
175
176 # check for user, if not running as root set $SUDO to sudo
177 (( EUID != 0 )) && SUDO='sudo' || SUDO=''
178
179 # change directory to home on first invocation of zsh
180 # important for rungetty -> autologin
181 # Thanks go to Bart Schaefer!
182 isgrml && checkhome() {
183     if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
184         export ALREADY_DID_CD_HOME=$HOME
185         cd
186     fi
187 }
188
189 # check for zsh v3.1.7+
190
191 if ! [[ ${ZSH_VERSION} == 3.1.<7->*      \
192      || ${ZSH_VERSION} == 3.<2->.<->*    \
193      || ${ZSH_VERSION} == <4->.<->*   ]] ; then
194
195     printf '-!-\n'
196     printf '-!- In this configuration we try to make use of features, that only\n'
197     printf '-!- require version 3.1.7 of the shell; That way this setup can be\n'
198     printf '-!- used with a wide range of zsh versions, while using fairly\n'
199     printf '-!- advanced features in all supported versions.\n'
200     printf '-!-\n'
201     printf '-!- However, you are running zsh version %s.\n' "$ZSH_VERSION"
202     printf '-!-\n'
203     printf '-!- While this *may* work, it might as well fail.\n'
204     printf '-!- Please consider updating to at least version 3.1.7 of zsh.\n'
205     printf '-!-\n'
206     printf '-!- DO NOT EXPECT THIS TO WORK FLAWLESSLY!\n'
207     printf '-!- If it does today, you'\''ve been lucky.\n'
208     printf '-!-\n'
209     printf '-!- Ye been warned!\n'
210     printf '-!-\n'
211
212     function zstyle() { : }
213 fi
214
215 # autoload wrapper - use this one instead of autoload directly
216 # We need to define this function as early as this, because autoloading
217 # 'is-at-least()' needs it.
218 function zrcautoload() {
219     setopt local_options extended_glob
220     local fdir ffile
221     local -i ffound
222
223     ffile=${1}
224     (( found = 0 ))
225     for fdir in ${fpath} ; do
226         [[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
227     done
228
229     (( ffound == 0 )) && return 1
230     if [[ $ZSH_VERSION == 3.1.<6-> || $ZSH_VERSION == <4->* ]] ; then
231         autoload -U ${ffile} || return 1
232     else
233         autoload ${ffile} || return 1
234     fi
235     return 0
236 }
237
238 # Load is-at-least() for more precise version checks
239 # Note that this test will *always* fail, if the is-at-least
240 # function could not be marked for autoloading.
241 zrcautoload is-at-least || is-at-least() { return 1 }
242
243 # }}}
244
245 # {{{ set some important options (as early as possible)
246 # Please update these tags, if you change the umask settings below.
247 #o# r_umask     002
248 #o# r_umaskstr  rwxrwxr-x
249 #o# umask       022
250 #o# umaskstr    rwxr-xr-x
251 (( EUID != 0 )) && umask 002 || umask 022
252
253 setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
254 is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
255 setopt extended_history     # save each command's beginning timestamp and the duration to the history file
256 is4 && setopt histignorealldups # If  a  new  command  line being added to the history
257                             # list duplicates an older one, the older command is removed from the list
258 setopt histignorespace      # remove command lines from the history list when
259                             # the first character on the line is a space
260 setopt auto_cd              # if a command is issued that can't be executed as a normal command,
261                             # and the command is the name of a directory, perform the cd command to that directory
262 setopt extended_glob        # in order to use #, ~ and ^ for filename generation
263                             # grep word *~(*.gz|*.bz|*.bz2|*.zip|*.Z) ->
264                             # -> searches for word not in compressed files
265                             # don't forget to quote '^', '~' and '#'!
266 setopt longlistjobs         # display PID when suspending processes as well
267 setopt notify               # report the status of backgrounds jobs immediately
268 setopt hash_list_all        # Whenever a command completion is attempted, make sure \
269                             # the entire command path is hashed first.
270 setopt completeinword       # not just at the end
271 setopt nohup                # and don't kill them, either
272 setopt auto_pushd           # make cd push the old directory onto the directory stack.
273 setopt nonomatch            # try to avoid the 'zsh: no matches found...'
274 setopt nobeep               # avoid "beep"ing
275 setopt pushd_ignore_dups    # don't push the same dir twice.
276 setopt noglobdots           # * shouldn't match dotfiles. ever.
277 setopt noshwordsplit        # use zsh style word splitting
278
279 # }}}
280
281 # setting some default values {{{
282
283 NOCOR=${NOCOR:-0}
284 NOMENU=${NOMENU:-0}
285 NOPRECMD=${NOPRECMD:-0}
286 COMMAND_NOT_FOUND=${COMMAND_NOT_FOUND:-0}
287 GRML_ZSH_CNF_HANDLER=${GRML_ZSH_CNF_HANDLER:-/usr/share/command-not-found/command-not-found}
288 BATTERY=${BATTERY:-0}
289 GRMLSMALL_SPECIFIC=${GRMLSMALL_SPECIFIC:-1}
290 GRML_ALWAYS_LOAD_ALL=${GRML_ALWAYS_LOAD_ALL:-0}
291 ZSH_NO_DEFAULT_LOCALE=${ZSH_NO_DEFAULT_LOCALE:-0}
292
293 if isgrmlcd ; then
294     GRML_WARN_SKEL=${GRML_WARN_SKEL:-0}
295 else
296     GRML_WARN_SKEL=${GRML_WARN_SKEL:-1}
297 fi
298
299 if (( GRML_WARN_SKEL != 0 )) ; then
300
301 function grml_warn_skel_main() {
302     printf '
303 Dear user,
304
305 You updated grml'\''s zshrc which brings a major change.
306 The configuration is kept only in one file, being the global zshrc.
307 In the past, the configuration was split in two files, with the
308 second file being the .zshrc file from /etc/skel.
309
310 If you have a .zshrc file in your home directory that originally
311 came from the skel directory, please remove it. This is also the case
312 if you followed earlier instructions from the grml-zsh-refcard or
313 from <http://grml.org/console/> on non-grml systems.
314
315 Please see the current grml-zsh-refcard (available at
316 <http://grml.org/zsh/>) for updated installation information. In short,
317 you don'\''t want a .zshrc.global file. Install the global zshrc to
318 ~/.zshrc and be done.
319
320 If you need changes to the configuration, use ~/.zshrc.pre and
321 ~/.zshrc.local.
322
323 '
324 }
325
326 function grml_warn_skel_remove() {
327     printf 'To remove this warning execute '\''grml_do_not_warn_skel'\''.\n\n'
328 }
329
330 function grml_do_not_warn_skel() {
331     printf '# Do not warn about old skel dot-files anymore\n' >>! ~/.zshrc.pre
332     printf 'GRML_WARN_SKEL=0\n' >>! ~/.zshrc.pre
333 }
334
335 # let's try to guess how the user uses us.
336 if is-at-least 4.3.7 ; then
337     # funcsourcetrace requires at least version 4.3.7 of zsh.
338     GRML_SRC_FILE="${${funcsourcetrace[1]}%:*}"
339
340     grml_warn_skel_main
341     case ${GRML_SRC_FILE} in
342         (${HOME}/.zshrc.global)
343             grml_warn_skel_remove
344             printf '\nIt looks like you copied the grml zshrc to '\''~/.zshrc.global'\''.\n'
345             printf 'Nowadays you just copy the global zshrc to '\''~/.zshrc'\'' to use\n'
346             printf 'it on a non-grml-system.\n'
347             ;;
348         (${HOME}/.zshrc)
349             printf '\nIt looks like you copied the grml zshrc to '\''~/.zshrc'\''.\n'
350             printf 'We'\''ll disable this warning automatically for later sessions.\n'
351             grml_do_not_warn_skel
352             ;;
353         (*)
354             grml_do_not_warn_skel
355             ;;
356     esac
357 else
358     grml_warn_skel_main
359     grml_warn_skel_remove
360 fi
361
362 unfunction grml_warn_skel_remove grml_warn_skel_main
363
364 fi # GRML_WARN_SKEL
365
366 # }}}
367
368 # utility functions {{{
369 # this function checks if a command exists and returns either true
370 # or false. This avoids using 'which' and 'whence', which will
371 # avoid problems with aliases for which on certain weird systems. :-)
372 # Usage: check_com [-c|-g] word
373 #   -c  only checks for external commands
374 #   -g  does the usual tests and also checks for global aliases
375 check_com() {
376     local -i comonly gatoo
377
378     if [[ ${1} == '-c' ]] ; then
379         (( comonly = 1 ))
380         shift
381     elif [[ ${1} == '-g' ]] ; then
382         (( gatoo = 1 ))
383     else
384         (( comonly = 0 ))
385         (( gatoo = 0 ))
386     fi
387
388     if (( ${#argv} != 1 )) ; then
389         printf 'usage: check_com [-c] <command>\n' >&2
390         return 1
391     fi
392
393     if (( comonly > 0 )) ; then
394         [[ -n ${commands[$1]}  ]] && return 0
395         return 1
396     fi
397
398     if   [[ -n ${commands[$1]}    ]] \
399       || [[ -n ${functions[$1]}   ]] \
400       || [[ -n ${aliases[$1]}     ]] \
401       || [[ -n ${reswords[(r)$1]} ]] ; then
402
403         return 0
404     fi
405
406     if (( gatoo > 0 )) && [[ -n ${galiases[$1]} ]] ; then
407         return 0
408     fi
409
410     return 1
411 }
412
413 # creates an alias and precedes the command with
414 # sudo if $EUID is not zero.
415 salias() {
416     local only=0 ; local multi=0
417     while [[ ${1} == -* ]] ; do
418         case ${1} in
419             (-o) only=1 ;;
420             (-a) multi=1 ;;
421             (--) shift ; break ;;
422             (-h)
423                 printf 'usage: salias [-h|-o|-a] <alias-expression>\n'
424                 printf '  -h      shows this help text.\n'
425                 printf '  -a      replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
426                 printf '          be careful using this option.\n'
427                 printf '  -o      only sets an alias if a preceding sudo would be needed.\n'
428                 return 0
429                 ;;
430             (*) printf "unkown option: '%s'\n" "${1}" ; return 1 ;;
431         esac
432         shift
433     done
434
435     if (( ${#argv} > 1 )) ; then
436         printf 'Too many arguments %s\n' "${#argv}"
437         return 1
438     fi
439
440     key="${1%%\=*}" ;  val="${1#*\=}"
441     if (( EUID == 0 )) && (( only == 0 )); then
442         alias -- "${key}=${val}"
443     elif (( EUID > 0 )) ; then
444         (( multi > 0 )) && val="${val// ; / ; sudo }"
445         alias -- "${key}=sudo ${val}"
446     fi
447
448     return 0
449 }
450
451 # a "print -l ${(u)foo}"-workaround for pre-4.2.0 shells
452 # usage: uprint foo
453 #   Where foo is the *name* of the parameter you want printed.
454 #   Note that foo is no typo; $foo would be wrong here!
455 if ! is42 ; then
456     uprint () {
457         local -a u
458         local w
459         local parameter=${1}
460
461         if [[ -z ${parameter} ]] ; then
462             printf 'usage: uprint <parameter>\n'
463             return 1
464         fi
465
466         for w in ${(P)parameter} ; do
467             [[ -z ${(M)u:#${w}} ]] && u=( ${u} ${w} )
468         done
469
470         builtin print -l ${u}
471     }
472 fi
473
474 # Check if we can read given files and source those we can.
475 xsource() {
476     if (( ${#argv} < 1 )) ; then
477         printf 'usage: xsource FILE(s)...\n' >&2
478         return 1
479     fi
480
481     while (( ${#argv} > 0 )) ; do
482         [[ -r ${1} ]] && source ${1}
483         shift
484     done
485     return 0
486 }
487
488 # Check if we can read a given file and 'cat(1)' it.
489 xcat() {
490     if (( ${#argv} != 1 )) ; then
491         printf 'usage: xcat FILE\n' >&2
492         return 1
493     fi
494
495     [[ -r ${1} ]] && cat ${1}
496     return 0
497 }
498
499 # Remove these functions again, they are of use only in these
500 # setup files. This should be called at the end of .zshrc.
501 xunfunction() {
502     local -a funcs
503     funcs=(salias xcat xsource xunfunction zrcautoload)
504
505     for func in $funcs ; do
506         [[ -n ${functions[$func]} ]] \
507             && unfunction $func
508     done
509     return 0
510 }
511
512 # this allows us to stay in sync with grml's zshrc and put own
513 # modifications in ~/.zshrc.local
514 zrclocal() {
515     xsource "/etc/zsh/zshrc.local"
516     xsource "${HOME}/.zshrc.local"
517     return 0
518 }
519
520 #}}}
521
522 # locale setup {{{
523 if (( ZSH_NO_DEFAULT_LOCALE == 0 )); then
524     xsource "/etc/default/locale"
525 fi
526
527 for var in LANG LC_ALL LC_MESSAGES ; do
528     [[ -n ${(P)var} ]] && export $var
529 done
530
531 xsource "/etc/sysconfig/keyboard"
532
533 TZ=$(xcat /etc/timezone)
534 # }}}
535
536 # check for potentially old files in 'completion.d' {{{
537 setopt extendedglob
538 xof=(/etc/zsh/completion.d/*~/etc/zsh/completion.d/_*(N))
539 if (( ${#xof} > 0 )) ; then
540     printf '\n -!- INFORMATION\n\n'
541     printf ' -!- %s file(s) not starting with an underscore (_) found in\n' ${#xof}
542     printf ' -!- /etc/zsh/completion.d/.\n\n'
543     printf ' -!- While this has been the case in old versions of grml-etc-core,\n'
544     printf ' -!- recent versions of the grml-zsh-setup have all these files rewritten\n'
545     printf ' -!- and renamed. Furthermore, the grml-zsh-setup will *only* add files\n'
546     printf ' -!- named _* to that directory.\n\n'
547     printf ' -!- If you added functions to completion.d yourself, please consider\n'
548     printf ' -!- moving them to /etc/zsh/functions.d/. Files in that directory, not\n'
549     printf ' -!- starting with an underscore are marked for automatic loading\n'
550     printf ' -!- by default (so that is quite convenient).\n\n'
551     printf ' -!- If there are files *not* starting with an underscore from an older\n'
552     printf ' -!- grml-etc-core in completion.d, you may safely remove them.\n\n'
553     printf ' -!- Delete the files for example via running:\n\n'
554     printf "      rm ${xof}\n\n"
555     printf ' -!- Note, that this message will *not* go away, unless you yourself\n'
556     printf ' -!- resolve the situation manually.\n\n'
557     BROKEN_COMPLETION_DIR=1
558 fi
559 unset xof
560 # }}}
561
562 # {{{ set some variables
563 if check_com -c vim ; then
564 #v#
565     export EDITOR=${EDITOR:-vim}
566 else
567     export EDITOR=${EDITOR:-vi}
568 fi
569
570 #v#
571 export PAGER=${PAGER:-less}
572
573 #v#
574 export MAIL=${MAIL:-/var/mail/$USER}
575
576 # if we don't set $SHELL then aterm, rxvt,.. will use /bin/sh or /bin/bash :-/
577 export SHELL='/bin/zsh'
578
579 # color setup for ls:
580 check_com -c dircolors && eval $(dircolors -b)
581 # color setup for ls on OS X:
582 isdarwin && export CLICOLOR=1
583
584 # do MacPorts setup on darwin
585 if isdarwin && [[ -d /opt/local ]]; then
586     # Note: PATH gets set in /etc/zprofile on Darwin, so this can't go into
587     # zshenv.
588     PATH="/opt/local/bin:/opt/local/sbin:$PATH"
589     MANPATH="/opt/local/share/man:$MANPATH"
590 fi
591 # do Fink setup on darwin
592 isdarwin && xsource /sw/bin/init.sh
593
594 # completion functions go to /etc/zsh/completion.d
595 # function files may be put into /etc/zsh/functions.d, from where they
596 # will be automatically autoloaded.
597 if [[ -n "$BROKEN_COMPLETION_DIR" ]] ; then
598     print 'Warning: not setting completion directories because broken files have been found.' >&2
599 else
600     [[ -d /etc/zsh/completion.d ]] && fpath=( $fpath /etc/zsh/completion.d )
601     if [[ -d /etc/zsh/functions.d ]] ; then
602         fdir='/etc/zsh/functions.d'
603         fpath=( ${fdir} ${fdir}/**/*(/N) ${fpath} )
604         for func in ${fdir}/**/[^_]*[^~](N.) ; do
605             zrcautoload ${func:t}
606         done
607         unset fdir
608     fi
609 fi
610
611 # support colors in less
612 export LESS_TERMCAP_mb=$'\E[01;31m'
613 export LESS_TERMCAP_md=$'\E[01;31m'
614 export LESS_TERMCAP_me=$'\E[0m'
615 export LESS_TERMCAP_se=$'\E[0m'
616 export LESS_TERMCAP_so=$'\E[01;44;33m'
617 export LESS_TERMCAP_ue=$'\E[0m'
618 export LESS_TERMCAP_us=$'\E[01;32m'
619
620 MAILCHECK=30       # mailchecks
621 REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 seconds
622 watch=(notme root) # watch for everyone but me and root
623
624 # automatically remove duplicates from these arrays
625 typeset -U path cdpath fpath manpath
626 # }}}
627
628 # {{{ keybindings
629 if [[ "$TERM" != emacs ]] ; then
630     [[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
631     [[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
632     [[ -z "$terminfo[kend]"  ]] || bindkey -M emacs "$terminfo[kend]"  end-of-line
633     [[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
634     [[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
635     [[ -z "$terminfo[kend]"  ]] || bindkey -M vicmd "$terminfo[kend]"  vi-end-of-line
636     [[ -z "$terminfo[cuu1]"  ]] || bindkey -M viins "$terminfo[cuu1]"  vi-up-line-or-history
637     [[ -z "$terminfo[cuf1]"  ]] || bindkey -M viins "$terminfo[cuf1]"  vi-forward-char
638     [[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
639     [[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
640     [[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
641     [[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char
642     # ncurses stuff:
643     [[ "$terminfo[kcuu1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
644     [[ "$terminfo[kcud1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
645     [[ "$terminfo[kcuf1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
646     [[ "$terminfo[kcub1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
647     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
648     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M viins "${terminfo[kend]/O/[}"  end-of-line
649     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
650     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M emacs "${terminfo[kend]/O/[}"  end-of-line
651 fi
652
653 ## keybindings (run 'bindkeys' for details, more details via man zshzle)
654 # use emacs style per default:
655 bindkey -e
656 # use vi style:
657 # bindkey -v
658
659 #if [[ "$TERM" == screen ]] ; then
660 bindkey '\e[1~' beginning-of-line       # home
661 bindkey '\e[4~' end-of-line             # end
662 bindkey '\e[A'  up-line-or-search       # cursor up
663 bindkey '\e[B'  down-line-or-search     # <ESC>-
664
665 bindkey '^xp'   history-beginning-search-backward
666 bindkey '^xP'   history-beginning-search-forward
667 # bindkey -s '^L' "|less\n"             # ctrl-L pipes to less
668 # bindkey -s '^B' " &\n"                # ctrl-B runs it in the background
669 # if terminal type is set to 'rxvt':
670 bindkey '\e[7~' beginning-of-line       # home
671 bindkey '\e[8~' end-of-line             # end
672 #fi
673
674 # insert unicode character
675 # usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an Â§
676 # See for example http://unicode.org/charts/ for unicode characters code
677 zrcautoload insert-unicode-char
678 zle -N insert-unicode-char
679 #k# Insert Unicode character
680 bindkey '^Xi' insert-unicode-char
681
682 # just type 'cd ...' to get 'cd ../..'
683 #  rationalise-dot() {
684 #  if [[ $LBUFFER == *.. ]] ; then
685 #    LBUFFER+=/..
686 #  else
687 #    LBUFFER+=.
688 #  fi
689 #  }
690 #  zle -N rationalise-dot
691 #  bindkey . rationalise-dot
692
693 #  bindkey '\eq' push-line-or-edit
694
695 ## toggle the ,. abbreviation feature on/off
696 # NOABBREVIATION: default abbreviation-state
697 #                 0 - enabled (default)
698 #                 1 - disabled
699 NOABBREVIATION=${NOABBREVIATION:-0}
700
701 grml_toggle_abbrev() {
702     if (( ${NOABBREVIATION} > 0 )) ; then
703         NOABBREVIATION=0
704     else
705         NOABBREVIATION=1
706     fi
707 }
708
709 zle -N grml_toggle_abbrev
710 bindkey '^xA' grml_toggle_abbrev
711
712 # add a command line to the shells history without executing it
713 commit-to-history() {
714     print -s ${(z)BUFFER}
715     zle send-break
716 }
717 zle -N commit-to-history
718 bindkey "^x^h" commit-to-history
719
720 # only slash should be considered as a word separator:
721 slash-backward-kill-word() {
722     local WORDCHARS="${WORDCHARS:s@/@}"
723     # zle backward-word
724     zle backward-kill-word
725 }
726 zle -N slash-backward-kill-word
727
728 #k# Kill everything in a word up to its last \kbd{/}
729 bindkey '\ev' slash-backward-kill-word
730
731 # }}}
732
733 # a generic accept-line wrapper {{{
734
735 # This widget can prevent unwanted autocorrections from command-name
736 # to _command-name, rehash automatically on enter and call any number
737 # of builtin and user-defined widgets in different contexts.
738 #
739 # For a broader description, see:
740 # <http://bewatermyfriend.org/posts/2007/12-26.11-50-38-tooltime.html>
741 #
742 # The code is imported from the file 'zsh/functions/accept-line' from
743 # <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>, which
744 # distributed under the same terms as zsh itself.
745
746 # A newly added command will may not be found or will cause false
747 # correction attempts, if you got auto-correction set. By setting the
748 # following style, we force accept-line() to rehash, if it cannot
749 # find the first word on the command line in the $command[] hash.
750 zstyle ':acceptline:*' rehash true
751
752 function Accept-Line() {
753     setopt localoptions noksharrays
754     local -a subs
755     local -xi aldone
756     local sub
757
758     zstyle -a ":acceptline:${alcontext}" actions subs
759
760     (( ${#subs} < 1 )) && return 0
761
762     (( aldone = 0 ))
763     for sub in ${subs} ; do
764         [[ ${sub} == 'accept-line' ]] && sub='.accept-line'
765         zle ${sub}
766
767         (( aldone > 0 )) && break
768     done
769 }
770
771 function Accept-Line-getdefault() {
772     local default_action
773
774     zstyle -s ":acceptline:${alcontext}" default_action default_action
775     case ${default_action} in
776         ((accept-line|))
777             printf ".accept-line"
778             ;;
779         (*)
780             printf ${default_action}
781             ;;
782     esac
783 }
784
785 function accept-line() {
786     setopt localoptions noksharrays
787     local -a cmdline
788     local -x alcontext
789     local buf com fname format msg default_action
790
791     alcontext='default'
792     buf="${BUFFER}"
793     cmdline=(${(z)BUFFER})
794     com="${cmdline[1]}"
795     fname="_${com}"
796
797     zstyle -t ":acceptline:${alcontext}" rehash \
798         && [[ -z ${commands[$com]} ]]           \
799         && rehash
800
801     if    [[ -n ${reswords[(r)$com]} ]] \
802        || [[ -n ${aliases[$com]}     ]] \
803        || [[ -n ${functions[$com]}   ]] \
804        || [[ -n ${builtins[$com]}    ]] \
805        || [[ -n ${commands[$com]}    ]] ; then
806
807         # there is something sensible to execute, just do it.
808         alcontext='normal'
809         zle Accept-Line
810
811         default_action=$(Accept-Line-getdefault)
812         zstyle -T ":acceptline:${alcontext}" call_default \
813             && zle ${default_action}
814         return
815     fi
816
817     if    [[ -o correct              ]] \
818        || [[ -o correctall           ]] \
819        && [[ -n ${functions[$fname]} ]] ; then
820
821         # nothing there to execute but there is a function called
822         # _command_name; a completion widget. Makes no sense to
823         # call it on the commandline, but the correct{,all} options
824         # will ask for it nevertheless, so warn the user.
825         if [[ ${LASTWIDGET} == 'accept-line' ]] ; then
826             # Okay, we warned the user before, he called us again,
827             # so have it his way.
828             alcontext='force'
829             zle Accept-Line
830
831             default_action=$(Accept-Line-getdefault)
832             zstyle -T ":acceptline:${alcontext}" call_default \
833                 && zle ${default_action}
834             return
835         fi
836
837         # prepare warning message for the user, configurable via zstyle.
838         zstyle -s ":acceptline:${alcontext}" compwarnfmt msg
839
840         if [[ -z ${msg} ]] ; then
841             msg="%c will not execute and completion %f exists."
842         fi
843
844         zformat -f msg "${msg}" "c:${com}" "f:${fname}"
845
846         zle -M -- "${msg}"
847         return
848     elif [[ -n ${buf//[$' \t\n']##/} ]] ; then
849         # If we are here, the commandline contains something that is not
850         # executable, which is neither subject to _command_name correction
851         # and is not empty. might be a variable assignment
852         alcontext='misc'
853         zle Accept-Line
854
855         default_action=$(Accept-Line-getdefault)
856         zstyle -T ":acceptline:${alcontext}" call_default \
857             && zle ${default_action}
858         return
859     fi
860
861     # If we got this far, the commandline only contains whitespace, or is empty.
862     alcontext='empty'
863     zle Accept-Line
864
865     default_action=$(Accept-Line-getdefault)
866     zstyle -T ":acceptline:${alcontext}" call_default \
867         && zle ${default_action}
868 }
869
870 zle -N accept-line
871 zle -N Accept-Line
872
873 # }}}
874
875 # power completion - abbreviation expansion {{{
876 # power completion / abbreviation expansion / buffer expansion
877 # see http://zshwiki.org/home/examples/zleiab for details
878 # less risky than the global aliases but powerful as well
879 # just type the abbreviation key and afterwards ',.' to expand it
880 declare -A abk
881 setopt extendedglob
882 setopt interactivecomments
883 abk=(
884 #   key   # value                  (#d additional doc string)
885 #A# start
886     '...'  '../..'
887     '....' '../../..'
888     'BG'   '& exit'
889     'C'    '| wc -l'
890     'G'    '|& grep --color=auto '
891     'H'    '| head'
892     'Hl'   ' --help |& less -r'    #d (Display help in pager)
893     'L'    '| less'
894     'LL'   '|& less -r'
895     'M'    '| most'
896     'N'    '&>/dev/null'           #d (No Output)
897     'R'    '| tr A-z N-za-m'       #d (ROT13)
898     'SL'   '| sort | less'
899     'S'    '| sort -u'
900     'T'    '| tail'
901     'V'    '|& vim -'
902 #A# end
903     'co'   './configure && make && sudo make install'
904 )
905
906 globalias() {
907     local MATCH
908
909     if (( NOABBREVIATION > 0 )) ; then
910         LBUFFER="${LBUFFER},."
911         return 0
912     fi
913
914     matched_chars='[.-|_a-zA-Z0-9]#'
915     LBUFFER=${LBUFFER%%(#m)[.-|_a-zA-Z0-9]#}
916     LBUFFER+=${abk[$MATCH]:-$MATCH}
917 }
918
919 zle -N globalias
920 bindkey ",." globalias
921 # }}}
922
923 # {{{ autoloading
924 zrcautoload zmv    # who needs mmv or rename?
925 zrcautoload history-search-end
926
927 # we don't want to quote/espace URLs on our own...
928 # if autoload -U url-quote-magic ; then
929 #    zle -N self-insert url-quote-magic
930 #    zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}='
931 # else
932 #    print 'Notice: no url-quote-magic available :('
933 # fi
934 alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic'
935
936 #m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
937 alias run-help >&/dev/null && unalias run-help
938 zrcautoload run-help # use via 'esc-h'
939
940 # completion system
941 if zrcautoload compinit ; then
942     compinit || print 'Notice: no compinit available :('
943 else
944     print 'Notice: no compinit available :('
945     function zstyle { }
946     function compdef { }
947 fi
948
949 is4 && zrcautoload zed # use ZLE editor to edit a file or function
950
951 is4 && \
952 for mod in complist deltochar mathfunc ; do
953     zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
954 done
955
956 # autoload zsh modules when they are referenced
957 if is4 ; then
958     tmpargs=(
959         a   stat
960         a   zpty
961         ap  mapfile
962     )
963
964     while (( ${#tmpargs} > 0 )) ; do
965         zmodload -${tmpargs[1]} zsh/${tmpargs[2]} ${tmpargs[2]}
966         shift 2 tmpargs
967     done
968     unset tmpargs
969 fi
970
971 if is4 && zrcautoload insert-files && zle -N insert-files ; then
972     #k# Insert files
973     bindkey "^Xf" insert-files # C-x-f
974 fi
975
976 bindkey ' '   magic-space    # also do history expansion on space
977 #k# Trigger menu-complete
978 bindkey '\ei' menu-complete  # menu completion via esc-i
979
980 # press esc-e for editing command line in $EDITOR or $VISUAL
981 if is4 && zrcautoload edit-command-line && zle -N edit-command-line ; then
982     #k# Edit the current line in \kbd{\$EDITOR}
983     bindkey '\ee' edit-command-line
984 fi
985
986 if is4 && [[ -n ${(k)modules[zsh/complist]} ]] ; then
987     #k# menu selection: pick item but stay in the menu
988     bindkey -M menuselect '\e^M' accept-and-menu-complete
989
990     # accept a completion and try to complete again by using menu
991     # completion; very useful with completing directories
992     # by using 'undo' one's got a simple file browser
993     bindkey -M menuselect '^o' accept-and-infer-next-history
994 fi
995
996 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
997 _bkdate() { BUFFER="$BUFFER$(date '+%F')"; CURSOR=$#BUFFER; }
998 zle -N _bkdate
999
1000 #k# Insert a timestamp on the command line (yyyy-mm-dd)
1001 bindkey '^Ed' _bkdate
1002
1003 # press esc-m for inserting last typed word again (thanks to caphuso!)
1004 insert-last-typed-word() { zle insert-last-word -- 0 -1 };
1005 zle -N insert-last-typed-word;
1006
1007 #k# Insert last typed word
1008 bindkey "\em" insert-last-typed-word
1009
1010 #k# Shortcut for \kbd{fg<enter>}
1011 bindkey -s '^z' "fg\n"
1012
1013 # run command line as user root via sudo:
1014 sudo-command-line() {
1015     [[ -z $BUFFER ]] && zle up-history
1016     [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
1017 }
1018 zle -N sudo-command-line
1019
1020 #k# Put the current command line into a \kbd{sudo} call
1021 bindkey "^Os" sudo-command-line
1022
1023 ### jump behind the first word on the cmdline.
1024 ### useful to add options.
1025 function jump_after_first_word() {
1026     local words
1027     words=(${(z)BUFFER})
1028
1029     if (( ${#words} <= 1 )) ; then
1030         CURSOR=${#BUFFER}
1031     else
1032         CURSOR=${#${words[1]}}
1033     fi
1034 }
1035 zle -N jump_after_first_word
1036
1037 bindkey '^x1' jump_after_first_word
1038
1039 # }}}
1040
1041 # {{{ history
1042
1043 ZSHDIR=$HOME/.zsh
1044
1045 #v#
1046 HISTFILE=$HOME/.zsh_history
1047 isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
1048 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
1049
1050 # }}}
1051
1052 # dirstack handling {{{
1053
1054 DIRSTACKSIZE=${DIRSTACKSIZE:-20}
1055 DIRSTACKFILE=${DIRSTACKFILE:-${HOME}/.zdirs}
1056
1057 if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
1058     dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
1059     # "cd -" won't work after login by just setting $OLDPWD, so
1060     [[ -d $dirstack[0] ]] && cd $dirstack[0] && cd $OLDPWD
1061 fi
1062
1063 chpwd() {
1064     if is42 ; then
1065         builtin print -l ${(u)dirstack} >! ${DIRSTACKFILE}
1066     else
1067         uprint dirstack >! ${DIRSTACKFILE}
1068     fi
1069 }
1070
1071 # }}}
1072
1073 # directory based profiles {{{
1074
1075 if is433 ; then
1076
1077 CHPWD_PROFILE='default'
1078 function chpwd_profiles() {
1079     # Say you want certain settings to be active in certain directories.
1080     # This is what you want.
1081     #
1082     # zstyle ':chpwd:profiles:/usr/src/grml(|/|/*)'   profile grml
1083     # zstyle ':chpwd:profiles:/usr/src/debian(|/|/*)' profile debian
1084     #
1085     # When that's done and you enter a directory that matches the pattern
1086     # in the third part of the context, a function called chpwd_profile_grml,
1087     # for example, is called (if it exists).
1088     #
1089     # If no pattern matches (read: no profile is detected) the profile is
1090     # set to 'default', which means chpwd_profile_default is attempted to
1091     # be called.
1092     #
1093     # A word about the context (the ':chpwd:profiles:*' stuff in the zstyle
1094     # command) which is used: The third part in the context is matched against
1095     # ${PWD}. That's why using a pattern such as /foo/bar(|/|/*) makes sense.
1096     # Because that way the profile is detected for all these values of ${PWD}:
1097     #   /foo/bar
1098     #   /foo/bar/
1099     #   /foo/bar/baz
1100     # So, if you want to make double damn sure a profile works in /foo/bar
1101     # and everywhere deeper in that tree, just use (|/|/*) and be happy.
1102     #
1103     # The name of the detected profile will be available in a variable called
1104     # 'profile' in your functions. You don't need to do anything, it'll just
1105     # be there.
1106     #
1107     # Then there is the parameter $CHPWD_PROFILE is set to the profile, that
1108     # was is currently active. That way you can avoid running code for a
1109     # profile that is already active, by running code such as the following
1110     # at the start of your function:
1111     #
1112     # function chpwd_profile_grml() {
1113     #     [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
1114     #   ...
1115     # }
1116     #
1117     # The initial value for $CHPWD_PROFILE is 'default'.
1118     #
1119     # Version requirement:
1120     #   This feature requires zsh 4.3.3 or newer.
1121     #   If you use this feature and need to know whether it is active in your
1122     #   current shell, there are several ways to do that. Here are two simple
1123     #   ways:
1124     #
1125     #   a) If knowing if the profiles feature is active when zsh starts is
1126     #      good enough for you, you can put the following snippet into your
1127     #      .zshrc.local:
1128     #
1129     #   (( ${+functions[chpwd_profiles]} )) && print "directory profiles active"
1130     #
1131     #   b) If that is not good enough, and you would prefer to be notified
1132     #      whenever a profile changes, you can solve that by making sure you
1133     #      start *every* profile function you create like this:
1134     #
1135     #   function chpwd_profile_myprofilename() {
1136     #       [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
1137     #       print "chpwd(): Switching to profile: $profile"
1138     #     ...
1139     #   }
1140     #
1141     #      That makes sure you only get notified if a profile is *changed*,
1142     #      not everytime you change directory, which would probably piss
1143     #      you off fairly quickly. :-)
1144     #
1145     # There you go. Now have fun with that.
1146     local -x profile
1147
1148     zstyle -s ":chpwd:profiles:${PWD}" profile profile || profile='default'
1149     if (( ${+functions[chpwd_profile_$profile]} )) ; then
1150         chpwd_profile_${profile}
1151     fi
1152
1153     CHPWD_PROFILE="${profile}"
1154     return 0
1155 }
1156 chpwd_functions=( ${chpwd_functions} chpwd_profiles )
1157
1158 fi # is433
1159
1160 # }}}
1161
1162 # {{{ display battery status on right side of prompt via running 'BATTERY=1 zsh'
1163 if [[ $BATTERY -gt 0 ]] ; then
1164     if ! check_com -c acpi ; then
1165         BATTERY=0
1166     fi
1167 fi
1168
1169 battery() {
1170 if [[ $BATTERY -gt 0 ]] ; then
1171     PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]#Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
1172     if [[ -z "$PERCENT" ]] ; then
1173         PERCENT='acpi not present'
1174     else
1175         if [[ "$PERCENT" -lt 20 ]] ; then
1176             PERCENT="warning: ${PERCENT}%%"
1177         else
1178             PERCENT="${PERCENT}%%"
1179         fi
1180     fi
1181 fi
1182 }
1183 # }}}
1184
1185 # set colors for use in prompts {{{
1186 if zrcautoload colors && colors 2>/dev/null ; then
1187     BLUE="%{${fg[blue]}%}"
1188     RED="%{${fg_bold[red]}%}"
1189     GREEN="%{${fg[green]}%}"
1190     CYAN="%{${fg[cyan]}%}"
1191     MAGENTA="%{${fg[magenta]}%}"
1192     YELLOW="%{${fg[yellow]}%}"
1193     WHITE="%{${fg[white]}%}"
1194     NO_COLOUR="%{${reset_color}%}"
1195 else
1196     BLUE=$'%{\e[1;34m%}'
1197     RED=$'%{\e[1;31m%}'
1198     GREEN=$'%{\e[1;32m%}'
1199     CYAN=$'%{\e[1;36m%}'
1200     WHITE=$'%{\e[1;37m%}'
1201     MAGENTA=$'%{\e[1;35m%}'
1202     YELLOW=$'%{\e[1;33m%}'
1203     NO_COLOUR=$'%{\e[0m%}'
1204 fi
1205
1206 # }}}
1207
1208 # gather version control information for inclusion in a prompt {{{
1209
1210 if ! is41 ; then
1211     # Be quiet about version problems in grml's zshrc as the user cannot disable
1212     # loading vcs_info() as it is *in* the zshrc - as you can see. :-)
1213     # Just unset most probable variables and disable vcs_info altogether.
1214     local -i i
1215     for i in {0..9} ; do
1216         unset VCS_INFO_message_${i}_
1217     done
1218     zstyle ':vcs_info:*' enable false
1219 fi
1220
1221 # The following code is imported from the file 'zsh/functions/vcs_info'
1222 # from <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>,
1223 # which distributed under the same terms as zsh itself.
1224
1225 # we will be using two variables, so let the code know now.
1226 zstyle ':vcs_info:*' max-exports 2
1227
1228 # vcs_info() documentation:
1229 #{{{
1230 # REQUIREMENTS:
1231 #{{{
1232 #     This functionality requires zsh version >= 4.1.*.
1233 #}}}
1234 #
1235 # LOADING:
1236 #{{{
1237 # To load vcs_info(), copy this file to your $fpath[] and do:
1238 #   % autoload -Uz vcs_info && vcs_info
1239 #
1240 # To work, vcs_info() needs 'setopt prompt_subst' in your setup.
1241 #}}}
1242 #
1243 # QUICKSTART:
1244 #{{{
1245 # To get vcs_info() working quickly (including colors), you can do the
1246 # following (assuming, you loaded vcs_info() properly - see above):
1247 #
1248 # % RED=$'%{\e[31m%}'
1249 # % GR=$'%{\e[32m%}'
1250 # % MA=$'%{\e[35m%}'
1251 # % YE=$'%{\e[33m%}'
1252 # % NC=$'%{\e[0m%}'
1253 #
1254 # % zstyle ':vcs_info:*' actionformats \
1255 #       "${MA}(${NC}%s${MA})${YE}-${MA}[${GR}%b${YE}|${RED}%a${MA}]${NC} "
1256 #
1257 # % zstyle ':vcs_info:*' formats       \
1258 #       "${MA}(${NC}%s${MA})${Y}-${MA}[${GR}%b${MA}]${NC}%} "
1259 #
1260 # % zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YE}%r"
1261 #
1262 # % precmd () { vcs_info }
1263 # % PS1='${MA}[${GR}%n${MA}] ${MA}(${RED}%!${MA}) ${YE}%3~ ${VCS_INFO_message_0_}${NC}%# '
1264 #
1265 # Obviously, the las two lines are there for demonstration: You need to
1266 # call vcs_info() from your precmd() function (see 'SPECIAL FUNCTIONS' in
1267 # 'man zshmisc'). Once that is done you need a *single* quoted
1268 # '${VCS_INFO_message_0_}' in your prompt.
1269 #
1270 # Now call the 'vcs_info_printsys' utility from the command line:
1271 #
1272 # % vcs_info_printsys
1273 # # list of supported version control backends:
1274 # # disabled systems are prefixed by a hash sign (#)
1275 # git
1276 # hg
1277 # bzr
1278 # darcs
1279 # svk
1280 # mtn
1281 # svn
1282 # cvs
1283 # cdv
1284 # tla
1285 # # flavours (cannot be used in the disable style; they
1286 # # are disabled with their master [git-svn -> git]):
1287 # git-p4
1288 # git-svn
1289 #
1290 # Ten version control backends as you can see. You may not want all
1291 # of these. Because there is no point in running the code to detect
1292 # systems you do not use. ever. So, there is a way to disable some
1293 # backends altogether:
1294 #
1295 # % zstyle ':vcs_info:*' disable bzr cdv darcs mtn svk tla
1296 #
1297 # If you rerun 'vcs_info_printsys' now, you will see the backends listed
1298 # in the 'disable' style marked as diabled by a hash sign. That means the
1299 # detection of these systems is skipped *completely*. No wasted time there.
1300 #
1301 # For more control, read the reference below.
1302 #}}}
1303 #
1304 # CONFIGURATION:
1305 #{{{
1306 # The vcs_info() feature can be configured via zstyle.
1307 #
1308 # First, the context in which we are working:
1309 #       :vcs_info:<vcs-string>:<user-context>
1310 #
1311 # ...where <vcs-string> is one of:
1312 #   - git, git-svn, git-p4, hg, darcs, bzr, cdv, mtn, svn, cvs, svk or tla.
1313 #
1314 # ...and <user-context> is a freely configurable string, assignable by the
1315 # user as the first argument to vcs_info() (see its description below).
1316 #
1317 # There is are three special values for <vcs-string>: The first is named
1318 # 'init', that is in effect as long as there was no decision what vcs
1319 # backend to use. The second is 'preinit; it is used *before* vcs_info()
1320 # is run, when initializing the data exporting variables. The third
1321 # special value is 'formats' and is used by the 'vcs_info_lastmsg' for
1322 # looking up its styles.
1323 #
1324 # There are two pre-defined values for <user-context>:
1325 #   default  - the one used if none is specified
1326 #   command  - used by vcs_info_lastmsg to lookup its styles.
1327 #
1328 # You may *not* use 'print_systems_' as a user-context string, because it
1329 # is used internally.
1330 #
1331 # You can of course use ':vcs_info:*' to match all VCSs in all
1332 # user-contexts at once.
1333 #
1334 # Another special context is 'formats', which is used by the
1335 # vcs_info_lastmsg() utility function (see below).
1336 #
1337 #
1338 # This is a description of all styles, that are looked up:
1339 #   formats             - A list of formats, used when actionformats is not
1340 #                         used (which is most of the time).
1341 #   actionformats       - A list of formats, used if a there is a special
1342 #                         action going on in your current repository;
1343 #                         (like an interactive rebase or a merge conflict)
1344 #   branchformat        - Some backends replace %b in the formats and
1345 #                         actionformats styles above, not only by a branch
1346 #                         name but also by a revision number. This style
1347 #                         let's you modify how that string should look like.
1348 #   nvcsformats         - These "formats" are exported, when we didn't detect
1349 #                         a version control system for the current directory.
1350 #                         This is useful, if you want vcs_info() to completely
1351 #                         take over the generation of your prompt.
1352 #                         You would do something like
1353 #                           PS1='${VCS_INFO_message_0_}'
1354 #                         to accomplish that.
1355 #   max-exports         - Defines the maximum number if VCS_INFO_message_*_
1356 #                         variables vcs_info() will export.
1357 #   enable              - Checked in the 'init' context. If set to false,
1358 #                         vcs_info() will do nothing.
1359 #   disable             - Provide a list of systems, you don't want
1360 #                         the vcs_info() to check for repositories
1361 #                         (checked in the 'init' context, too).
1362 #   disable-patterns    - A list of patterns that are checked against $PWD.
1363 #                         If the pattern matches, vcs_info will be disabled.
1364 #                         Say, ~/.zsh is a directory under version control,
1365 #                         in which you do not want vcs_info to be active, do:
1366 #                         zstyle ':vcs_info:*' disable-patterns "$HOME/.zsh+(|/*)"
1367 #   use-simple          - If there are two different ways of gathering
1368 #                         information, you can select the simpler one
1369 #                         by setting this style to true; the default
1370 #                         is to use the not-that-simple code, which is
1371 #                         potentially a lot slower but might be more
1372 #                         accurate in all possible cases.
1373 #   use-prompt-escapes  - determines if we assume that the assembled
1374 #                         string from vcs_info() includes prompt escapes.
1375 #                         (Used by vcs_info_lastmsg().
1376 #
1377 # The use-simple style is only available for the bzr backend.
1378 #
1379 # The default values for these in all contexts are:
1380 #   formats             " (%s)-[%b|%a]-"
1381 #   actionformats       " (%s)-[%b]-"
1382 #   branchformat        "%b:%r" (for bzr, svn and svk)
1383 #   nvcsformats         ""
1384 #   max-exports         2
1385 #   enable              true
1386 #   disable             (empty list)
1387 #   disable-patterns    (empty list)
1388 #   use-simple          false
1389 #   use-prompt-escapes  true
1390 #
1391 #
1392 # In normal formats and actionformats, the following replacements
1393 # are done:
1394 #   %s  - The vcs in use (git, hg, svn etc.)
1395 #   %b  - Information about the current branch.
1396 #   %a  - An identifier, that describes the action.
1397 #         Only makes sense in actionformats.
1398 #   %R  - base directory of the repository.
1399 #   %r  - repository name
1400 #         If %R is '/foo/bar/repoXY', %r is 'repoXY'.
1401 #   %S  - subdirectory within a repository. if $PWD is
1402 #         '/foo/bar/reposXY/beer/tasty', %S is 'beer/tasty'.
1403 #
1404 #
1405 # In branchformat these replacements are done:
1406 #   %b  - the branch name
1407 #   %r  - the current revision number
1408 #
1409 # Not all vcs backends have to support all replacements.
1410 # nvcsformat does not perform *any* replacements. It is just a string.
1411 #}}}
1412 #
1413 # ODDITIES:
1414 #{{{
1415 # If you want to use the %b (bold off) prompt expansion in 'formats', which
1416 # expands %b itself, use %%b. That will cause the vcs_info() expansion to
1417 # replace %%b with %b. So zsh's prompt expansion mechanism can handle it.
1418 # Similarly, to hand down %b from branchformat, use %%%%b. Sorry for this
1419 # inconvenience, but it cannot be easily avoided. Luckily we do not clash
1420 # with a lot of prompt expansions and this only needs to be done for those.
1421 # See 'man zshmisc' for details about EXPANSION OF PROMPT SEQUENCES.
1422 #}}}
1423 #
1424 # FUNCTION DESCRIPTIONS (public API):
1425 #{{{
1426 #   vcs_info()
1427 #       The main function, that runs all backends and assembles
1428 #       all data into ${VCS_INFO_message_*_}. This is the function
1429 #       you want to call from precmd() if you want to include
1430 #       up-to-date information in your prompt (see VARIABLE
1431 #       DESCRIPTION below).
1432 #
1433 #   vcs_info_printsys()
1434 #       Prints a list of all supported version control systems.
1435 #       Useful to find out possible contexts (and which of them are enabled)
1436 #       or values for the 'disable' style.
1437 #
1438 #   vcs_info_lastmsg()
1439 #       Outputs the last ${VCS_INFO_message_*_} value. Takes into account
1440 #       the value of the use-prompt-escapes style in ':vcs_info:formats'.
1441 #       It also only prints max-exports values.
1442 #
1443 # All functions named VCS_INFO_* are for internal use only.
1444 #}}}
1445 #
1446 # VARIABLE DESCRIPTION:
1447 #{{{
1448 #   ${VCS_INFO_message_N_}    (Note the trailing underscore)
1449 #       Where 'N' is an integer, eg: VCS_INFO_message_0_
1450 #       These variables are the storage for the informational message the
1451 #       last vcs_info() call has assembled. These are strongly connected
1452 #       to the formats, actionformats and nvcsformats styles described
1453 #       above. Those styles are lists. the first member of that list gets
1454 #       expanded into ${VCS_INFO_message_0_}, the second into
1455 #       ${VCS_INFO_message_1_} and the Nth into ${VCS_INFO_message_N-1_}.
1456 #       These parameters are exported into the environment.
1457 #       (See the max-exports style above.)
1458 #}}}
1459 #
1460 # EXAMPLES:
1461 #{{{
1462 #   Don't use vcs_info at all (even though it's in your prompt):
1463 #   % zstyle ':vcs_info:*' enable false
1464 #
1465 #   Disable the backends for bzr and svk:
1466 #   % zstyle ':vcs_info:*' disable bzr svk
1467 #
1468 #   Provide a special formats for git:
1469 #   % zstyle ':vcs_info:git:*' formats       ' GIT, BABY! [%b]'
1470 #   % zstyle ':vcs_info:git:*' actionformats ' GIT ACTION! [%b|%a]'
1471 #
1472 #   Use the quicker bzr backend (if you do, please report if it does
1473 #   the-right-thing[tm] - thanks):
1474 #   % zstyle ':vcs_info:bzr:*' use-simple true
1475 #
1476 #   Display the revision number in yellow for bzr and svn:
1477 #   % zstyle ':vcs_info:(svn|bzr):*' branchformat '%b%{'${fg[yellow]}'%}:%r'
1478 #
1479 # If you want colors, make sure you enclose the color codes in %{...%},
1480 # if you want to use the string provided by vcs_info() in prompts.
1481 #
1482 # Here is how to print the vcs infomation as a command:
1483 #   % alias vcsi='vcs_info command; vcs_info_lastmsg'
1484 #
1485 #   This way, you can even define different formats for output via
1486 #   vcs_info_lastmsg() in the ':vcs_info:command:*' namespace.
1487 #}}}
1488 #}}}
1489 # utilities
1490 VCS_INFO_adjust () { #{{{
1491     [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
1492     return 0
1493 }
1494 # }}}
1495 VCS_INFO_check_com () { #{{{
1496     (( ${+commands[$1]} )) && [[ -x ${commands[$1]} ]] && return 0
1497     return 1
1498 }
1499 # }}}
1500 VCS_INFO_formats () { # {{{
1501     setopt localoptions noksharrays
1502     local action=$1 branch=$2 base=$3
1503     local msg
1504     local -i i
1505
1506     if [[ -n ${action} ]] ; then
1507         zstyle -a ":vcs_info:${vcs}:${usercontext}" actionformats msgs
1508         (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b|%a]-'
1509     else
1510         zstyle -a ":vcs_info:${vcs}:${usercontext}" formats msgs
1511         (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b]-'
1512     fi
1513
1514     (( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=()
1515     for i in {1..${#msgs}} ; do
1516         zformat -f msg ${msgs[$i]}                      \
1517                         a:${action}                     \
1518                         b:${branch}                     \
1519                         r:${base:t}                     \
1520                         s:${vcs}                        \
1521                         R:${base}                       \
1522                         S:"$(VCS_INFO_reposub ${base})"
1523         msgs[$i]=${msg}
1524     done
1525     return 0
1526 }
1527 # }}}
1528 VCS_INFO_maxexports () { #{{{
1529     zstyle -s ":vcs_info:${vcs}:${usercontext}" "max-exports" maxexports || maxexports=2
1530     if [[ ${maxexports} != <-> ]] || (( maxexports < 1 )); then
1531         printf 'vcs_info(): expecting numeric arg >= 1 for max-exports (got %s).\n' ${maxexports}
1532         printf 'Defaulting to 2.\n'
1533         maxexports=2
1534     fi
1535 }
1536 # }}}
1537 VCS_INFO_nvcsformats () { #{{{
1538     setopt localoptions noksharrays
1539     local c v
1540
1541     if [[ $1 == 'preinit' ]] ; then
1542         c=default
1543         v=preinit
1544     fi
1545     zstyle -a ":vcs_info:${v:-$vcs}:${c:-$usercontext}" nvcsformats msgs
1546     (( ${#msgs} > maxexports )) && msgs[${maxexports},-1]=()
1547 }
1548 # }}}
1549 VCS_INFO_realpath () { #{{{
1550     # a portable 'readlink -f'
1551     # forcing a subshell, to ensure chpwd() is not removed
1552     # from the calling shell (if VCS_INFO_realpath() is called
1553     # manually).
1554     (
1555         (( ${+functions[chpwd]} )) && unfunction chpwd
1556         setopt chaselinks
1557         cd $1 2>/dev/null && pwd
1558     )
1559 }
1560 # }}}
1561 VCS_INFO_reposub () { #{{{
1562     setopt localoptions extendedglob
1563     local base=${1%%/##}
1564
1565     [[ ${PWD} == ${base}/* ]] || {
1566         printf '.'
1567         return 1
1568     }
1569     printf '%s' ${PWD#$base/}
1570     return 0
1571 }
1572 # }}}
1573 VCS_INFO_set () { #{{{
1574     setopt localoptions noksharrays
1575     local -i i j
1576
1577     if [[ $1 == '--clear' ]] ; then
1578         for i in {0..9} ; do
1579             unset VCS_INFO_message_${i}_
1580         done
1581     fi
1582     if [[ $1 == '--nvcs' ]] ; then
1583         [[ $2 == 'preinit' ]] && (( maxexports == 0 )) && (( maxexports = 1 ))
1584         for i in {0..$((maxexports - 1))} ; do
1585             typeset -gx VCS_INFO_message_${i}_=
1586         done
1587         VCS_INFO_nvcsformats $2
1588     fi
1589
1590     (( ${#msgs} - 1 < 0 )) && return 0
1591     for i in {0..$(( ${#msgs} - 1 ))} ; do
1592         (( j = i + 1 ))
1593         typeset -gx VCS_INFO_message_${i}_=${msgs[$j]}
1594     done
1595     return 0
1596 }
1597 # }}}
1598 # information gathering
1599 VCS_INFO_bzr_get_data () { # {{{
1600     setopt localoptions noksharrays
1601     local bzrbase bzrbr
1602     local -a bzrinfo
1603
1604     if zstyle -t ":vcs_info:${vcs}:${usercontext}" "use-simple" ; then
1605         bzrbase=${vcs_comm[basedir]}
1606         bzrinfo[2]=${bzrbase:t}
1607         if [[ -f ${bzrbase}/.bzr/branch/last-revision ]] ; then
1608             bzrinfo[1]=$(< ${bzrbase}/.bzr/branch/last-revision)
1609             bzrinfo[1]=${${bzrinfo[1]}%% *}
1610         fi
1611     else
1612         bzrbase=${${(M)${(f)"$( bzr info )"}:# ##branch\ root:*}/*: ##/}
1613         bzrinfo=( ${${${(M)${(f)"$( bzr version-info )"}:#(#s)(revno|branch-nick)*}/*: /}/*\//} )
1614         bzrbase="$(VCS_INFO_realpath ${bzrbase})"
1615     fi
1616
1617     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat bzrbr || bzrbr="%b:%r"
1618     zformat -f bzrbr "${bzrbr}" "b:${bzrinfo[2]}" "r:${bzrinfo[1]}"
1619     VCS_INFO_formats '' "${bzrbr}" "${bzrbase}"
1620     return 0
1621 }
1622 # }}}
1623 VCS_INFO_cdv_get_data () { # {{{
1624     local cdvbase
1625
1626     cdvbase=${vcs_comm[basedir]}
1627     VCS_INFO_formats '' "${cdvbase:t}" "${cdvbase}"
1628     return 0
1629 }
1630 # }}}
1631 VCS_INFO_cvs_get_data () { # {{{
1632     local cvsbranch cvsbase basename
1633
1634     cvsbase="."
1635     while [[ -d "${cvsbase}/../CVS" ]]; do
1636         cvsbase="${cvsbase}/.."
1637     done
1638     cvsbase="$(VCS_INFO_realpath ${cvsbase})"
1639     cvsbranch=$(< ./CVS/Repository)
1640     basename=${cvsbase:t}
1641     cvsbranch=${cvsbranch##${basename}/}
1642     [[ -z ${cvsbranch} ]] && cvsbranch=${basename}
1643     VCS_INFO_formats '' "${cvsbranch}" "${cvsbase}"
1644     return 0
1645 }
1646 # }}}
1647 VCS_INFO_darcs_get_data () { # {{{
1648     local darcsbase
1649
1650     darcsbase=${vcs_comm[basedir]}
1651     VCS_INFO_formats '' "${darcsbase:t}" "${darcsbase}"
1652     return 0
1653 }
1654 # }}}
1655 VCS_INFO_git_getaction () { #{{{
1656     local gitaction='' gitdir=$1
1657     local tmp
1658
1659     for tmp in "${gitdir}/rebase-apply" \
1660                "${gitdir}/rebase"       \
1661                "${gitdir}/../.dotest" ; do
1662         if [[ -d ${tmp} ]] ; then
1663             if   [[ -f "${tmp}/rebasing" ]] ; then
1664                 gitaction="rebase"
1665             elif [[ -f "${tmp}/applying" ]] ; then
1666                 gitaction="am"
1667             else
1668                 gitaction="am/rebase"
1669             fi
1670             printf '%s' ${gitaction}
1671             return 0
1672         fi
1673     done
1674
1675     for tmp in "${gitdir}/rebase-merge/interactive" \
1676                "${gitdir}/.dotest-merge/interactive" ; do
1677         if [[ -f "${tmp}" ]] ; then
1678             printf '%s' "rebase-i"
1679             return 0
1680         fi
1681     done
1682
1683     for tmp in "${gitdir}/rebase-merge" \
1684                "${gitdir}/.dotest-merge" ; do
1685         if [[ -d "${tmp}" ]] ; then
1686             printf '%s' "rebase-m"
1687             return 0
1688         fi
1689     done
1690
1691     if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1692         printf '%s' "merge"
1693         return 0
1694     fi
1695
1696     if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
1697         printf '%s' "bisect"
1698         return 0
1699     fi
1700     return 1
1701 }
1702 # }}}
1703 VCS_INFO_git_getbranch () { #{{{
1704     local gitbranch gitdir=$1
1705     local gitsymref='git symbolic-ref HEAD'
1706
1707     if    [[ -d "${gitdir}/rebase-apply" ]] \
1708        || [[ -d "${gitdir}/rebase" ]]       \
1709        || [[ -d "${gitdir}/../.dotest" ]]   \
1710        || [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1711         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1712         [[ -z ${gitbranch} ]] && [[ -r ${gitdir}/rebase-apply/head-name ]] \
1713             && gitbranch="$(< ${gitdir}/rebase-apply/head-name)"
1714
1715     elif   [[ -f "${gitdir}/rebase-merge/interactive" ]] \
1716         || [[ -d "${gitdir}/rebase-merge" ]] ; then
1717         gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
1718
1719     elif   [[ -f "${gitdir}/.dotest-merge/interactive" ]] \
1720         || [[ -d "${gitdir}/.dotest-merge" ]] ; then
1721         gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
1722
1723     else
1724         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1725
1726         if [[ $? -ne 0 ]] ; then
1727             gitbranch="$(git describe --exact-match HEAD 2>/dev/null)"
1728
1729             if [[ $? -ne 0 ]] ; then
1730                 gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
1731             fi
1732         fi
1733     fi
1734
1735     printf '%s' "${gitbranch##refs/heads/}"
1736     return 0
1737 }
1738 # }}}
1739 VCS_INFO_git_get_data () { # {{{
1740     setopt localoptions extendedglob
1741     local gitdir gitbase gitbranch gitaction
1742
1743     gitdir=${vcs_comm[gitdir]}
1744     gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"
1745
1746     if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
1747         return 1
1748     fi
1749
1750     VCS_INFO_adjust
1751     gitaction="$(VCS_INFO_git_getaction ${gitdir})"
1752     gitbase=${PWD%/${$( git rev-parse --show-prefix )%/##}}
1753     VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}"
1754     return 0
1755 }
1756 # }}}
1757 VCS_INFO_hg_get_data () { # {{{
1758     local hgbranch hgbase file
1759
1760     hgbase=${vcs_comm[basedir]}
1761
1762     file="${hgbase}/.hg/branch"
1763     if [[ -r ${file} ]] ; then
1764         hgbranch=$(< ${file})
1765     else
1766         hgbranch='default'
1767     fi
1768
1769     VCS_INFO_formats '' "${hgbranch}" "${hgbase}"
1770     return 0
1771 }
1772 # }}}
1773 VCS_INFO_mtn_get_data () { # {{{
1774     local mtnbranch mtnbase
1775
1776     mtnbase=${vcs_comm[basedir]}
1777     mtnbranch=${${(M)${(f)"$( mtn status )"}:#(#s)Current branch:*}/*: /}
1778     VCS_INFO_formats '' "${mtnbranch}" "${mtnbase}"
1779     return 0
1780 }
1781 # }}}
1782 VCS_INFO_svk_get_data () { # {{{
1783     local svkbranch svkbase
1784
1785     svkbase=${vcs_comm[basedir]}
1786     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat svkbranch || svkbranch="%b:%r"
1787     zformat -f svkbranch "${svkbranch}" "b:${vcs_comm[branch]}" "r:${vcs_comm[revision]}"
1788     VCS_INFO_formats '' "${svkbranch}" "${svkbase}"
1789     return 0
1790 }
1791 # }}}
1792 VCS_INFO_svn_get_data () { # {{{
1793     setopt localoptions noksharrays
1794     local svnbase svnbranch
1795     local -a svninfo
1796
1797     svnbase="."
1798     while [[ -d "${svnbase}/../.svn" ]]; do
1799         svnbase="${svnbase}/.."
1800     done
1801     svnbase="$(VCS_INFO_realpath ${svnbase})"
1802     svninfo=( ${${${(M)${(f)"$( svn info )"}:#(#s)(URL|Revision)*}/*: /}/*\//} )
1803
1804     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat svnbranch || svnbranch="%b:%r"
1805     zformat -f svnbranch "${svnbranch}" "b:${svninfo[1]}" "r:${svninfo[2]}"
1806     VCS_INFO_formats '' "${svnbranch}" "${svnbase}"
1807     return 0
1808 }
1809 # }}}
1810 VCS_INFO_tla_get_data () { # {{{
1811     local tlabase tlabranch
1812
1813     tlabase="$(VCS_INFO_realpath ${vcs_comm[basedir]})"
1814     # tree-id gives us something like 'foo@example.com/demo--1.0--patch-4', so:
1815     tlabranch=${${"$( tla tree-id )"}/*\//}
1816     VCS_INFO_formats '' "${tlabranch}" "${tlabase}"
1817     return 0
1818 }
1819 # }}}
1820 # detection
1821 VCS_INFO_detect_by_dir() { #{{{
1822     local dirname=$1
1823     local basedir="." realbasedir
1824
1825     realbasedir="$(VCS_INFO_realpath ${basedir})"
1826     while [[ ${realbasedir} != '/' ]]; do
1827         if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
1828             [[ -d ${basedir}/${dirname} ]] && \
1829             [[ -e ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
1830                 break
1831         else
1832             [[ -d ${basedir}/${dirname} ]] && break
1833         fi
1834
1835         basedir=${basedir}/..
1836         realbasedir="$(VCS_INFO_realpath ${basedir})"
1837     done
1838
1839     [[ ${realbasedir} == "/" ]] && return 1
1840     vcs_comm[basedir]=${realbasedir}
1841     return 0
1842 }
1843 # }}}
1844 VCS_INFO_bzr_detect() { #{{{
1845     VCS_INFO_check_com bzr || return 1
1846     vcs_comm[detect_need_file]=branch/format
1847     VCS_INFO_detect_by_dir '.bzr'
1848     return $?
1849 }
1850 # }}}
1851 VCS_INFO_cdv_detect() { #{{{
1852     VCS_INFO_check_com cdv || return 1
1853     vcs_comm[detect_need_file]=format
1854     VCS_INFO_detect_by_dir '.cdv'
1855     return $?
1856 }
1857 # }}}
1858 VCS_INFO_cvs_detect() { #{{{
1859     VCS_INFO_check_com svn || return 1
1860     [[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
1861     return 1
1862 }
1863 # }}}
1864 VCS_INFO_darcs_detect() { #{{{
1865     VCS_INFO_check_com darcs || return 1
1866     vcs_comm[detect_need_file]=format
1867     VCS_INFO_detect_by_dir '_darcs'
1868     return $?
1869 }
1870 # }}}
1871 VCS_INFO_git_detect() { #{{{
1872     if VCS_INFO_check_com git && git rev-parse --is-inside-work-tree &> /dev/null ; then
1873         vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
1874         if   [[ -d ${vcs_comm[gitdir]}/svn ]]             ; then vcs_comm[overwrite_name]='git-svn'
1875         elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
1876         return 0
1877     fi
1878     return 1
1879 }
1880 # }}}
1881 VCS_INFO_hg_detect() { #{{{
1882     VCS_INFO_check_com hg || return 1
1883     vcs_comm[detect_need_file]=store
1884     VCS_INFO_detect_by_dir '.hg'
1885     return $?
1886 }
1887 # }}}
1888 VCS_INFO_mtn_detect() { #{{{
1889     VCS_INFO_check_com mtn || return 1
1890     vcs_comm[detect_need_file]=revision
1891     VCS_INFO_detect_by_dir '_MTN'
1892     return $?
1893 }
1894 # }}}
1895 VCS_INFO_svk_detect() { #{{{
1896     setopt localoptions noksharrays extendedglob
1897     local -a info
1898     local -i fhash
1899     fhash=0
1900
1901     VCS_INFO_check_com svk || return 1
1902     [[ -f ~/.svk/config ]] || return 1
1903
1904     # This detection function is a bit different from the others.
1905     # We need to read svk's config file to detect a svk repository
1906     # in the first place. Therefore, we'll just proceed and read
1907     # the other information, too. This is more then any of the
1908     # other detections do but this takes only one file open for
1909     # svk at most. VCS_INFO_svk_get_data() get simpler, too. :-)
1910     while IFS= read -r line ; do
1911         if [[ -n ${vcs_comm[basedir]} ]] ; then
1912             line=${line## ##}
1913             [[ ${line} == depotpath:* ]] && vcs_comm[branch]=${line##*/}
1914             [[ ${line} == revision:* ]] && vcs_comm[revision]=${line##*[[:space:]]##}
1915             [[ -n ${vcs_comm[branch]} ]] && [[ -n ${vcs_comm[revision]} ]] && break
1916             continue
1917         fi
1918         (( fhash > 0 )) && [[ ${line} == '  '[^[:space:]]*:* ]] && break
1919         [[ ${line} == '  hash:'* ]] && fhash=1 && continue
1920         (( fhash == 0 )) && continue
1921         [[ ${PWD}/ == ${${line## ##}%:*}/* ]] && vcs_comm[basedir]=${${line## ##}%:*}
1922     done < ~/.svk/config
1923
1924     [[ -n ${vcs_comm[basedir]} ]]  && \
1925     [[ -n ${vcs_comm[branch]} ]]   && \
1926     [[ -n ${vcs_comm[revision]} ]] && return 0
1927     return 1
1928 }
1929 # }}}
1930 VCS_INFO_svn_detect() { #{{{
1931     VCS_INFO_check_com svn || return 1
1932     [[ -d ".svn" ]] && return 0
1933     return 1
1934 }
1935 # }}}
1936 VCS_INFO_tla_detect() { #{{{
1937     VCS_INFO_check_com tla || return 1
1938     vcs_comm[basedir]="$(tla tree-root 2> /dev/null)" && return 0
1939     return 1
1940 }
1941 # }}}
1942 # public API
1943 vcs_info_printsys () { # {{{
1944     vcs_info print_systems_
1945 }
1946 # }}}
1947 vcs_info_lastmsg () { # {{{
1948     local -i i
1949
1950     VCS_INFO_maxexports
1951     for i in {0..$((maxexports - 1))} ; do
1952         printf '$VCS_INFO_message_%d_: "' $i
1953         if zstyle -T ':vcs_info:formats:command' use-prompt-escapes ; then
1954             print -nP ${(P)${:-VCS_INFO_message_${i}_}}
1955         else
1956             print -n ${(P)${:-VCS_INFO_message_${i}_}}
1957         fi
1958         printf '"\n'
1959     done
1960 }
1961 # }}}
1962 vcs_info () { # {{{
1963     local pat
1964     local -i found
1965     local -a VCSs disabled dps
1966     local -x vcs usercontext
1967     local -ix maxexports
1968     local -ax msgs
1969     local -Ax vcs_comm
1970
1971     vcs="init"
1972     VCSs=(git hg bzr darcs svk mtn svn cvs cdv tla)
1973     case $1 in
1974         (print_systems_)
1975             zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable" disabled
1976             print -l '# list of supported version control backends:' \
1977                      '# disabled systems are prefixed by a hash sign (#)'
1978             for vcs in ${VCSs} ; do
1979                 [[ -n ${(M)disabled:#${vcs}} ]] && printf '#'
1980                 printf '%s\n' ${vcs}
1981             done
1982             print -l '# flavours (cannot be used in the disable style; they' \
1983                      '# are disabled with their master [git-svn -> git]):'   \
1984                      git-{p4,svn}
1985             return 0
1986             ;;
1987         ('')
1988             [[ -z ${usercontext} ]] && usercontext=default
1989             ;;
1990         (*) [[ -z ${usercontext} ]] && usercontext=$1
1991             ;;
1992     esac
1993
1994     zstyle -T ":vcs_info:${vcs}:${usercontext}" "enable" || {
1995         [[ -n ${VCS_INFO_message_0_} ]] && VCS_INFO_set --clear
1996         return 0
1997     }
1998     zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable" disabled
1999
2000     zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable-patterns" dps
2001     for pat in ${dps} ; do
2002         if [[ ${PWD} == ${~pat} ]] ; then
2003             [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --clear
2004             return 0
2005         fi
2006     done
2007
2008     VCS_INFO_maxexports
2009
2010     (( found = 0 ))
2011     for vcs in ${VCSs} ; do
2012         [[ -n ${(M)disabled:#${vcs}} ]] && continue
2013         vcs_comm=()
2014         VCS_INFO_${vcs}_detect && (( found = 1 )) && break
2015     done
2016
2017     (( found == 0 )) && {
2018         VCS_INFO_set --nvcs
2019         return 0
2020     }
2021
2022     VCS_INFO_${vcs}_get_data || {
2023         VCS_INFO_set --nvcs
2024         return 1
2025     }
2026
2027     VCS_INFO_set
2028     return 0
2029 }
2030
2031 VCS_INFO_set --nvcs preinit
2032 # }}}
2033
2034 # Change vcs_info formats for the grml prompt. The 2nd format sets up
2035 # $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title.
2036 # TODO: The included vcs_info() version still uses $VCS_INFO_message_N_.
2037 #       That needs to be the use of $VCS_INFO_message_N_ needs to be changed
2038 #       to $vcs_info_msg_N_ as soon as we use the included version.
2039 if [[ "$TERM" == dumb ]] ; then
2040     zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] " "zsh: %r"
2041     zstyle ':vcs_info:*' formats       "(%s%)-[%b] "    "zsh: %r"
2042 else
2043     # these are the same, just with a lot of colours:
2044     zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOUR} " \
2045                                        "zsh: %r"
2046     zstyle ':vcs_info:*' formats       "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOUR}%} " \
2047                                        "zsh: %r"
2048     zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r"
2049 fi
2050
2051 # }}}
2052
2053 # command not found handling {{{
2054
2055 (( ${COMMAND_NOT_FOUND} == 1 )) &&
2056 function command_not_found_handler() {
2057     setopt localoptions no_sh_wordsplit
2058     if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then
2059         ${GRML_ZSH_CNF_HANDLER} $1
2060     fi
2061     return 1
2062 }
2063
2064 # }}}
2065
2066 # {{{ set prompt
2067 if zrcautoload promptinit && promptinit 2>/dev/null ; then
2068     promptinit # people should be able to use their favourite prompt
2069 else
2070     print 'Notice: no promptinit available :('
2071 fi
2072
2073 setopt prompt_subst
2074
2075 # make sure to use right prompt only when not running a command
2076 is41 && setopt transient_rprompt
2077
2078 # TODO: revise all these NO* variables and especially their documentation
2079 #       in zsh-help() below.
2080 is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
2081     [[ $NOPRECMD -gt 0 ]] && return 0
2082     # update VCS information
2083     vcs_info
2084
2085     if [[ $TERM == screen* ]] ; then
2086         if [[ -n ${VCS_INFO_message_1_} ]] ; then
2087             print -nP "\ek${VCS_INFO_message_1_}\e\\"
2088         else
2089             print -nP "\ekzsh\e\\"
2090         fi
2091     fi
2092     # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
2093     if [[ $DONTSETRPROMPT -eq 0 ]] ; then
2094         if [[ $BATTERY -gt 0 ]] ; then
2095             # update battery (dropped into $PERCENT) information
2096             battery
2097             RPROMPT="%(?..:() ${PERCENT}"
2098         else
2099             RPROMPT="%(?..:() "
2100         fi
2101     fi
2102     # adjust title of xterm
2103     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
2104     [[ ${NOTITLE} -gt 0 ]] && return 0
2105     case $TERM in
2106         (xterm*|rxvt*)
2107             print -Pn "\e]0;%n@%m: %~\a"
2108             ;;
2109     esac
2110 }
2111
2112 # preexec() => a function running before every command
2113 is4 && [[ $NOPRECMD -eq 0 ]] && \
2114 preexec () {
2115     [[ $NOPRECMD -gt 0 ]] && return 0
2116 # set hostname if not running on host with name 'grml'
2117     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
2118        NAME="@$HOSTNAME"
2119     fi
2120 # get the name of the program currently running and hostname of local machine
2121 # set screen window title if running in a screen
2122     if [[ "$TERM" == screen* ]] ; then
2123         # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]}       # don't use hostname
2124         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname
2125         echo -ne "\ek$CMD\e\\"
2126     fi
2127 # adjust title of xterm
2128     [[ ${NOTITLE} -gt 0 ]] && return 0
2129     case $TERM in
2130         (xterm*|rxvt*)
2131             print -Pn "\e]0;%n@%m: $1\a"
2132             ;;
2133     esac
2134 }
2135
2136 EXITCODE="%(?..%?%1v )"
2137 PS2='\`%_> '      # secondary prompt, printed when the shell needs more information to complete a command.
2138 PS3='?# '         # selection prompt used within a select loop.
2139 PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
2140
2141 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
2142 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
2143     debian_chroot=$(cat /etc/debian_chroot)
2144 fi
2145
2146 # don't use colors on dumb terminals (like emacs):
2147 if [[ "$TERM" == dumb ]] ; then
2148     PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_0_}'"%# "
2149 else
2150     # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt
2151     # set variable identifying the chroot you work in (used in the prompt below)
2152     if [[ $GRMLPROMPT -gt 0 ]] ; then
2153         PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D
2154 ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
2155     else
2156         # This assembles the primary prompt string
2157         if (( EUID != 0 )); then
2158             PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_0_}'"%# "
2159         else
2160             PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_0_}'"%# "
2161         fi
2162     fi
2163 fi
2164
2165 # if we are inside a grml-chroot set a specific prompt theme
2166 if [[ -n "$GRML_CHROOT" ]] ; then
2167     PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# "
2168 fi
2169 # }}}
2170
2171 # {{{ 'hash' some often used directories
2172 #d# start
2173 hash -d deb=/var/cache/apt/archives
2174 hash -d doc=/usr/share/doc
2175 hash -d linux=/lib/modules/$(command uname -r)/build/
2176 hash -d log=/var/log
2177 hash -d slog=/var/log/syslog
2178 hash -d src=/usr/src
2179 hash -d templ=/usr/share/doc/grml-templates
2180 hash -d tt=/usr/share/doc/texttools-doc
2181 hash -d www=/var/www
2182 #d# end
2183 # }}}
2184
2185 # {{{ some aliases
2186 if check_com -c screen ; then
2187     if [[ $UID -eq 0 ]] ; then
2188         [[ -r /etc/grml/screenrc ]] && alias screen="${commands[screen]} -c /etc/grml/screenrc"
2189     elif [[ -r $HOME/.screenrc ]] ; then
2190         alias screen="${commands[screen]} -c $HOME/.screenrc"
2191     else
2192         [[ -r /etc/grml/screenrc_grml ]] && alias screen="${commands[screen]} -c /etc/grml/screenrc_grml"
2193     fi
2194 fi
2195
2196 # do we have GNU ls with color-support?
2197 if ls --help 2>/dev/null | grep -- --color= >/dev/null && [[ "$TERM" != dumb ]] ; then
2198     #a1# execute \kbd{@a@}:\quad ls with colors
2199     alias ls='ls -b -CF --color=auto'
2200     #a1# execute \kbd{@a@}:\quad list all files, with colors
2201     alias la='ls -la --color=auto'
2202     #a1# long colored list, without dotfiles (@a@)
2203     alias ll='ls -l --color=auto'
2204     #a1# long colored list, human readable sizes (@a@)
2205     alias lh='ls -hAl --color=auto'
2206     #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
2207     alias l='ls -lF --color=auto'
2208 else
2209     alias ls='ls -b -CF'
2210     alias la='ls -la'
2211     alias ll='ls -l'
2212     alias lh='ls -hAl'
2213     alias l='ls -lF'
2214 fi
2215
2216 alias mdstat='cat /proc/mdstat'
2217 alias ...='cd ../../'
2218
2219 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
2220 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
2221     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
2222 fi
2223
2224 alias cp='nocorrect cp'         # no spelling correction on cp
2225 alias mkdir='nocorrect mkdir'   # no spelling correction on mkdir
2226 alias mv='nocorrect mv'         # no spelling correction on mv
2227 alias rm='nocorrect rm'         # no spelling correction on rm
2228
2229 #a1# Execute \kbd{rmdir}
2230 alias rd='rmdir'
2231 #a1# Execute \kbd{rmdir}
2232 alias md='mkdir'
2233
2234 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
2235 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
2236 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
2237
2238 # make sure it is not assigned yet
2239 [[ -n ${aliases[utf2iso]} ]] && unalias utf2iso
2240 utf2iso() {
2241     if isutfenv ; then
2242         for ENV in $(env | command grep -i '.utf') ; do
2243             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
2244         done
2245     fi
2246 }
2247
2248 # make sure it is not assigned yet
2249 [[ -n ${aliases[iso2utf]} ]] && unalias iso2utf
2250 iso2utf() {
2251     if ! isutfenv ; then
2252         for ENV in $(env | command grep -i '\.iso') ; do
2253             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
2254         done
2255     fi
2256 }
2257
2258 # set up software synthesizer via speakup
2259 swspeak() {
2260     if [ -x /usr/sbin/swspeak-setup ] ; then
2261        setopt singlelinezle
2262        unsetopt prompt_cr
2263        export PS1="%m%# "
2264        /usr/sbin/swspeak-setup $@
2265      else # old version:
2266         aumix -w 90 -v 90 -p 90 -m 90
2267         if ! [[ -r /dev/softsynth ]] ; then
2268             flite -o play -t "Sorry, software synthesizer not available. Did you boot with swspeak bootoption?"
2269             return 1
2270         else
2271            setopt singlelinezle
2272            unsetopt prompt_cr
2273            export PS1="%m%# "
2274             nice -n -20 speechd-up
2275             sleep 2
2276             flite -o play -t "Finished setting up software synthesizer"
2277         fi
2278      fi
2279 }
2280
2281 # I like clean prompt, so provide simple way to get that
2282 check_com 0 || alias 0='return 0'
2283
2284 # for really lazy people like mika:
2285 check_com S &>/dev/null || alias S='screen'
2286 check_com s &>/dev/null || alias s='ssh'
2287
2288 # get top 10 shell commands:
2289 alias top10='print -l ? ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
2290
2291 # truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i'
2292 if check_com -c truecrypt ; then
2293     if isutfenv ; then
2294         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" '
2295     else
2296         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" '
2297     fi
2298 fi
2299
2300 #f1# Hints for the use of zsh on grml
2301 zsh-help() {
2302     print "$bg[white]$fg[black]
2303 zsh-help - hints for use of zsh on grml
2304 =======================================$reset_color"
2305
2306     print '
2307 Main configuration of zsh happens in /etc/zsh/zshrc.
2308 That file is part of the package grml-etc-core, if you want to
2309 use them on a non-grml-system just get the tar.gz from
2310 http://deb.grml.org/ or (preferably) get it from the git repository:
2311
2312   http://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
2313
2314 This version of grml'\''s zsh setup does not use skel/.zshrc anymore.
2315 The file is still there, but it is empty for backwards compatibility.
2316
2317 For your own changes use these two files:
2318     $HOME/.zshrc.pre
2319     $HOME/.zshrc.local
2320
2321 The former is sourced very early in our zshrc, the latter is sourced
2322 very lately.
2323
2324 System wide configuration without touching configuration files of grml
2325 can take place in /etc/zsh/zshrc.local.
2326
2327 Normally, the root user (EUID == 0) does not get the whole grml setup.
2328 If you want to force the whole setup for that user, too, set
2329 GRML_ALWAYS_LOAD_ALL=1 in .zshrc.pre in root'\''s home directory.
2330
2331 For information regarding zsh start at http://grml.org/zsh/
2332
2333 Take a look at grml'\''s zsh refcard:
2334 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
2335
2336 Check out the main zsh refcard:
2337 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
2338
2339 And of course visit the zsh-lovers:
2340 % man zsh-lovers
2341
2342 You can adjust some options through environment variables when
2343 invoking zsh without having to edit configuration files.
2344 Basically meant for bash users who are not used to the power of
2345 the zsh yet. :)
2346
2347   "NOCOR=1    zsh" => deactivate automatic correction
2348   "NOMENU=1   zsh" => do not use auto menu completion (note: use ctrl-d for completion instead!)
2349   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
2350   "NOTITLE=1  zsh" => disable setting the title of xterms without disabling
2351                       preexec() and precmd() completely
2352   "BATTERY=1  zsh" => activate battery status (via acpi) on right side of prompt
2353   "COMMAND_NOT_FOUND=1 zsh"
2354                    => Enable a handler if an external command was not found
2355                       The command called in the handler can be altered by setting
2356                       the GRML_ZSH_CNF_HANDLER variable, the default is:
2357                       "/usr/share/command-not-found/command-not-found"
2358
2359 A value greater than 0 is enables a feature; a value equal to zero
2360 disables it. If you like one or the other of these settings, you can
2361 add them to ~/.zshrc.pre to ensure they are set when sourcing grml'\''s
2362 zshrc.'
2363
2364     print "
2365 $bg[white]$fg[black]
2366 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
2367 Enjoy your grml system with the zsh!$reset_color"
2368 }
2369
2370 # debian stuff
2371 if [[ -r /etc/debian_version ]] ; then
2372     #a3# Execute \kbd{apt-cache search}
2373     alias acs='apt-cache search'
2374     #a3# Execute \kbd{apt-cache show}
2375     alias acsh='apt-cache show'
2376     #a3# Execute \kbd{apt-cache policy}
2377     alias acp='apt-cache policy'
2378     #a3# Execute \kbd{apt-get dist-upgrade}
2379     salias adg="apt-get dist-upgrade"
2380     #a3# Execute \kbd{apt-get install}
2381     salias agi="apt-get install"
2382     #a3# Execute \kbd{aptitude install}
2383     salias ati="aptitude install"
2384     #a3# Execute \kbd{apt-get upgrade}
2385     salias ag="apt-get upgrade"
2386     #a3# Execute \kbd{apt-get update}
2387     salias au="apt-get update"
2388     #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
2389     salias -a up="aptitude update ; aptitude safe-upgrade"
2390     #a3# Execute \kbd{dpkg-buildpackage}
2391     alias dbp='dpkg-buildpackage'
2392     #a3# Execute \kbd{grep-excuses}
2393     alias ge='grep-excuses'
2394
2395     # debian upgrade
2396     #f3# Execute \kbd{apt-get update \&\& }\\&\quad \kbd{apt-get dist-upgrade}
2397     upgrade() {
2398         if [[ -z "$1" ]] ; then
2399             $SUDO apt-get update
2400             $SUDO apt-get -u upgrade
2401         else
2402             ssh $1 $SUDO apt-get update
2403             # ask before the upgrade
2404             local dummy
2405             ssh $1 $SUDO apt-get --no-act upgrade
2406             echo -n 'Process the upgrade?'
2407             read -q dummy
2408             if [[ $dummy == "y" ]] ; then
2409                 ssh $1 $SUDO apt-get -u upgrade --yes
2410             fi
2411         fi
2412     }
2413
2414     # get a root shell as normal user in live-cd mode:
2415     if isgrmlcd && [[ $UID -ne 0 ]] ; then
2416        alias su="sudo su"
2417      fi
2418
2419     #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
2420     salias llog="$PAGER /var/log/syslog"     # take a look at the syslog
2421     #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
2422     salias tlog="tail -f /var/log/syslog"    # follow the syslog
2423 fi
2424
2425 # sort installed Debian-packages by size
2426 if check_com -c grep-status ; then
2427     #a3# List installed Debian-packages sorted by size
2428     alias debs-by-size='grep-status -FStatus -sInstalled-Size,Package -n "install ok installed" | paste -sd "  \n" | sort -rn'
2429 fi
2430
2431 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
2432 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord ; then
2433     if check_com -c wodim ; then
2434         alias cdrecord="echo 'cdrecord is not provided under its original name by Debian anymore.
2435 See #377109 in the BTS of Debian for more details.
2436
2437 Please use the wodim binary instead' ; return 1"
2438     fi
2439 fi
2440
2441 # get_tw_cli has been renamed into get_3ware
2442 if check_com -c get_3ware ; then
2443     get_tw_cli() {
2444         echo 'Warning: get_tw_cli has been renamed into get_3ware. Invoking get_3ware for you.'>&2
2445         get_3ware
2446     }
2447 fi
2448
2449 # I hate lacking backward compatibility, so provide an alternative therefore
2450 if ! check_com -c apache2-ssl-certificate ; then
2451
2452     apache2-ssl-certificate() {
2453
2454     print 'Debian does not ship apache2-ssl-certificate anymore (see #398520). :('
2455     print 'You might want to take a look at Debian the package ssl-cert as well.'
2456     print 'To generate a certificate for use with apache2 follow the instructions:'
2457
2458     echo '
2459
2460 export RANDFILE=/dev/random
2461 mkdir /etc/apache2/ssl/
2462 openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem
2463 chmod 600 /etc/apache2/ssl/apache.pem
2464
2465 Run "grml-tips ssl-certificate" if you need further instructions.
2466 '
2467     }
2468 fi
2469 # }}}
2470
2471 # {{{ Use hard limits, except for a smaller stack and no core dumps
2472 unlimit
2473 is425 && limit stack 8192
2474 isgrmlcd && limit core 0 # important for a live-cd-system
2475 limit -s
2476 # }}}
2477
2478 # {{{ completion system
2479
2480 # called later (via is4 && grmlcomp)
2481 # note: use 'zstyle' for getting current settings
2482 #         press ^Xh (control-x h) for getting tags in context; ^X? (control-x ?) to run complete_debug with trace output
2483 grmlcomp() {
2484     # TODO: This could use some additional information
2485
2486     # allow one error for every three characters typed in approximate completer
2487     zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
2488
2489     # don't complete backup files as executables
2490     zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
2491
2492     # start menu completion only if it could find no unambiguous initial string
2493     zstyle ':completion:*:correct:*'       insert-unambiguous true
2494     zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
2495     zstyle ':completion:*:correct:*'       original true
2496
2497     # activate color-completion
2498     zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}
2499
2500     # format on completion
2501     zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
2502
2503     # complete 'cd -<tab>' with menu
2504     zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
2505
2506     # insert all expansions for expand completer
2507     zstyle ':completion:*:expand:*'        tag-order all-expansions
2508     zstyle ':completion:*:history-words'   list false
2509
2510     # activate menu
2511     zstyle ':completion:*:history-words'   menu yes
2512
2513     # ignore duplicate entries
2514     zstyle ':completion:*:history-words'   remove-all-dups yes
2515     zstyle ':completion:*:history-words'   stop yes
2516
2517     # match uppercase from lowercase
2518     zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'
2519
2520     # separate matches into groups
2521     zstyle ':completion:*:matches'         group 'yes'
2522     zstyle ':completion:*'                 group-name ''
2523
2524     if [[ "$NOMENU" -eq 0 ]] ; then
2525         # if there are more than 5 options allow selecting from a menu
2526         zstyle ':completion:*'               menu select=5
2527     else
2528         # don't use any menus at all
2529         setopt no_auto_menu
2530     fi
2531
2532     zstyle ':completion:*:messages'        format '%d'
2533     zstyle ':completion:*:options'         auto-description '%d'
2534
2535     # describe options in full
2536     zstyle ':completion:*:options'         description 'yes'
2537
2538     # on processes completion complete all user processes
2539     zstyle ':completion:*:processes'       command 'ps -au$USER'
2540
2541     # offer indexes before parameters in subscripts
2542     zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
2543
2544     # provide verbose completion information
2545     zstyle ':completion:*'                 verbose true
2546
2547     # recent (as of Dec 2007) zsh versions are able to provide descriptions
2548     # for commands (read: 1st word in the line) that it will list for the user
2549     # to choose from. The following disables that, because it's not exactly fast.
2550     zstyle ':completion:*:-command-:*:'    verbose false
2551
2552     # set format for warnings
2553     zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
2554
2555     # define files to ignore for zcompile
2556     zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
2557     zstyle ':completion:correct:'          prompt 'correct to: %e'
2558
2559     # Ignore completion functions for commands you don't have:
2560     zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
2561
2562     # Provide more processes in completion of programs like killall:
2563     zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'
2564
2565     # complete manual by their section
2566     zstyle ':completion:*:manuals'    separate-sections true
2567     zstyle ':completion:*:manuals.*'  insert-sections   true
2568     zstyle ':completion:*:man:*'      menu yes select
2569
2570     # provide .. as a completion
2571     zstyle ':completion:*' special-dirs ..
2572
2573     # run rehash on completion so new installed program are found automatically:
2574     _force_rehash() {
2575         (( CURRENT == 1 )) && rehash
2576         return 1
2577     }
2578
2579     ## correction
2580     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
2581     if [[ "$NOCOR" -gt 0 ]] ; then
2582         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
2583         setopt nocorrect
2584     else
2585         # try to be smart about when to use what completer...
2586         setopt correct
2587         zstyle -e ':completion:*' completer '
2588             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
2589                 _last_try="$HISTNO$BUFFER$CURSOR"
2590                 reply=(_complete _match _ignored _prefix _files)
2591             else
2592                 if [[ $words[1] == (rm|mv) ]] ; then
2593                     reply=(_complete _files)
2594                 else
2595                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
2596                 fi
2597             fi'
2598     fi
2599
2600     # command for process lists, the local web server details and host completion
2601     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
2602
2603     # caching
2604     [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
2605                             zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
2606
2607     # host completion /* add brackets as vim can't parse zsh's complex cmdlines 8-) {{{ */
2608     if is42 ; then
2609         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
2610         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
2611     else
2612         _ssh_hosts=()
2613         _etc_hosts=()
2614     fi
2615     hosts=(
2616         $(hostname)
2617         "$_ssh_hosts[@]"
2618         "$_etc_hosts[@]"
2619         grml.org
2620         localhost
2621     )
2622     zstyle ':completion:*:hosts' hosts $hosts
2623     # TODO: so, why is this here?
2624     #  zstyle '*' hosts $hosts
2625
2626     # use generic completion system for programs not yet defined; (_gnu_generic works
2627     # with commands that provide a --help option with "standard" gnu-like output.)
2628     for compcom in cp deborphan df feh fetchipac head hnb ipacsum mv \
2629                    pal stow tail uname ; do
2630         [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
2631     done; unset compcom
2632
2633     # see upgrade function in this file
2634     compdef _hosts upgrade
2635 }
2636 # }}}
2637
2638 # {{{ grmlstuff
2639 grmlstuff() {
2640 # people should use 'grml-x'!
2641     startx() {
2642         if [[ -e /etc/X11/xorg.conf ]] ; then
2643             [[ -x /usr/bin/startx ]] && /usr/bin/startx "$@" || /usr/X11R6/bin/startx "$@"
2644         else
2645             echo "Please use the script \"grml-x\" for starting the X Window System
2646 because there does not exist /etc/X11/xorg.conf yet.
2647 If you want to use startx anyway please call \"/usr/bin/startx\"."
2648             return -1
2649         fi
2650     }
2651
2652     xinit() {
2653         if [[ -e /etc/X11/xorg.conf ]] ; then
2654             [[ -x /usr/bin/xinit ]] && /usr/bin/xinit || /usr/X11R6/bin/xinit
2655         else
2656             echo "Please use the script \"grml-x\" for starting the X Window System.
2657 because there does not exist /etc/X11/xorg.conf yet.
2658 If you want to use xinit anyway please call \"/usr/bin/xinit\"."
2659             return -1
2660         fi
2661     }
2662
2663     if check_com -c 915resolution ; then
2664         alias 855resolution='echo -e "Please use 915resolution as resolution modify tool for Intel graphic chipset."; return -1'
2665     fi
2666
2667     #a1# Output version of running grml
2668     alias grml-version='cat /etc/grml_version'
2669
2670     if check_com -c rebuildfstab ; then
2671         #a1# Rebuild /etc/fstab
2672         alias grml-rebuildfstab='rebuildfstab -v -r -config'
2673     fi
2674
2675     if check_com -c grml-debootstrap ; then
2676         alias debian2hd='print "Installing debian to harddisk is possible via using grml-debootstrap." ; return 1'
2677     fi
2678 }
2679 # }}}
2680
2681 # {{{ now run the functions
2682 isgrml && checkhome
2683 is4    && isgrml    && grmlstuff
2684 is4    && grmlcomp
2685 # }}}
2686
2687 # {{{ keephack
2688 is4 && xsource "/etc/zsh/keephack"
2689 # }}}
2690
2691 # {{{ wonderful idea of using "e" glob qualifier by Peter Stephenson
2692 # You use it as follows:
2693 # $ NTREF=/reference/file
2694 # $ ls -l *(e:nt:)
2695 # This lists all the files in the current directory newer than the reference file.
2696 # You can also specify the reference file inline; note quotes:
2697 # $ ls -l *(e:'nt ~/.zshenv':)
2698 is4 && nt() {
2699     if [[ -n $1 ]] ; then
2700         local NTREF=${~1}
2701     fi
2702     [[ $REPLY -nt $NTREF ]]
2703 }
2704 # }}}
2705
2706 # shell functions {{{
2707
2708 #f1# Provide csh compatibility
2709 setenv()  { typeset -x "${1}${1:+=}${(@)argv[2,$#]}" }  # csh compatibility
2710
2711 #f1# Reload an autoloadable function
2712 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2713
2714 #f1# Reload zsh setup
2715 reload() {
2716     if [[ "$#*" -eq 0 ]] ; then
2717         [[ -r ~/.zshrc ]] && . ~/.zshrc
2718     else
2719         local fn
2720         for fn in "$@"; do
2721             unfunction $fn
2722             autoload -U $fn
2723         done
2724     fi
2725 }
2726 compdef _functions reload freload
2727
2728 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
2729 sll() {
2730     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
2731     for i in "$@" ; do
2732         file=$i
2733         while [[ -h "$file" ]] ; do
2734             ls -l $file
2735             file=$(readlink "$file")
2736         done
2737     done
2738 }
2739
2740 # fast manual access
2741 if check_com qma ; then
2742     #f1# View the zsh manual
2743     manzsh()  { qma zshall "$1" }
2744     compdef _man qma
2745 else
2746     manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
2747 fi
2748
2749 if check_com -c $PAGER ; then
2750     #f1# View Debian's changelog of a given package
2751     dchange() {
2752         if [[ -r /usr/share/doc/${1}/changelog.Debian.gz ]] ; then
2753             $PAGER /usr/share/doc/${1}/changelog.Debian.gz
2754         elif [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
2755             $PAGER /usr/share/doc/${1}/changelog.gz
2756         else
2757             if check_com -c aptitude ; then
2758                 echo "No changelog for package $1 found, using aptitude to retrieve it."
2759                 if isgrml ; then
2760                     aptitude -t unstable changelog ${1}
2761                 else
2762                     aptitude changelog ${1}
2763                 fi
2764             else
2765                 echo "No changelog for package $1 found, sorry."
2766                 return 1
2767             fi
2768         fi
2769     }
2770     _dchange() { _files -W /usr/share/doc -/ }
2771     compdef _dchange dchange
2772
2773     #f1# View Debian's NEWS of a given package
2774     dnews() {
2775         if [[ -r /usr/share/doc/${1}/NEWS.Debian.gz ]] ; then
2776             $PAGER /usr/share/doc/${1}/NEWS.Debian.gz
2777         else
2778             if [[ -r /usr/share/doc/${1}/NEWS.gz ]] ; then
2779                 $PAGER /usr/share/doc/${1}/NEWS.gz
2780             else
2781                 echo "No NEWS file for package $1 found, sorry."
2782                 return 1
2783             fi
2784         fi
2785     }
2786     _dnews() { _files -W /usr/share/doc -/ }
2787     compdef _dnews dnews
2788
2789     #f1# View upstream's changelog of a given package
2790     uchange() {
2791         if [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
2792             $PAGER /usr/share/doc/${1}/changelog.gz
2793         else
2794             echo "No changelog for package $1 found, sorry."
2795             return 1
2796         fi
2797     }
2798     _uchange() { _files -W /usr/share/doc -/ }
2799     compdef _uchange uchange
2800 fi
2801
2802 # zsh profiling
2803 profile() {
2804     ZSH_PROFILE_RC=1 $SHELL "$@"
2805 }
2806
2807 #f1# Edit an alias via zle
2808 edalias() {
2809     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
2810 }
2811 compdef _aliases edalias
2812
2813 #f1# Edit a function via zle
2814 edfunc() {
2815     [[ -z "$1" ]] && { echo "Usage: edfun <function_to_edit>" ; return 1 } || zed -f "$1" ;
2816 }
2817 compdef _functions edfunc
2818
2819 # use it e.g. via 'Restart apache2'
2820 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
2821 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
2822 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
2823 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
2824 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
2825 if [[ -d /etc/init.d || -d /etc/service ]] ; then
2826     __start_stop() {
2827         local action_="${1:l}"  # e.g Start/Stop/Restart
2828         local service_="$2"
2829         local param_="$3"
2830
2831         local service_target_="$(readlink /etc/init.d/$service_)"
2832         if [[ $service_target_ == "/usr/bin/sv" ]]; then
2833             # runit
2834             case "${action_}" in
2835                 start) if [[ ! -e /etc/service/$service_ ]]; then
2836                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
2837                        else
2838                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2839                        fi ;;
2840                 # there is no reload in runits sysv emulation
2841                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
2842                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
2843             esac
2844         else
2845             # sysvinit
2846             $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2847         fi
2848     }
2849
2850     for i in Start Restart Stop Force-Reload Reload ; do
2851         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
2852     done
2853 fi
2854
2855 #f1# Provides useful information on globbing
2856 H-Glob() {
2857     echo -e "
2858     /      directories
2859     .      plain files
2860     @      symbolic links
2861     =      sockets
2862     p      named pipes (FIFOs)
2863     *      executable plain files (0100)
2864     %      device files (character or block special)
2865     %b     block special files
2866     %c     character special files
2867     r      owner-readable files (0400)
2868     w      owner-writable files (0200)
2869     x      owner-executable files (0100)
2870     A      group-readable files (0040)
2871     I      group-writable files (0020)
2872     E      group-executable files (0010)
2873     R      world-readable files (0004)
2874     W      world-writable files (0002)
2875     X      world-executable files (0001)
2876     s      setuid files (04000)
2877     S      setgid files (02000)
2878     t      files with the sticky bit (01000)
2879
2880   print *(m-1)          # Files modified up to a day ago
2881   print *(a1)           # Files accessed a day ago
2882   print *(@)            # Just symlinks
2883   print *(Lk+50)        # Files bigger than 50 kilobytes
2884   print *(Lk-50)        # Files smaller than 50 kilobytes
2885   print **/*.c          # All *.c files recursively starting in \$PWD
2886   print **/*.c~file.c   # Same as above, but excluding 'file.c'
2887   print (foo|bar).*     # Files starting with 'foo' or 'bar'
2888   print *~*.*           # All Files that do not contain a dot
2889   chmod 644 *(.^x)      # make all plain non-executable files publically readable
2890   print -l *(.c|.h)     # Lists *.c and *.h
2891   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
2892   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
2893 }
2894 alias help-zshglob=H-Glob
2895
2896 check_com -c qma && alias ?='qma zshall'
2897
2898 # grep for running process, like: 'any vim'
2899 any() {
2900     if [[ -z "$1" ]] ; then
2901         echo "any - grep for process(es) by keyword" >&2
2902         echo "Usage: any <keyword>" >&2 ; return 1
2903     else
2904         local STRING=$1
2905         local LENGTH=$(expr length $STRING)
2906         local FIRSCHAR=$(echo $(expr substr $STRING 1 1))
2907         local REST=$(echo $(expr substr $STRING 2 $LENGTH))
2908         ps xauwww| grep "[$FIRSCHAR]$REST"
2909     fi
2910 }
2911
2912 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
2913 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
2914 [[ -r /proc/1/maps ]] && \
2915 deswap() {
2916     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
2917     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
2918     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
2919 }
2920
2921 # print hex value of a number
2922 hex() {
2923     [[ -n "$1" ]] && printf "%x\n" $1 || { print 'Usage: hex <number-to-convert>' ; return 1 }
2924 }
2925
2926 # calculate (or eval at all ;-)) with perl => p[erl-]eval
2927 # hint: also take a look at zcalc -> 'autoload zcalc' -> 'man zshmodules | less -p MATHFUNC'
2928 peval() {
2929     [[ -n "$1" ]] && CALC="$*" || print "Usage: calc [expression]"
2930     perl -e "print eval($CALC),\"\n\";"
2931 }
2932 functions peval &>/dev/null && alias calc=peval
2933
2934 # brltty seems to have problems with utf8 environment and/or font Uni3-Terminus16 under
2935 # certain circumstances, so work around it, no matter which environment we have
2936 brltty() {
2937     if [[ -z "$DISPLAY" ]] ; then
2938         consolechars -f /usr/share/consolefonts/default8x16.psf.gz
2939         command brltty "$@"
2940     else
2941         command brltty "$@"
2942     fi
2943 }
2944
2945 # just press 'asdf' keys to toggle between dvorak and us keyboard layout
2946 aoeu() {
2947     echo -n 'Switching to us keyboard layout: '
2948     [[ -z "$DISPLAY" ]] && $SUDO loadkeys us &>/dev/null || setxkbmap us &>/dev/null
2949     echo 'Done'
2950 }
2951 asdf() {
2952     echo -n 'Switching to dvorak keyboard layout: '
2953     [[ -z "$DISPLAY" ]] && $SUDO loadkeys dvorak &>/dev/null || setxkbmap dvorak &>/dev/null
2954     echo 'Done'
2955 }
2956 # just press 'asdf' key to toggle from neon layout to us keyboard layout
2957 uiae() {
2958     echo -n 'Switching to us keyboard layout: '
2959     setxkbmap us && echo 'Done' || echo 'Failed'
2960 }
2961
2962 # set up an ipv6 tunnel
2963 ipv6-tunnel() {
2964     case $1 in
2965         start)
2966             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2967                 print 'ipv6 tunnel already set up, nothing to be done.'
2968                 print 'execute: "ifconfig sit1 down ; ifconfig sit0 down" to remove ipv6-tunnel.' ; return 1
2969             else
2970                 [[ -n "$PUBLIC_IP" ]] || \
2971                     local PUBLIC_IP=$(ifconfig $(route -n | awk '/^0\.0\.0\.0/{print $8; exit}') | \
2972                                       awk '/inet addr:/ {print $2}' | tr -d 'addr:')
2973
2974                 [[ -n "$PUBLIC_IP" ]] || { print 'No $PUBLIC_IP set and could not determine default one.' ; return 1 }
2975                 local IPV6ADDR=$(printf "2002:%02x%02x:%02x%02x:1::1" $(print ${PUBLIC_IP//./ }))
2976                 print -n "Setting up ipv6 tunnel $IPV6ADDR via ${PUBLIC_IP}: "
2977                 ifconfig sit0 tunnel ::192.88.99.1 up
2978                 ifconfig sit1 add "$IPV6ADDR" && print done || print failed
2979             fi
2980             ;;
2981         status)
2982             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2983                 print 'ipv6 tunnel available' ; return 0
2984             else
2985                 print 'ipv6 tunnel not available' ; return 1
2986             fi
2987             ;;
2988         stop)
2989             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2990                 print -n 'Stopping ipv6 tunnel (sit0 + sit1): '
2991                 ifconfig sit1 down ; ifconfig sit0 down && print done || print failed
2992             else
2993                 print 'No ipv6 tunnel found, nothing to be done.' ; return 1
2994             fi
2995             ;;
2996         *)
2997             print "Usage: ipv6-tunnel [start|stop|status]">&2 ; return 1
2998             ;;
2999     esac
3000 }
3001
3002 # run dhclient for wireless device
3003 iwclient() {
3004     salias dhclient "$(wavemon -d | awk '/device/{print $2}')"
3005 }
3006
3007 # spawn a minimally set up ksh - useful if you want to umount /usr/.
3008 minimal-shell() {
3009     exec env -i ENV="/etc/minimal-shellrc" HOME="$HOME" TERM="$TERM" ksh
3010 }
3011
3012 # a wrapper for vim, that deals with title setting
3013 #   VIM_OPTIONS
3014 #       set this array to a set of options to vim you always want
3015 #       to have set when calling vim (in .zshrc.local), like:
3016 #           VIM_OPTIONS=( -p )
3017 #       This will cause vim to send every file given on the
3018 #       commandline to be send to it's own tab (needs vim7).
3019 vim() {
3020     VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
3021 }
3022
3023 # make a backup of a file
3024 bk() {
3025     cp -a "$1" "${1}_$(date --iso-8601=seconds)"
3026 }
3027
3028 #f1# grep for patterns in grml's zsh setup
3029 zg() {
3030 #{{{
3031     LANG=C perl -e '
3032
3033 sub usage {
3034     print "usage: zg -[anr] <pattern>\n";
3035     print " Search for patterns in grml'\''s zshrc.\n";
3036     print " zg takes no or exactly one option plus a non empty pattern.\n\n";
3037     print "   options:\n";
3038     print "     --  no options (use if your pattern starts in with a dash.\n";
3039     print "     -a  search for the pattern in all code regions\n";
3040     print "     -n  search for the pattern in non-root code only\n";
3041     print "     -r  search in code for everyone (also root) only\n\n";
3042     print "   The default is -a for non-root users and -r for root.\n\n";
3043     print " If you installed the zshrc to a non-default locations (ie *NOT*\n";
3044     print " in /etc/zsh/zshrc) do: export GRML_ZSHRC=\$HOME/.zshrc\n";
3045     print " ...in case you copied the file to that location.\n\n";
3046     exit 1;
3047 }
3048
3049 if ($ENV{GRML_ZSHRC} ne "") {
3050     $RC = $ENV{GRML_ZSHRC};
3051 } else {
3052     $RC = "/etc/zsh/zshrc";
3053 }
3054
3055 usage if ($#ARGV < 0 || $#ARGV > 1);
3056 if ($> == 0) { $mode = "allonly"; }
3057 else { $mode = "all"; }
3058
3059 $opt = $ARGV[0];
3060 if ($opt eq "--")     { shift; }
3061 elsif ($opt eq "-a")  { $mode = "all"; shift; }
3062 elsif ($opt eq "-n")  { $mode = "nonroot"; shift; }
3063 elsif ($opt eq "-r" ) { $mode = "allonly"; shift; }
3064 elsif ($opt =~ m/^-/ || $#ARGV > 0) { usage(); }
3065
3066 $pattern = $ARGV[0];
3067 usage() if ($pattern eq "");
3068
3069 open FH, "<$RC" or die "zg: Could not open $RC: $!\n";
3070 while ($line = <FH>) {
3071     chomp $line;
3072     if ($line =~ m/^#:grep:marker:for:mika:/) { $markerfound = 1; next; }
3073     next if ($mode eq "nonroot" && markerfound == 0);
3074     break if ($mode eq "allonly" && markerfound == 1);
3075     print $line, "\n" if ($line =~ /$pattern/);
3076 }
3077 close FH;
3078 exit 0;
3079
3080     ' -- "$@"
3081 #}}}
3082     return $?
3083 }
3084
3085 # }}}
3086
3087 # {{{ make sure our environment is clean regarding colors
3088 for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
3089 # }}}
3090
3091 # "persistent history" {{{
3092 # just write important commands you always need to ~/.important_commands
3093 if [[ -r ~/.important_commands ]] ; then
3094     fc -R ~/.important_commands
3095 fi
3096 # }}}
3097
3098 #:grep:marker:for:mika: :-)
3099 ### non-root (EUID != 0) code below
3100 ###
3101
3102 if (( GRML_ALWAYS_LOAD_ALL == 0 )) && (( $EUID == 0 )) ; then
3103     zrclocal
3104     return 0
3105 fi
3106
3107
3108 # variables {{{
3109
3110 # set terminal property (used e.g. by msgid-chooser)
3111 export COLORTERM="yes"
3112
3113 # set default browser
3114 if [[ -z "$BROWSER" ]] ; then
3115     if [[ -n "$DISPLAY" ]] ; then
3116         #v# If X11 is running
3117         check_com -c firefox && export BROWSER=firefox
3118     else
3119         #v# If no X11 is running
3120         check_com -c w3m && export BROWSER=w3m
3121     fi
3122 fi
3123
3124 #m# v QTDIR \kbd{/usr/share/qt[34]}\quad [for non-root only]
3125 [[ -d /usr/share/qt3 ]] && export QTDIR=/usr/share/qt3
3126 [[ -d /usr/share/qt4 ]] && export QTDIR=/usr/share/qt4
3127
3128 # support running 'jikes *.java && jamvm HelloWorld' OOTB:
3129 #v# [for non-root only]
3130 [[ -f /usr/share/classpath/glibj.zip ]] && export JIKESPATH=/usr/share/classpath/glibj.zip
3131 # }}}
3132
3133 # aliases {{{
3134
3135 # Xterm resizing-fu.
3136 # Based on http://svn.kitenet.net/trunk/home-full/.zshrc?rev=11710&view=log (by Joey Hess)
3137 alias hide='echo -en "\033]50;nil2\007"'
3138 alias tiny='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"'
3139 alias small='echo -en "\033]50;6x10\007"'
3140 alias medium='echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"'
3141 alias default='echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"'
3142 alias large='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"'
3143 alias huge='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"'
3144 alias smartfont='echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"'
3145 alias semifont='echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"'
3146
3147 # general
3148 #a2# Execute \kbd{du -sch}
3149 alias da='du -sch'
3150 #a2# Execute \kbd{jobs -l}
3151 alias j='jobs -l'
3152
3153 # compile stuff
3154 #a2# Execute \kbd{./configure}
3155 alias CO="./configure"
3156 #a2# Execute \kbd{./configure --help}
3157 alias CH="./configure --help"
3158
3159 # arch/tla stuff
3160 if check_com -c tla ; then
3161     #a2# Execute \kbd{tla what-changed --diffs | less}
3162     alias tdi='tla what-changed --diffs | less'
3163     #a2# Execute \kbd{tla-buildpackage}
3164     alias tbp='tla-buildpackage'
3165     #a2# Execute \kbd{tla archive-mirror}
3166     alias tmi='tla archive-mirror'
3167     #a2# Execute \kbd{tla commit}
3168     alias tco='tla commit'
3169     #a2# Execute \kbd{tla star-merge}
3170     alias tme='tla star-merge'
3171 fi
3172
3173 # listing stuff
3174 #a2# Execute \kbd{ls -lSrah}
3175 alias dir="ls -lSrah"
3176 #a2# Only show dot-directories
3177 alias lad='ls -d .*(/)'                # only show dot-directories
3178 #a2# Only show dot-files
3179 alias lsa='ls -a .*(.)'                # only show dot-files
3180 #a2# Only files with setgid/setuid/sticky flag
3181 alias lss='ls -l *(s,S,t)'             # only files with setgid/setuid/sticky flag
3182 #a2# Only show 1st ten symlinks
3183 alias lsl='ls -l *(@[1,10])'           # only symlinks
3184 #a2# Display only executables
3185 alias lsx='ls -l *(*[1,10])'           # only executables
3186 #a2# Display world-{readable,writable,executable} files
3187 alias lsw='ls -ld *(R,W,X.^ND/)'       # world-{readable,writable,executable} files
3188 #a2# Display the ten biggest files
3189 alias lsbig="ls -flh *(.OL[1,10])"     # display the biggest files
3190 #a2# Only show directories
3191 alias lsd='ls -d *(/)'                 # only show directories
3192 #a2# Only show empty directories
3193 alias lse='ls -d *(/^F)'               # only show empty directories
3194 #a2# Display the ten newest files
3195 alias lsnew="ls -rl *(D.om[1,10])"     # display the newest files
3196 #a2# Display the ten oldest files
3197 alias lsold="ls -rtlh *(D.om[1,10])"   # display the oldest files
3198 #a2# Display the ten smallest files
3199 alias lssmall="ls -Srl *(.oL[1,10])"   # display the smallest files
3200
3201 # chmod
3202 #a2# Execute \kbd{chmod 600}
3203 alias rw-='chmod 600'
3204 #a2# Execute \kbd{chmod 700}
3205 alias rwx='chmod 700'
3206 #m# a2 r-{}- Execute \kbd{chmod 644}
3207 alias r--='chmod 644'
3208 #a2# Execute \kbd{chmod 755}
3209 alias r-x='chmod 755'
3210
3211 # some useful aliases
3212 #a2# Execute \kbd{mkdir -o}
3213 alias md='mkdir -p'
3214
3215 check_com -c ipython && alias ips='ipython -p sh'
3216
3217 # console stuff
3218 #a2# Execute \kbd{mplayer -vo fbdev}
3219 alias cmplayer='mplayer -vo fbdev'
3220 #a2# Execute \kbd{mplayer -vo fbdev -fs -zoom}
3221 alias fbmplayer='mplayer -vo fbdev -fs -zoom'
3222 #a2# Execute \kbd{links2 -driver fb}
3223 alias fblinks='links2 -driver fb'
3224
3225 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3226 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3227 alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3228
3229 # simple webserver
3230 check_com -c python && alias http="python -m SimpleHTTPServer"
3231
3232 # Use 'g' instead of 'git':
3233 check_com g || alias g='git'
3234
3235 # check whether Debian's package management (dpkg) is running
3236 if check_com salias ; then
3237     #a2# Check whether a dpkg instance is currently running
3238     salias check_dpkg_running="dpkg_running"
3239 fi
3240
3241 # work around non utf8 capable software in utf environment via $LANG and luit
3242 if check_com isutfenv && check_com luit ; then
3243     if check_com -c mrxvt ; then
3244         isutfenv && [[ -n "$LANG" ]] && \
3245             alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
3246     fi
3247
3248     if check_com -c aterm ; then
3249         isutfenv && [[ -n "$LANG" ]] && \
3250             alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
3251     fi
3252
3253     if check_com -c centericq ; then
3254         isutfenv && [[ -n "$LANG" ]] && \
3255             alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
3256     fi
3257 fi
3258 # }}}
3259
3260 # useful functions {{{
3261
3262 # searching
3263 #f4# Search for newspostings from authors
3264 agoogle() { ${=BROWSER} "http://groups.google.com/groups?as_uauthors=$*" ; }
3265 #f4# Search Debian Bug Tracking System
3266 debbug()  {
3267     setopt localoptions extendedglob
3268     if [[ $# -eq 1 ]]; then
3269         case "$1" in
3270             ([0-9]##)
3271             ${=BROWSER} "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=$1"
3272             ;;
3273             (*@*)
3274             ${=BROWSER} "http://bugs.debian.org/cgi-bin/pkgreport.cgi?submitter=$1"
3275             ;;
3276             (*)
3277             ${=BROWSER} "http://bugs.debian.org/$*"
3278             ;;
3279         esac
3280     else
3281         print "$0 needs one argument"
3282         return 1
3283     fi
3284 }
3285 #f4# Search Debian Bug Tracking System in mbox format
3286 debbugm() { bts show --mbox $1 } # provide bugnummer as "$1"
3287 #f4# Search DMOZ
3288 dmoz()    { ${=BROWSER} http://search.dmoz.org/cgi-bin/search\?search=${1// /_} }
3289 #f4# Search German   Wiktionary
3290 dwicti()  { ${=BROWSER} http://de.wiktionary.org/wiki/${(C)1// /_} }
3291 #f4# Search English  Wiktionary
3292 ewicti()  { ${=BROWSER} http://en.wiktionary.org/wiki/${(C)1// /_} }
3293 #f4# Search Google Groups
3294 ggogle()  { ${=BROWSER} "http://groups.google.com/groups?q=$*" }
3295 #f4# Search Google
3296 google()  { ${=BROWSER} "http://www.google.com/search?&num=100&q=$*" }
3297 #f4# Search Google Groups for MsgID
3298 mggogle() { ${=BROWSER} "http://groups.google.com/groups?selm=$*" }
3299 #f4# Search Netcraft
3300 netcraft(){ ${=BROWSER} "http://toolbar.netcraft.com/site_report?url=$1" }
3301 #f4# Use German Wikipedia's full text search
3302 swiki()   { ${=BROWSER} http://de.wikipedia.org/wiki/Spezial:Search/${(C)1} }
3303 #f4# search \kbd{dict.leo.org}
3304 oleo()    { ${=BROWSER} "http://dict.leo.org/?search=$*" }
3305 #f4# Search German   Wikipedia
3306 wikide()  { ${=BROWSER} http://de.wikipedia.org/wiki/"${(C)*}" }
3307 #f4# Search English  Wikipedia
3308 wikien()  { ${=BROWSER} http://en.wikipedia.org/wiki/"${(C)*}" }
3309 #f4# Search official debs
3310 wodeb()   { ${=BROWSER} "http://packages.debian.org/search?keywords=$1&searchon=contents&suite=${2:=unstable}&section=all" }
3311
3312 #m# f4 gex() Exact search via Google
3313 check_com google && gex () { google "\"[ $1]\" $*" } # exact search at google
3314
3315 # misc
3316 #f5# Backup \kbd{file {\rm to} file\_timestamp}
3317 bk()      { cp -b ${1} ${1}_`date --iso-8601=m` }
3318 #f5# Copied diff
3319 cdiff()   { diff -crd "$*" | egrep -v "^Only in |^Binary files " }
3320 #f5# cd to directoy and list files
3321 cl()      { cd $1 && ls -a }        # cd && ls
3322 #f5# Cvs add
3323 cvsa()    { cvs add $* && cvs com -m 'initial checkin' $* }
3324 #f5# Cvs diff
3325 cvsd()    { cvs diff -N $* |& $PAGER }
3326 #f5# Cvs log
3327 cvsl()    { cvs log $* |& $PAGER }
3328 #f5# Cvs update
3329 cvsq()    { cvs -nq update }
3330 #f5# Rcs2log
3331 cvsr()    { rcs2log $* | $PAGER }
3332 #f5# Cvs status
3333 cvss()    { cvs status -v $* }
3334 #f5# Disassemble source files using gcc and as
3335 disassemble(){ gcc -pipe -S -o - -O -g $* | as -aldh -o /dev/null }
3336 #f5# Firefox remote control - open given URL
3337 fir()     { firefox -a firefox -remote "openURL($1)" }
3338 #f5# Create Directoy and \kbd{cd} to it
3339 mcd()     { mkdir -p "$@"; cd "$@" } # mkdir && cd
3340 #f5# Unified diff to timestamped outputfile
3341 mdiff()   { diff -udrP "$1" "$2" > diff.`date "+%Y-%m-%d"`."$1" }
3342 #f5# Memory overview
3343 memusage(){ ps aux | awk '{if (NR > 1) print $5; if (NR > 2) print "+"} END { print "p" }' | dc }
3344 #f5# Show contents of tar file
3345 shtar()   { gunzip -c $1 | tar -tf - -- | $PAGER }
3346 #f5# Show contents of tgz file
3347 shtgz()   { tar -ztf $1 | $PAGER }
3348 #f5# Show contents of zip file
3349 shzip()   { unzip -l $1 | $PAGER }
3350 #f5# Greps signature from file
3351 sig()     { agrep -d '^-- $' "$*" ~/.Signature }
3352 #f5# Unified diff
3353 udiff()   { diff -urd $* | egrep -v "^Only in |^Binary files " }
3354 #f5# (Mis)use \kbd{vim} as \kbd{less}
3355 viless()  { vim --cmd 'let no_plugin_maps = 1' -c "so \$VIMRUNTIME/macros/less.vim" "${@:--}" }
3356
3357 # download video from youtube
3358 ytdl() {
3359     if ! [[ -n "$2" ]] ; then
3360         print "Usage: ydtl http://youtube.com/watch?v=.... outputfile.flv">&2
3361         return 1
3362     else
3363         wget -O${2} "http://youtube.com/get_video?"${${${"$(wget -o/dev/null -O- "${1}" | grep -e watch_fullscreen)"}##*watch_fullscreen\?}%%\&fs=*}
3364     fi
3365 }
3366
3367 # Function Usage: uopen $URL/$file
3368 #f5# Download a file and display it locally
3369 uopen() {
3370     if ! [[ -n "$1" ]] ; then
3371         print "Usage: uopen \$URL/\$file">&2
3372         return 1
3373     else
3374         FILE=$1
3375         MIME=$(curl --head $FILE | grep Content-Type | cut -d ' ' -f 2 | cut -d\; -f 1)
3376         MIME=${MIME%$'\r'}
3377         curl $FILE | see ${MIME}:-
3378     fi
3379 }
3380
3381 # Function Usage: doc packagename
3382 #f5# \kbd{cd} to /usr/share/doc/\textit{package}
3383 doc() { cd /usr/share/doc/$1 && ls }
3384 _doc() { _files -W /usr/share/doc -/ }
3385 check_com compdef && compdef _doc doc
3386
3387 #f5# Make screenshot
3388 sshot() {
3389     [[ ! -d ~/shots  ]] && mkdir ~/shots
3390     #cd ~/shots ; sleep 5 ; import -window root -depth 8 -quality 80 `date "+%Y-%m-%d--%H:%M:%S"`.png
3391     cd ~/shots ; sleep 5; import -window root shot_`date --iso-8601=m`.jpg
3392 }
3393
3394 # list images only
3395 limg() {
3396     local -a images
3397     images=( *.{jpg,gif,png}(.N) )
3398
3399     if [[ $#images -eq 0 ]] ; then
3400         print "No image files found"
3401     else
3402         ls "$@" "$images[@]"
3403     fi
3404 }
3405
3406 #f5# Create PDF file from source code
3407 makereadable() {
3408     output=$1
3409     shift
3410     a2ps --medium A4dj -E -o $output $*
3411     ps2pdf $output
3412 }
3413
3414 # zsh with perl-regex - use it e.g. via:
3415 # regcheck '\s\d\.\d{3}\.\d{3} Euro' ' 1.000.000 Euro'
3416 #f5# Checks whether a regex matches or not.\\&\quad Example: \kbd{regcheck '.\{3\} EUR' '500 EUR'}
3417 regcheck() {
3418     zmodload -i zsh/pcre
3419     pcre_compile $1 && \
3420     pcre_match $2 && echo "regex matches" || echo "regex does not match"
3421 }
3422
3423 #f5# List files which have been modified within the last {\it n} days
3424 new() { print -l *(m-$1) }
3425
3426 #f5# Grep in history
3427 greph() { history 0 | grep $1 }
3428 # use colors when GNU grep with color-support
3429 #a2# Execute \kbd{grep -{}-color=auto}
3430 (grep --help 2>/dev/null |grep -- --color) >/dev/null && alias grep='grep --color=auto'
3431 #a2# Execute \kbd{grep -i -{}-color=auto}
3432 alias GREP='grep -i --color=auto'
3433
3434 #f5# Watch manpages in a stretched style
3435 man2() { PAGER='dash -c "sed G | /usr/bin/less"' command man "$@" ; }
3436
3437 # d():Copyright 2005 Nikolai Weibull <nikolai@bitwi.se>
3438 # note: option AUTO_PUSHD has to be set
3439 #f5# Jump between directories
3440 d() {
3441     emulate -L zsh
3442     autoload -U colors
3443     local color=$fg_bold[blue]
3444     integer i=0
3445     dirs -p | while read dir; do
3446         local num="${$(printf "%-4d " $i)/ /.}"
3447         printf " %s  $color%s$reset_color\n" $num $dir
3448         (( i++ ))
3449     done
3450     integer dir=-1
3451     read -r 'dir?Jump to directory: ' || return
3452     (( dir == -1 )) && return
3453     if (( dir < 0 || dir >= i )); then
3454         echo d: no such directory stack entry: $dir
3455         return 1
3456     fi
3457     cd ~$dir
3458 }
3459
3460 # usage example: 'lcheck strcpy'
3461 #f5# Find out which libs define a symbol
3462 lcheck() {
3463     if [[ -n "$1" ]] ; then
3464         nm -go /usr/lib/lib*.a 2>/dev/null | grep ":[[:xdigit:]]\{8\} . .*$1"
3465     else
3466         echo "Usage: lcheck <function>" >&2
3467     fi
3468 }
3469
3470 #f5# Clean up directory - remove well known tempfiles
3471 purge() {
3472     FILES=(*~(N) .*~(N) \#*\#(N) *.o(N) a.out(N) *.core(N) *.cmo(N) *.cmi(N) .*.swp(N))
3473     NBFILES=${#FILES}
3474     if [[ $NBFILES > 0 ]] ; then
3475         print $FILES
3476         local ans
3477         echo -n "Remove these files? [y/n] "
3478         read -q ans
3479         if [[ $ans == "y" ]] ; then
3480             rm ${FILES}
3481             echo ">> $PWD purged, $NBFILES files removed"
3482         else
3483             echo "Ok. .. than not.."
3484         fi
3485     fi
3486 }
3487
3488 # Translate DE<=>EN
3489 # 'translate' looks up fot a word in a file with language-to-language
3490 # translations (field separator should be " : "). A typical wordlist looks
3491 # like at follows:
3492 #  | english-word : german-transmission
3493 # It's also only possible to translate english to german but not reciprocal.
3494 # Use the following oneliner to turn back the sort order:
3495 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
3496 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
3497 #f5# Translates a word
3498 trans() {
3499     case "$1" in
3500         -[dD]*)
3501             translate -l de-en $2
3502             ;;
3503         -[eE]*)
3504             translate -l en-de $2
3505             ;;
3506         *)
3507             echo "Usage: $0 { -D | -E }"
3508             echo "         -D == German to English"
3509             echo "         -E == English to German"
3510     esac
3511 }
3512
3513 #f5# List all occurrences of programm in current PATH
3514 plap() {
3515     if [[ $# = 0 ]] ; then
3516         echo "Usage:    $0 program"
3517         echo "Example:  $0 zsh"
3518         echo "Lists all occurrences of program in the current PATH."
3519     else
3520         ls -l ${^path}/*$1*(*N)
3521     fi
3522 }
3523
3524 # Found in the mailinglistarchive from Zsh (IIRC ~1996)
3525 #f5# Select items for specific command(s) from history
3526 selhist() {
3527     emulate -L zsh
3528     local TAB=$'\t';
3529     (( $# < 1 )) && {
3530         echo "Usage: $0 command"
3531         return 1
3532     };
3533     cmd=(${(f)"$(grep -w $1 $HISTFILE | sort | uniq | pr -tn)"})
3534     print -l $cmd | less -F
3535     echo -n "enter number of desired command [1 - $(( ${#cmd[@]} - 1 ))]: "
3536     local answer
3537     read answer
3538     print -z "${cmd[$answer]#*$TAB}"
3539 }
3540
3541 # Use vim to convert plaintext to HTML
3542 #f5# Transform files to html with highlighting
3543 2html() { vim -u NONE -n -c ':syntax on' -c ':so $VIMRUNTIME/syntax/2html.vim' -c ':wqa' $1 &>/dev/null }
3544
3545 # Usage: simple-extract <file>
3546 #f5# Smart archive extractor
3547 simple-extract () {
3548     if [[ -f $1 ]] ; then
3549         case $1 in
3550             *.tar.bz2)  bzip2 -v -d $1      ;;
3551             *.tar.gz)   tar -xvzf $1        ;;
3552             *.rar)      unrar $1            ;;
3553             *.deb)      ar -x $1            ;;
3554             *.bz2)      bzip2 -d $1         ;;
3555             *.lzh)      lha x $1            ;;
3556             *.gz)       gunzip -d $1        ;;
3557             *.tar)      tar -xvf $1         ;;
3558             *.tgz)      gunzip -d $1        ;;
3559             *.tbz2)     tar -jxvf $1        ;;
3560             *.zip)      unzip $1            ;;
3561             *.Z)        uncompress $1       ;;
3562             *)          echo "'$1' Error. Please go away" ;;
3563         esac
3564     else
3565         echo "'$1' is not a valid file"
3566     fi
3567 }
3568
3569 # Usage: smartcompress <file> (<type>)
3570 #f5# Smart archive creator
3571 smartcompress() {
3572     if [[ -n $2 ]] ; then
3573         case $2 in
3574             tgz | tar.gz)   tar -zcvf$1.$2 $1 ;;
3575             tbz2 | tar.bz2) tar -jcvf$1.$2 $1 ;;
3576             tar.Z)          tar -Zcvf$1.$2 $1 ;;
3577             tar)            tar -cvf$1.$2  $1 ;;
3578             gz | gzip)      gzip           $1 ;;
3579             bz2 | bzip2)    bzip2          $1 ;;
3580             *)
3581                 echo "Error: $2 is not a valid compression type"
3582                 ;;
3583         esac
3584     else
3585         smartcompress $1 tar.gz
3586     fi
3587 }
3588
3589 # Usage: show-archive <archive>
3590 #f5# List an archive's content
3591 show-archive() {
3592     if [[ -f $1 ]] ; then
3593         case $1 in
3594             *.tar.gz)      gunzip -c $1 | tar -tf - -- ;;
3595             *.tar)         tar -tf $1 ;;
3596             *.tgz)         tar -ztf $1 ;;
3597             *.zip)         unzip -l $1 ;;
3598             *.bz2)         bzless $1 ;;
3599             *.deb)         dpkg-deb --fsys-tarfile $1 | tar -tf - -- ;;
3600             *)             echo "'$1' Error. Please go away" ;;
3601         esac
3602     else
3603         echo "'$1' is not a valid archive"
3604     fi
3605 }
3606
3607 # It's shameless stolen from <http://www.vim.org/tips/tip.php?tip_id=167>
3608 #f5# Use \kbd{vim} as your manpage reader
3609 vman() { man $* | col -b | view -c 'set ft=man nomod nolist' - }
3610
3611 # function readme() { $PAGER -- (#ia3)readme* }
3612 #f5# View all README-like files in current directory in pager
3613 readme() {
3614     local files
3615     files=(./(#i)*(read*me|lue*m(in|)ut)*(ND))
3616     if (($#files)) ; then
3617         $PAGER $files
3618     else
3619         print 'No README files.'
3620     fi
3621 }
3622
3623 # function ansi-colors()
3624 #f5# Display ANSI colors
3625 ansi-colors() {
3626     typeset esc="\033[" line1 line2
3627     echo " _ _ _40 _ _ _41_ _ _ _42 _ _ 43_ _ _ 44_ _ _45 _ _ _ 46_ _ _ 47_ _ _ 49_ _"
3628     for fore in 30 31 32 33 34 35 36 37; do
3629         line1="$fore "
3630         line2="   "
3631         for back in 40 41 42 43 44 45 46 47 49; do
3632             line1="${line1}${esc}${back};${fore}m Normal ${esc}0m"
3633             line2="${line2}${esc}${back};${fore};1m Bold   ${esc}0m"
3634         done
3635         echo -e "$line1\n$line2"
3636     done
3637 }
3638
3639 # suidfind() { ls -latg $path | grep '^...s' }
3640 #f5# Find all files in \$PATH with setuid bit set
3641 suidfind() { ls -latg $path/*(sN) }
3642
3643 # See above but this is /better/ ... anywise ..
3644 findsuid() {
3645     print 'Output will be written to ~/suid_* ...'
3646     $SUDO find / -type f \( -perm -4000 -o -perm -2000 \) -ls > ~/suid_suidfiles.`date "+%Y-%m-%d"`.out 2>&1
3647     $SUDO find / -type d \( -perm -4000 -o -perm -2000 \) -ls > ~/suid_suiddirs.`date "+%Y-%m-%d"`.out 2>&1
3648     $SUDO find / -type f \( -perm -2 -o -perm -20 \) -ls > ~/suid_writefiles.`date "+%Y-%m-%d"`.out 2>&1
3649     $SUDO find / -type d \( -perm -2 -o -perm -20 \) -ls > ~/suid_writedirs.`date "+%Y-%m-%d"`.out 2>&1
3650     print 'Finished'
3651 }
3652
3653 #f5# Reload given functions
3654 refunc() {
3655     for func in $argv ; do
3656         unfunction $func
3657         autoload $func
3658     done
3659 }
3660
3661 # a small check to see which DIR is located on which server/partition.
3662 # stolen and modified from Sven's zshrc.forall
3663 #f5# Report diskusage of a directory
3664 dirspace() {
3665     if [[ -n "$1" ]] ; then
3666         for dir in $* ; do
3667             if [[ -d "$dir" ]] ; then
3668                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3669             else
3670                 echo "warning: $dir does not exist" >&2
3671             fi
3672         done
3673     else
3674         for dir in $path; do
3675             if [[ -d "$dir" ]] ; then
3676                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3677             else
3678                 echo "warning: $dir does not exist" >&2
3679             fi
3680         done
3681     fi
3682 }
3683
3684 # % slow_print `cat /etc/passwd`
3685 #f5# Slowly print out parameters
3686 slow_print() {
3687     for argument in "${@}" ; do
3688         for ((i = 1; i <= ${#1} ;i++)) ; do
3689             print -n "${argument[i]}"
3690             sleep 0.08
3691         done
3692         print -n " "
3693     done
3694     print ""
3695 }
3696
3697 #f5# Show some status info
3698 status() {
3699     print ""
3700     print "Date..: "$(date "+%Y-%m-%d %H:%M:%S")""
3701     print "Shell.: Zsh $ZSH_VERSION (PID = $$, $SHLVL nests)"
3702     print "Term..: $TTY ($TERM), ${BAUD:+$BAUD bauds, }$COLUMNS x $LINES cars"
3703     print "Login.: $LOGNAME (UID = $EUID) on $HOST"
3704     print "System: $(cat /etc/[A-Za-z]*[_-][rv]e[lr]*)"
3705     print "Uptime:$(uptime)"
3706     print ""
3707 }
3708
3709 # Rip an audio CD
3710 #f5# Rip an audio CD
3711 audiorip() {
3712     mkdir -p ~/ripps
3713     cd ~/ripps
3714     cdrdao read-cd --device $DEVICE --driver generic-mmc audiocd.toc
3715     cdrdao read-cddb --device $DEVICE --driver generic-mmc audiocd.toc
3716     echo " * Would you like to burn the cd now? (yes/no)"
3717     read input
3718     if [[ "$input" = "yes" ]] ; then
3719         echo " ! Burning Audio CD"
3720         audioburn
3721         echo " * done."
3722     else
3723         echo " ! Invalid response."
3724     fi
3725 }
3726
3727 # and burn it
3728 #f5# Burn an audio CD (in combination with audiorip)
3729 audioburn() {
3730     cd ~/ripps
3731     cdrdao write --device $DEVICE --driver generic-mmc audiocd.toc
3732     echo " * Should I remove the temporary files? (yes/no)"
3733     read input
3734     if [[ "$input" = "yes" ]] ; then
3735         echo " ! Removing Temporary Files."
3736         cd ~
3737         rm -rf ~/ripps
3738         echo " * done."
3739     else
3740         echo " ! Invalid response."
3741     fi
3742 }
3743
3744 #f5# Make an audio CD from all mp3 files
3745 mkaudiocd() {
3746     # TODO: do the renaming more zshish, possibly with zmv()
3747     cd ~/ripps
3748     for i in *.[Mm][Pp]3; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done
3749     for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`; done
3750     for i in *.mp3; do mpg123 -w `basename $i .mp3`.wav $i; done
3751     normalize -m *.wav
3752     for i in *.wav; do sox $i.wav -r 44100 $i.wav resample; done
3753 }
3754
3755 #f5# Create an ISO image. You are prompted for\\&\quad volume name, filename and directory
3756 mkiso() {
3757     echo " * Volume name "
3758     read volume
3759     echo " * ISO Name (ie. tmp.iso)"
3760     read iso
3761     echo " * Directory or File"
3762     read files
3763     mkisofs -o ~/$iso -A $volume -allow-multidot -J -R -iso-level 3 -V $volume -R $files
3764 }
3765
3766 #f5# Simple thumbnails generator
3767 genthumbs() {
3768     rm -rf thumb-* index.html
3769     echo "
3770 <html>
3771   <head>
3772     <title>Images</title>
3773   </head>
3774   <body>" > index.html
3775     for f in *.(gif|jpeg|jpg|png) ; do
3776         convert -size 100x200 "$f" -resize 100x200 thumb-"$f"
3777         echo "    <a href=\"$f\"><img src=\"thumb-$f\"></a>" >> index.html
3778     done
3779     echo "
3780   </body>
3781 </html>" >> index.html
3782 }
3783
3784 #f5# Set all ulimit parameters to \kbd{unlimited}
3785 allulimit() {
3786     ulimit -c unlimited
3787     ulimit -d unlimited
3788     ulimit -f unlimited
3789     ulimit -l unlimited
3790     ulimit -n unlimited
3791     ulimit -s unlimited
3792     ulimit -t unlimited
3793 }
3794
3795 # ogg2mp3 with bitrate of 192
3796 ogg2mp3_192() {
3797     oggdec -o - ${1} | lame -b 192 - ${1:r}.mp3
3798 }
3799
3800 #f5# RFC 2396 URL encoding in Z-Shell
3801 urlencode() {
3802     setopt localoptions extendedglob
3803     input=( ${(s::)1} )
3804     print ${(j::)input/(#b)([^A-Za-z0-9_.!~*\'\(\)-])/%${(l:2::0:)$(([##16]#match))}}
3805 }
3806
3807 #f5# Install x-lite (VoIP software)
3808 getxlite() {
3809     setopt local_options
3810     setopt errreturn
3811     [[ -d ~/tmp ]] || mkdir ~/tmp
3812     cd ~/tmp
3813
3814     echo "Downloading http://www.counterpath.com/download/X-Lite_Install.tar.gz and storing it in ~/tmp:"
3815     if wget http://www.counterpath.com/download/X-Lite_Install.tar.gz ; then
3816         unp X-Lite_Install.tar.gz && echo done || echo failed
3817     else
3818         echo "Error while downloading." ; return 1
3819     fi
3820
3821     if [[ -x xten-xlite/xtensoftphone ]] ; then
3822         echo "Execute xten-xlite/xtensoftphone to start xlite."
3823     fi
3824 }
3825
3826 #f5# Install skype
3827 getskype() {
3828     setopt local_options
3829     setopt errreturn
3830     echo "Downloading debian package of skype."
3831     echo "Notice: If you want to use a more recent skype version run 'getskypebeta'."
3832     wget http://www.skype.com/go/getskype-linux-deb
3833     $SUDO dpkg -i skype*.deb && echo "skype installed."
3834 }
3835
3836 #f5# Install beta-version of skype
3837 getskypebeta() {
3838     setopt local_options
3839     setopt errreturn
3840     echo "Downloading debian package of skype (beta version)."
3841     wget http://www.skype.com/go/getskype-linux-beta-deb
3842     $SUDO dpkg -i skype-beta*.deb && echo "skype installed."
3843 }
3844
3845 #f5# Install gizmo (VoIP software)
3846 getgizmo() {
3847     setopt local_options
3848     setopt errreturn
3849     echo "libgtk2.0-0, gconf2, libstdc++6, libasound2 and zlib1g have to be available. Installing."
3850     $SUDO apt-get update
3851     $SUDO apt-get install libgtk2.0-0 gconf2 libstdc++6 libasound2 zlib1g
3852     wget "$(lynx --dump http://gizmo5.com/pc/download/linux/ | awk '/libstdc\+\+6.*\.deb/ {print $2}')"
3853     $SUDO dpkg -i gizmo-project*.deb && echo "gizmo installed."
3854 }
3855
3856 #f5# Get and run AIR (Automated Image and Restore)
3857 getair() {
3858     setopt local_options
3859     setopt errreturn
3860     [[ -w . ]] || { echo 'Error: you do not have write permissions in this directory. Exiting.' ; return 1 }
3861     local VER='1.2.8'
3862     wget http://puzzle.dl.sourceforge.net/sourceforge/air-imager/air-$VER.tar.gz
3863     tar zxf air-$VER.tar.gz
3864     cd air-$VER
3865     INTERACTIVE=no $SUDO ./install-air-1.2.8
3866     [[ -x /usr/local/bin/air ]] && [[ -n "$DISPLAY" ]] && $SUDO air
3867 }
3868
3869 #f5# Get specific git commitdiff
3870 git-get-diff() {
3871     if [[ -z $GITTREE ]] ; then
3872         GITTREE='linux/kernel/git/torvalds/linux-2.6.git'
3873     fi
3874     if ! [[ -z $1 ]] ; then
3875         ${=BROWSER} "http://kernel.org/git/?p=$GITTREE;a=commitdiff;h=$1"
3876     else
3877         echo "Usage: git-get-diff <commit>"
3878     fi
3879 }
3880
3881 #f5# Get specific git commit
3882 git-get-commit() {
3883     if [[ -z $GITTREE ]] ; then
3884         GITTREE='linux/kernel/git/torvalds/linux-2.6.git'
3885     fi
3886     if ! [[ -z $1 ]] ; then
3887         ${=BROWSER} "http://kernel.org/git/?p=$GITTREE;a=commit;h=$1"
3888     else
3889         echo "Usage: git-get-commit <commit>"
3890     fi
3891 }
3892
3893 #f5# Get specific git diff
3894 git-get-plaindiff () {
3895     if [[ -z $GITTREE ]] ; then
3896        GITTREE='linux/kernel/git/torvalds/linux-2.6.git'
3897     fi
3898     if [[ -z $1 ]] ; then
3899        echo 'Usage: git-get-plaindiff '
3900     else
3901        echo -n "Downloading $1.diff ... "
3902        # avoid "generating ..." stuff from kernel.org server:
3903        wget --quiet "http://kernel.org/git/?p=$GITTREE;a=commitdiff_plain;h=$1" -O /dev/null
3904        wget --quiet "http://kernel.org/git/?p=$GITTREE;a=commitdiff_plain;h=$1" -O $1.diff \
3905             && echo done || echo failed
3906     fi
3907 }
3908
3909
3910 # http://strcat.de/blog/index.php?/archives/335-Software-sauber-deinstallieren...html
3911 #f5# Log 'make install' output
3912 mmake() {
3913     [[ ! -d ~/.errorlogs ]] && mkdir ~/.errorlogs
3914     make -n install > ~/.errorlogs/${PWD##*/}-makelog
3915 }
3916
3917 #f5# Indent source code
3918 smart-indent() {
3919     indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs $*
3920 }
3921
3922 # highlight important stuff in diff output, usage example: hg diff | hidiff
3923 #m# a2 hidiff \kbd{histring} oneliner for diffs
3924 check_com -c histring && \
3925     alias hidiff="histring -fE '^Comparing files .*|^diff .*' | histring -c yellow -fE '^\-.*' | histring -c green -fE '^\+.*'"
3926
3927 # rename pictures based on information found in exif headers
3928 #f5# Rename pictures based on information found in exif headers
3929 exirename() {
3930     if [[ $# -lt 1 ]] ; then
3931         echo 'Usage: jpgrename $FILES' >& 2
3932         return 1
3933     else
3934         echo -n 'Checking for jhead with version newer than 1.9: '
3935         jhead_version=`jhead -h | grep 'used by most Digital Cameras.  v.*' | awk '{print $6}' | tr -d v`
3936         if [[ $jhead_version > '1.9' ]]; then
3937             echo 'success - now running jhead.'
3938             jhead -n%Y-%m-%d_%Hh%M_%f $*
3939         else
3940             echo 'failed - exiting.'
3941         fi
3942     fi
3943 }
3944
3945 # open file in vim and jump to line
3946 # http://www.downgra.de/archives/2007/05/08/T19_21_11/
3947 j2v() {
3948     local -a params
3949     params=(${*//(#m):[0-9]*:/\\n+${MATCH//:/}}) # replace ':23:' to '\n+23'
3950     params=(${(s|\n|)${(j|\n|)params}}) # join array using '\n', then split on all '\n'
3951     vim ${params}
3952 }
3953
3954 # get_ic() - queries imap servers for capabilities; real simple. no imaps
3955 ic_get() {
3956     local port
3957     if [[ ! -z $1 ]] ; then
3958         port=${2:-143}
3959         print "querying imap server on $1:${port}...\n";
3960         print "a1 capability\na2 logout\n" | nc $1 ${port}
3961     else
3962         print "usage:\n  $0 <imap-server> [port]"
3963     fi
3964 }
3965
3966 # creates a Maildir/ with its {new,cur,tmp} subdirs
3967 mkmaildir() {
3968     local root subdir
3969     root=${MAILDIR_ROOT:-${HOME}/Mail}
3970     if [[ -z ${1} ]] ; then print "Usage:\n $0 <dirname>" ; return 1 ; fi
3971     subdir=${1}
3972     mkdir -p ${root}/${subdir}/{cur,new,tmp}
3973 }
3974
3975 #f5# Change the xterm title from within GNU-screen
3976 xtrename() {
3977     if [[ ${1} != "-f" ]] ; then
3978         if [[ -z ${DISPLAY} ]] ; then
3979             printf 'xtrename only makes sense in X11.\n'
3980             return 1
3981         fi
3982     else
3983         shift
3984     fi
3985     if [[ -z ${1} ]] ; then
3986         printf 'usage: xtrename [-f] "title for xterm"\n'
3987         printf '  renames the title of xterm from _within_ screen.\n'
3988         printf '  also works without screen.\n'
3989         printf '  will not work if DISPLAY is unset, use -f to override.\n'
3990         return 0
3991     fi
3992     print -n "\eP\e]0;${1}\C-G\e\\"
3993     return 0
3994 }
3995
3996 # hl() highlighted less
3997 # http://ft.bewatermyfriend.org/comp/data/zsh/zfunct.html
3998 if check_com -c highlight ; then
3999     function hl() {
4000         local theme lang
4001         theme=${HL_THEME:-""}
4002         case ${1} in
4003             (-l|--list)
4004                 ( printf 'available languages (syntax parameter):\n\n' ;
4005                     highlight --list-langs ; ) | less -SMr
4006                 ;;
4007             (-t|--themes)
4008                 ( printf 'available themes (style parameter):\n\n' ;
4009                     highlight --list-themes ; ) | less -SMr
4010                 ;;
4011             (-h|--help)
4012                 printf 'usage: hl <syntax[:theme]> <file>\n'
4013                 printf '    available options: --list (-l), --themes (-t), --help (-h)\n\n'
4014                 printf '  Example: hl c main.c\n'
4015                 ;;
4016             (*)
4017                 if [[ -z ${2} ]] || (( ${#argv} > 2 )) ; then
4018                     printf 'usage: hl <syntax[:theme]> <file>\n'
4019                     printf '    available options: --list (-l), --themes (-t), --help (-h)\n'
4020                     (( ${#argv} > 2 )) && printf '  Too many arguments.\n'
4021                     return 1
4022                 fi
4023                 lang=${1%:*}
4024                 [[ ${1} == *:* ]] && [[ -n ${1#*:} ]] && theme=${1#*:}
4025                 if [[ -n ${theme} ]] ; then
4026                     highlight --xterm256 --syntax ${lang} --style ${theme} ${2} | less -SMr
4027                 else
4028                     highlight --ansi --syntax ${lang} ${2} | less -SMr
4029                 fi
4030                 ;;
4031         esac
4032         return 0
4033     }
4034     # ... and a proper completion for hl()
4035     # needs 'highlight' as well, so it fits fine in here.
4036     function _hl_genarg()  {
4037         local expl
4038         if [[ -prefix 1 *: ]] ; then
4039             local themes
4040             themes=(${${${(f)"$(LC_ALL=C highlight --list-themes)"}/ #/}:#*(Installed|Use name)*})
4041             compset -P 1 '*:'
4042             _wanted -C list themes expl theme compadd ${themes}
4043         else
4044             local langs
4045             langs=(${${${(f)"$(LC_ALL=C highlight --list-langs)"}/ #/}:#*(Installed|Use name)*})
4046             _wanted -C list languages expl languages compadd -S ':' -q ${langs}
4047         fi
4048     }
4049     function _hl_complete() {
4050         _arguments -s '1: :_hl_genarg' '2:files:_path_files'
4051     }
4052     compdef _hl_complete hl
4053 fi
4054
4055 # Create small urls via http://tinyurl.com using wget(1).
4056 function zurl() {
4057     [[ -z ${1} ]] && { print "USAGE: zurl <URL>" ; return 1 }
4058
4059     local PN url tiny grabber search result preview
4060     PN=${0}
4061     url=${1}
4062 #   Check existence of given URL with the help of ping(1).
4063 #   N.B. ping(1) only works without an eventual given protocol.
4064     ping -c 1 ${${url#(ftp|http)://}%%/*} >& /dev/null || \
4065         read -q "?Given host ${${url#http://*/}%/*} is not reachable by pinging. Proceed anyway? [y|n] "
4066
4067     if (( $? == 0 )) ; then
4068 #           Prepend 'http://' to given URL where necessary for later output.
4069             [[ ${url} != http(s|)://* ]] && url='http://'${url}
4070             tiny='http://tinyurl.com/create.php?url='
4071             if check_com -c wget ; then
4072                 grabber='wget -O- -o/dev/null'
4073             else
4074                 print "wget is not available, but mandatory for ${PN}. Aborting."
4075             fi
4076 #           Looking for i.e.`copy('http://tinyurl.com/7efkze')' in TinyURL's HTML code.
4077             search='copy\(?http://tinyurl.com/[[:alnum:]]##*'
4078             result=${(M)${${${(f)"$(${=grabber} ${tiny}${url})"}[(fr)${search}*]}//[()\';]/}%%http:*}
4079 #           TinyURL provides the rather new feature preview for more confidence. <http://tinyurl.com/preview.php>
4080             preview='http://preview.'${result#http://}
4081
4082             printf '%s\n\n' "${PN} - Shrinking long URLs via webservice TinyURL <http://tinyurl.com>."
4083             printf '%s\t%s\n\n' 'Given URL:' ${url}
4084             printf '%s\t%s\n\t\t%s\n' 'TinyURL:' ${result} ${preview}
4085     else
4086         return 1
4087     fi
4088 }
4089
4090 #f2# Print a specific line of file(s).
4091 linenr () {
4092 # {{{
4093     if [ $# -lt 2 ] ; then
4094        print "Usage: linenr <number>[,<number>] <file>" ; return 1
4095     elif [ $# -eq 2 ] ; then
4096          local number=$1
4097          local file=$2
4098          command ed -s $file <<< "${number}n"
4099     else
4100          local number=$1
4101          shift
4102          for file in "$@" ; do
4103              if [ ! -d $file ] ; then
4104                 echo "${file}:"
4105                 command ed -s $file <<< "${number}n" 2> /dev/null
4106              else
4107                 continue
4108              fi
4109          done | less
4110     fi
4111 # }}}
4112 }
4113
4114 #f2# Find history events by search pattern and list them by date.
4115 whatwhen()  {
4116 # {{{
4117     local usage help ident format_l format_s first_char remain first last
4118     usage='USAGE: whatwhen [options] <searchstring> <search range>'
4119     help='Use' \`'whatwhen -h'\'' for further explanations.'
4120     ident=${(l,${#${:-Usage: }},, ,)}
4121     format_l="${ident}%s\t\t\t%s\n"
4122     format_s="${format_l//(\\t)##/\\t}"
4123     # Make the first char of the word to search for case
4124     # insensitive; e.g. [aA]
4125     first_char=[${(L)1[1]}${(U)1[1]}]
4126     remain=${1[2,-1]}
4127     # Default search range is `-100'.
4128     first=${2:-\-100}
4129     # Optional, just used for `<first> <last>' given.
4130     last=$3
4131     case $1 in
4132         ("")
4133             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
4134             printf '%s\n%s\n\n' ${usage} ${help} && return 1
4135         ;;
4136         (-h)
4137             printf '%s\n\n' ${usage}
4138             print 'OPTIONS:'
4139             printf $format_l '-h' 'show help text'
4140             print '\f'
4141             print 'SEARCH RANGE:'
4142             printf $format_l "'0'" 'the whole history,'
4143             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
4144             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
4145             printf '\n%s\n' 'EXAMPLES:'
4146             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
4147             printf $format_l 'whatwhen zsh -250'
4148             printf $format_l 'whatwhen foo 1 99'
4149         ;;
4150         (\?)
4151             printf '%s\n%s\n\n' ${usage} ${help} && return 1
4152         ;;
4153         (*)
4154             # -l list results on stout rather than invoking $EDITOR.
4155             # -i Print dates as in YYYY-MM-DD.
4156             # -m Search for a - quoted - pattern within the history.
4157             fc -li -m "*${first_char}${remain}*" $first $last
4158         ;;
4159     esac
4160 # }}}
4161 }
4162
4163 # change fluxbox keys from 'Alt-#' to 'Alt-F#' and vice versa
4164 fluxkey-change() {
4165     [[ -n "$FLUXKEYS" ]] || local FLUXKEYS="$HOME/.fluxbox/keys"
4166     if ! [[ -r "$FLUXKEYS" ]] ; then
4167         echo "Sorry, \$FLUXKEYS file $FLUXKEYS could not be read - nothing to be done."
4168         return 1
4169     else
4170         if grep -q 'Mod1 F[0-9] :Workspace [0-9]' $FLUXKEYS ; then
4171             echo -n 'Switching to Alt-# mode in ~/.fluxbox/keys: '
4172             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)F\([0-9]\+[: space :]\+:Workspace.*\)|\1\2|' $FLUXKEYS && echo done || echo failed
4173         elif grep -q 'Mod1 [0-9] :Workspace [0-9]' $FLUXKEYS ; then
4174             echo -n 'Switching to Alt-F# mode in ~/.fluxbox/keys: '
4175             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)\([0-9]\+[: space :]\+:Workspace.*\)|\1F\2|' $FLUXKEYS && echo done || echo failed
4176         else
4177             echo 'Sorry, do not know what to do.'
4178             return 1
4179         fi
4180     fi
4181 }
4182
4183 # retrieve weather information on the console
4184 # Usage example: 'weather LOWG'
4185 weather() {
4186     [[ -n "$1" ]] || {
4187         print 'Usage: weather <station_id>' >&2
4188         print 'List of stations: http://en.wikipedia.org/wiki/List_of_airports_by_ICAO_code'>&2
4189         return 1
4190     }
4191
4192     local PLACE="${1:u}"
4193     local FILE="$HOME/.weather/$PLACE"
4194     local LOG="$HOME/.weather/log"
4195
4196     [[ -d $HOME/.weather ]] || {
4197         print -n "Creating $HOME/.weather: "
4198         mkdir $HOME/.weather
4199         print 'done'
4200     }
4201
4202     print "Retrieving information for ${PLACE}:"
4203     print
4204     wget -T 10 --no-verbose --output-file=$LOG --output-document=$FILE --timestamping http://weather.noaa.gov/pub/data/observations/metar/decoded/$PLACE.TXT
4205
4206     if [[ $? -eq 0 ]] ; then
4207         if [[ -n "$VERBOSE" ]] ; then
4208             cat $FILE
4209         else
4210             DATE=$(grep 'UTC' $FILE | sed 's#.* /##')
4211             TEMPERATURE=$(awk '/Temperature/ { print $4" degree Celcius / " $2" degree Fahrenheit" }' $FILE| tr -d '(')
4212             echo "date: $DATE"
4213             echo "temp:  $TEMPERATURE"
4214         fi
4215     else
4216         print "There was an error retrieving the weather information for $PLACE" >&2
4217         cat $LOG
4218         return 1
4219     fi
4220 }
4221 # }}}
4222
4223 # mercurial related stuff {{{
4224 if check_com -c hg ; then
4225     # gnu like diff for mercurial
4226     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
4227     #f5# GNU like diff for mercurial
4228     hgdi() {
4229         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
4230     }
4231
4232     # build debian package
4233     #a2# Alias for \kbd{hg-buildpackage}
4234     alias hbp='hg-buildpackage'
4235
4236     # execute commands on the versioned patch-queue from the current repos
4237     alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
4238
4239     # diffstat for specific version of a mercurial repository
4240     #   hgstat      => display diffstat between last revision and tip
4241     #   hgstat 1234 => display diffstat between revision 1234 and tip
4242     #f5# Diffstat for specific version of a mercurial repos
4243     hgstat() {
4244         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
4245     }
4246
4247     #f5# Get current mercurial tip via hg itself
4248     gethgclone() {
4249         setopt local_options
4250         setopt errreturn
4251         if [[ -f mercurial-tree/.hg ]] ; then
4252             cd mercurial-tree
4253             echo "Running hg pull for retreiving latest version..."
4254             hg pull
4255             echo "Finished update. Building mercurial"
4256             make local
4257             echo "Setting \$PATH to $PWD:\$PATH..."
4258             export PATH="$PWD:$PATH"
4259         else
4260             echo "Downloading mercurial via hg"
4261             hg clone http://selenic.com/repo/hg mercurial-tree
4262             cd mercurial-tree
4263             echo "Building mercurial"
4264             make local
4265             echo "Setting \$PATH to $PWD:\$PATH..."
4266             export PATH="$PWD:$PATH"
4267             echo "make sure you set it permanent via ~/.zshrc if you plan to use it permanently."
4268             # echo "Setting \$PYTHONPATH to PYTHONPATH=\${HOME}/lib/python,"
4269             # export PYTHONPATH=${HOME}/lib/python
4270         fi
4271     }
4272
4273 fi # end of check whether we have the 'hg'-executable
4274
4275 # get current mercurial snapshot
4276 #f5# Get current mercurial snapshot
4277 gethgsnap() {
4278     setopt local_options
4279     setopt errreturn
4280     if [[ -f mercurial-snapshot.tar.gz ]] ; then
4281          echo "mercurial-snapshot.tar.gz exists already, skipping download."
4282     else
4283         echo "Downloading mercurial snapshot"
4284         wget http://www.selenic.com/mercurial/mercurial-snapshot.tar.gz
4285     fi
4286     echo "Unpacking mercurial-snapshot.tar.gz"
4287     tar zxf mercurial-snapshot.tar.gz
4288     cd mercurial-snapshot/
4289     echo "Installing required build-dependencies"
4290     $SUDO apt-get update
4291     $SUDO apt-get install python2.4-dev
4292     echo "Building mercurial"
4293     make local
4294     echo "Setting \$PATH to $PWD:\$PATH..."
4295     export PATH="$PWD:$PATH"
4296     echo "make sure you set it permanent via ~/.zshrc if you plan to use it permanently."
4297 }
4298 # }}}
4299
4300 # some useful commands often hard to remember - let's grep for them {{{
4301 # actually use our zg() function now. :)
4302
4303 # Work around ion/xterm resize bug.
4304 #if [[ "$SHLVL" -eq 1 ]]; then
4305 #       if check_com -c resize ; then
4306 #               eval `resize </dev/null`
4307 #       fi
4308 #fi
4309
4310 # enable jackd:
4311 #  /usr/bin/jackd -dalsa -dhw:0 -r48000 -p1024 -n2
4312 # now play audio file:
4313 #  alsaplayer -o jack foobar.mp3
4314
4315 # send files via netcat
4316 # on sending side:
4317 #  send() {j=$*; tar cpz ${j/%${!#}/}|nc -w 1 ${!#} 51330;}
4318 #  send dir* $HOST
4319 #  alias receive='nc -vlp 51330 | tar xzvp'
4320
4321 # debian stuff:
4322 # dh_make -e foo@localhost -f $1
4323 # dpkg-buildpackage -rfakeroot
4324 # lintian *.deb
4325 # dpkg-scanpackages ./ /dev/null | gzip > Packages.gz
4326 # dpkg-scansources . | gzip > Sources.gz
4327 # grep-dctrl --field Maintainer $* /var/lib/apt/lists/*
4328
4329 # other stuff:
4330 # convert -geometry 200x200 -interlace LINE -verbose
4331 # ldapsearch -x -b "OU=Bedienstete,O=tug" -h ldap.tugraz.at sn=$1
4332 # ps -ao user,pcpu,start,command
4333 # gpg --keyserver blackhole.pca.dfn.de --recv-keys
4334 # xterm -bg black -fg yellow -fn -misc-fixed-medium-r-normal--14-140-75-75-c-90-iso8859-15 -ah
4335 # nc -vz $1 1-1024   # portscan via netcat
4336 # wget --mirror --no-parent --convert-links
4337 # pal -d `date +%d`
4338 # autoload -U tetris; zle -N tetris; bindkey '...' ; echo "press ... for playing tennis"
4339 #
4340 # modify console cursor
4341 # see http://www.tldp.org/HOWTO/Framebuffer-HOWTO-5.html
4342 # print $'\e[?96;0;64c'
4343 # }}}
4344
4345 # grml-small cleanups {{{
4346
4347 # The following is used to remove zsh-config-items that do not work
4348 # in grml-small by default.
4349 # If you do not want these adjustments (for whatever reason), set
4350 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
4351 # sources if it is there).
4352
4353 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
4354
4355     unset abk[V]
4356     unalias    'V'      &> /dev/null
4357     unfunction vman     &> /dev/null
4358     unfunction vimpm    &> /dev/null
4359     unfunction vimhelp  &> /dev/null
4360     unfunction viless   &> /dev/null
4361     unfunction 2html    &> /dev/null
4362
4363     # manpages are not in grmlsmall
4364     unfunction manzsh   &> /dev/null
4365     unalias    man2     &> /dev/null
4366     unalias    man      &> /dev/null
4367     unfunction man2     &> /dev/null
4368
4369 fi
4370
4371 #}}}
4372
4373 zrclocal
4374
4375 ## genrefcard.pl settings {{{
4376
4377 ### doc strings for external functions from files
4378 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
4379
4380 ### example: split functions-search 8,16,24,32
4381 #@# split functions-search 8
4382
4383 ## }}}
4384
4385 ## END OF FILE #################################################################
4386 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4