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