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