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