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