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