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