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