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