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