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