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