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