Remove included vcs_info
[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# Unified diff to timestamped outputfile
2660 mdiff() {
2661     diff -udrP "$1" "$2" > diff.`date "+%Y-%m-%d"`."$1"
2662 }
2663 #f5# Memory overview
2664 memusage() {
2665     ps aux | awk '{if (NR > 1) print $5; if (NR > 2) print "+"} END { print "p" }' | dc
2666 }
2667 #f5# Show contents of gzipped tar file
2668 shtar() {
2669     emulate -L zsh
2670     gunzip -c $1 | tar -tf - -- | $PAGER
2671 }
2672 #f5# Show contents of zip file
2673 shzip() {
2674     emulate -L zsh
2675     unzip -l $1 | $PAGER
2676 }
2677 #f5# Unified diff
2678 udiff() {
2679     emulate -L zsh
2680     diff -urd $* | egrep -v "^Only in |^Binary files "
2681 }
2682 #f5# (Mis)use \kbd{vim} as \kbd{less}
2683 viless() {
2684     emulate -L zsh
2685     vim --cmd 'let no_plugin_maps = 1' -c "so \$VIMRUNTIME/macros/less.vim" "${@:--}"
2686 }
2687
2688 # Function Usage: uopen $URL/$file
2689 #f5# Download a file and display it locally
2690 uopen() {
2691     emulate -L zsh
2692     if ! [[ -n "$1" ]] ; then
2693         print "Usage: uopen \$URL/\$file">&2
2694         return 1
2695     else
2696         FILE=$1
2697         MIME=$(curl --head $FILE | grep Content-Type | cut -d ' ' -f 2 | cut -d\; -f 1)
2698         MIME=${MIME%$'\r'}
2699         curl $FILE | see ${MIME}:-
2700     fi
2701 }
2702
2703 # Function Usage: doc packagename
2704 #f5# \kbd{cd} to /usr/share/doc/\textit{package}
2705 doc() {
2706     emulate -L zsh
2707     cd /usr/share/doc/$1 && ls
2708 }
2709 _doc() { _files -W /usr/share/doc -/ }
2710 check_com compdef && compdef _doc doc
2711
2712 #f5# Make screenshot
2713 sshot() {
2714     [[ ! -d ~/shots  ]] && mkdir ~/shots
2715     #cd ~/shots ; sleep 5 ; import -window root -depth 8 -quality 80 `date "+%Y-%m-%d--%H:%M:%S"`.png
2716     cd ~/shots ; sleep 5; import -window root shot_`date --iso-8601=m`.jpg
2717 }
2718
2719 # list images only
2720 limg() {
2721     local -a images
2722     images=( *.{jpg,gif,png}(.N) )
2723
2724     if [[ $#images -eq 0 ]] ; then
2725         print "No image files found"
2726     else
2727         ls "$images[@]"
2728     fi
2729 }
2730
2731 #f5# Create PDF file from source code
2732 makereadable() {
2733     emulate -L zsh
2734     output=$1
2735     shift
2736     a2ps --medium A4dj -E -o $output $*
2737     ps2pdf $output
2738 }
2739
2740 # zsh with perl-regex - use it e.g. via:
2741 # regcheck '\s\d\.\d{3}\.\d{3} Euro' ' 1.000.000 Euro'
2742 #f5# Checks whether a regex matches or not.\\&\quad Example: \kbd{regcheck '.\{3\} EUR' '500 EUR'}
2743 regcheck() {
2744     emulate -L zsh
2745     zmodload -i zsh/pcre
2746     pcre_compile $1 && \
2747     pcre_match $2 && echo "regex matches" || echo "regex does not match"
2748 }
2749
2750 #f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
2751 accessed() {
2752     emulate -L zsh
2753     print -l -- *(a-${1:-1})
2754 }
2755
2756 #f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
2757 changed() {
2758     emulate -L zsh
2759     print -l -- *(c-${1:-1})
2760 }
2761
2762 #f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
2763 modified() {
2764     emulate -L zsh
2765     print -l -- *(m-${1:-1})
2766 }
2767 # modified() was named new() in earlier versions, add an alias for backwards compatibility
2768 check_com new || alias new=modified
2769
2770 #f5# Grep in history
2771 greph() {
2772     emulate -L zsh
2773     history 0 | grep $1
2774 }
2775 # use colors when GNU grep with color-support
2776 #a2# Execute \kbd{grep -{}-color=auto}
2777 (grep --help 2>/dev/null |grep -- --color) >/dev/null && alias grep='grep --color=auto'
2778 #a2# Execute \kbd{grep -i -{}-color=auto}
2779 alias GREP='grep -i --color=auto'
2780
2781 #f5# Watch manpages in a stretched style
2782 man2() { PAGER='dash -c "sed G | /usr/bin/less"' command man "$@" ; }
2783
2784 # usage example: 'lcheck strcpy'
2785 #f5# Find out which libs define a symbol
2786 lcheck() {
2787     if [[ -n "$1" ]] ; then
2788         nm -go /usr/lib/lib*.a 2>/dev/null | grep ":[[:xdigit:]]\{8\} . .*$1"
2789     else
2790         echo "Usage: lcheck <function>" >&2
2791     fi
2792 }
2793
2794 #f5# Clean up directory - remove well known tempfiles
2795 purge() {
2796     emulate -L zsh
2797     setopt HIST_SUBST_PATTERN
2798     local -a TEXTEMPFILES GHCTEMPFILES PYTEMPFILES FILES
2799     TEXTEMPFILES=(*.tex(N:s/%tex/'(log|toc|aux|nav|snm|out|tex.backup|bbl|blg|bib.backup|vrb|lof|lot|hd|idx)(N)'/))
2800     GHCTEMPFILES=(*.(hs|lhs)(N:r:s/%/'.(hi|hc|(p|u|s)_(o|hi))(N)'/))
2801     PYTEMPFILES=(*.py(N:s/%py/'(pyc|pyo)(N)'/))
2802     LONELY_MOOD_FILES=((*.mood)(NDe:'local -a AF;AF=( ${${REPLY#.}%mood}(mp3|flac|ogg|asf|wmv|aac)(N) ); [[ -z "$AF" ]]':))
2803     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})
2804     local NBFILES=${#FILES}
2805     local CURDIRSUDO=""
2806     [[ ! -w ./ ]] && CURDIRSUDO=$SUDO
2807     if [[ $NBFILES > 0 ]] ; then
2808         print -l $FILES
2809         local ans
2810         echo -n "Remove these files? [y/n] "
2811         read -q ans
2812         if [[ $ans == "y" ]] ; then
2813             $CURDIRSUDO rm ${FILES}
2814             echo ">> $PWD purged, $NBFILES files removed"
2815         else
2816             echo "Ok. .. then not.."
2817         fi
2818     fi
2819 }
2820
2821 #f5# show labels and uuids of disk devices
2822 if is439 && [[ -d /dev/disk/by-id/ ]]; then
2823     lsdisk() {
2824         emulate -L zsh
2825         setopt extendedglob
2826         local -a -U disks
2827         disks=( /dev/disk/by-id/*(@:A) )
2828         for dev in "$disks[@]"; do
2829             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)
2830             print -f "  %s\n" /dev/disk/by-id/*(@e/'[[ ${REPLY:A} == $dev ]]'/N:t)
2831         done
2832     }
2833 fi
2834
2835 #f5# run command or function in a list of directories
2836 rundirs() {
2837   local d CMD STARTDIR=$PWD
2838   CMD=$1; shift
2839   ( for d ($@) {cd -q $d && { print cd $d; ${(z)CMD} ; cd -q $STARTDIR }} )
2840 }
2841
2842 # Translate DE<=>EN
2843 # 'translate' looks up fot a word in a file with language-to-language
2844 # translations (field separator should be " : "). A typical wordlist looks
2845 # like at follows:
2846 #  | english-word : german-transmission
2847 # It's also only possible to translate english to german but not reciprocal.
2848 # Use the following oneliner to turn back the sort order:
2849 #  $ awk -F ':' '{ print $2" : "$1" "$3 }' \
2850 #    /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
2851 #f5# Translates a word
2852 trans() {
2853     emulate -L zsh
2854     case "$1" in
2855         -[dD]*)
2856             translate -l de-en $2
2857             ;;
2858         -[eE]*)
2859             translate -l en-de $2
2860             ;;
2861         *)
2862             echo "Usage: $0 { -D | -E }"
2863             echo "         -D == German to English"
2864             echo "         -E == English to German"
2865     esac
2866 }
2867
2868 #f5# List all occurrences of programm in current PATH
2869 plap() {
2870     emulate -L zsh
2871     if [[ $# = 0 ]] ; then
2872         echo "Usage:    $0 program"
2873         echo "Example:  $0 zsh"
2874         echo "Lists all occurrences of program in the current PATH."
2875     else
2876         ls -l ${^path}/*$1*(*N)
2877     fi
2878 }
2879
2880 # Found in the mailinglistarchive from Zsh (IIRC ~1996)
2881 #f5# Select items for specific command(s) from history
2882 selhist() {
2883     emulate -L zsh
2884     local TAB=$'\t';
2885     (( $# < 1 )) && {
2886         echo "Usage: $0 command"
2887         return 1
2888     };
2889     cmd=(${(f)"$(grep -w $1 $HISTFILE | sort | uniq | pr -tn)"})
2890     print -l $cmd | less -F
2891     echo -n "enter number of desired command [1 - $(( ${#cmd[@]} - 1 ))]: "
2892     local answer
2893     read answer
2894     print -z "${cmd[$answer]#*$TAB}"
2895 }
2896
2897 # Use vim to convert plaintext to HTML
2898 #f5# Transform files to html with highlighting
2899 2html() {
2900     emulate -L zsh
2901     vim -u NONE -n -c ':syntax on' -c ':so $VIMRUNTIME/syntax/2html.vim' -c ':wqa' $1 &>/dev/null
2902 }
2903
2904 # Usage: simple-extract <file>
2905 # Using option -d deletes the original archive file.
2906 #f5# Smart archive extractor
2907 simple-extract() {
2908     emulate -L zsh
2909     setopt extended_glob noclobber
2910     local DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
2911     local RC=0
2912     zparseopts -D -E "d=DELETE_ORIGINAL"
2913     for ARCHIVE in "${@}"; do
2914         case $ARCHIVE in
2915             *.(tar.bz2|tbz2|tbz))
2916                 DECOMP_CMD="tar -xvjf -"
2917                 USES_STDIN=true
2918                 USES_STDOUT=false
2919                 ;;
2920             *.(tar.gz|tgz))
2921                 DECOMP_CMD="tar -xvzf -"
2922                 USES_STDIN=true
2923                 USES_STDOUT=false
2924                 ;;
2925             *.(tar.xz|txz|tar.lzma))
2926                 DECOMP_CMD="tar -xvJf -"
2927                 USES_STDIN=true
2928                 USES_STDOUT=false
2929                 ;;
2930             *.tar)
2931                 DECOMP_CMD="tar -xvf -"
2932                 USES_STDIN=true
2933                 USES_STDOUT=false
2934                 ;;
2935             *.rar)
2936                 DECOMP_CMD="unrar x"
2937                 USES_STDIN=false
2938                 USES_STDOUT=false
2939                 ;;
2940             *.lzh)
2941                 DECOMP_CMD="lha x"
2942                 USES_STDIN=false
2943                 USES_STDOUT=false
2944                 ;;
2945             *.7z)
2946                 DECOMP_CMD="7z x"
2947                 USES_STDIN=false
2948                 USES_STDOUT=false
2949                 ;;
2950             *.(zip|jar))
2951                 DECOMP_CMD="unzip"
2952                 USES_STDIN=false
2953                 USES_STDOUT=false
2954                 ;;
2955             *.deb)
2956                 DECOMP_CMD="ar -x"
2957                 USES_STDIN=false
2958                 USES_STDOUT=false
2959                 ;;
2960             *.bz2)
2961                 DECOMP_CMD="bzip2 -d -c -"
2962                 USES_STDIN=true
2963                 USES_STDOUT=true
2964                 ;;
2965             *.(gz|Z))
2966                 DECOMP_CMD="gzip -d -c -"
2967                 USES_STDIN=true
2968                 USES_STDOUT=true
2969                 ;;
2970             *.(xz|lzma))
2971                 DECOMP_CMD="xz -d -c -"
2972                 USES_STDIN=true
2973                 USES_STDOUT=true
2974                 ;;
2975             *)
2976                 print "ERROR: '$ARCHIVE' has unrecognized archive type." >&2
2977                 RC=$((RC+1))
2978                 continue
2979                 ;;
2980         esac
2981
2982         if ! check_com ${DECOMP_CMD[(w)1]}; then
2983             echo "ERROR: ${DECOMP_CMD[(w)1]} not installed." >&2
2984             RC=$((RC+2))
2985             continue
2986         fi
2987
2988         GZTARGET="${ARCHIVE:t:r}"
2989         if [[ -f $ARCHIVE ]] ; then
2990
2991             print "Extracting '$ARCHIVE' ..."
2992             if $USES_STDIN; then
2993                 if $USES_STDOUT; then
2994                     ${=DECOMP_CMD} < "$ARCHIVE" > $GZTARGET
2995                 else
2996                     ${=DECOMP_CMD} < "$ARCHIVE"
2997                 fi
2998             else
2999                 if $USES_STDOUT; then
3000                     ${=DECOMP_CMD} "$ARCHIVE" > $GZTARGET
3001                 else
3002                     ${=DECOMP_CMD} "$ARCHIVE"
3003                 fi
3004             fi
3005             [[ $? -eq 0 && -n "$DELETE_ORIGINAL" ]] && rm -f "$ARCHIVE"
3006
3007         elif [[ "$ARCHIVE" == (#s)(https|http|ftp)://* ]] ; then
3008             if check_com curl; then
3009                 WGET_CMD="curl -k -s -o -"
3010             elif check_com wget; then
3011                 WGET_CMD="wget -q -O - --no-check-certificate"
3012             else
3013                 print "ERROR: neither wget nor curl is installed" >&2
3014                 RC=$((RC+4))
3015                 continue
3016             fi
3017             print "Downloading and Extracting '$ARCHIVE' ..."
3018             if $USES_STDIN; then
3019                 if $USES_STDOUT; then
3020                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD} > $GZTARGET
3021                     RC=$((RC+$?))
3022                 else
3023                     ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD}
3024                     RC=$((RC+$?))
3025                 fi
3026             else
3027                 if $USES_STDOUT; then
3028                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE") > $GZTARGET
3029                 else
3030                     ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE")
3031                 fi
3032             fi
3033
3034         else
3035             print "ERROR: '$ARCHIVE' is neither a valid file nor a supported URI." >&2
3036             RC=$((RC+8))
3037         fi
3038     done
3039     return $RC
3040 }
3041
3042 __archive_or_uri()
3043 {
3044     _alternative \
3045         '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)"' \
3046         '_urls:Remote Archives:_urls'
3047 }
3048
3049 _simple_extract()
3050 {
3051     _arguments \
3052         '-d[delete original archivefile after extraction]' \
3053         '*:Archive Or Uri:__archive_or_uri'
3054 }
3055 compdef _simple_extract simple-extract
3056 alias se=simple-extract
3057
3058 # Usage: smartcompress <file> (<type>)
3059 #f5# Smart archive creator
3060 smartcompress() {
3061     emulate -L zsh
3062     if [[ -n $2 ]] ; then
3063         case $2 in
3064             tgz | tar.gz)   tar -zcvf$1.$2 $1 ;;
3065             tbz2 | tar.bz2) tar -jcvf$1.$2 $1 ;;
3066             tar.Z)          tar -Zcvf$1.$2 $1 ;;
3067             tar)            tar -cvf$1.$2  $1 ;;
3068             gz | gzip)      gzip           $1 ;;
3069             bz2 | bzip2)    bzip2          $1 ;;
3070             *)
3071                 echo "Error: $2 is not a valid compression type"
3072                 ;;
3073         esac
3074     else
3075         smartcompress $1 tar.gz
3076     fi
3077 }
3078
3079 # Usage: show-archive <archive>
3080 #f5# List an archive's content
3081 show-archive() {
3082     emulate -L zsh
3083     if [[ -f $1 ]] ; then
3084         case $1 in
3085             *.tar.gz)      gunzip -c $1 | tar -tf - -- ;;
3086             *.tar)         tar -tf $1 ;;
3087             *.tgz)         tar -ztf $1 ;;
3088             *.zip)         unzip -l $1 ;;
3089             *.bz2)         bzless $1 ;;
3090             *.deb)         dpkg-deb --fsys-tarfile $1 | tar -tf - -- ;;
3091             *)             echo "'$1' Error. Please go away" ;;
3092         esac
3093     else
3094         echo "'$1' is not a valid archive"
3095     fi
3096 }
3097
3098 # It's shameless stolen from <http://www.vim.org/tips/tip.php?tip_id=167>
3099 #f5# Use \kbd{vim} as your manpage reader
3100 vman() {
3101     emulate -L zsh
3102     if (( ${#argv} == 0 )); then
3103         printf 'usage: vman <topic>\n'
3104         return 1
3105     fi
3106     man "$@" | col -b | view -c 'set ft=man nomod nolist' -
3107 }
3108
3109 # function readme() { $PAGER -- (#ia3)readme* }
3110 #f5# View all README-like files in current directory in pager
3111 readme() {
3112     emulate -L zsh
3113     local files
3114     files=(./(#i)*(read*me|lue*m(in|)ut)*(ND))
3115     if (($#files)) ; then
3116         $PAGER $files
3117     else
3118         print 'No README files.'
3119     fi
3120 }
3121
3122 # function ansi-colors()
3123 #f5# Display ANSI colors
3124 ansi-colors() {
3125     typeset esc="\033[" line1 line2
3126     echo " _ _ _40 _ _ _41_ _ _ _42 _ _ 43_ _ _ 44_ _ _45 _ _ _ 46_ _ _ 47_ _ _ 49_ _"
3127     for fore in 30 31 32 33 34 35 36 37; do
3128         line1="$fore "
3129         line2="   "
3130         for back in 40 41 42 43 44 45 46 47 49; do
3131             line1="${line1}${esc}${back};${fore}m Normal ${esc}0m"
3132             line2="${line2}${esc}${back};${fore};1m Bold   ${esc}0m"
3133         done
3134         echo -e "$line1\n$line2"
3135     done
3136 }
3137
3138 #f5# Find all files in \$PATH with setuid bit set
3139 suidfind() { ls -latg $path | grep '^...s' }
3140
3141 # TODO: So, this is the third incarnation of this function!?
3142 #f5# Reload given functions
3143 refunc() {
3144     for func in $argv ; do
3145         unfunction $func
3146         autoload $func
3147     done
3148 }
3149 compdef _functions refunc
3150
3151 # a small check to see which DIR is located on which server/partition.
3152 # stolen and modified from Sven's zshrc.forall
3153 #f5# Report diskusage of a directory
3154 dirspace() {
3155     emulate -L zsh
3156     if [[ -n "$1" ]] ; then
3157         for dir in "$@" ; do
3158             if [[ -d "$dir" ]] ; then
3159                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3160             else
3161                 echo "warning: $dir does not exist" >&2
3162             fi
3163         done
3164     else
3165         for dir in $path; do
3166             if [[ -d "$dir" ]] ; then
3167                 ( cd $dir; echo "-<$dir>"; du -shx .; echo);
3168             else
3169                 echo "warning: $dir does not exist" >&2
3170             fi
3171         done
3172     fi
3173 }
3174
3175 # % slow_print `cat /etc/passwd`
3176 #f5# Slowly print out parameters
3177 slow_print() {
3178     for argument in "$@" ; do
3179         for ((i = 1; i <= ${#1} ;i++)) ; do
3180             print -n "${argument[i]}"
3181             sleep 0.08
3182         done
3183         print -n " "
3184     done
3185     print ""
3186 }
3187
3188 #f5# Show some status info
3189 status() {
3190     print
3191     print "Date..: "$(date "+%Y-%m-%d %H:%M:%S")
3192     print "Shell.: Zsh $ZSH_VERSION (PID = $$, $SHLVL nests)"
3193     print "Term..: $TTY ($TERM), ${BAUD:+$BAUD bauds, }$COLUMNS x $LINES chars"
3194     print "Login.: $LOGNAME (UID = $EUID) on $HOST"
3195     print "System: $(cat /etc/[A-Za-z]*[_-][rv]e[lr]*)"
3196     print "Uptime:$(uptime)"
3197     print
3198 }
3199
3200 # Rip an audio CD
3201 #f5# Rip an audio CD
3202 audiorip() {
3203     mkdir -p ~/ripps
3204     cd ~/ripps
3205     cdrdao read-cd --device $DEVICE --driver generic-mmc audiocd.toc
3206     cdrdao read-cddb --device $DEVICE --driver generic-mmc audiocd.toc
3207     echo " * Would you like to burn the cd now? (yes/no)"
3208     read input
3209     if [[ "$input" = "yes" ]] ; then
3210         echo " ! Burning Audio CD"
3211         audioburn
3212         echo " * done."
3213     else
3214         echo " ! Invalid response."
3215     fi
3216 }
3217
3218 # and burn it
3219 #f5# Burn an audio CD (in combination with audiorip)
3220 audioburn() {
3221     cd ~/ripps
3222     cdrdao write --device $DEVICE --driver generic-mmc audiocd.toc
3223     echo " * Should I remove the temporary files? (yes/no)"
3224     read input
3225     if [[ "$input" = "yes" ]] ; then
3226         echo " ! Removing Temporary Files."
3227         cd ~
3228         rm -rf ~/ripps
3229         echo " * done."
3230     else
3231         echo " ! Invalid response."
3232     fi
3233 }
3234
3235 #f5# Make an audio CD from all mp3 files
3236 mkaudiocd() {
3237     # TODO: do the renaming more zshish, possibly with zmv()
3238     emulate -L zsh
3239     cd ~/ripps
3240     for i in *.[Mm][Pp]3; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done
3241     for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`; done
3242     for i in *.mp3; do mpg123 -w `basename $i .mp3`.wav $i; done
3243     normalize -m *.wav
3244     for i in *.wav; do sox $i.wav -r 44100 $i.wav resample; done
3245 }
3246
3247 #f5# Create an ISO image. You are prompted for\\&\quad volume name, filename and directory
3248 mkiso() {
3249     emulate -L zsh
3250     echo " * Volume name "
3251     read volume
3252     echo " * ISO Name (ie. tmp.iso)"
3253     read iso
3254     echo " * Directory or File"
3255     read files
3256     mkisofs -o ~/$iso -A $volume -allow-multidot -J -R -iso-level 3 -V $volume -R $files
3257 }
3258
3259 #f5# Simple thumbnails generator
3260 genthumbs() {
3261     rm -rf thumb-* index.html
3262     echo "
3263 <html>
3264   <head>
3265     <title>Images</title>
3266   </head>
3267   <body>" > index.html
3268     for f in *.(gif|jpeg|jpg|png) ; do
3269         convert -size 100x200 "$f" -resize 100x200 thumb-"$f"
3270         echo "    <a href=\"$f\"><img src=\"thumb-$f\"></a>" >> index.html
3271     done
3272     echo "
3273   </body>
3274 </html>" >> index.html
3275 }
3276
3277 #f5# Set all ulimit parameters to \kbd{unlimited}
3278 allulimit() {
3279     ulimit -c unlimited
3280     ulimit -d unlimited
3281     ulimit -f unlimited
3282     ulimit -l unlimited
3283     ulimit -n unlimited
3284     ulimit -s unlimited
3285     ulimit -t unlimited
3286 }
3287
3288 # 2mp3 transcodes flac and ogg to mp3 with bitrate of 192 while preserving basic tags
3289 if check_com lame; then
3290     2mp3_192() {
3291         emulate -L zsh
3292         setopt extendedglob
3293         unsetopt ksharrays
3294
3295         local -a DECODE id3tags
3296         local -A tagmap
3297         local tagdata
3298         local RC=0
3299         tagmap=("(#l)title" --tt "(#l)artist" --ta "(#l)tracknumber" --tn "(#l)genre" --tg "(#l)album" --tl)
3300
3301         if [[ ${@[(i)*.ogg]} -le ${#@} ]] && ! check_com oggdec; then
3302             echo "ERROR: please install oggdec" >&2
3303             return 1
3304         fi
3305         if [[ ${@[(i)*.flac]} -le ${#@} ]] && ! check_com flac; then
3306             echo "ERROR: please install flac" >&2
3307             return 1
3308         fi
3309
3310         for af in "$@"; do
3311             id3tags=()
3312             case "$af" in
3313                 (*.flac)
3314                     DECODE=(flac -d -c "$af")
3315                     tagdata="$(metaflac --export-tags-to=- "$af")"
3316                     ;;
3317                 (*.ogg)
3318                     DECODE=(oggdec -Q -o - "$af")
3319                     tagdata="$(ogginfo "$af")"
3320                     ;;
3321                 (*) continue ;;
3322             esac
3323             for line (${(f)tagdata}) \
3324                 [[ "$line" == (#s)[[:space:]]#(#b)([^=]##)=(*)(#e) && -n $tagmap[(k)$match[1]] ]] && \
3325                 id3tags+=($tagmap[(k)$match[1]] "$match[2]")
3326             [[ ${#id3tags} -gt 0 ]] && id3tags=(--add-id3v2 --ignore-tag-errors $id3tags)
3327             $DECODE[*] | lame -b 192 -v -h --replaygain-fast  "${id3tags[@]}" - "${af:r}.mp3" || {RC=$?; print "Error transcoding" "${af}"; }
3328         done
3329         # return 0 if no error or exit code if at least one error happened
3330         return $RC
3331     }
3332     alias ogg2mp3_192 2mp3_192
3333 fi
3334
3335 #f5# RFC 2396 URL encoding in Z-Shell
3336 urlencode() {
3337     emulate -L zsh
3338     setopt extendedglob
3339     input=( ${(s::)1} )
3340     print ${(j::)input/(#b)([^A-Za-z0-9_.!~*\'\(\)-])/%${(l:2::0:)$(([##16]#match))}}
3341 }
3342
3343 # http://strcat.de/blog/index.php?/archives/335-Software-sauber-deinstallieren...html
3344 #f5# Log 'make install' output
3345 mmake() {
3346     emulate -L zsh
3347     [[ ! -d ~/.errorlogs ]] && mkdir ~/.errorlogs
3348     make -n install > ~/.errorlogs/${PWD##*/}-makelog
3349 }
3350
3351 #f5# Indent source code
3352 smart-indent() {
3353     indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs "$@"
3354 }
3355
3356 # highlight important stuff in diff output, usage example: hg diff | hidiff
3357 #m# a2 hidiff \kbd{histring} oneliner for diffs
3358 check_com -c histring && \
3359     alias hidiff="histring -fE '^Comparing files .*|^diff .*' | histring -c yellow -fE '^\-.*' | histring -c green -fE '^\+.*'"
3360
3361 # rename pictures based on information found in exif headers
3362 #f5# Rename pictures based on information found in exif headers
3363 exirename() {
3364     emulate -L zsh
3365     if [[ $# -lt 1 ]] ; then
3366         echo 'Usage: jpgrename $FILES' >& 2
3367         return 1
3368     else
3369         echo -n 'Checking for jhead with version newer than 1.9: '
3370         jhead_version=`jhead -h | grep 'used by most Digital Cameras.  v.*' | awk '{print $6}' | tr -d v`
3371         if [[ $jhead_version > '1.9' ]]; then
3372             echo 'success - now running jhead.'
3373             jhead -n%Y-%m-%d_%Hh%M_%f $*
3374         else
3375             echo 'failed - exiting.'
3376         fi
3377     fi
3378 }
3379
3380 # get_ic() - queries imap servers for capabilities; real simple. no imaps
3381 ic_get() {
3382     emulate -L zsh
3383     local port
3384     if [[ ! -z $1 ]] ; then
3385         port=${2:-143}
3386         print "querying imap server on $1:${port}...\n";
3387         print "a1 capability\na2 logout\n" | nc $1 ${port}
3388     else
3389         print "usage:\n  $0 <imap-server> [port]"
3390     fi
3391 }
3392
3393 # creates a Maildir/ with its {new,cur,tmp} subdirs
3394 mkmaildir() {
3395     emulate -L zsh
3396     local root subdir
3397     root=${MAILDIR_ROOT:-${HOME}/Mail}
3398     if [[ -z ${1} ]] ; then print "Usage:\n $0 <dirname>" ; return 1 ; fi
3399     subdir=${1}
3400     mkdir -p ${root}/${subdir}/{cur,new,tmp}
3401 }
3402
3403 #f5# Change the xterm title from within GNU-screen
3404 xtrename() {
3405     emulate -L zsh
3406     if [[ $1 != "-f" ]] ; then
3407         if [[ -z ${DISPLAY} ]] ; then
3408             printf 'xtrename only makes sense in X11.\n'
3409             return 1
3410         fi
3411     else
3412         shift
3413     fi
3414     if [[ -z $1 ]] ; then
3415         printf 'usage: xtrename [-f] "title for xterm"\n'
3416         printf '  renames the title of xterm from _within_ screen.\n'
3417         printf '  also works without screen.\n'
3418         printf '  will not work if DISPLAY is unset, use -f to override.\n'
3419         return 0
3420     fi
3421     print -n "\eP\e]0;${1}\C-G\e\\"
3422     return 0
3423 }
3424
3425 # hl() highlighted less
3426 # http://ft.bewatermyfriend.org/comp/data/zsh/zfunct.html
3427 if check_com -c highlight ; then
3428     function hl() {
3429     emulate -L zsh
3430         local theme lang
3431         theme=${HL_THEME:-""}
3432         case ${1} in
3433             (-l|--list)
3434                 ( printf 'available languages (syntax parameter):\n\n' ;
3435                     highlight --list-langs ; ) | less -SMr
3436                 ;;
3437             (-t|--themes)
3438                 ( printf 'available themes (style parameter):\n\n' ;
3439                     highlight --list-themes ; ) | less -SMr
3440                 ;;
3441             (-h|--help)
3442                 printf 'usage: hl <syntax[:theme]> <file>\n'
3443                 printf '    available options: --list (-l), --themes (-t), --help (-h)\n\n'
3444                 printf '  Example: hl c main.c\n'
3445                 ;;
3446             (*)
3447                 if [[ -z ${2} ]] || (( ${#argv} > 2 )) ; then
3448                     printf 'usage: hl <syntax[:theme]> <file>\n'
3449                     printf '    available options: --list (-l), --themes (-t), --help (-h)\n'
3450                     (( ${#argv} > 2 )) && printf '  Too many arguments.\n'
3451                     return 1
3452                 fi
3453                 lang=${1%:*}
3454                 [[ ${1} == *:* ]] && [[ -n ${1#*:} ]] && theme=${1#*:}
3455                 if [[ -n ${theme} ]] ; then
3456                     highlight --xterm256 --syntax ${lang} --style ${theme} ${2} | less -SMr
3457                 else
3458                     highlight --ansi --syntax ${lang} ${2} | less -SMr
3459                 fi
3460                 ;;
3461         esac
3462         return 0
3463     }
3464     # ... and a proper completion for hl()
3465     # needs 'highlight' as well, so it fits fine in here.
3466     function _hl_genarg()  {
3467         local expl
3468         if [[ -prefix 1 *: ]] ; then
3469             local themes
3470             themes=(${${${(f)"$(LC_ALL=C highlight --list-themes)"}/ #/}:#*(Installed|Use name)*})
3471             compset -P 1 '*:'
3472             _wanted -C list themes expl theme compadd ${themes}
3473         else
3474             local langs
3475             langs=(${${${(f)"$(LC_ALL=C highlight --list-langs)"}/ #/}:#*(Installed|Use name)*})
3476             _wanted -C list languages expl languages compadd -S ':' -q ${langs}
3477         fi
3478     }
3479     function _hl_complete() {
3480         _arguments -s '1: :_hl_genarg' '2:files:_path_files'
3481     }
3482     compdef _hl_complete hl
3483 fi
3484
3485 # TODO:
3486 # Rewrite this by either using tinyurl.com's API
3487 # or using another shortening service to comply with
3488 # tinyurl.com's policy.
3489 #
3490 # Create small urls via http://tinyurl.com using wget(1).
3491 #function zurl() {
3492 #    emulate -L zsh
3493 #    [[ -z $1 ]] && { print "USAGE: zurl <URL>" ; return 1 }
3494 #
3495 #    local PN url tiny grabber search result preview
3496 #    PN=$0
3497 #    url=$1
3498 ##   Check existence of given URL with the help of ping(1).
3499 ##   N.B. ping(1) only works without an eventual given protocol.
3500 #    ping -c 1 ${${url#(ftp|http)://}%%/*} >& /dev/null || \
3501 #        read -q "?Given host ${${url#http://*/}%/*} is not reachable by pinging. Proceed anyway? [y|n] "
3502 #
3503 #    if (( $? == 0 )) ; then
3504 ##           Prepend 'http://' to given URL where necessary for later output.
3505 #            [[ ${url} != http(s|)://* ]] && url='http://'${url}
3506 #            tiny='http://tinyurl.com/create.php?url='
3507 #            if check_com -c wget ; then
3508 #                grabber='wget -O- -o/dev/null'
3509 #            else
3510 #                print "wget is not available, but mandatory for ${PN}. Aborting."
3511 #            fi
3512 ##           Looking for i.e.`copy('http://tinyurl.com/7efkze')' in TinyURL's HTML code.
3513 #            search='copy\(?http://tinyurl.com/[[:alnum:]]##*'
3514 #            result=${(M)${${${(f)"$(${=grabber} ${tiny}${url})"}[(fr)${search}*]}//[()\';]/}%%http:*}
3515 ##           TinyURL provides the rather new feature preview for more confidence. <http://tinyurl.com/preview.php>
3516 #            preview='http://preview.'${result#http://}
3517 #
3518 #            printf '%s\n\n' "${PN} - Shrinking long URLs via webservice TinyURL <http://tinyurl.com>."
3519 #            printf '%s\t%s\n\n' 'Given URL:' ${url}
3520 #            printf '%s\t%s\n\t\t%s\n' 'TinyURL:' ${result} ${preview}
3521 #    else
3522 #        return 1
3523 #    fi
3524 #}
3525
3526 #f2# Print a specific line of file(s).
3527 linenr () {
3528 # {{{
3529     emulate -L zsh
3530     if [ $# -lt 2 ] ; then
3531        print "Usage: linenr <number>[,<number>] <file>" ; return 1
3532     elif [ $# -eq 2 ] ; then
3533          local number=$1
3534          local file=$2
3535          command ed -s $file <<< "${number}n"
3536     else
3537          local number=$1
3538          shift
3539          for file in "$@" ; do
3540              if [ ! -d $file ] ; then
3541                 echo "${file}:"
3542                 command ed -s $file <<< "${number}n" 2> /dev/null
3543              else
3544                 continue
3545              fi
3546          done | less
3547     fi
3548 # }}}
3549 }
3550
3551 #f2# Find history events by search pattern and list them by date.
3552 whatwhen()  {
3553 # {{{
3554     emulate -L zsh
3555     local usage help ident format_l format_s first_char remain first last
3556     usage='USAGE: whatwhen [options] <searchstring> <search range>'
3557     help='Use `whatwhen -h'\'' for further explanations.'
3558     ident=${(l,${#${:-Usage: }},, ,)}
3559     format_l="${ident}%s\t\t\t%s\n"
3560     format_s="${format_l//(\\t)##/\\t}"
3561     # Make the first char of the word to search for case
3562     # insensitive; e.g. [aA]
3563     first_char=[${(L)1[1]}${(U)1[1]}]
3564     remain=${1[2,-1]}
3565     # Default search range is `-100'.
3566     first=${2:-\-100}
3567     # Optional, just used for `<first> <last>' given.
3568     last=$3
3569     case $1 in
3570         ("")
3571             printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
3572             printf '%s\n%s\n\n' ${usage} ${help} && return 1
3573         ;;
3574         (-h)
3575             printf '%s\n\n' ${usage}
3576             print 'OPTIONS:'
3577             printf $format_l '-h' 'show help text'
3578             print '\f'
3579             print 'SEARCH RANGE:'
3580             printf $format_l "'0'" 'the whole history,'
3581             printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
3582             printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
3583             printf '\n%s\n' 'EXAMPLES:'
3584             printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
3585             printf $format_l 'whatwhen zsh -250'
3586             printf $format_l 'whatwhen foo 1 99'
3587         ;;
3588         (\?)
3589             printf '%s\n%s\n\n' ${usage} ${help} && return 1
3590         ;;
3591         (*)
3592             # -l list results on stout rather than invoking $EDITOR.
3593             # -i Print dates as in YYYY-MM-DD.
3594             # -m Search for a - quoted - pattern within the history.
3595             fc -li -m "*${first_char}${remain}*" $first $last
3596         ;;
3597     esac
3598 # }}}
3599 }
3600
3601 # change fluxbox keys from 'Alt-#' to 'Alt-F#' and vice versa
3602 fluxkey-change() {
3603     emulate -L zsh
3604     [[ -n "$FLUXKEYS" ]] || local FLUXKEYS="$HOME/.fluxbox/keys"
3605     if ! [[ -r "$FLUXKEYS" ]] ; then
3606         echo "Sorry, \$FLUXKEYS file $FLUXKEYS could not be read - nothing to be done."
3607         return 1
3608     else
3609         if grep -q 'Mod1 F[0-9] :Workspace [0-9]' $FLUXKEYS ; then
3610             echo -n 'Switching to Alt-# mode in ~/.fluxbox/keys: '
3611             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)F\([0-9]\+[: space :]\+:Workspace.*\)|\1\2|' $FLUXKEYS && echo done || echo failed
3612         elif grep -q 'Mod1 [0-9] :Workspace [0-9]' $FLUXKEYS ; then
3613             echo -n 'Switching to Alt-F# mode in ~/.fluxbox/keys: '
3614             sed -i -e 's|^\(Mod[0-9]\+[: space :]\+\)\([0-9]\+[: space :]\+:Workspace.*\)|\1F\2|' $FLUXKEYS && echo done || echo failed
3615         else
3616             echo 'Sorry, do not know what to do.'
3617             return 1
3618         fi
3619     fi
3620 }
3621
3622 # retrieve weather information on the console
3623 # Usage example: 'weather LOWG'
3624 weather() {
3625     emulate -L zsh
3626     [[ -n "$1" ]] || {
3627         print 'Usage: weather <station_id>' >&2
3628         print 'List of stations: http://en.wikipedia.org/wiki/List_of_airports_by_ICAO_code'>&2
3629         return 1
3630     }
3631
3632     local VERBOSE="yes"    # TODO: Make this a command line switch
3633
3634     local ODIR=`pwd`
3635     local PLACE="${1:u}"
3636     local DIR="${HOME}/.weather"
3637     local LOG="${DIR}/log"
3638
3639     [[ -d ${DIR} ]] || {
3640         print -n "Creating ${DIR}: "
3641         mkdir ${DIR}
3642         print 'done'
3643     }
3644
3645     print "Retrieving information for ${PLACE}:"
3646     print
3647     cd ${DIR} && wget -T 10 --no-verbose --output-file=$LOG --timestamping http://weather.noaa.gov/pub/data/observations/metar/decoded/$PLACE.TXT
3648
3649     if [[ $? -eq 0 ]] ; then
3650         if [[ -n "$VERBOSE" ]] ; then
3651             cat ${PLACE}.TXT
3652         else
3653             DATE=$(grep 'UTC' ${PLACE}.TXT | sed 's#.* /##')
3654             TEMPERATURE=$(awk '/Temperature/ { print $4" degree Celcius / " $2" degree Fahrenheit" }' ${PLACE}.TXT | tr -d '(')
3655             echo "date: $DATE"
3656             echo "temp:  $TEMPERATURE"
3657         fi
3658     else
3659         print "There was an error retrieving the weather information for $PLACE" >&2
3660         cat $LOG
3661         cd $ODIR
3662         return 1
3663     fi
3664     cd $ODIR
3665 }
3666 # }}}
3667
3668 # mercurial related stuff {{{
3669 if check_com -c hg ; then
3670     # gnu like diff for mercurial
3671     # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
3672     #f5# GNU like diff for mercurial
3673     hgdi() {
3674         emulate -L zsh
3675         for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
3676     }
3677
3678     # build debian package
3679     #a2# Alias for \kbd{hg-buildpackage}
3680     alias hbp='hg-buildpackage'
3681
3682     # execute commands on the versioned patch-queue from the current repos
3683     alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
3684
3685     # diffstat for specific version of a mercurial repository
3686     #   hgstat      => display diffstat between last revision and tip
3687     #   hgstat 1234 => display diffstat between revision 1234 and tip
3688     #f5# Diffstat for specific version of a mercurial repos
3689     hgstat() {
3690         emulate -L zsh
3691         [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
3692     }
3693
3694 fi # end of check whether we have the 'hg'-executable
3695
3696 # }}}
3697
3698 # some useful commands often hard to remember - let's grep for them {{{
3699 # actually use our zg() function now. :)
3700
3701 # Work around ion/xterm resize bug.
3702 #if [[ "$SHLVL" -eq 1 ]]; then
3703 #       if check_com -c resize ; then
3704 #               eval `resize </dev/null`
3705 #       fi
3706 #fi
3707
3708 # enable jackd:
3709 #  /usr/bin/jackd -dalsa -dhw:0 -r48000 -p1024 -n2
3710 # now play audio file:
3711 #  alsaplayer -o jack foobar.mp3
3712
3713 # send files via netcat
3714 # on sending side:
3715 #  send() {j=$*; tar cpz ${j/%${!#}/}|nc -w 1 ${!#} 51330;}
3716 #  send dir* $HOST
3717 #  alias receive='nc -vlp 51330 | tar xzvp'
3718
3719 # debian stuff:
3720 # dh_make -e foo@localhost -f $1
3721 # dpkg-buildpackage -rfakeroot
3722 # lintian *.deb
3723 # dpkg-scanpackages ./ /dev/null | gzip > Packages.gz
3724 # dpkg-scansources . | gzip > Sources.gz
3725 # grep-dctrl --field Maintainer $* /var/lib/apt/lists/*
3726
3727 # other stuff:
3728 # convert -geometry 200x200 -interlace LINE -verbose
3729 # ldapsearch -x -b "OU=Bedienstete,O=tug" -h ldap.tugraz.at sn=$1
3730 # ps -ao user,pcpu,start,command
3731 # gpg --keyserver blackhole.pca.dfn.de --recv-keys
3732 # xterm -bg black -fg yellow -fn -misc-fixed-medium-r-normal--14-140-75-75-c-90-iso8859-15 -ah
3733 # nc -vz $1 1-1024   # portscan via netcat
3734 # wget --mirror --no-parent --convert-links
3735 # pal -d `date +%d`
3736 # autoload -U tetris; zle -N tetris; bindkey '...' ; echo "press ... for playing tennis"
3737 #
3738 # modify console cursor
3739 # see http://www.tldp.org/HOWTO/Framebuffer-HOWTO-5.html
3740 # print $'\e[?96;0;64c'
3741 # }}}
3742
3743 # grml-small cleanups {{{
3744
3745 # The following is used to remove zsh-config-items that do not work
3746 # in grml-small by default.
3747 # If you do not want these adjustments (for whatever reason), set
3748 # $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
3749 # sources if it is there).
3750
3751 if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
3752
3753     unset abk[V]
3754     unalias    'V'      &> /dev/null
3755     unfunction vman     &> /dev/null
3756     unfunction viless   &> /dev/null
3757     unfunction 2html    &> /dev/null
3758
3759     # manpages are not in grmlsmall
3760     unfunction manzsh   &> /dev/null
3761     unfunction man2     &> /dev/null
3762
3763 fi
3764
3765 #}}}
3766
3767 zrclocal
3768
3769 ## genrefcard.pl settings {{{
3770
3771 ### doc strings for external functions from files
3772 #m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
3773
3774 ### example: split functions-search 8,16,24,32
3775 #@# split functions-search 8
3776
3777 ## }}}
3778
3779 ## END OF FILE #################################################################
3780 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
3781 # Local variables:
3782 # mode: sh
3783 # End: