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