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