zshrc: Unification cleanup - Episode V
[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 #:grep:marker:for:mika: :-)
2933 ### non-root (EUID != 0) code below
2934 ###
2935
2936 (( GRML_ALWAYS_LOAD_ALL == 0 )) && (( $EUID == 0 )) && return 0
2937
2938 # autoloading stuff {{{
2939 # associate types and extensions (be aware with perl scripts and anwanted behaviour!)
2940 #  check_com zsh-mime-setup || { autoload zsh-mime-setup && zsh-mime-setup }
2941 #  alias -s pl='perl -S'
2942 # }}}
2943
2944 # variables {{{
2945
2946 # set terminal property (used e.g. by msgid-chooser)
2947 export COLORTERM="yes"
2948
2949 # set default browser
2950 if [[ -z "$BROWSER" ]] ; then
2951     if [[ -n "$DISPLAY" ]] ; then
2952         #v# If X11 is running
2953         check_com -c firefox && export BROWSER=firefox
2954     else
2955         #v# If no X11 is running
2956         check_com -c w3m && export BROWSER=w3m
2957     fi
2958 fi
2959
2960 #m# v QTDIR \kbd{/usr/share/qt[34]}\quad [for non-root only]
2961 [[ -d /usr/share/qt3 ]] && export QTDIR=/usr/share/qt3
2962 [[ -d /usr/share/qt4 ]] && export QTDIR=/usr/share/qt4
2963
2964 # support running 'jikes *.java && jamvm HelloWorld' OOTB:
2965 #v# [for non-root only]
2966 [[ -f /usr/share/classpath/glibj.zip ]] && export JIKESPATH=/usr/share/classpath/glibj.zip
2967 # }}}
2968
2969 # set options {{{
2970
2971 # Allow comments even in interactive shells i. e.
2972 # $ uname # This command prints system informations
2973 # zsh: bad pattern: #
2974 # $ setopt interactivecomments
2975 # $ uname # This command prints system informations
2976 # Linux
2977 #  setopt interactivecomments
2978
2979 # ctrl-s will no longer freeze the terminal.
2980 #  stty erase "^?"
2981
2982 # }}}
2983
2984 # {{{ global aliases
2985 # These do not have to be at the beginning of the command line.
2986 # Avoid typing cd ../../ for going two dirs down and so on
2987 # Usage, e.g.: "$ cd ...' or just '$ ...' with 'setopt auto_cd'
2988 # Notice: deactivated by 061112 by default, we use another approach
2989 # known as "power completion / abbreviation expansion"
2990 #  alias -g '...'='../..'
2991 #  alias -g '....'='../../..'
2992 #  alias -g BG='& exit'
2993 #  alias -g C='|wc -l'
2994 #  alias -g G='|grep'
2995 #  alias -g H='|head'
2996 #  alias -g Hl=' --help |& less -r'
2997 #  alias -g K='|keep'
2998 #  alias -g L='|less'
2999 #  alias -g LL='|& less -r'
3000 #  alias -g M='|most'
3001 #  alias -g N='&>/dev/null'
3002 #  alias -g R='| tr A-z N-za-m'
3003 #  alias -g SL='| sort | less'
3004 #  alias -g S='| sort'
3005 #  alias -g T='|tail'
3006 #  alias -g V='| vim -'
3007 # }}}
3008
3009 # aliases {{{
3010
3011 # Xterm resizing-fu.
3012 # Based on http://svn.kitenet.net/trunk/home-full/.zshrc?rev=11710&view=log (by Joey Hess)
3013 alias hide='echo -en "\033]50;nil2\007"'
3014 alias tiny='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"'
3015 alias small='echo -en "\033]50;6x10\007"'
3016 alias medium='echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"'
3017 alias default='echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"'
3018 alias large='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"'
3019 alias huge='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"'
3020 alias smartfont='echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"'
3021 alias semifont='echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"'
3022 #  if [[ "$TERM" == "xterm" ]] && [[ "$LINES" -ge 50 ]] && [[ "$COLUMNS" -ge 100 ]] && [[ -z "$SSH_CONNECTION" ]] ; then
3023 #          large
3024 #  fi
3025
3026 # general
3027 #a2# Execute \kbd{du -sch}
3028 alias da='du -sch'
3029 #a2# Execute \kbd{jobs -l}
3030 alias j='jobs -l'
3031 #  alias u='translate -i'          # translate
3032
3033 # compile stuff
3034 #a2# Execute \kbd{./configure}
3035 alias CO="./configure"
3036 #a2# Execute \kbd{./configure --help}
3037 alias CH="./configure --help"
3038
3039 # http://conkeror.mozdev.org/
3040 #a2# Run a keyboard driven firefox
3041 alias conkeror='firefox -chrome chrome://conkeror/content'
3042
3043 # arch/tla stuff
3044 if check_com -c tla ; then
3045     #a2# Execute \kbd{tla what-changed --diffs | less}
3046     alias tdi='tla what-changed --diffs | less'
3047     #a2# Execute \kbd{tla-buildpackage}
3048     alias tbp='tla-buildpackage'
3049     #a2# Execute \kbd{tla archive-mirror}
3050     alias tmi='tla archive-mirror'
3051     #a2# Execute \kbd{tla commit}
3052     alias tco='tla commit'
3053     #a2# Execute \kbd{tla star-merge}
3054     alias tme='tla star-merge'
3055 fi
3056
3057 # listing stuff
3058 #a2# Execute \kbd{ls -lSrah}
3059 alias dir="ls -lSrah"
3060 #a2# Only show dot-directories
3061 alias lad='ls -d .*(/)'                # only show dot-directories
3062 #a2# Only show dot-files
3063 alias lsa='ls -a .*(.)'                # only show dot-files
3064 #a2# Only files with setgid/setuid/sticky flag
3065 alias lss='ls -l *(s,S,t)'             # only files with setgid/setuid/sticky flag
3066 #a2# Only show 1st ten symlinks
3067 alias lsl='ls -l *(@[1,10])'           # only symlinks
3068 #a2# Display only executables
3069 alias lsx='ls -l *(*[1,10])'           # only executables
3070 #a2# Display world-{readable,writable,executable} files
3071 alias lsw='ls -ld *(R,W,X.^ND/)'       # world-{readable,writable,executable} files
3072 #a2# Display the ten biggest files
3073 alias lsbig="ls -flh *(.OL[1,10])"     # display the biggest files
3074 #a2# Only show directories
3075 alias lsd='ls -d *(/)'                 # only show directories
3076 #a2# Only show empty directories
3077 alias lse='ls -d *(/^F)'               # only show empty directories
3078 #a2# Display the ten newest files
3079 alias lsnew="ls -rl *(D.om[1,10])"     # display the newest files
3080 #a2# Display the ten oldest files
3081 alias lsold="ls -rtlh *(D.om[1,10])"   # display the oldest files
3082 #a2# Display the ten smallest files
3083 alias lssmall="ls -Srl *(.oL[1,10])"   # display the smallest files
3084
3085 # chmod
3086 #a2# Execute \kbd{chmod 600}
3087 alias rw-='chmod 600'
3088 #a2# Execute \kbd{chmod 700}
3089 alias rwx='chmod 700'
3090 #m# a2 r-{}- Execute \kbd{chmod 644}
3091 alias r--='chmod 644'
3092 #a2# Execute \kbd{chmod 755}
3093 alias r-x='chmod 755'
3094
3095 # some useful aliases
3096 #a2# Execute \kbd{mkdir -o}
3097 alias md='mkdir -p'
3098
3099 check_com -c ipython && alias ips='ipython -p sh'
3100
3101 # console stuff
3102 #a2# Execute \kbd{mplayer -vo fbdev}
3103 alias cmplayer='mplayer -vo fbdev'
3104 #a2# Execute \kbd{mplayer -vo fbdev -fs -zoom}
3105 alias fbmplayer='mplayer -vo fbdev -fs -zoom'
3106 #a2# Execute \kbd{links2 -driver fb}
3107 alias fblinks='links2 -driver fb'
3108
3109 # ignore ~/.ssh/known_hosts entries
3110 #  alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -o "PreferredAuthentications=keyboard-interactive"'
3111 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3112 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3113 alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3114
3115 # simple webserver
3116 check_com -c python && alias http="python -m SimpleHTTPServer"
3117
3118 # Use 'g' instead of 'git':
3119 check_com g || alias g='git'
3120
3121 # use colors when browsing man pages, but only if not using LESS_TERMCAP_* from /etc/zsh/zshenv:
3122 if [[ -z "$LESS_TERMCAP_md" ]] ; then
3123     [[ -d ~/.terminfo/ ]] && alias man='TERMINFO=~/.terminfo/ LESS=C TERM=mostlike PAGER=less man'
3124 fi
3125
3126 # check whether Debian's package management (dpkg) is running
3127 if check_com salias ; then
3128     #a2# Check whether a dpkg instance is currently running
3129     salias check_dpkg_running="dpkg_running"
3130 fi
3131
3132 # work around non utf8 capable software in utf environment via $LANG and luit
3133 if check_com isutfenv && check_com luit ; then
3134     if check_com -c mrxvt ; then
3135         isutfenv && [[ -n "$LANG" ]] && \
3136             alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
3137     fi
3138
3139     if check_com -c aterm ; then
3140         isutfenv && [[ -n "$LANG" ]] && \
3141             alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
3142     fi
3143
3144     if check_com -c centericq ; then
3145         isutfenv && [[ -n "$LANG" ]] && \
3146             alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
3147     fi
3148 fi
3149 # }}}
3150
3151 # useful functions {{{
3152
3153 # searching
3154 #f4# Search for newspostings from authors
3155 agoogle() { ${=BROWSER} "http://groups.google.com/groups?as_uauthors=$*" ; }
3156 #f4# Search Debian Bug Tracking System
3157 debbug()  {
3158     setopt localoptions extendedglob
3159     if [[ $# -eq 1 ]]; then
3160         case "$1" in
3161             ([0-9]##)
3162             ${=BROWSER} "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=$1"
3163             ;;
3164             (*@*)
3165             ${=BROWSER} "http://bugs.debian.org/cgi-bin/pkgreport.cgi?submitter=$1"
3166             ;;
3167             (*)
3168             ${=BROWSER} "http://bugs.debian.org/$*"
3169             ;;
3170         esac
3171     else
3172         print "$0 needs one argument"
3173         return 1
3174     fi
3175 }
3176 #f4# Search Debian Bug Tracking System in mbox format
3177 debbugm() { bts show --mbox $1 } # provide bugnummer as "$1"
3178 #f4# Search DMOZ
3179 dmoz()    { ${=BROWSER} http://search.dmoz.org/cgi-bin/search\?search=${1// /_} }
3180 #f4# Search German   Wiktionary
3181 dwicti()  { ${=BROWSER} http://de.wiktionary.org/wiki/${(C)1// /_} }
3182 #f4# Search English  Wiktionary
3183 ewicti()  { ${=BROWSER} http://en.wiktionary.org/wiki/${(C)1// /_} }
3184 #f4# Search Google Groups
3185 ggogle()  { ${=BROWSER} "http://groups.google.com/groups?q=$*" }
3186 #f4# Search Google
3187 google()  { ${=BROWSER} "http://www.google.com/search?&num=100&q=$*" }
3188 #f4# Search Google Groups for MsgID
3189 mggogle() { ${=BROWSER} "http://groups.google.com/groups?selm=$*" }
3190 #f4# Search Netcraft
3191 netcraft(){ ${=BROWSER} "http://toolbar.netcraft.com/site_report?url=$1" }
3192 #f4# Use German Wikipedia's full text search
3193 swiki()   { ${=BROWSER} http://de.wikipedia.org/wiki/Spezial:Search/${(C)1} }
3194 #f4# search \kbd{dict.leo.org}
3195 oleo()    { ${=BROWSER} "http://dict.leo.org/?search=$*" }
3196 #f4# Search German   Wikipedia
3197 wikide()  { ${=BROWSER} http://de.wikipedia.org/wiki/"${(C)*}" }
3198 #f4# Search English  Wikipedia
3199 wikien()  { ${=BROWSER} http://en.wikipedia.org/wiki/"${(C)*}" }
3200 #f4# Search official debs
3201 wodeb()   { ${=BROWSER} "http://packages.debian.org/search?keywords=$1&searchon=contents&suite=${2:=unstable}&section=all" }
3202
3203 #m# f4 gex() Exact search via Google
3204 check_com google && gex () { google "\"[ $1]\" $*" } # exact search at google
3205
3206 # misc
3207 #f5# Backup \kbd{file {\rm to} file\_timestamp}
3208 bk()      { cp -b ${1} ${1}_`date --iso-8601=m` }
3209 #f5# Copied diff
3210 cdiff()   { diff -crd "$*" | egrep -v "^Only in |^Binary files " }
3211 #f5# cd to directoy and list files
3212 cl()      { cd $1 && ls -a }        # cd && ls
3213 #f5# Cvs add
3214 cvsa()    { cvs add $* && cvs com -m 'initial checkin' $* }
3215 #f5# Cvs diff
3216 cvsd()    { cvs diff -N $* |& $PAGER }
3217 #f5# Cvs log
3218 cvsl()    { cvs log $* |& $PAGER }
3219 #f5# Cvs update
3220 cvsq()    { cvs -nq update }
3221 #f5# Rcs2log
3222 cvsr()    { rcs2log $* | $PAGER }
3223 #f5# Cvs status
3224 cvss()    { cvs status -v $* }
3225 #f5# Disassemble source files using gcc and as
3226 disassemble(){ gcc -pipe -S -o - -O -g $* | as -aldh -o /dev/null }
3227 #f5# Firefox remote control - open given URL
3228 fir()     { firefox -a firefox -remote "openURL($1)" }
3229 #f5# Create Directoy and \kbd{cd} to it
3230 mcd()     { mkdir -p "$@"; cd "$@" } # mkdir && cd
3231 #f5# Unified diff to timestamped outputfile
3232 mdiff()   { diff -udrP "$1" "$2" > diff.`date "+%Y-%m-%d"`."$1" }
3233 #f5# Memory overview
3234 memusage(){ ps aux | awk '{if (NR > 1) print $5; if (NR > 2) print "+"} END { print "p" }' | dc }
3235 #f5# Show contents of tar file
3236 shtar()   { gunzip -c $1 | tar -tf - -- | $PAGER }
3237 #f5# Show contents of tgz file
3238 shtgz()   { tar -ztf $1 | $PAGER }
3239 #f5# Show contents of zip file
3240 shzip()   { unzip -l $1 | $PAGER }
3241 #f5# Greps signature from file
3242 sig()     { agrep -d '^-- $' "$*" ~/.Signature }
3243 #f5# Unified diff
3244 udiff()   { diff -urd $* | egrep -v "^Only in |^Binary files " }
3245 #f5# (Mis)use \kbd{vim} as \kbd{less}
3246 viless()  { vim --cmd 'let no_plugin_maps = 1' -c "so \$VIMRUNTIME/macros/less.vim" "${@:--}" }
3247
3248 # download video from youtube
3249 ytdl() {
3250     if ! [[ -n "$2" ]] ; then
3251         print "Usage: ydtl http://youtube.com/watch?v=.... outputfile.flv">&2
3252         return 1
3253     else
3254         wget -O${2} "http://youtube.com/get_video?"${${${"$(wget -o/dev/null -O- "${1}" | grep -e watch_fullscreen)"}##*watch_fullscreen\?}%%\&fs=*}
3255     fi
3256 }
3257
3258 # Function Usage: uopen $URL/$file
3259 #f5# Download a file and display it locally
3260 uopen() {
3261     if ! [[ -n "$1" ]] ; then
3262         print "Usage: uopen \$URL/\$file">&2
3263         return 1
3264     else
3265         FILE=$1
3266         MIME=$(curl --head $FILE | grep Content-Type | cut -d ' ' -f 2 | cut -d\; -f 1)
3267         MIME=${MIME%$'\r'}
3268         curl $FILE | see ${MIME}:-
3269     fi
3270 }
3271
3272 # Function Usage: doc packagename
3273 #f5# \kbd{cd} to /usr/share/doc/\textit{package}
3274 doc() { cd /usr/share/doc/$1 && ls }
3275 _doc() { _files -W /usr/share/doc -/ }
3276 check_com compdef && compdef _doc doc
3277
3278 #f5# Make screenshot
3279 sshot() {
3280     [[ ! -d ~/shots  ]] && mkdir ~/shots
3281     #cd ~/shots ; sleep 5 ; import -window root -depth 8 -quality 80 `date "+%Y-%m-%d--%H:%M:%S"`.png
3282     cd ~/shots ; sleep 5; import -window root shot_`date --iso-8601=m`.jpg
3283 }
3284
3285 # list images only
3286 limg() {
3287     local -a images
3288     images=( *.{jpg,gif,png}(.N) )
3289
3290     if [[ $#images -eq 0 ]] ; then
3291         print "No image files found"
3292     else
3293         ls "$@" "$images[@]"
3294     fi
3295 }
3296
3297 #f5# Create PDF file from source code
3298 makereadable() {
3299     output=$1
3300     shift
3301     a2ps --medium A4dj -E -o $output $*
3302     ps2pdf $output
3303 }
3304
3305 # zsh with perl-regex - use it e.g. via:
3306 # regcheck '\s\d\.\d{3}\.\d{3} Euro' ' 1.000.000 Euro'
3307 #f5# Checks whether a regex matches or not.\\&\quad Example: \kbd{regcheck '.\{3\} EUR' '500 EUR'}
3308 regcheck() {
3309     zmodload -i zsh/pcre
3310     pcre_compile $1 && \
3311     pcre_match $2 && echo "regex matches" || echo "regex does not match"
3312 }
3313
3314 #f5# List files which have been modified within the last {\it n} days
3315 new() { print -l *(m-$1) }
3316
3317 #f5# Grep in history
3318 greph() { history 0 | grep $1 }
3319 # use colors when GNU grep with color-support
3320 #a2# Execute \kbd{grep -{}-color=auto}
3321 (grep --help 2>/dev/null |grep -- --color) >/dev/null && alias grep='grep --color=auto'
3322 #a2# Execute \kbd{grep -i -{}-color=auto}
3323 alias GREP='grep -i --color=auto'
3324
3325 # one blank line between each line
3326 if [[ -r ~/.terminfo/m/mostlike ]] ; then
3327 #   alias man2='MANPAGER="sed -e G |less" TERMINFO=~/.terminfo TERM=mostlike /usr/bin/man'
3328     #f5# Watch manpages in a stretched style
3329     man2() { PAGER='dash -c "sed G | /usr/bin/less"' TERM=mostlike /usr/bin/man "$@" ; }
3330 fi
3331
3332 # d():Copyright 2005 Nikolai Weibull <nikolai@bitwi.se>
3333 # notice: option AUTO_PUSHD has to be set
3334 #f5# Jump between directories
3335 d() {
3336     emulate -L zsh
3337     autoload -U colors
3338     local color=$fg_bold[blue]
3339     integer i=0
3340     dirs -p | while read dir; do
3341         local num="${$(printf "%-4d " $i)/ /.}"
3342         printf " %s  $color%s$reset_color\n" $num $dir
3343         (( i++ ))
3344     done
3345     integer dir=-1
3346     read -r 'dir?Jump to directory: ' || return
3347     (( dir == -1 )) && return
3348     if (( dir < 0 || dir >= i )); then
3349         echo d: no such directory stack entry: $dir
3350         return 1
3351     fi
3352     cd ~$dir
3353 }
3354
3355 # usage example: 'lcheck strcpy'
3356 #f5# Find out which libs define a symbol
3357 lcheck() {
3358     if [[ -n "$1" ]] ; then
3359         nm -go /usr/lib/lib*.a 2>/dev/null | grep ":[[:xdigit:]]\{8\} . .*$1"
3360     else
3361         echo "Usage: lcheck <function>" >&2
3362     fi
3363 }
3364
3365 #f5# Clean up directory - remove well known tempfiles
3366 purge() {
3367     FILES=(*~(N) .*~(N) \#*\#(N) *.o(N) a.out(N) *.core(N) *.cmo(N) *.cmi(N) .*.swp(N))
3368     NBFILES=${#FILES}
3369     if [[ $NBFILES > 0 ]] ; then
3370         print $FILES
3371         local ans
3372         echo -n "Remove these files? [y/n] "
3373         read -q ans
3374         if [[ $ans == "y" ]] ; then
3375             rm ${FILES}
3376             echo ">> $PWD purged, $NBFILES files removed"
3377         else
3378             echo "Ok. .. than not.."
3379         fi
3380     fi
3381 }
3382
3383 # Translate DE<=>EN
3384 # 'translate' looks up fot a word in a file with language-to-language
3385 # translations (field separator should be " : "). A typical wordlist looks
3386 # like at follows:
3387 #  | english-word : german-transmission
3388 # It's also only possible to translate english to german but not reciprocal.
3389 # Use the following oneliner to turn back the sort order:
3390 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
3391 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
3392 #f5# Translates a word
3393 trans() {
3394     case "$1" in
3395         -[dD]*)
3396             translate -l de-en $2
3397             ;;
3398         -[eE]*)
3399             translate -l en-de $2
3400             ;;
3401         *)
3402             echo "Usage: $0 { -D | -E }"
3403             echo "         -D == German to English"
3404             echo "         -E == English to German"
3405     esac
3406 }
3407
3408 # Some quick Perl-hacks aka /useful/ oneliner
3409 #  bew() { perl -le 'print unpack "B*","'$1'"' }
3410 #  web() { perl -le 'print pack "B*","'$1'"' }
3411 #  hew() { perl -le 'print unpack "H*","'$1'"' }
3412 #  weh() { perl -le 'print pack "H*","'$1'"' }
3413 #  pversion()    { perl -M$1 -le "print $1->VERSION" } # i. e."pversion LWP -> 5.79"
3414 #  getlinks ()   { perl -ne 'while ( m/"((www|ftp|http):\/\/.*?)"/gc ) { print $1, "\n"; }' $* }
3415 #  gethrefs ()   { perl -ne 'while ( m/href="([^"]*)"/gc ) { print $1, "\n"; }' $* }
3416 #  getanames ()  { perl -ne 'while ( m/a name="([^"]*)"/gc ) { print $1, "\n"; }' $* }
3417 #  getforms ()   { perl -ne 'while ( m:(\</?(input|form|select|option).*?\>):gic ) { print $1, "\n"; }' $* }
3418 #  getstrings () { perl -ne 'while ( m/"(.*?)"/gc ) { print $1, "\n"; }' $*}
3419 #  getanchors () { perl -ne 'while ( m/«([^«»\n]+)»/gc ) { print $1, "\n"; }' $* }
3420 #  showINC ()    { perl -e 'for (@INC) { printf "%d %s\n", $i++, $_ }' }
3421 #  vimpm ()      { vim `perldoc -l $1 | sed -e 's/pod$/pm/'` }
3422 #  vimhelp ()    { vim -c "help $1" -c on -c "au! VimEnter *" }
3423
3424 #f5# List all occurrences of programm in current PATH
3425 plap() {
3426     if [[ $# = 0 ]] ; then
3427         echo "Usage:    $0 program"
3428         echo "Example:  $0 zsh"
3429         echo "Lists all occurrences of program in the current PATH."
3430     else
3431         ls -l ${^path}/*$1*(*N)
3432     fi
3433 }
3434
3435 # Found in the mailinglistarchive from Zsh (IIRC ~1996)
3436 #f5# Select items for specific command(s) from history
3437 selhist() {
3438     emulate -L zsh
3439     local TAB=$'\t';
3440     (( $# < 1 )) && {
3441         echo "Usage: $0 command"
3442         return 1
3443     };
3444     cmd=(${(f)"$(grep -w $1 $HISTFILE | sort | uniq | pr -tn)"})
3445     print -l $cmd | less -F
3446     echo -n "enter number of desired command [1 - $(( ${#cmd[@]} - 1 ))]: "
3447     local answer
3448     read answer
3449     print -z "${cmd[$answer]#*$TAB}"
3450 }
3451
3452 # Use vim to convert plaintext to HTML
3453 #f5# Transform files to html with highlighting
3454 2html() { vim -u NONE -n -c ':syntax on' -c ':so $VIMRUNTIME/syntax/2html.vim' -c ':wqa' $1 &>/dev/null }
3455
3456 # Usage: simple-extract <file>
3457 #f5# Smart archive extractor
3458 simple-extract () {
3459     if [[ -f $1 ]] ; then
3460         case $1 in
3461             *.tar.bz2)  bzip2 -v -d $1      ;;
3462             *.tar.gz)   tar -xvzf $1        ;;
3463             *.rar)      unrar $1            ;;
3464             *.deb)      ar -x $1            ;;
3465             *.bz2)      bzip2 -d $1         ;;
3466             *.lzh)      lha x $1            ;;
3467             *.gz)       gunzip -d $1        ;;
3468             *.tar)      tar -xvf $1         ;;
3469             *.tgz)      gunzip -d $1        ;;
3470             *.tbz2)     tar -jxvf $1        ;;
3471             *.zip)      unzip $1            ;;
3472             *.Z)        uncompress $1       ;;
3473             *)          echo "'$1' Error. Please go away" ;;
3474         esac
3475     else
3476         echo "'$1' is not a valid file"
3477     fi
3478 }
3479
3480 # Usage: smartcompress <file> (<type>)
3481 #f5# Smart archive creator
3482 smartcompress() {
3483     if [[ -n $2 ]] ; then
3484         case $2 in
3485             tgz | tar.gz)   tar -zcvf$1.$2 $1 ;;
3486             tbz2 | tar.bz2) tar -jcvf$1.$2 $1 ;;
3487             tar.Z)          tar -Zcvf$1.$2 $1 ;;
3488             tar)            tar -cvf$1.$2  $1 ;;
3489             gz | gzip)      gzip           $1 ;;
3490             bz2 | bzip2)    bzip2          $1 ;;
3491             *)
3492                 echo "Error: $2 is not a valid compression type"
3493                 ;;
3494         esac
3495     else
3496         smartcompress $1 tar.gz
3497     fi
3498 }
3499
3500 # Usage: show-archive <archive>
3501 #f5# List an archive's content
3502 show-archive() {
3503     if [[ -f $1 ]] ; then
3504         case $1 in
3505             *.tar.gz)      gunzip -c $1 | tar -tf - -- ;;
3506             *.tar)         tar -tf $1 ;;
3507             *.tgz)         tar -ztf $1 ;;
3508             *.zip)         unzip -l $1 ;;
3509             *.bz2)         bzless $1 ;;
3510             *.deb)         dpkg-deb --fsys-tarfile $1 | tar -tf - -- ;;
3511             *)             echo "'$1' Error. Please go away" ;;
3512         esac
3513     else
3514         echo "'$1' is not a valid archive"
3515     fi
3516 }
3517
3518 # It's shameless stolen from <http://www.vim.org/tips/tip.php?tip_id=167>
3519 #f5# Use \kbd{vim} as your manpage reader
3520 vman() { man $* | col -b | view -c 'set ft=man nomod nolist' - }
3521
3522 # function readme() { $PAGER -- (#ia3)readme* }
3523 #f5# View all README-like files in current directory in pager
3524 readme() {
3525     local files
3526     files=(./(#i)*(read*me|lue*m(in|)ut)*(ND))
3527     if (($#files)) ; then
3528         $PAGER $files
3529     else
3530         print 'No README files.'
3531     fi
3532 }
3533
3534 # function ansi-colors()
3535 #f5# Display ANSI colors
3536 ansi-colors() {
3537     typeset esc="\033[" line1 line2
3538     echo " _ _ _40 _ _ _41_ _ _ _42 _ _ 43_ _ _ 44_ _ _45 _ _ _ 46_ _ _ 47_ _ _ 49_ _"
3539     for fore in 30 31 32 33 34 35 36 37; do
3540         line1="$fore "
3541         line2="   "
3542         for back in 40 41 42 43 44 45 46 47 49; do
3543             line1="${line1}${esc}${back};${fore}m Normal ${esc}0m"
3544             line2="${line2}${esc}${back};${fore};1m Bold   ${esc}0m"
3545         done
3546         echo -e "$line1\n$line2"
3547     done
3548 }
3549
3550 # suidfind() { ls -latg $path | grep '^...s' }
3551 #f5# Find all files in \$PATH with setuid bit set
3552 suidfind() { ls -latg $path/*(sN) }
3553
3554 # See above but this is /better/ ... anywise ..
3555 findsuid() {
3556     print 'Output will be written to ~/suid_* ...'
3557     $SUDO find / -type f \( -perm -4000 -o -perm -2000 \) -ls > ~/suid_suidfiles.`date "+%Y-%m-%d"`.out 2>&1
3558     $SUDO find / -type d \( -perm -4000 -o -perm -2000 \) -ls > ~/suid_suiddirs.`date "+%Y-%m-%d"`.out 2>&1
3559     $SUDO find / -type f \( -perm -2 -o -perm -20 \) -ls > ~/suid_writefiles.`date "+%Y-%m-%d"`.out 2>&1
3560     $SUDO find / -type d \( -perm -2 -o -perm -20 \) -ls > ~/suid_writedirs.`date "+%Y-%m-%d"`.out 2>&1
3561     print 'Finished'
3562 }
3563
3564 #f5# Reload given functions
3565 refunc() {
3566     for func in $argv ; do
3567         unfunction $func
3568         autoload $func
3569     done
3570 }
3571
3572 # a small check to see which DIR is located on which server/partition.
3573 # stolen and modified from Sven's zshrc.forall
3574 #f5# Report diskusage of a directory
3575 dirspace() {
3576     if [[ -n "$1" ]] ; then
3577         for dir in $* ; do
3578             if [[ -d "$dir" ]] ; then
3579                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3580             else
3581                 echo "warning: $dir does not exist" >&2
3582             fi
3583         done
3584     else
3585         for dir in $path; do
3586             if [[ -d "$dir" ]] ; then
3587                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3588             else
3589                 echo "warning: $dir does not exist" >&2
3590             fi
3591         done
3592     fi
3593 }
3594
3595 # % slow_print `cat /etc/passwd`
3596 #f5# Slowly print out parameters
3597 slow_print() {
3598     for argument in "${@}" ; do
3599         for ((i = 1; i <= ${#1} ;i++)) ; do
3600             print -n "${argument[i]}"
3601             sleep 0.08
3602         done
3603         print -n " "
3604     done
3605     print ""
3606 }
3607
3608 #f5# Show some status info
3609 status() {
3610     print ""
3611     print "Date..: "$(date "+%Y-%m-%d %H:%M:%S")""
3612     print "Shell.: Zsh $ZSH_VERSION (PID = $$, $SHLVL nests)"
3613     print "Term..: $TTY ($TERM), $BAUD bauds, $COLUMNS x $LINES cars"
3614     print "Login.: $LOGNAME (UID = $EUID) on $HOST"
3615     print "System: $(cat /etc/[A-Za-z]*[_-][rv]e[lr]*)"
3616     print "Uptime:$(uptime)"
3617     print ""
3618 }
3619
3620 # Rip an audio CD
3621 #f5# Rip an audio CD
3622 audiorip() {
3623     mkdir -p ~/ripps
3624     cd ~/ripps
3625     cdrdao read-cd --device $DEVICE --driver generic-mmc audiocd.toc
3626     cdrdao read-cddb --device $DEVICE --driver generic-mmc audiocd.toc
3627     echo " * Would you like to burn the cd now? (yes/no)"
3628     read input
3629     if [[ "$input" = "yes" ]] ; then
3630         echo " ! Burning Audio CD"
3631         audioburn
3632         echo " * done."
3633     else
3634         echo " ! Invalid response."
3635     fi
3636 }
3637
3638 # and burn it
3639 #f5# Burn an audio CD (in combination with audiorip)
3640 audioburn() {
3641     cd ~/ripps
3642     cdrdao write --device $DEVICE --driver generic-mmc audiocd.toc
3643     echo " * Should I remove the temporary files? (yes/no)"
3644     read input
3645     if [[ "$input" = "yes" ]] ; then
3646         echo " ! Removing Temporary Files."
3647         cd ~
3648         rm -rf ~/ripps
3649         echo " * done."
3650     else
3651         echo " ! Invalid response."
3652     fi
3653 }
3654
3655 #f5# Make an audio CD from all mp3 files
3656 mkaudiocd() {
3657     # TODO: do the renaming more zshish, possibly with zmv()
3658     cd ~/ripps
3659     for i in *.[Mm][Pp]3; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done
3660     for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`; done
3661     for i in *.mp3; do mpg123 -w `basename $i .mp3`.wav $i; done
3662     normalize -m *.wav
3663     for i in *.wav; do sox $i.wav -r 44100 $i.wav resample; done
3664 }
3665
3666 #f5# Create an ISO image. You are prompted for\\&\quad volume name, filename and directory
3667 mkiso() {
3668     echo " * Volume name "
3669     read volume
3670     echo " * ISO Name (ie. tmp.iso)"
3671     read iso
3672     echo " * Directory or File"
3673     read files
3674     mkisofs -o ~/$iso -A $volume -allow-multidot -J -R -iso-level 3 -V $volume -R $files
3675 }
3676
3677 #f5# Simple thumbnails generator
3678 genthumbs() {
3679     rm -rf thumb-* index.html
3680     echo "
3681 <html>
3682   <head>
3683     <title>Images</title>
3684   </head>
3685   <body>" > index.html
3686     for f in *.(gif|jpeg|jpg|png) ; do
3687         convert -size 100x200 "$f" -resize 100x200 thumb-"$f"
3688         echo "    <a href=\"$f\"><img src=\"thumb-$f\"></a>" >> index.html
3689     done
3690     echo "
3691   </body>
3692 </html>" >> index.html
3693 }
3694
3695 #f5# Set all ulimit parameters to \kbd{unlimited}
3696 allulimit() {
3697     ulimit -c unlimited
3698     ulimit -d unlimited
3699     ulimit -f unlimited
3700     ulimit -l unlimited
3701     ulimit -n unlimited
3702     ulimit -s unlimited
3703     ulimit -t unlimited
3704 }
3705
3706 # ogg2mp3 with bitrate of 192
3707 ogg2mp3_192() {
3708     oggdec -o - ${1} | lame -b 192 - ${1:r}.mp3
3709 }
3710
3711 #f5# RFC 2396 URL encoding in Z-Shell
3712 urlencode() {
3713     setopt localoptions extendedglob
3714     input=( ${(s::)1} )
3715     print ${(j::)input/(#b)([^A-Za-z0-9_.!~*\'\(\)-])/%${(l:2::0:)$(([##16]#match))}}
3716 }
3717
3718 #f5# Install x-lite (VoIP software)
3719 getxlite() {
3720     setopt local_options
3721     setopt errreturn
3722     [[ -d ~/tmp ]] || mkdir ~/tmp
3723     cd ~/tmp
3724
3725     echo "Downloading http://www.counterpath.com/download/X-Lite_Install.tar.gz and storing it in ~/tmp:"
3726     if wget http://www.counterpath.com/download/X-Lite_Install.tar.gz ; then
3727         unp X-Lite_Install.tar.gz && echo done || echo failed
3728     else
3729         echo "Error while downloading." ; return 1
3730     fi
3731
3732     if [[ -x xten-xlite/xtensoftphone ]] ; then
3733         echo "Execute xten-xlite/xtensoftphone to start xlite."
3734     fi
3735 }
3736
3737 #f5# Install skype
3738 getskype() {
3739     setopt local_options
3740     setopt errreturn
3741     echo "Downloading debian package of skype."
3742     echo "Notice: If you want to use a more recent skype version run 'getskypebeta'."
3743     wget http://www.skype.com/go/getskype-linux-deb
3744     $SUDO dpkg -i skype*.deb && echo "skype installed."
3745 }
3746
3747 #f5# Install beta-version of skype
3748 getskypebeta() {
3749     setopt local_options
3750     setopt errreturn
3751     echo "Downloading debian package of skype (beta version)."
3752     wget http://www.skype.com/go/getskype-linux-beta-deb
3753     $SUDO dpkg -i skype-beta*.deb && echo "skype installed."
3754 }
3755
3756 #f5# Install gizmo (VoIP software)
3757 getgizmo() {
3758     setopt local_options
3759     setopt errreturn
3760     echo "libgtk2.0-0, gconf2, libstdc++6, libasound2 and zlib1g have to be available. Installing."
3761     $SUDO apt-get update
3762     $SUDO apt-get install libgtk2.0-0 gconf2 libstdc++6 libasound2 zlib1g
3763     wget "$(lynx --dump http://gizmo5.com/pc/download/linux/ | awk '/libstdc\+\+6.*\.deb/ {print $2}')"
3764     $SUDO dpkg -i gizmo-project*.deb && echo "gizmo installed."
3765 }
3766
3767 #f5# Get and run AIR (Automated Image and Restore)
3768 getair() {
3769     setopt local_options
3770     setopt errreturn
3771     [[ -w . ]] || { echo 'Error: you do not have write permissions in this directory. Exiting.' ; return 1 }
3772     local VER='1.2.8'
3773     wget http://puzzle.dl.sourceforge.net/sourceforge/air-imager/air-$VER.tar.gz
3774     tar zxf air-$VER.tar.gz
3775     cd air-$VER
3776     INTERACTIVE=no $SUDO ./install-air-1.2.8
3777     [[ -x /usr/local/bin/air ]] && [[ -n "$DISPLAY" ]] && $SUDO air
3778 }
3779
3780 #f5# Get specific git commitdiff
3781 git-get-diff() {
3782     if [[ -z $GITTREE ]] ; then
3783         GITTREE='linux/kernel/git/torvalds/linux-2.6.git'
3784     fi
3785     if ! [[ -z $1 ]] ; then
3786         ${=BROWSER} "http://kernel.org/git/?p=$GITTREE;a=commitdiff;h=$1"
3787     else
3788         echo "Usage: git-get-diff <commit>"
3789     fi
3790 }
3791
3792 #f5# Get specific git commit
3793 git-get-commit() {
3794     if [[ -z $GITTREE ]] ; then
3795         GITTREE='linux/kernel/git/torvalds/linux-2.6.git'
3796     fi
3797     if ! [[ -z $1 ]] ; then
3798         ${=BROWSER} "http://kernel.org/git/?p=$GITTREE;a=commit;h=$1"
3799     else
3800         echo "Usage: git-get-commit <commit>"
3801     fi
3802 }
3803
3804 #f5# Get specific git diff
3805 git-get-plaindiff () {
3806     if [[ -z $GITTREE ]] ; then
3807        GITTREE='linux/kernel/git/torvalds/linux-2.6.git'
3808     fi
3809     if [[ -z $1 ]] ; then
3810        echo 'Usage: git-get-plaindiff '
3811     else
3812        echo -n "Downloading $1.diff ... "
3813        # avoid "generating ..." stuff from kernel.org server:
3814        wget --quiet "http://kernel.org/git/?p=$GITTREE;a=commitdiff_plain;h=$1" -O /dev/null
3815        wget --quiet "http://kernel.org/git/?p=$GITTREE;a=commitdiff_plain;h=$1" -O $1.diff \
3816             && echo done || echo failed
3817     fi
3818 }
3819
3820
3821 # http://strcat.de/blog/index.php?/archives/335-Software-sauber-deinstallieren...html
3822 #f5# Log 'make install' output
3823 mmake() {
3824     [[ ! -d ~/.errorlogs ]] && mkdir ~/.errorlogs
3825     make -n install > ~/.errorlogs/${PWD##*/}-makelog
3826 }
3827
3828 #f5# Indent source code
3829 smart-indent() {
3830     indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs $*
3831 }
3832
3833 # highlight important stuff in diff output, usage example: hg diff | hidiff
3834 #m# a2 hidiff \kbd{histring} oneliner for diffs
3835 check_com -c histring && \
3836     alias hidiff="histring -fE '^Comparing files .*|^diff .*' | histring -c yellow -fE '^\-.*' | histring -c green -fE '^\+.*'"
3837
3838 # rename pictures based on information found in exif headers
3839 #f5# Rename pictures based on information found in exif headers
3840 exirename() {
3841     if [[ $# -lt 1 ]] ; then
3842         echo 'Usage: jpgrename $FILES' >& 2
3843         return 1
3844     else
3845         echo -n 'Checking for jhead with version newer than 1.9: '
3846         jhead_version=`jhead -h | grep 'used by most Digital Cameras.  v.*' | awk '{print $6}' | tr -d v`
3847         if [[ $jhead_version > '1.9' ]]; then
3848             echo 'success - now running jhead.'
3849             jhead -n%Y-%m-%d_%Hh%M_%f $*
3850         else
3851             echo 'failed - exiting.'
3852         fi
3853     fi
3854 }
3855
3856 # open file in vim and jump to line
3857 # http://www.downgra.de/archives/2007/05/08/T19_21_11/
3858 j2v() {
3859     local -a params
3860     params=(${*//(#m):[0-9]*:/\\n+${MATCH//:/}}) # replace ':23:' to '\n+23'
3861     params=(${(s|\n|)${(j|\n|)params}}) # join array using '\n', then split on all '\n'
3862     vim ${params}
3863 }
3864
3865 # get_ic() - queries imap servers for capabilities; real simple. no imaps
3866 ic_get() {
3867     local port
3868     if [[ ! -z $1 ]] ; then
3869         port=${2:-143}
3870         print "querying imap server on $1:${port}...\n";
3871         print "a1 capability\na2 logout\n" | nc $1 ${port}
3872     else
3873         print "usage:\n  $0 <imap-server> [port]"
3874     fi
3875 }
3876
3877 # creates a Maildir/ with its {new,cur,tmp} subdirs
3878 mkmaildir() {
3879     local root subdir
3880     root=${MAILDIR_ROOT:-${HOME}/Mail}
3881     if [[ -z ${1} ]] ; then print "Usage:\n $0 <dirname>" ; return 1 ; fi
3882     subdir=${1}
3883     mkdir -p ${root}/${subdir}/{cur,new,tmp}
3884 }
3885
3886 # xtrename() rename xterm from within GNU-screen
3887 xtrename() {
3888     if [[ -z ${DISPLAY} ]] ; then
3889         printf 'xtrename only makes sense in X11.\n'
3890         return 1
3891     fi
3892     if [[ -z ${1} ]] ; then
3893         printf 'usage: xtrename() "title for xterm"\n'
3894         printf '  renames the title of xterm from _within_ screen.\n'
3895         printf '  Also works without screen.\n'
3896         return 0
3897     fi
3898     print -n "\eP\e]0;${1}\C-G\e\\"
3899     return 0
3900 }
3901
3902 # hl() highlighted less
3903 # http://ft.bewatermyfriend.org/comp/data/zsh/zfunct.html
3904 if check_com -c highlight ; then
3905     function hl() {
3906         local theme lang
3907         theme=${HL_THEME:-""}
3908         case ${1} in
3909             (-l|--list)
3910                 ( printf 'available languages (syntax parameter):\n\n' ;
3911                     highlight --list-langs ; ) | less -SMr
3912                 ;;
3913             (-t|--themes)
3914                 ( printf 'available themes (style parameter):\n\n' ;
3915                     highlight --list-themes ; ) | less -SMr
3916                 ;;
3917             (-h|--help)
3918                 printf 'usage: hl <syntax[:theme]> <file>\n'
3919                 printf '    available options: --list (-l), --themes (-t), --help (-h)\n\n'
3920                 printf '  Example: hl c main.c\n'
3921                 ;;
3922             (*)
3923                 if [[ -z ${2} ]] || (( ${#argv} > 2 )) ; then
3924                     printf 'usage: hl <syntax[:theme]> <file>\n'
3925                     printf '    available options: --list (-l), --themes (-t), --help (-h)\n'
3926                     (( ${#argv} > 2 )) && printf '  Too many arguments.\n'
3927                     return 1
3928                 fi
3929                 lang=${1%:*}
3930                 [[ ${1} == *:* ]] && [[ -n ${1#*:} ]] && theme=${1#*:}
3931                 if [[ -n ${theme} ]] ; then
3932                     highlight --xterm256 --syntax ${lang} --style ${theme} ${2} | less -SMr
3933                 else
3934                     highlight --ansi --syntax ${lang} ${2} | less -SMr
3935                 fi
3936                 ;;
3937         esac
3938         return 0
3939     }
3940     # ... and a proper completion for hl()
3941     # needs 'highlight' as well, so it fits fine in here.
3942     function _hl_genarg()  {
3943         local expl
3944         if [[ -prefix 1 *: ]] ; then
3945             local themes
3946             themes=(${${${(f)"$(LC_ALL=C highlight --list-themes)"}/ #/}:#*(Installed|Use name)*})
3947             compset -P 1 '*:'
3948             _wanted -C list themes expl theme compadd ${themes}
3949         else
3950             local langs
3951             langs=(${${${(f)"$(LC_ALL=C highlight --list-langs)"}/ #/}:#*(Installed|Use name)*})
3952             _wanted -C list languages expl languages compadd -S ':' -q ${langs}
3953         fi
3954     }
3955     function _hl_complete() {
3956         _arguments -s '1: :_hl_genarg' '2:files:_path_files'
3957     }
3958     compdef _hl_complete hl
3959 fi
3960
3961 # create small urls via tinyurl.com using wget, grep and sed
3962 zurl() {
3963     [[ -z ${1} ]] && print "please give an url to shrink." && return 1
3964     local url=${1}
3965     local tiny="http://tinyurl.com/create.php?url="
3966     #print "${tiny}${url}" ; return
3967     wget  -O-             \
3968           -o/dev/null     \
3969           "${tiny}${url}" \
3970         | grep -Eio 'value="(http://tinyurl.com/.*)"' \
3971         | sed 's/value=//;s/"//g'
3972 }
3973
3974 #f2# Print a specific line of file(s).
3975 linenr () {
3976 # {{{
3977     if [ $# -lt 2 ] ; then
3978        print "Usage: linenr <number>[,<number>] <file>" ; return 1
3979     elif [ $# -eq 2 ] ; then
3980          local number=$1
3981          local file=$2
3982          command ed -s $file <<< "${number}n"
3983     else
3984          local number=$1
3985          shift
3986          for file in "$@" ; do
3987              if [ ! -d $file ] ; then
3988                 echo "${file}:"
3989                 command ed -s $file <<< "${number}n" 2> /dev/null
3990              else
3991                 continue
3992              fi
3993          done | less
3994     fi
3995 # }}}
3996 }
3997
3998 #f2# Find history events by search pattern and list them by date.
3999 whatwhen()  {
4000 # {{{
4001     local usage help ident format_l format_s first_char remain first last
4002     usage='USAGE: whatwhen [options] <searchstring> <search range>'
4003     help='Use' \`'whatwhen -h'\'' for further explanations.'
4004     ident=${(l,${#${:-Usage: }},, ,)}
4005     format_l="${ident}%s\t\t\t%s\n"
4006     format_s="${format_l//(\\t)##/\\t}"
4007     # Make the first char of the word to search for case
4008     # insensitive; e.g. [aA]
4009     first_char=[${(L)1[1]}${(U)1[1]}]
4010     remain=${1[2,-1]}
4011     # Default search range is `-100'.
4012     first=${2:-\-100}
4013     # Optional, just used for `<first> <last>' given.
4014     last=$3
4015     case $1 in
4016         ("")
4017             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
4018             printf '%s\n%s\n\n' ${usage} ${help} && return 1
4019         ;;
4020         (-h)
4021             printf '%s\n\n' ${usage}
4022             print 'OPTIONS:'
4023             printf $format_l '-h' 'show help text'
4024             print '\f'
4025             print 'SEARCH RANGE:'
4026             printf $format_l "'0'" 'the whole history,'
4027             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
4028             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
4029             printf '\n%s\n' 'EXAMPLES:'
4030             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
4031             printf $format_l 'whatwhen zsh -250'
4032             printf $format_l 'whatwhen foo 1 99'
4033         ;;
4034         (\?)
4035             printf '%s\n%s\n\n' ${usage} ${help} && return 1
4036         ;;
4037         (*)
4038             # -l list results on stout rather than invoking $EDITOR.
4039             # -i Print dates as in YYYY-MM-DD.
4040             # -m Search for a - quoted - pattern within the history.
4041             fc -li -m "*${first_char}${remain}*" $first $last
4042         ;;
4043     esac
4044 # }}}
4045 }
4046
4047 # change fluxbox keys from 'Alt-#' to 'Alt-F#' and vice versa
4048 fluxkey-change() {
4049     [[ -n "$FLUXKEYS" ]] || local FLUXKEYS="$HOME/.fluxbox/keys"
4050     if ! [[ -r "$FLUXKEYS" ]] ; then
4051         echo "Sorry, \$FLUXKEYS file $FLUXKEYS could not be read - nothing to be done."
4052         return 1
4053     else
4054         if grep -q 'Mod1 F[0-9] :Workspace [0-9]' $FLUXKEYS ; then
4055             echo -n 'Switching to Alt-# mode in ~/.fluxbox/keys: '
4056             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)F\([0-9]\+[: space :]\+:Workspace.*\)|\1\2|' $FLUXKEYS && echo done || echo failed
4057         elif grep -q 'Mod1 [0-9] :Workspace [0-9]' $FLUXKEYS ; then
4058             echo -n 'Switching to Alt-F# mode in ~/.fluxbox/keys: '
4059             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)\([0-9]\+[: space :]\+:Workspace.*\)|\1F\2|' $FLUXKEYS && echo done || echo failed
4060         else
4061             echo 'Sorry, do not know what to do.'
4062             return 1
4063         fi
4064     fi
4065 }
4066
4067 # retrieve weather information on the console
4068 # Usage example: 'weather LOWG'
4069 weather() {
4070     [[ -n "$1" ]] || {
4071         print 'Usage: weather <station_id>' >&2
4072         print 'List of stations: http://en.wikipedia.org/wiki/List_of_airports_by_ICAO_code'>&2
4073         return 1
4074     }
4075
4076     local PLACE="${1:u}"
4077     local FILE="$HOME/.weather/$PLACE"
4078     local LOG="$HOME/.weather/log"
4079
4080     [[ -d $HOME/.weather ]] || {
4081         print -n "Creating $HOME/.weather: "
4082         mkdir $HOME/.weather
4083         print 'done'
4084     }
4085
4086     print "Retrieving information for ${PLACE}:"
4087     print
4088     wget -T 10 --no-verbose --output-file=$LOG --output-document=$FILE --timestamping http://weather.noaa.gov/pub/data/observations/metar/decoded/$PLACE.TXT
4089
4090     if [[ $? -eq 0 ]] ; then
4091         if [[ -n "$VERBOSE" ]] ; then
4092             cat $FILE
4093         else
4094             DATE=$(grep 'UTC' $FILE | sed 's#.* /##')
4095             TEMPERATURE=$(awk '/Temperature/ { print $4" degree Celcius / " $2" degree Fahrenheit" }' $FILE| tr -d '(')
4096             echo "date: $DATE"
4097             echo "temp:  $TEMPERATURE"
4098         fi
4099     else
4100         print "There was an error retrieving the weather information for $PLACE" >&2
4101         cat $LOG
4102         return 1
4103     fi
4104 }
4105 # }}}
4106
4107 # mercurial related stuff {{{
4108 if check_com -c hg ; then
4109     # gnu like diff for mercurial
4110     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
4111     #f5# GNU like diff for mercurial
4112     hgdi() {
4113         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
4114     }
4115
4116     # build debian package
4117     #a2# Alias for \kbd{hg-buildpackage}
4118     alias hbp='hg-buildpackage'
4119
4120     # execute commands on the versioned patch-queue from the current repos
4121     alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
4122
4123     # diffstat for specific version of a mercurial repository
4124     #   hgstat      => display diffstat between last revision and tip
4125     #   hgstat 1234 => display diffstat between revision 1234 and tip
4126     #f5# Diffstat for specific version of a mercurial repos
4127     hgstat() {
4128         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
4129     }
4130
4131     #f5# Get current mercurial tip via hg itself
4132     gethgclone() {
4133         setopt local_options
4134         setopt errreturn
4135         if [[ -f mercurial-tree/.hg ]] ; then
4136             cd mercurial-tree
4137             echo "Running hg pull for retreiving latest version..."
4138             hg pull
4139             echo "Finished update. Building mercurial"
4140             make local
4141             echo "Setting \$PATH to $PWD:\$PATH..."
4142             export PATH="$PWD:$PATH"
4143         else
4144             echo "Downloading mercurial via hg"
4145             hg clone http://selenic.com/repo/hg mercurial-tree
4146             cd mercurial-tree
4147             echo "Building mercurial"
4148             make local
4149             echo "Setting \$PATH to $PWD:\$PATH..."
4150             export PATH="$PWD:$PATH"
4151             echo "make sure you set it permanent via ~/.zshrc if you plan to use it permanently."
4152             # echo "Setting \$PYTHONPATH to PYTHONPATH=\${HOME}/lib/python,"
4153             # export PYTHONPATH=${HOME}/lib/python
4154         fi
4155     }
4156
4157 fi # end of check whether we have the 'hg'-executable
4158
4159 # get current mercurial snapshot
4160 #f5# Get current mercurial snapshot
4161 gethgsnap() {
4162     setopt local_options
4163     setopt errreturn
4164     if [[ -f mercurial-snapshot.tar.gz ]] ; then
4165          echo "mercurial-snapshot.tar.gz exists already, skipping download."
4166     else
4167         echo "Downloading mercurial snapshot"
4168         wget http://www.selenic.com/mercurial/mercurial-snapshot.tar.gz
4169     fi
4170     echo "Unpacking mercurial-snapshot.tar.gz"
4171     tar zxf mercurial-snapshot.tar.gz
4172     cd mercurial-snapshot/
4173     echo "Installing required build-dependencies"
4174     $SUDO apt-get update
4175     $SUDO apt-get install python2.4-dev
4176     echo "Building mercurial"
4177     make local
4178     echo "Setting \$PATH to $PWD:\$PATH..."
4179     export PATH="$PWD:$PATH"
4180     echo "make sure you set it permanent via ~/.zshrc if you plan to use it permanently."
4181 }
4182 # }}}
4183
4184 # some useful commands often hard to remember - let's grep for them {{{
4185
4186 # Work around ion/xterm resize bug.
4187 #if [[ "$SHLVL" -eq 1 ]]; then
4188 #       if check_com -c resize ; then
4189 #               eval `resize </dev/null`
4190 #       fi
4191 #fi
4192
4193 # enable jackd:
4194 #  /usr/bin/jackd -dalsa -dhw:0 -r48000 -p1024 -n2
4195 # now play audio file:
4196 #  alsaplayer -o jack foobar.mp3
4197
4198 # send files via netcat
4199 # on sending side:
4200 #  send() {j=$*; tar cpz ${j/%${!#}/}|nc -w 1 ${!#} 51330;}
4201 #  send dir* $HOST
4202 #  alias receive='nc -vlp 51330 | tar xzvp'
4203
4204 # debian stuff:
4205 # dh_make -e foo@localhost -f $1
4206 # dpkg-buildpackage -rfakeroot
4207 # lintian *.deb
4208 # dpkg-scanpackages ./ /dev/null | gzip > Packages.gz
4209 # dpkg-scansources . | gzip > Sources.gz
4210 # grep-dctrl --field Maintainer $* /var/lib/apt/lists/*
4211
4212 # other stuff:
4213 # convert -geometry 200x200 -interlace LINE -verbose
4214 # ldapsearch -x -b "OU=Bedienstete,O=tug" -h ldap.tugraz.at sn=$1
4215 # ps -ao user,pcpu,start,command
4216 # gpg --keyserver blackhole.pca.dfn.de --recv-keys
4217 # xterm -bg black -fg yellow -fn -misc-fixed-medium-r-normal--14-140-75-75-c-90-iso8859-15 -ah
4218 # nc -vz $1 1-1024   # portscan via netcat
4219 # wget --mirror --no-parent --convert-links
4220 # pal -d `date +%d`
4221 # autoload -U tetris; zle -N tetris; bindkey '...' ; echo "press ... for playing tennis"
4222 #
4223 # modify console cursor
4224 # see http://www.tldp.org/HOWTO/Framebuffer-HOWTO-5.html
4225 # print $'\e[?96;0;64c'
4226 # }}}
4227
4228 # grml-small cleanups {{{
4229
4230 # The following is used to remove zsh-config-items that do not work
4231 # in grml-small by default.
4232 # If you do not want these adjustments (for whatever reason), set
4233 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
4234 # sources if it is there).
4235
4236 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
4237
4238     unset abk[V]
4239     unalias    'V'      &> /dev/null
4240     unfunction vman     &> /dev/null
4241     unfunction vimpm    &> /dev/null
4242     unfunction vimhelp  &> /dev/null
4243     unfunction viless   &> /dev/null
4244     unfunction 2html    &> /dev/null
4245
4246     # manpages are not in grmlsmall
4247     unfunction manzsh   &> /dev/null
4248     unalias    man2     &> /dev/null
4249     unalias    man      &> /dev/null
4250     unfunction man2     &> /dev/null
4251
4252 fi
4253
4254 #}}}
4255
4256 # finally source a local zshrc {{{
4257
4258 # this allows us to stay in sync with grml's zshrc and put own
4259 # modifications in ~/.zshrc.local
4260
4261 xsource "${HOME}/.zshrc.local"
4262
4263 # }}}
4264
4265 ## genrefcard.pl settings {{{
4266
4267 ### doc strings for external functions from files
4268 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
4269
4270 ### example: split functions-search 8,16,24,32
4271 #@# split functions-search 8
4272
4273 ## }}}
4274
4275 ## END OF FILE #################################################################
4276 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4