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