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