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