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