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