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