zshrc: update zsh-help() output
[grml-etc-core.git] / etc / zsh / zshrc
1 # Filename:      zshrc
2 # Purpose:       config file for zsh (z shell)
3 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
4 # Bug-Reports:   see http://grml.org/bugs/
5 # License:       This file is licensed under the GPL v2.
6 # Latest change: Wed Aug 06 23:50:53 CEST 2008 [mika]
7 ################################################################################
8 # This file is sourced only for interactive shells. It
9 # should contain commands to set up aliases, functions,
10 # options, key bindings, etc.
11 #
12 # Global Order: zshenv, zprofile, zshrc, zlogin
13 ################################################################################
14
15 # zsh-refcard-tag documentation: {{{
16 #   You may notice strange looking comments in the zshrc (and ~/.zshrc as
17 #   well). These are there for a purpose. grml's zsh-refcard can now be
18 #   automatically generated from the contents of the actual configuration
19 #   files. However, we need a little extra information on which comments
20 #   and what lines of code to take into account (and for what purpose).
21 #
22 # Here is what they mean:
23 #
24 # List of tags (comment types) used:
25 #   #a#     Next line contains an important alias, that should
26 #           be included in the grml-zsh-refcard.
27 #           (placement tag: @@INSERT-aliases@@)
28 #   #f#     Next line contains the beginning of an important function.
29 #           (placement tag: @@INSERT-functions@@)
30 #   #v#     Next line contains an important variable.
31 #           (placement tag: @@INSERT-variables@@)
32 #   #k#     Next line contains an important keybinding.
33 #           (placement tag: @@INSERT-keybindings@@)
34 #   #d#     Hashed directories list generation:
35 #               start   denotes the start of a list of 'hash -d'
36 #                       definitions.
37 #               end     denotes its end.
38 #           (placement tag: @@INSERT-hasheddirs@@)
39 #   #A#     Abbreviation expansion list generation:
40 #               start   denotes the beginning of abbreviations.
41 #               end     denotes their end.
42 #           Lines within this section that end in '#d .*' provide
43 #           extra documentation to be included in the refcard.
44 #           (placement tag: @@INSERT-abbrev@@)
45 #   #m#     This tag allows you to manually generate refcard entries
46 #           for code lines that are hard/impossible to parse.
47 #               Example:
48 #                   #m# k ESC-h Call the run-help function
49 #               That would add a refcard entry in the keybindings table
50 #               for 'ESC-h' with the given comment.
51 #           So the syntax is: #m# <section> <argument> <comment>
52 #   #o#     This tag lets you insert entries to the 'other' hash.
53 #           Generally, this should not be used. It is there for
54 #           things that cannot be done easily in another way.
55 #           (placement tag: @@INSERT-other-foobar@@)
56 #
57 #   All of these tags (except for m and o) take two arguments, the first
58 #   within the tag, the other after the tag:
59 #
60 #   #<tag><section># <comment>
61 #
62 #   Where <section> is really just a number, which are defined by the
63 #   @secmap array on top of 'genrefcard.pl'. The reason for numbers
64 #   instead of names is, that for the reader, the tag should not differ
65 #   much from a regular comment. For zsh, it is a regular comment indeed.
66 #   The numbers have got the following meanings:
67 #         0 -> "default"
68 #         1 -> "system"
69 #         2 -> "user"
70 #         3 -> "debian"
71 #         4 -> "search"
72 #         5 -> "shortcuts"
73 #         6 -> "services"
74 #
75 #   So, the following will add an entry to the 'functions' table in the
76 #   'system' section, with a (hopefully) descriptive comment:
77 #       #f1# Edit an alias via zle
78 #       edalias() {
79 #
80 #   It will then show up in the @@INSERT-aliases-system@@ replacement tag
81 #   that can be found in 'grml-zsh-refcard.tex.in'.
82 #   If the section number is omitted, the 'default' section is assumed.
83 #   Furthermore, in 'grml-zsh-refcard.tex.in' @@INSERT-aliases@@ is
84 #   exactly the same as @@INSERT-aliases-default@@. If you want a list of
85 #   *all* aliases, for example, use @@INSERT-aliases-all@@.
86 #}}}
87
88 # zsh profiling {{{
89 # just execute 'ZSH_PROFILE_RC=1 zsh' and run 'zprof' to get the details
90 if [[ $ZSH_PROFILE_RC -gt 0 ]] ; then
91     zmodload zsh/zprof
92 fi
93 # }}}
94
95 # {{{ check for version/system
96 # check for versions (compatibility reasons)
97 is4(){
98     [[ $ZSH_VERSION == <4->* ]] && return 0
99     return 1
100 }
101
102 is41(){
103     [[ $ZSH_VERSION == 4.<1->* || $ZSH_VERSION == <5->* ]] && return 0
104     return 1
105 }
106
107 is42(){
108     [[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
109     return 1
110 }
111
112 is425(){
113     [[ $ZSH_VERSION == 4.2.<5->* || $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
114     return 1
115 }
116
117 is43(){
118     [[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
119     return 1
120 }
121
122 #f1# Checks whether or not you're running grml
123 isgrml(){
124     [[ -f /etc/grml_version ]] && return 0
125     return 1
126 }
127
128 #f1# Checks whether or not you're running a grml cd
129 isgrmlcd(){
130     [[ -f /etc/grml_cd ]] && return 0
131     return 1
132 }
133
134 if isgrml ; then
135 #f1# Checks whether or not you're running grml-small
136     isgrmlsmall() {
137         [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
138     }
139 else
140     isgrmlsmall() { return 1 }
141 fi
142
143 #f1# are we running within an utf environment?
144 isutfenv() {
145     case "$LANG $CHARSET $LANGUAGE" in
146         *utf*) return 0 ;;
147         *UTF*) return 0 ;;
148         *)     return 1 ;;
149     esac
150 }
151
152 # check for user, if not running as root set $SUDO to sudo
153 (( EUID != 0 )) && SUDO='sudo' || SUDO=''
154
155 # change directory to home on first invocation of zsh
156 # important for rungetty -> autologin
157 # Thanks go to Bart Schaefer!
158 isgrml && checkhome() {
159     if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
160         export ALREADY_DID_CD_HOME=$HOME
161         cd
162     fi
163 }
164
165 # check for zsh v3.1.7+
166
167 if ! [[ ${ZSH_VERSION} == 3.1.<7->*      \
168      || ${ZSH_VERSION} == 3.<2->.<->*    \
169      || ${ZSH_VERSION} == <4->.<->*   ]] ; then
170
171     printf '-!-\n'
172     printf '-!- In this configuration we try to make use of features, that only\n'
173     printf '-!- require version 3.1.7 of the shell; That way this setup can be\n'
174     printf '-!- used with a wide range of zsh versions, while using fairly\n'
175     printf '-!- advanced features in all supported versions.\n'
176     printf '-!-\n'
177     printf '-!- However, you are running zsh version %s.\n' "$ZSH_VERSION"
178     printf '-!-\n'
179     printf '-!- While this *may* work, it might as well fail.\n'
180     printf '-!- Please consider updating to at least version 3.1.7 of zsh.\n'
181     printf '-!-\n'
182     printf '-!- DO NOT EXPECT THIS TO WORK FLAWLESSLY!\n'
183     printf '-!- If it does today, you'\''ve been lucky.\n'
184     printf '-!-\n'
185     printf '-!- Ye been warned!\n'
186     printf '-!-\n'
187
188     function zstyle() { : }
189 fi
190
191 # }}}
192
193 # utility functions {{{
194 # this function checks if a command exists and returns either true
195 # or false. This avoids using 'which' and 'whence', which will
196 # avoid problems with aliases for which on certain weird systems. :-)
197 check_com() {
198     local -i comonly
199
200     if [[ ${1} == '-c' ]] ; then
201         (( comonly = 1 ))
202         shift
203     else
204         (( comonly = 0 ))
205     fi
206
207     if (( ${#argv} != 1 )) ; then
208         printf 'usage: check_com [-c] <command>\n' >&2
209         return 1
210     fi
211
212     if (( comonly > 0 )) ; then
213         [[ -n ${commands[$1]}  ]] && return 0
214         return 1
215     fi
216
217     if   [[ -n ${commands[$1]}    ]] \
218       || [[ -n ${functions[$1]}   ]] \
219       || [[ -n ${aliases[$1]}     ]] \
220       || [[ -n ${reswords[(r)$1]} ]] ; then
221
222         return 0
223     fi
224
225     return 1
226 }
227
228 # creates an alias and precedes the command with
229 # sudo if $EUID is not zero.
230 salias() {
231     local only=0 ; local multi=0
232     while [[ ${1} == -* ]] ; do
233         case ${1} in
234             (-o) only=1 ;;
235             (-a) multi=1 ;;
236             (--) shift ; break ;;
237             (-h)
238                 printf 'usage: salias [-h|-o|-a] <alias-expression>\n'
239                 printf '  -h      shows this help text.\n'
240                 printf '  -a      replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
241                 printf '          be careful using this option.\n'
242                 printf '  -o      only sets an alias if a preceding sudo would be needed.\n'
243                 return 0
244                 ;;
245             (*) printf "unkown option: '%s'\n" "${1}" ; return 1 ;;
246         esac
247         shift
248     done
249
250     if (( ${#argv} > 1 )) ; then
251         printf 'Too many arguments %s\n' "${#argv}"
252         return 1
253     fi
254
255     key="${1%%\=*}" ;  val="${1#*\=}"
256     if (( EUID == 0 )) && (( only == 0 )); then
257         alias -- "${key}=${val}"
258     elif (( EUID > 0 )) ; then
259         (( multi > 0 )) && val="${val// ; / ; sudo }"
260         alias -- "${key}=sudo ${val}"
261     fi
262
263     return 0
264 }
265
266 # a "print -l ${(u)foo}"-workaround for pre-4.2.0 shells
267 # usage: uprint foo
268 #   Where foo is the *name* of the parameter you want printed.
269 #   Note that foo is no typo; $foo would be wrong here!
270 if ! is42 ; then
271     uprint () {
272         local -a u
273         local w
274         local parameter=${1}
275
276         if [[ -z ${parameter} ]] ; then
277             printf 'usage: uprint <parameter>\n'
278             return 1
279         fi
280
281         for w in ${(P)parameter} ; do
282             [[ -z ${(M)u:#${w}} ]] && u=( ${u} ${w} )
283         done
284
285         builtin print -l ${u}
286     }
287 fi
288
289 # Check if we can read given files and source those we can.
290 xsource() {
291     if (( ${#argv} < 1 )) ; then
292         printf 'usage: xsource FILE(s)...\n' >&2
293         return 1
294     fi
295
296     while (( ${#argv} > 0 )) ; do
297         [[ -r ${1} ]] && source ${1}
298         shift
299     done
300     return 0
301 }
302
303 # Check if we can read a given file and 'cat(1)' it.
304 xcat() {
305     if (( ${#argv} != 1 )) ; then
306         printf 'usage: xcat FILE\n' >&2
307         return 1
308     fi
309
310     [[ -r ${1} ]] && cat ${1}
311     return 0
312 }
313
314 # Remove these functions again, they are of use only in these
315 # setup files. This should be called at the end of .zshrc.
316 xunfunction() {
317     local -a funcs
318     funcs=(salias xcat xsource xunfunction zrcautoload)
319
320     for func in $funcs ; do
321         [[ -n ${functions[$func]} ]] \
322             && unfunction $func
323     done
324     return 0
325 }
326
327 # autoload wrapper - use this one instead of autoload directly
328 function zrcautoload() {
329     setopt local_options extended_glob
330     local fdir ffile
331     local -i ffound
332
333     ffile=${1}
334     (( found = 0 ))
335     for fdir in ${fpath} ; do
336         [[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
337     done
338
339     (( ffound == 0 )) && return 1
340     if [[ $ZSH_VERSION == 3.1.<6-> || $ZSH_VERSION == <4->* ]] ; then
341         autoload -U ${ffile} || return 1
342     else
343         autoload ${ffile} || return 1
344     fi
345     return 0
346 }
347
348 #}}}
349
350 # Load is-at-least() for more precise version checks {{{
351
352 # Note that this test will *always* fail, if the is-at-least
353 # function could not be marked for autoloading.
354 zrcautoload is-at-least || is-at-least() { return 1 }
355
356 # }}}
357
358 # locale setup {{{
359 if [[ -z "$LANG" ]] ; then
360    xsource "/etc/default/locale"
361 fi
362
363 export LANG=${LANG:-en_US.iso885915}
364 for var in LC_ALL LC_MESSAGES ; do
365     [[ -n ${(P)var} ]] && export $var
366 done
367
368 xsource "/etc/sysconfig/keyboard"
369
370 TZ=$(xcat /etc/timezone)
371 # }}}
372
373 # check for potentially old files in 'completion.d' {{{
374 setopt extendedglob
375 xof=(/etc/zsh/completion.d/*~/etc/zsh/completion.d/_*(N))
376 if (( ${#xof} > 0 )) ; then
377     printf '\n -!- INFORMATION\n\n'
378     printf ' -!- %s file(s) not starting with an underscore (_) found in\n' ${#xof}
379     printf ' -!- /etc/zsh/completion.d/.\n\n'
380     printf ' -!- While this has been the case in old versions of grml-etc-core,\n'
381     printf ' -!- recent versions of the grml-zsh-setup have all these files rewritten\n'
382     printf ' -!- and renamed. Furthermore, the grml-zsh-setup will *only* add files\n'
383     printf ' -!- named _* to that directory.\n\n'
384     printf ' -!- If you added functions to completion.d yourself, please consider\n'
385     printf ' -!- moving them to /etc/zsh/functions.d/. Files in that directory, not\n'
386     printf ' -!- starting with an underscore are marked for automatic loading\n'
387     printf ' -!- by default (so that is quite convenient).\n\n'
388     printf ' -!- If there are files *not* starting with an underscore from an older\n'
389     printf ' -!- grml-etc-core in completion.d, you may safely remove them.\n\n'
390     printf ' -!- Delete the files for example via running:\n\n'
391     printf "      rm ${xof}\n\n"
392     printf ' -!- Note, that this message will *not* go away, unless you yourself\n'
393     printf ' -!- resolve the situation manually.\n\n'
394     BROKEN_COMPLETION_DIR=1
395 fi
396 unset xof
397 # }}}
398
399 # {{{ set some variables
400 if check_com -c vim ; then
401 #v#
402     export EDITOR=${EDITOR:-vim}
403 else
404     export EDITOR=${EDITOR:-vi}
405 fi
406
407 #v#
408 export PAGER=${PAGER:-less}
409
410 #v#
411 export MAIL=${MAIL:-/var/mail/$USER}
412
413 # if we don't set $SHELL then aterm, rxvt,.. will use /bin/sh or /bin/bash :-/
414 export SHELL='/bin/zsh'
415
416 # color setup for ls:
417 check_com -c dircolors && eval $(dircolors -b)
418
419 # set width of man pages to 80 for more convenient reading
420 # export MANWIDTH=${MANWIDTH:-80}
421
422 # Search path for the cd command
423 #  cdpath=(.. ~)
424
425 # completion functions go to /etc/zsh/completion.d
426 # function files may be put into /etc/zsh/functions.d, from where they
427 # will be automatically autoloaded.
428 if [[ -n "$BROKEN_COMPLETION_DIR" ]] ; then
429     print 'Warning: not setting completion directories because broken files have been found.' >&2
430 else
431     [[ -d /etc/zsh/completion.d ]] && fpath=( $fpath /etc/zsh/completion.d )
432     if [[ -d /etc/zsh/functions.d ]] ; then
433         fpath+=( /etc/zsh/functions.d )
434         for func in /etc/zsh/functions.d/[^_]*[^~](N.) ; do
435             zrcautoload -U ${func:t}
436         done
437     fi
438 fi
439
440 # automatically remove duplicates from these arrays
441 typeset -U path cdpath fpath manpath
442 # }}}
443
444 # {{{ keybindings
445 if [[ "$TERM" != emacs ]] ; then
446     [[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
447     [[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
448     [[ -z "$terminfo[kend]"  ]] || bindkey -M emacs "$terminfo[kend]"  end-of-line
449     [[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
450     [[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
451     [[ -z "$terminfo[kend]"  ]] || bindkey -M vicmd "$terminfo[kend]"  vi-end-of-line
452     [[ -z "$terminfo[cuu1]"  ]] || bindkey -M viins "$terminfo[cuu1]"  vi-up-line-or-history
453     [[ -z "$terminfo[cuf1]"  ]] || bindkey -M viins "$terminfo[cuf1]"  vi-forward-char
454     [[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
455     [[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
456     [[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
457     [[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char
458     # ncurses stuff:
459     [[ "$terminfo[kcuu1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
460     [[ "$terminfo[kcud1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
461     [[ "$terminfo[kcuf1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
462     [[ "$terminfo[kcub1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
463     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
464     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M viins "${terminfo[kend]/O/[}"  end-of-line
465     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
466     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M emacs "${terminfo[kend]/O/[}"  end-of-line
467 fi
468
469 ## keybindings (run 'bindkeys' for details, more details via man zshzle)
470 # use emacs style per default:
471 bindkey -e
472 # use vi style:
473 # bindkey -v
474
475 #if [[ "$TERM" == screen ]] ; then
476 bindkey '\e[1~' beginning-of-line       # home
477 bindkey '\e[4~' end-of-line             # end
478 bindkey '\e[A'  up-line-or-search       # cursor up
479 bindkey '\e[B'  down-line-or-search     # <ESC>-
480
481 bindkey '^xp'   history-beginning-search-backward
482 bindkey '^xP'   history-beginning-search-forward
483 # bindkey -s '^L' "|less\n"             # ctrl-L pipes to less
484 # bindkey -s '^B' " &\n"                # ctrl-B runs it in the background
485 # if terminal type is set to 'rxvt':
486 bindkey '\e[7~' beginning-of-line       # home
487 bindkey '\e[8~' end-of-line             # end
488 #fi
489
490 # insert unicode character
491 # usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an Â§
492 # See for example http://unicode.org/charts/ for unicode characters code
493 zrcautoload insert-unicode-char
494 zle -N insert-unicode-char
495 #k# Insert Unicode character
496 bindkey '^Xi' insert-unicode-char
497
498 # just type 'cd ...' to get 'cd ../..'
499 #  rationalise-dot() {
500 #  if [[ $LBUFFER == *.. ]] ; then
501 #    LBUFFER+=/..
502 #  else
503 #    LBUFFER+=.
504 #  fi
505 #  }
506 #  zle -N rationalise-dot
507 #  bindkey . rationalise-dot
508
509 #  bindkey '\eq' push-line-or-edit
510
511 ## toggle the ,. abbreviation feature on/off
512 # NOABBREVIATION: default abbreviation-state
513 #                 0 - enabled (default)
514 #                 1 - disabled
515 NOABBREVIATION=${NOABBREVIATION:-0}
516
517 grml_toggle_abbrev() {
518     if (( ${NOABBREVIATION} > 0 )) ; then
519         NOABBREVIATION=0
520     else
521         NOABBREVIATION=1
522     fi
523 }
524
525 zle -N grml_toggle_abbrev
526 bindkey '^xA' grml_toggle_abbrev
527
528 # }}}
529
530 # a generic accept-line wrapper {{{
531
532 # This widget can prevent unwanted autocorrections from command-name
533 # to _command-name, rehash automatically on enter and call any number
534 # of builtin and user-defined widgets in different contexts.
535 #
536 # For a broader description, see:
537 # <http://bewatermyfriend.org/posts/2007/12-26.11-50-38-tooltime.html>
538 #
539 # The code is imported from the file 'zsh/functions/accept-line' from
540 # <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>, which
541 # distributed under the same terms as zsh itself.
542
543 # A newly added command will may not be found or will cause false
544 # correction attempts, if you got auto-correction set. By setting the
545 # following style, we force accept-line() to rehash, if it cannot
546 # find the first word on the command line in the $command[] hash.
547 zstyle ':acceptline:*' rehash true
548
549 function Accept-Line() {
550     setopt localoptions noksharrays
551     local -a subs
552     local -xi aldone
553     local sub
554
555     zstyle -a ":acceptline:${alcontext}" actions subs
556
557     (( ${#subs} < 1 )) && return 0
558
559     (( aldone = 0 ))
560     for sub in ${subs} ; do
561         [[ ${sub} == 'accept-line' ]] && sub='.accept-line'
562         zle ${sub}
563
564         (( aldone > 0 )) && break
565     done
566 }
567
568 function Accept-Line-getdefault() {
569     local default_action
570
571     zstyle -s ":acceptline:${alcontext}" default_action default_action
572     case ${default_action} in
573         ((accept-line|))
574             printf ".accept-line"
575             ;;
576         (*)
577             printf ${default_action}
578             ;;
579     esac
580 }
581
582 function accept-line() {
583     setopt localoptions noksharrays
584     local -a cmdline
585     local -x alcontext
586     local buf com fname format msg default_action
587
588     alcontext='default'
589     buf="${BUFFER}"
590     cmdline=(${(z)BUFFER})
591     com="${cmdline[1]}"
592     fname="_${com}"
593
594     zstyle -t ":acceptline:${alcontext}" rehash \
595         && [[ -z ${commands[$com]} ]]           \
596         && rehash
597
598     if    [[ -n ${reswords[(r)$com]} ]] \
599        || [[ -n ${aliases[$com]}     ]] \
600        || [[ -n ${functions[$com]}   ]] \
601        || [[ -n ${builtins[$com]}    ]] \
602        || [[ -n ${commands[$com]}    ]] ; then
603
604         # there is something sensible to execute, just do it.
605         alcontext='normal'
606         zle Accept-Line
607
608         default_action=$(Accept-Line-getdefault)
609         zstyle -T ":acceptline:${alcontext}" call_default \
610             && zle ${default_action}
611         return
612     fi
613
614     if    [[ -o correct              ]] \
615        || [[ -o correctall           ]] \
616        && [[ -n ${functions[$fname]} ]] ; then
617
618         # nothing there to execute but there is a function called
619         # _command_name; a completion widget. Makes no sense to
620         # call it on the commandline, but the correct{,all} options
621         # will ask for it nevertheless, so warn the user.
622         if [[ ${LASTWIDGET} == 'accept-line' ]] ; then
623             # Okay, we warned the user before, he called us again,
624             # so have it his way.
625             alcontext='force'
626             zle Accept-Line
627
628             default_action=$(Accept-Line-getdefault)
629             zstyle -T ":acceptline:${alcontext}" call_default \
630                 && zle ${default_action}
631             return
632         fi
633
634         # prepare warning message for the user, configurable via zstyle.
635         zstyle -s ":acceptline:${alcontext}" compwarnfmt msg
636
637         if [[ -z ${msg} ]] ; then
638             msg="%c will not execute and completion %f exists."
639         fi
640
641         zformat -f msg "${msg}" "c:${com}" "f:${fname}"
642
643         zle -M -- "${msg}"
644         return
645     elif [[ -n ${buf//[$' \t\n']##/} ]] ; then
646         # If we are here, the commandline contains something that is not
647         # executable, which is neither subject to _command_name correction
648         # and is not empty. might be a variable assignment
649         alcontext='misc'
650         zle Accept-Line
651
652         default_action=$(Accept-Line-getdefault)
653         zstyle -T ":acceptline:${alcontext}" call_default \
654             && zle ${default_action}
655         return
656     fi
657
658     # If we got this far, the commandline only contains whitespace, or is empty.
659     alcontext='empty'
660     zle Accept-Line
661
662     default_action=$(Accept-Line-getdefault)
663     zstyle -T ":acceptline:${alcontext}" call_default \
664         && zle ${default_action}
665 }
666
667 zle -N accept-line
668 zle -N Accept-Line
669
670 # }}}
671
672 # power completion - abbreviation expansion {{{
673 # power completion / abbreviation expansion / buffer expansion
674 # see http://zshwiki.org/home/examples/zleiab for details
675 # less risky than the global aliases but powerful as well
676 # just type the abbreviation key and afterwards ',.' to expand it
677 declare -A abk
678 setopt extendedglob
679 setopt interactivecomments
680 abk=(
681 # key  # value                (#d additional doc string)
682 #A# start
683     '...' '../..'
684     '....' '../../..'
685     'BG' '& exit'
686     'C' '| wc -l'
687     'G' '|& grep --color=auto'
688     'H' '| head'
689     'Hl' ' --help |& less -r'      #d (Display help in pager)
690     'L' '| less'
691     'LL' '|& less -r'
692     'M' '| most'
693     'N' '&>/dev/null'              #d (No Output)
694     'R' '| tr A-z N-za-m'          #d (ROT13)
695     'SL' '| sort | less'
696     'S' '| sort -u'
697     'T' '| tail'
698     'V' '|& vim -'
699 #A# end
700     'hide' "echo -en '\033]50;nil2\007'"
701     'tiny' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"'
702     'small' 'echo -en "\033]50;6x10\007"'
703     'medium' 'echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"'
704     'default' 'echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"'
705     'large' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"'
706     'huge' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"'
707     'smartfont' 'echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"'
708     'semifont' 'echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"'
709     'da' 'du -sch'
710     'j' 'jobs -l'
711     'u' 'translate -i'
712     'co' "./configure && make && sudo make install"
713     'CH' "./configure --help"
714     'conkeror' 'firefox -chrome chrome://conkeror/content'
715     'dir' 'ls -lSrah'
716     'lad' $'ls -d .*(/)\n# only show dot-directories'
717     'lsa' $'ls -a .*(.)\n# only show dot-files'
718     'lss' $'ls -l *(s,S,t)\n# only files with setgid/setuid/sticky flag'
719     'lsl' $'ls -l *(@[1,10])\n# only symlinks'
720     'lsx' $'ls -l *(*[1,10])\n# only executables'
721     'lsw' $'ls -ld *(R,W,X.^ND/)\n# world-{readable,writable,executable} files'
722     'lsbig' $'ls -flh *(.OL[1,10])\n# display the biggest files'
723     'lsd' $'ls -d *(/)\n# only show directories'
724     'lse' $'ls -d *(/^F)\n# only show empty directories'
725     'lsnew' $'ls -rl *(D.om[1,10])\n# display the newest files'
726     'lsold' $'ls -rtlh *(D.om[-11,-1])\n # display the oldest files'
727     'lssmall' $'ls -Srl *(.oL[1,10])\n# display the smallest files'
728     'rw-' 'chmod 600'
729     '600' 'chmod u+rw-x,g-rwx,o-rwx'
730     'rwx' 'chmod u+rwx'
731     '700' 'chmod u+rwx,g-rwx,o-rwx'
732     'r--' 'chmod u+r-wx,g-rwx,o-rwx'
733     '644' $'chmod u+rw-x,g+r-wx,o+r-wx\n # 4=r,2=w,1=x'
734     '755' 'chmod u+rwx,g+r-w+x,o+r-w+x'
735     'md' 'mkdir -p '
736     'cmplayer' 'mplayer -vo -fs -zoom fbdev'
737     'fbmplayer' 'mplayer -vo -fs -zoom fbdev'
738     'fblinks' 'links2 -driver fb'
739     'insecssh' 'ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
740     'insecscp' 'scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
741     'fori' 'for i ({..}) { }'
742     'cx' 'chmod +x'
743     'e'  'print -l'
744     'se' 'setopt interactivecomments'
745     'va' 'valac --vapidir=../vapi/ --pkg=gtk+-2.0 gtktest.vala'
746     'fb2' '=mplayer -vo fbdev -fs -zoom 1>/dev/null -xy 2'
747     'fb3' '=mplayer -vo fbdev -fs  -zoom 1>/dev/null -xy 3'
748     'ci' 'centericq'
749     'D'  'export DISPLAY=:0.0'
750     'mp' 'mplayer -vo xv -fs -zoom'
751 )
752
753 globalias() {
754     local MATCH
755
756     if (( NOABBREVIATION > 0 )) ; then
757         LBUFFER="${LBUFFER},."
758         return 0
759     fi
760
761     matched_chars='[.-|_a-zA-Z0-9]#'
762     LBUFFER=${LBUFFER%%(#m)[.-|_a-zA-Z0-9]#}
763     LBUFFER+=${abk[$MATCH]:-$MATCH}
764 }
765
766 zle -N globalias
767 bindkey ",." globalias
768 # }}}
769
770 # {{{ autoloading
771 zrcautoload zmv    # who needs mmv or rename?
772 zrcautoload history-search-end
773
774 # we don't want to quote/espace URLs on our own...
775 # if autoload -U url-quote-magic ; then
776 #    zle -N self-insert url-quote-magic
777 #    zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}='
778 # else
779 #    print 'Notice: no url-quote-magic available :('
780 # fi
781 alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic'
782
783 #m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
784 alias run-help >&/dev/null && unalias run-help
785 zrcautoload run-help # use via 'esc-h'
786
787 # completion system
788 if zrcautoload compinit && compinit 2>/dev/null ; then
789     compinit 2>/dev/null || print 'Notice: no compinit available :('
790 else
791     print 'Notice: no compinit available :('
792     function zstyle { }
793     function compdef { }
794 fi
795
796 is4 && zrcautoload zed # use ZLE editor to edit a file or function
797
798 is4 && \
799 for mod in complist deltochar mathfunc ; do
800     zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
801 done
802
803 # autoload zsh modules when they are referenced
804 if is4 ; then
805     tmpargs=(
806         a   stat
807         a   zpty
808         ap  mapfile
809     )
810
811     while (( ${#tmpargs} > 0 )) ; do
812         zmodload -${tmpargs[1]} zsh/${tmpargs[2]} ${tmpargs[2]}
813         shift 2 tmpargs
814     done
815     unset tmpargs
816 fi
817
818 if is4 && zrcautoload insert-files && zle -N insert-files ; then
819     #k# Insert files
820     bindkey "^Xf" insert-files # C-x-f
821 fi
822
823 bindkey ' '   magic-space    # also do history expansion on space
824 #k# Trigger menu-complete
825 bindkey '\ei' menu-complete  # menu completion via esc-i
826
827 # press esc-e for editing command line in $EDITOR or $VISUAL
828 if is4 && zrcautoload edit-command-line && zle -N edit-command-line ; then
829     #k# Edit the current line in \kbd{\$EDITOR}
830     bindkey '\ee' edit-command-line
831 fi
832
833 if is4 && [[ -n ${(k)modules[zsh/complist]} ]] ; then
834     #k# menu selection: pick item but stay in the menu
835     bindkey -M menuselect '\e^M' accept-and-menu-complete
836
837     # use the vi navigation keys (hjkl) besides cursor keys in menu completion
838     #bindkey -M menuselect 'h' vi-backward-char        # left
839     #bindkey -M menuselect 'k' vi-up-line-or-history   # up
840     #bindkey -M menuselect 'l' vi-forward-char         # right
841     #bindkey -M menuselect 'j' vi-down-line-or-history # bottom
842
843     # accept a completion and try to complete again by using menu
844     # completion; very useful with completing directories
845     # by using 'undo' one's got a simple file browser
846     bindkey -M menuselect '^o' accept-and-infer-next-history
847 fi
848
849 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
850 _bkdate() { BUFFER="$BUFFER$(date '+%F')"; CURSOR=$#BUFFER; }
851 zle -N _bkdate
852
853 #k# Insert a timestamp on the command line (yyyy-mm-dd)
854 bindkey '^Ed' _bkdate
855
856 # press esc-m for inserting last typed word again (thanks to caphuso!)
857 insert-last-typed-word() { zle insert-last-word -- 0 -1 };
858 zle -N insert-last-typed-word;
859
860 #k# Insert last typed word
861 bindkey "\em" insert-last-typed-word
862
863 # set command prediction from history, see 'man 1 zshcontrib'
864 #  is4 && zrcautoload predict-on && \
865 #  zle -N predict-on         && \
866 #  zle -N predict-off        && \
867 #  bindkey "^X^Z" predict-on && \
868 #  bindkey "^Z" predict-off
869
870 #k# Shortcut for \kbd{fg<enter>}
871 bindkey -s '^z' "fg\n"
872
873 # press ctrl-q to quote line:
874 #  mquote () {
875 #        zle beginning-of-line
876 #        zle forward-word
877 #        # RBUFFER="'$RBUFFER'"
878 #        RBUFFER=${(q)RBUFFER}
879 #        zle end-of-line
880 #  }
881 #  zle -N mquote && bindkey '^q' mquote
882
883 # run command line as user root via sudo:
884 sudo-command-line() {
885     [[ -z $BUFFER ]] && zle up-history
886     [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
887 }
888 zle -N sudo-command-line
889
890 #k# Put the current command line into a \kbd{sudo} call
891 bindkey "^Os" sudo-command-line
892
893 ### jump behind the first word on the cmdline.
894 ### useful to add options.
895 function jump_after_first_word() {
896     local words
897     words=(${(z)BUFFER})
898
899     if (( ${#words} <= 1 )) ; then
900         CURSOR=${#BUFFER}
901     else
902         CURSOR=${#${words[1]}}
903     fi
904 }
905 zle -N jump_after_first_word
906
907 bindkey '^x1' jump_after_first_word
908
909 # }}}
910
911 # {{{ set some important options
912 # Please update these tags, if you change the umask settings below.
913 #o# r_umask     002
914 #o# r_umaskstr  rwxrwxr-x
915 #o# umask       022
916 #o# umaskstr    rwxr-xr-x
917 (( EUID != 0 )) && umask 002 || umask 022
918
919 # history:
920 setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
921 is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
922 setopt extended_history     # save each command's beginning timestamp and the duration to the history file
923 is4 && setopt histignorealldups # If  a  new  command  line being added to the history
924                             # list duplicates an older one, the older command is removed from the list
925 setopt histignorespace      # remove command lines from the history list when
926                             # the first character on the line is a space
927 #  setopt histallowclobber    # add `|' to output redirections in the history
928 #  setopt NO_clobber          # warning if file exists ('cat /dev/null > ~/.zshrc')
929 setopt auto_cd              # if a command is issued that can't be executed as a normal command,
930                             # and the command is the name of a directory, perform the cd command to that directory
931 setopt extended_glob        # in order to use #, ~ and ^ for filename generation
932                             # grep word *~(*.gz|*.bz|*.bz2|*.zip|*.Z) ->
933                             # -> searches for word not in compressed files
934                             # don't forget to quote '^', '~' and '#'!
935 setopt longlistjobs         # display PID when suspending processes as well
936 setopt notify               # report the status of backgrounds jobs immediately
937 setopt hash_list_all        # Whenever a command completion is attempted, make sure \
938                             # the entire command path is hashed first.
939 setopt completeinword       # not just at the end
940 # setopt nocheckjobs          # don't warn me about bg processes when exiting
941 setopt nohup                # and don't kill them, either
942 # setopt printexitvalue       # alert me if something failed
943 # setopt dvorak               # with spelling correction, assume dvorak kb
944 setopt auto_pushd           # make cd push the old directory onto the directory stack.
945 setopt nonomatch            # try to avoid the 'zsh: no matches found...'
946 setopt nobeep               # avoid "beep"ing
947 setopt pushd_ignore_dups    # don't push the same dir twice.
948
949 MAILCHECK=30       # mailchecks
950 REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 seconds
951 watch=(notme root) # watch for everyone but me and root
952
953 # define word separators (for stuff like backward-word, forward-word, backward-kill-word,..)
954 #  WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' # the default
955 #  WORDCHARS=.
956 #  WORDCHARS='*?_[]~=&;!#$%^(){}'
957 #  WORDCHARS='${WORDCHARS:s@/@}'
958
959 # only slash should be considered as a word separator:
960 slash-backward-kill-word() {
961     local WORDCHARS="${WORDCHARS:s@/@}"
962     # zle backward-word
963     zle backward-kill-word
964 }
965 zle -N slash-backward-kill-word
966
967 #k# Kill everything in a word up to its last \kbd{/}
968 bindkey '\ev' slash-backward-kill-word
969
970 # }}}
971
972 # {{{ history
973
974 ZSHDIR=$HOME/.zsh
975
976 #v#
977 HISTFILE=$HOME/.zsh_history
978 isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
979 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
980
981 # }}}
982
983 # dirstack handling {{{
984
985 DIRSTACKSIZE=${DIRSTACKSIZE:-20}
986 DIRSTACKFILE=${DIRSTACKFILE:-${HOME}/.zdirs}
987
988 if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
989     dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
990     # "cd -" won't work after login by just setting $OLDPWD, so
991     [[ -d $dirstack[0] ]] && cd $dirstack[0] && cd $OLDPWD
992 fi
993
994 chpwd() {
995     if is42 ; then
996         builtin print -l ${(u)dirstack} >! ${DIRSTACKFILE}
997     else
998         uprint dirstack >! ${DIRSTACKFILE}
999     fi
1000 }
1001
1002 # }}}
1003
1004 # {{{ display battery status on right side of prompt via running 'BATTERY=1 zsh'
1005 if [[ $BATTERY -gt 0 ]] ; then
1006     if ! check_com -c acpi ; then
1007         BATTERY=0
1008     fi
1009 fi
1010
1011 battery() {
1012 if [[ $BATTERY -gt 0 ]] ; then
1013     PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]##Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
1014     if [[ -z "$PERCENT" ]] ; then
1015         PERCENT='acpi not present'
1016     else
1017         if [[ "$PERCENT" -lt 20 ]] ; then
1018             PERCENT="warning: ${PERCENT}%%"
1019         else
1020             PERCENT="${PERCENT}%%"
1021         fi
1022     fi
1023 fi
1024 }
1025 # }}}
1026
1027 # set colors for use in prompts {{{
1028 if zrcautoload colors && colors 2>/dev/null ; then
1029     BLUE="%{${fg[blue]}%}"
1030     RED="%{${fg_bold[red]}%}"
1031     GREEN="%{${fg[green]}%}"
1032     CYAN="%{${fg[cyan]}%}"
1033     MAGENTA="%{${fg[magenta]}%}"
1034     YELLOW="%{${fg[yellow]}%}"
1035     WHITE="%{${fg[white]}%}"
1036     NO_COLOUR="%{${reset_color}%}"
1037 else
1038     BLUE=$'%{\e[1;34m%}'
1039     RED=$'%{\e[1;31m%}'
1040     GREEN=$'%{\e[1;32m%}'
1041     CYAN=$'%{\e[1;36m%}'
1042     WHITE=$'%{\e[1;37m%}'
1043     MAGENTA=$'%{\e[1;35m%}'
1044     YELLOW=$'%{\e[1;33m%}'
1045     NO_COLOUR=$'%{\e[0m%}'
1046 fi
1047
1048 # }}}
1049
1050 # gather version control information for inclusion in a prompt {{{
1051
1052 if ! is41 ; then
1053     # Be quiet about version problems in grml's zshrc as the user cannot disable
1054     # loading vcs_info() as it is *in* the zshrc - as you can see. :-)
1055     # Just unset most probable variables and disable vcs_info altogether.
1056     local -i i
1057     for i in {0..9} ; do
1058         unset VCS_INFO_message_${i}_
1059     done
1060     zstyle ':vcs_info:*' enable false
1061 fi
1062
1063 # The following code is imported from the file 'zsh/functions/vcs_info'
1064 # from <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>,
1065 # which distributed under the same terms as zsh itself.
1066
1067 # we will only be using one variable, so let the code know now.
1068 zstyle ':vcs_info:*' max-exports 1
1069
1070 # vcs_info() documentation:
1071 #{{{
1072 # REQUIREMENTS:
1073 #{{{
1074 #     This functionality requires zsh version >= 4.1.*.
1075 #}}}
1076 #
1077 # LOADING:
1078 #{{{
1079 # To load vcs_info(), copy this file to your $fpath[] and do:
1080 #   % autoload -Uz vcs_info && vcs_info
1081 #
1082 # To work, vcs_info() needs 'setopt prompt_subst' in your setup.
1083 #}}}
1084 #
1085 # QUICKSTART:
1086 #{{{
1087 # To get vcs_info() working quickly (including colors), you can do the
1088 # following (assuming, you loaded vcs_info() properly - see above):
1089 #
1090 # % RED=$'%{\e[31m%}'
1091 # % GR=$'%{\e[32m%}'
1092 # % MA=$'%{\e[35m%}'
1093 # % YE=$'%{\e[33m%}'
1094 # % NC=$'%{\e[0m%}'
1095 #
1096 # % zstyle ':vcs_info:*' actionformats \
1097 #       "${MA}(${NC}%s${MA})${YE}-${MA}[${GR}%b${YE}|${RED}%a${MA}]${NC} "
1098 #
1099 # % zstyle ':vcs_info:*' formats       \
1100 #       "${MA}(${NC}%s${MA})${Y}-${MA}[${GR}%b${MA}]${NC}%} "
1101 #
1102 # % zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YE}%r"
1103 #
1104 # % precmd () { vcs_info }
1105 # % PS1='${MA}[${GR}%n${MA}] ${MA}(${RED}%!${MA}) ${YE}%3~ ${VCS_INFO_message_0_}${NC}%# '
1106 #
1107 # Obviously, the las two lines are there for demonstration: You need to
1108 # call vcs_info() from your precmd() function (see 'SPECIAL FUNCTIONS' in
1109 # 'man zshmisc'). Once that is done you need a *single* quoted
1110 # '${VCS_INFO_message_0_}' in your prompt.
1111 #
1112 # Now call the 'vcs_info_printsys' utility from the command line:
1113 #
1114 # % vcs_info_printsys
1115 # # list of supported version control backends:
1116 # # disabled systems are prefixed by a hash sign (#)
1117 # git
1118 # hg
1119 # bzr
1120 # darcs
1121 # svk
1122 # mtn
1123 # svn
1124 # cvs
1125 # cdv
1126 # tla
1127 # # flavours (cannot be used in the disable style; they
1128 # # are disabled with their master [git-svn -> git]):
1129 # git-p4
1130 # git-svn
1131 #
1132 # Ten version control backends as you can see. You may not want all
1133 # of these. Because there is no point in running the code to detect
1134 # systems you do not use. ever. So, there is a way to disable some
1135 # backends altogether:
1136 #
1137 # % zstyle ':vcs_info:*' disable bzr cdv darcs mtn svk tla
1138 #
1139 # If you rerun 'vcs_info_printsys' now, you will see the backends listed
1140 # in the 'disable' style marked as diabled by a hash sign. That means the
1141 # detection of these systems is skipped *completely*. No wasted time there.
1142 #
1143 # For more control, read the reference below.
1144 #}}}
1145 #
1146 # CONFIGURATION:
1147 #{{{
1148 # The vcs_info() feature can be configured via zstyle.
1149 #
1150 # First, the context in which we are working:
1151 #       :vcs_info:<vcs-string>:<user-context>
1152 #
1153 # ...where <vcs-string> is one of:
1154 #   - git, git-svn, git-p4, hg, darcs, bzr, cdv, mtn, svn, cvs, svk or tla.
1155 #
1156 # ...and <user-context> is a freely configurable string, assignable by the
1157 # user as the first argument to vcs_info() (see its description below).
1158 #
1159 # There is are three special values for <vcs-string>: The first is named
1160 # 'init', that is in effect as long as there was no decision what vcs
1161 # backend to use. The second is 'preinit; it is used *before* vcs_info()
1162 # is run, when initializing the data exporting variables. The third
1163 # special value is 'formats' and is used by the 'vcs_info_lastmsg' for
1164 # looking up its styles.
1165 #
1166 # There are two pre-defined values for <user-context>:
1167 #   default  - the one used if none is specified
1168 #   command  - used by vcs_info_lastmsg to lookup its styles.
1169 #
1170 # You may *not* use 'print_systems_' as a user-context string, because it
1171 # is used internally.
1172 #
1173 # You can of course use ':vcs_info:*' to match all VCSs in all
1174 # user-contexts at once.
1175 #
1176 # Another special context is 'formats', which is used by the
1177 # vcs_info_lastmsg() utility function (see below).
1178 #
1179 #
1180 # This is a description of all styles, that are looked up:
1181 #   formats             - A list of formats, used when actionformats is not
1182 #                         used (which is most of the time).
1183 #   actionformats       - A list of formats, used if a there is a special
1184 #                         action going on in your current repository;
1185 #                         (like an interactive rebase or a merge conflict)
1186 #   branchformat        - Some backends replace %b in the formats and
1187 #                         actionformats styles above, not only by a branch
1188 #                         name but also by a revision number. This style
1189 #                         let's you modify how that string should look like.
1190 #   nvcsformats         - These "formats" are exported, when we didn't detect
1191 #                         a version control system for the current directory.
1192 #                         This is useful, if you want vcs_info() to completely
1193 #                         take over the generation of your prompt.
1194 #                         You would do something like
1195 #                           PS1='${VCS_INFO_message_0_}'
1196 #                         to accomplish that.
1197 #   max-exports         - Defines the maximum number if VCS_INFO_message_*_
1198 #                         variables vcs_info() will export.
1199 #   enable              - Checked in the 'init' context. If set to false,
1200 #                         vcs_info() will do nothing.
1201 #   disable             - Provide a list of systems, you don't want
1202 #                         the vcs_info() to check for repositories
1203 #                         (checked in the 'init' context, too).
1204 #   use-simple          - If there are two different ways of gathering
1205 #                         information, you can select the simpler one
1206 #                         by setting this style to true; the default
1207 #                         is to use the not-that-simple code, which is
1208 #                         potentially a lot slower but might be more
1209 #                         accurate in all possible cases.
1210 #   use-prompt-escapes  - determines if we assume that the assembled
1211 #                         string from vcs_info() includes prompt escapes.
1212 #                         (Used by vcs_info_lastmsg().
1213 #
1214 # The use-simple style is only available for the bzr backend.
1215 #
1216 # The default values for these in all contexts are:
1217 #   formats             " (%s)-[%b|%a]-"
1218 #   actionformats       " (%s)-[%b]-"
1219 #   branchformat        "%b:%r" (for bzr, svn and svk)
1220 #   nvcsformats         ""
1221 #   max-exports         2
1222 #   enable              true
1223 #   disable             (empty list)
1224 #   use-simple          false
1225 #   use-prompt-escapes  true
1226 #
1227 #
1228 # In normal formats and actionformats, the following replacements
1229 # are done:
1230 #   %s  - The vcs in use (git, hg, svn etc.)
1231 #   %b  - Information about the current branch.
1232 #   %a  - An identifier, that describes the action.
1233 #         Only makes sense in actionformats.
1234 #   %R  - base directory of the repository.
1235 #   %r  - repository name
1236 #         If %R is '/foo/bar/repoXY', %r is 'repoXY'.
1237 #   %S  - subdirectory within a repository. if $PWD is
1238 #         '/foo/bar/reposXY/beer/tasty', %S is 'beer/tasty'.
1239 #
1240 #
1241 # In branchformat these replacements are done:
1242 #   %b  - the branch name
1243 #   %r  - the current revision number
1244 #
1245 # Not all vcs backends have to support all replacements.
1246 # nvcsformat does not perform *any* replacements. It is just a string.
1247 #}}}
1248 #
1249 # ODDITIES:
1250 #{{{
1251 # If you want to use the %b (bold off) prompt expansion in 'formats', which
1252 # expands %b itself, use %%b. That will cause the vcs_info() expansion to
1253 # replace %%b with %b. So zsh's prompt expansion mechanism can handle it.
1254 # Similarly, to hand down %b from branchformat, use %%%%b. Sorry for this
1255 # inconvenience, but it cannot be easily avoided. Luckily we do not clash
1256 # with a lot of prompt expansions and this only needs to be done for those.
1257 # See 'man zshmisc' for details about EXPANSION OF PROMPT SEQUENCES.
1258 #}}}
1259 #
1260 # FUNCTION DESCRIPTIONS (public API):
1261 #{{{
1262 #   vcs_info()
1263 #       The main function, that runs all backends and assembles
1264 #       all data into ${VCS_INFO_message_*_}. This is the function
1265 #       you want to call from precmd() if you want to include
1266 #       up-to-date information in your prompt (see VARIABLE
1267 #       DESCRIPTION below).
1268 #
1269 #   vcs_info_printsys()
1270 #       Prints a list of all supported version control systems.
1271 #       Useful to find out possible contexts (and which of them are enabled)
1272 #       or values for the 'disable' style.
1273 #
1274 #   vcs_info_lastmsg()
1275 #       Outputs the last ${VCS_INFO_message_*_} value. Takes into account
1276 #       the value of the use-prompt-escapes style in ':vcs_info:formats'.
1277 #       It also only prints max-exports values.
1278 #
1279 # All functions named VCS_INFO_* are for internal use only.
1280 #}}}
1281 #
1282 # VARIABLE DESCRIPTION:
1283 #{{{
1284 #   ${VCS_INFO_message_N_}    (Note the trailing underscore)
1285 #       Where 'N' is an integer, eg: VCS_INFO_message_0_
1286 #       These variables are the storage for the informational message the
1287 #       last vcs_info() call has assembled. These are strongly connected
1288 #       to the formats, actionformats and nvcsformats styles described
1289 #       above. Those styles are lists. the first member of that list gets
1290 #       expanded into ${VCS_INFO_message_0_}, the second into
1291 #       ${VCS_INFO_message_1_} and the Nth into ${VCS_INFO_message_N-1_}.
1292 #       These parameters are exported into the environment.
1293 #       (See the max-exports style above.)
1294 #}}}
1295 #
1296 # EXAMPLES:
1297 #{{{
1298 #   Don't use vcs_info at all (even though it's in your prompt):
1299 #   % zstyle ':vcs_info:*' enable false
1300 #
1301 #   Disable the backends for bzr and svk:
1302 #   % zstyle ':vcs_info:*' disable bzr svk
1303 #
1304 #   Provide a special formats for git:
1305 #   % zstyle ':vcs_info:git:*' formats       ' GIT, BABY! [%b]'
1306 #   % zstyle ':vcs_info:git:*' actionformats ' GIT ACTION! [%b|%a]'
1307 #
1308 #   Use the quicker bzr backend (if you do, please report if it does
1309 #   the-right-thing[tm] - thanks):
1310 #   % zstyle ':vcs_info:bzr:*' use-simple true
1311 #
1312 #   Display the revision number in yellow for bzr and svn:
1313 #   % zstyle ':vcs_info:(svn|bzr):*' branchformat '%b%{'${fg[yellow]}'%}:%r'
1314 #
1315 # If you want colors, make sure you enclose the color codes in %{...%},
1316 # if you want to use the string provided by vcs_info() in prompts.
1317 #
1318 # Here is how to print the vcs infomation as a command:
1319 #   % alias vcsi='vcs_info command; vcs_info_lastmsg'
1320 #
1321 #   This way, you can even define different formats for output via
1322 #   vcs_info_lastmsg() in the ':vcs_info:command:*' namespace.
1323 #}}}
1324 #}}}
1325 # utilities
1326 VCS_INFO_adjust () { #{{{
1327     [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
1328     return 0
1329 }
1330 # }}}
1331 VCS_INFO_check_com () { #{{{
1332     (( ${+commands[$1]} )) && [[ -x ${commands[$1]} ]] && return 0
1333     return 1
1334 }
1335 # }}}
1336 VCS_INFO_formats () { # {{{
1337     setopt localoptions noksharrays
1338     local action=$1 branch=$2 base=$3
1339     local msg
1340     local -i i
1341
1342     if [[ -n ${action} ]] ; then
1343         zstyle -a ":vcs_info:${vcs}:${usercontext}" actionformats msgs
1344         (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b|%a]-'
1345     else
1346         zstyle -a ":vcs_info:${vcs}:${usercontext}" formats msgs
1347         (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b]-'
1348     fi
1349
1350     (( ${#msgs} > maxexports )) && msgs[${maxexports},-1]=()
1351     for i in {1..${#msgs}} ; do
1352         zformat -f msg ${msgs[$i]} a:${action} b:${branch} s:${vcs} r:${base:t} R:${base} S:"$(VCS_INFO_reposub ${base})"
1353         msgs[$i]=${msg}
1354     done
1355     return 0
1356 }
1357 # }}}
1358 VCS_INFO_maxexports () { #{{{
1359     local -ix maxexports
1360
1361     zstyle -s ":vcs_info:${vcs}:${usercontext}" "max-exports" maxexports || maxexports=2
1362     if [[ ${maxexports} != <-> ]] || (( maxexports < 1 )); then
1363         printf 'vcs_info(): expecting numeric arg >= 1 for max-exports (got %s).\n' ${maxexports}
1364         printf 'Defaulting to 2.\n'
1365         maxexports=2
1366     fi
1367 }
1368 # }}}
1369 VCS_INFO_nvcsformats () { #{{{
1370     setopt localoptions noksharrays
1371     local c v
1372
1373     if [[ $1 == 'preinit' ]] ; then
1374         c=default
1375         v=preinit
1376     fi
1377     zstyle -a ":vcs_info:${v:-$vcs}:${c:-$usercontext}" nvcsformats msgs
1378     (( ${#msgs} > maxexports )) && msgs[${maxexports},-1]=()
1379 }
1380 # }}}
1381 VCS_INFO_realpath () { #{{{
1382     # a portable 'readlink -f'
1383     # forcing a subshell, to ensure chpwd() is not removed
1384     # from the calling shell (if VCS_INFO_realpath() is called
1385     # manually).
1386     (
1387         (( ${+functions[chpwd]} )) && unfunction chpwd
1388         setopt chaselinks
1389         cd $1 2>/dev/null && pwd
1390     )
1391 }
1392 # }}}
1393 VCS_INFO_reposub () { #{{{
1394     setopt localoptions extendedglob
1395     local base=${1%%/##}
1396
1397     [[ ${PWD} == ${base}/* ]] || {
1398         printf '.'
1399         return 1
1400     }
1401     printf '%s' ${PWD#$base/}
1402     return 0
1403 }
1404 # }}}
1405 VCS_INFO_set () { #{{{
1406     setopt localoptions noksharrays
1407     local -i i j
1408
1409     if [[ $1 == '--clear' ]] ; then
1410         for i in {0..9} ; do
1411             unset VCS_INFO_message_${i}_
1412         done
1413     fi
1414     if [[ $1 == '--nvcs' ]] ; then
1415         [[ $2 == 'preinit' ]] && (( maxexports == 0 )) && (( maxexports = 1 ))
1416         for i in {0..$((maxexports - 1))} ; do
1417             typeset -gx VCS_INFO_message_${i}_=
1418         done
1419         VCS_INFO_nvcsformats $2
1420     fi
1421
1422     (( ${#msgs} - 1 < 0 )) && return 0
1423     for i in {0..$(( ${#msgs} - 1 ))} ; do
1424         (( j = i + 1 ))
1425         typeset -gx VCS_INFO_message_${i}_=${msgs[$j]}
1426     done
1427     return 0
1428 }
1429 # }}}
1430 # information gathering
1431 VCS_INFO_bzr_get_data () { # {{{
1432     setopt localoptions noksharrays
1433     local bzrbase bzrbr
1434     local -a bzrinfo
1435
1436     if zstyle -t ":vcs_info:${vcs}:${usercontext}" "use-simple" ; then
1437         bzrbase=${vcs_comm[basedir]}
1438         bzrinfo[2]=${bzrbase:t}
1439         if [[ -f ${bzrbase}/.bzr/branch/last-revision ]] ; then
1440             bzrinfo[1]=$(< ${bzrbase}/.bzr/branch/last-revision)
1441             bzrinfo[1]=${${bzrinfo[1]}%% *}
1442         fi
1443     else
1444         bzrbase=${${(M)${(f)"$( bzr info )"}:# ##branch\ root:*}/*: ##/}
1445         bzrinfo=( ${${${(M)${(f)"$( bzr version-info )"}:#(#s)(revno|branch-nick)*}/*: /}/*\//} )
1446         bzrbase="$(VCS_INFO_realpath ${bzrbase})"
1447     fi
1448
1449     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat bzrbr || bzrbr="%b:%r"
1450     zformat -f bzrbr "${bzrbr}" "b:${bzrinfo[2]}" "r:${bzrinfo[1]}"
1451     VCS_INFO_formats '' "${bzrbr}" "${bzrbase}"
1452     return 0
1453 }
1454 # }}}
1455 VCS_INFO_cdv_get_data () { # {{{
1456     local cdvbase
1457
1458     cdvbase=${vcs_comm[basedir]}
1459     VCS_INFO_formats '' "${cdvbase:t}" "${cdvbase}"
1460     return 0
1461 }
1462 # }}}
1463 VCS_INFO_cvs_get_data () { # {{{
1464     local cvsbranch cvsbase basename
1465
1466     cvsbase="."
1467     while [[ -d "${cvsbase}/../CVS" ]]; do
1468         cvsbase="${cvsbase}/.."
1469     done
1470     cvsbase="$(VCS_INFO_realpath ${cvsbase})"
1471     cvsbranch=$(< ./CVS/Repository)
1472     basename=${cvsbase:t}
1473     cvsbranch=${cvsbranch##${basename}/}
1474     [[ -z ${cvsbranch} ]] && cvsbranch=${basename}
1475     VCS_INFO_formats '' "${cvsbranch}" "${cvsbase}"
1476     return 0
1477 }
1478 # }}}
1479 VCS_INFO_darcs_get_data () { # {{{
1480     local darcsbase
1481
1482     darcsbase=${vcs_comm[basedir]}
1483     VCS_INFO_formats '' "${darcsbase:t}" "${darcsbase}"
1484     return 0
1485 }
1486 # }}}
1487 VCS_INFO_git_getaction () { #{{{
1488     local gitaction='' gitdir=$1
1489     local tmp
1490
1491     for tmp in "${gitdir}/rebase-apply" \
1492                "${gitdir}/rebase"       \
1493                "${gitdir}/../.dotest" ; do
1494         if [[ -d ${tmp} ]] ; then
1495             if   [[ -f "${tmp}/rebasing" ]] ; then
1496                 gitaction="rebase"
1497             elif [[ -f "${tmp}/applying" ]] ; then
1498                 gitaction="am"
1499             else
1500                 gitaction="am/rebase"
1501             fi
1502             printf '%s' ${gitaction}
1503             return 0
1504         fi
1505     done
1506
1507     for tmp in "${gitdir}/rebase-merge/interactive" \
1508                "${gitdir}/.dotest-merge/interactive" ; do
1509         if [[ -f "${tmp}" ]] ; then
1510             printf '%s' "rebase-i"
1511             return 0
1512         fi
1513     done
1514
1515     for tmp in "${gitdir}/rebase-merge" \
1516                "${gitdir}/.dotest-merge" ; do
1517         if [[ -d "${tmp}" ]] ; then
1518             printf '%s' "rebase-m"
1519             return 0
1520         fi
1521     done
1522
1523     if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1524         printf '%s' "merge"
1525         return 0
1526     fi
1527
1528     if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
1529         printf '%s' "bisect"
1530         return 0
1531     fi
1532     return 1
1533 }
1534 # }}}
1535 VCS_INFO_git_getbranch () { #{{{
1536     local gitbranch gitdir=$1
1537     local gitsymref='git symbolic-ref HEAD'
1538
1539     if    [[ -d "${gitdir}/rebase-apply" ]] \
1540        || [[ -d "${gitdir}/rebase" ]]       \
1541        || [[ -d "${gitdir}/../.dotest" ]]   \
1542        || [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1543         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1544         [[ -z ${gitbranch} ]] && [[ -r ${gitdir}/rebase-apply/head-name ]] \
1545             && gitbranch="$(< ${gitdir}/rebase-apply/head-name)"
1546
1547     elif   [[ -f "${gitdir}/rebase-merge/interactive" ]] \
1548         || [[ -d "${gitdir}/rebase-merge" ]] ; then
1549         gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
1550
1551     elif   [[ -f "${gitdir}/.dotest-merge/interactive" ]] \
1552         || [[ -d "${gitdir}/.dotest-merge" ]] ; then
1553         gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
1554
1555     else
1556         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1557
1558         if [[ $? -ne 0 ]] ; then
1559             gitbranch="$(git describe --exact-match HEAD 2>/dev/null)"
1560
1561             if [[ $? -ne 0 ]] ; then
1562                 gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
1563             fi
1564         fi
1565     fi
1566
1567     printf '%s' "${gitbranch##refs/heads/}"
1568     return 0
1569 }
1570 # }}}
1571 VCS_INFO_git_get_data () { # {{{
1572     setopt localoptions extendedglob
1573     local gitdir gitbase gitbranch gitaction
1574
1575     gitdir=${vcs_comm[gitdir]}
1576     gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"
1577
1578     if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
1579         return 1
1580     fi
1581
1582     VCS_INFO_adjust
1583     gitaction="$(VCS_INFO_git_getaction ${gitdir})"
1584     gitbase=${PWD%/${$( git rev-parse --show-prefix )%/##}}
1585     VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}"
1586     return 0
1587 }
1588 # }}}
1589 VCS_INFO_hg_get_data () { # {{{
1590     local hgbranch hgbase
1591
1592     hgbase=${vcs_comm[basedir]}
1593     hgbranch=$(< ${hgbase}/.hg/branch)
1594     VCS_INFO_formats '' "${hgbranch}" "${hgbase}"
1595     return 0
1596 }
1597 # }}}
1598 VCS_INFO_mtn_get_data () { # {{{
1599     local mtnbranch mtnbase
1600
1601     mtnbase=${vcs_comm[basedir]}
1602     mtnbranch=${${(M)${(f)"$( mtn status )"}:#(#s)Current branch:*}/*: /}
1603     VCS_INFO_formats '' "${mtnbranch}" "${mtnbase}"
1604     return 0
1605 }
1606 # }}}
1607 VCS_INFO_svk_get_data () { # {{{
1608     local svkbranch svkbase
1609
1610     svkbase=${vcs_comm[basedir]}
1611     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat svkbranch || svkbranch="%b:%r"
1612     zformat -f svkbranch "${svkbranch}" "b:${vcs_comm[branch]}" "r:${vcs_comm[revision]}"
1613     VCS_INFO_formats '' "${svkbranch}" "${svkbase}"
1614     return 0
1615 }
1616 # }}}
1617 VCS_INFO_svn_get_data () { # {{{
1618     setopt localoptions noksharrays
1619     local svnbase svnbranch
1620     local -a svninfo
1621
1622     svnbase="."
1623     while [[ -d "${svnbase}/../.svn" ]]; do
1624         svnbase="${svnbase}/.."
1625     done
1626     svnbase="$(VCS_INFO_realpath ${svnbase})"
1627     svninfo=( ${${${(M)${(f)"$( svn info )"}:#(#s)(URL|Revision)*}/*: /}/*\//} )
1628
1629     zstyle -s ":vcs_info:${vcs}:${usercontext}" branchformat svnbranch || svnbranch="%b:%r"
1630     zformat -f svnbranch "${svnbranch}" "b:${svninfo[1]}" "r:${svninfo[2]}"
1631     VCS_INFO_formats '' "${svnbranch}" "${svnbase}"
1632     return 0
1633 }
1634 # }}}
1635 VCS_INFO_tla_get_data () { # {{{
1636     local tlabase tlabranch
1637
1638     tlabase="$(VCS_INFO_realpath ${vcs_comm[basedir]})"
1639     # tree-id gives us something like 'foo@example.com/demo--1.0--patch-4', so:
1640     tlabranch=${${"$( tla tree-id )"}/*\//}
1641     VCS_INFO_formats '' "${tlabranch}" "${tlabase}"
1642     return 0
1643 }
1644 # }}}
1645 # detection
1646 VCS_INFO_detect_by_dir() { #{{{
1647     local dirname=$1
1648     local basedir="." realbasedir
1649
1650     realbasedir="$(VCS_INFO_realpath ${basedir})"
1651     while [[ ${realbasedir} != '/' ]]; do
1652         if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
1653             [[ -d ${basedir}/${dirname} ]] && \
1654             [[ -f ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
1655                 break
1656         else
1657             [[ -d ${basedir}/${dirname} ]] && break
1658         fi
1659
1660         basedir=${basedir}/..
1661         realbasedir="$(VCS_INFO_realpath ${basedir})"
1662     done
1663
1664     [[ ${realbasedir} == "/" ]] && return 1
1665     vcs_comm[basedir]=${realbasedir}
1666     return 0
1667 }
1668 # }}}
1669 VCS_INFO_bzr_detect() { #{{{
1670     VCS_INFO_check_com bzr || return 1
1671     vcs_comm[detect_need_file]=branch/format
1672     VCS_INFO_detect_by_dir '.bzr'
1673     return $?
1674 }
1675 # }}}
1676 VCS_INFO_cdv_detect() { #{{{
1677     VCS_INFO_check_com cdv || return 1
1678     vcs_comm[detect_need_file]=format
1679     VCS_INFO_detect_by_dir '.cdv'
1680     return $?
1681 }
1682 # }}}
1683 VCS_INFO_cvs_detect() { #{{{
1684     VCS_INFO_check_com svn || return 1
1685     [[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
1686     return 1
1687 }
1688 # }}}
1689 VCS_INFO_darcs_detect() { #{{{
1690     VCS_INFO_check_com darcs || return 1
1691     vcs_comm[detect_need_file]=format
1692     VCS_INFO_detect_by_dir '_darcs'
1693     return $?
1694 }
1695 # }}}
1696 VCS_INFO_git_detect() { #{{{
1697     if VCS_INFO_check_com git && git rev-parse --is-inside-work-tree &> /dev/null ; then
1698         vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
1699         if   [[ -d ${vcs_comm[gitdir]}/svn ]]             ; then vcs_comm[overwrite_name]='git-svn'
1700         elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
1701         return 0
1702     fi
1703     return 1
1704 }
1705 # }}}
1706 VCS_INFO_hg_detect() { #{{{
1707     VCS_INFO_check_com hg || return 1
1708     vcs_comm[detect_need_file]=branch
1709     VCS_INFO_detect_by_dir '.hg'
1710     return $?
1711 }
1712 # }}}
1713 VCS_INFO_mtn_detect() { #{{{
1714     VCS_INFO_check_com mtn || return 1
1715     vcs_comm[detect_need_file]=revision
1716     VCS_INFO_detect_by_dir '_MTN'
1717     return $?
1718 }
1719 # }}}
1720 VCS_INFO_svk_detect() { #{{{
1721     setopt localoptions noksharrays extendedglob
1722     local -a info
1723     local -i fhash
1724     fhash=0
1725
1726     VCS_INFO_check_com svk || return 1
1727     [[ -f ~/.svk/config ]] || return 1
1728
1729     # This detection function is a bit different from the others.
1730     # We need to read svk's config file to detect a svk repository
1731     # in the first place. Therefore, we'll just proceed and read
1732     # the other information, too. This is more then any of the
1733     # other detections do but this takes only one file open for
1734     # svk at most. VCS_INFO_svk_get_data() get simpler, too. :-)
1735     while IFS= read -r line ; do
1736         if [[ -n ${vcs_comm[basedir]} ]] ; then
1737             line=${line## ##}
1738             [[ ${line} == depotpath:* ]] && vcs_comm[branch]=${line##*/}
1739             [[ ${line} == revision:* ]] && vcs_comm[revision]=${line##*[[:space:]]##}
1740             [[ -n ${vcs_comm[branch]} ]] && [[ -n ${vcs_comm[revision]} ]] && break
1741             continue
1742         fi
1743         (( fhash > 0 )) && [[ ${line} == '  '[^[:space:]]*:* ]] && break
1744         [[ ${line} == '  hash:'* ]] && fhash=1 && continue
1745         (( fhash == 0 )) && continue
1746         [[ ${PWD}/ == ${${line## ##}%:*}/* ]] && vcs_comm[basedir]=${${line## ##}%:*}
1747     done < ~/.svk/config
1748
1749     [[ -n ${vcs_comm[basedir]} ]]  && \
1750     [[ -n ${vcs_comm[branch]} ]]   && \
1751     [[ -n ${vcs_comm[revision]} ]] && return 0
1752     return 1
1753 }
1754 # }}}
1755 VCS_INFO_svn_detect() { #{{{
1756     VCS_INFO_check_com svn || return 1
1757     [[ -d ".svn" ]] && return 0
1758     return 1
1759 }
1760 # }}}
1761 VCS_INFO_tla_detect() { #{{{
1762     VCS_INFO_check_com tla || return 1
1763     vcs_comm[basedir]="$(tla tree-root 2> /dev/null)" && return 0
1764     return 1
1765 }
1766 # }}}
1767 # public API
1768 vcs_info_printsys () { # {{{
1769     vcs_info print_systems_
1770 }
1771 # }}}
1772 vcs_info_lastmsg () { # {{{
1773     local -i i
1774
1775     VCS_INFO_maxexports
1776     for i in {0..$((maxexports - 1))} ; do
1777         printf '$VCS_INFO_message_%d_: "' $i
1778         if zstyle -T ':vcs_info:formats:command' use-prompt-escapes ; then
1779             print -nP ${(P)${:-VCS_INFO_message_${i}_}}
1780         else
1781             print -n ${(P)${:-VCS_INFO_message_${i}_}}
1782         fi
1783         printf '"\n'
1784     done
1785 }
1786 # }}}
1787 vcs_info () { # {{{
1788     local -i found
1789     local -a VCSs disabled
1790     local -x vcs usercontext
1791     local -ax msgs
1792     local -Ax vcs_comm
1793
1794     vcs="init"
1795     VCSs=(git hg bzr darcs svk mtn svn cvs cdv tla)
1796     case $1 in
1797         (print_systems_)
1798             zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable" disabled
1799             print -l '# list of supported version control backends:' \
1800                      '# disabled systems are prefixed by a hash sign (#)'
1801             for vcs in ${VCSs} ; do
1802                 [[ -n ${(M)disabled:#${vcs}} ]] && printf '#'
1803                 printf '%s\n' ${vcs}
1804             done
1805             print -l '# flavours (cannot be used in the disable style; they' \
1806                      '# are disabled with their master [git-svn -> git]):'   \
1807                      git-{p4,svn}
1808             return 0
1809             ;;
1810         ('')
1811             [[ -z ${usercontext} ]] && usercontext=default
1812             ;;
1813         (*) [[ -z ${usercontext} ]] && usercontext=$1
1814             ;;
1815     esac
1816
1817     zstyle -T ":vcs_info:${vcs}:${usercontext}" "enable" || {
1818         [[ -n ${VCS_INFO_message_0_} ]] && VCS_INFO_set --clear
1819         return 0
1820     }
1821     zstyle -a ":vcs_info:${vcs}:${usercontext}" "disable" disabled
1822     VCS_INFO_maxexports
1823
1824     (( found = 0 ))
1825     for vcs in ${VCSs} ; do
1826         [[ -n ${(M)disabled:#${vcs}} ]] && continue
1827         vcs_comm=()
1828         VCS_INFO_${vcs}_detect && (( found = 1 )) && break
1829     done
1830
1831     (( found == 0 )) && {
1832         VCS_INFO_set --nvcs
1833         return 0
1834     }
1835
1836     VCS_INFO_${vcs}_get_data || {
1837         VCS_INFO_set --nvcs
1838         return 1
1839     }
1840
1841     VCS_INFO_set
1842     return 0
1843 }
1844
1845 VCS_INFO_set --nvcs preinit
1846 # }}}
1847
1848 # change vcs_info formats for the grml prompt
1849 if [[ "$TERM" == dumb ]] ; then
1850     zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] "
1851     zstyle ':vcs_info:*' formats       "(%s%)-[%b] "
1852 else
1853     # these are the same, just with a lot of colours:
1854     zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOUR} "
1855     zstyle ':vcs_info:*' formats       "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOUR}%} "
1856     zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r"
1857 fi
1858
1859 # }}}
1860
1861 # {{{ set prompt
1862 if zrcautoload promptinit && promptinit 2>/dev/null ; then
1863     promptinit # people should be able to use their favourite prompt
1864 else
1865     print 'Notice: no promptinit available :('
1866 fi
1867
1868 setopt prompt_subst
1869
1870 # make sure to use right prompt only when not running a command
1871 is41 && setopt transient_rprompt
1872
1873 is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
1874     [[ $NOPRECMD -gt 0 ]] && return 0
1875     # update VCS information
1876     vcs_info
1877
1878     # allow manual overwriting of RPROMPT
1879     if [[ -n $RPROMPT ]] ; then
1880         [[ $TERM == screen* ]] && print -nP "\ekzsh\e\\"
1881         # return 0
1882     fi
1883     # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
1884     if [[ $DONTSETRPROMPT -eq 0 ]] ; then
1885         if [[ $BATTERY -gt 0 ]] ; then
1886             # update BATTERY information
1887             battery
1888             RPROMPT="%(?..:()% ${PERCENT}${SCREENTITLE}"
1889             # RPROMPT="${PERCENT}${SCREENTITLE}"
1890         else
1891             RPROMPT="%(?..:()% ${SCREENTITLE}"
1892             # RPROMPT="${SCREENTITLE}"
1893         fi
1894     fi
1895     # adjust title of xterm
1896     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
1897     case $TERM in
1898         (xterm*|rxvt)
1899             print -Pn "\e]0;%n@%m: %~\a"
1900             ;;
1901     esac
1902 }
1903
1904 # preexec() => a function running before every command
1905 is4 && [[ $NOPRECMD -eq 0 ]] && \
1906 preexec () {
1907     [[ $NOPRECMD -gt 0 ]] && return 0
1908 # set hostname if not running on host with name 'grml'
1909     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
1910        NAME="@$HOSTNAME"
1911     fi
1912 # get the name of the program currently running and hostname of local machine
1913 # set screen window title if running in a screen
1914     if [[ "$TERM" == screen* ]] ; then
1915         # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]}       # don't use hostname
1916         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname
1917         echo -ne "\ek$CMD\e\\"
1918     fi
1919 # set the screen title to "zsh" when sitting at the command prompt:
1920     if [[ "$TERM" == screen* ]] ; then
1921         SCREENTITLE=$'%{\ekzsh\e\\%}'
1922     else
1923         SCREENTITLE=''
1924     fi
1925 # adjust title of xterm
1926     case $TERM in
1927         (xterm*|rxvt)
1928             print -Pn "\e]0;%n@%m: $1\a"
1929             ;;
1930     esac
1931 }
1932
1933 EXITCODE="%(?..%?%1v )"
1934 PS2='\`%_> '      # secondary prompt, printed when the shell needs more information to complete a command.
1935 PS3='?# '         # selection prompt used within a select loop.
1936 PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
1937
1938 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
1939 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
1940     debian_chroot=$(cat /etc/debian_chroot)
1941 fi
1942
1943 # don't use colors on dumb terminals (like emacs):
1944 if [[ "$TERM" == dumb ]] ; then
1945     PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_0_}'"%# "
1946 else
1947     # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt
1948     # set variable identifying the chroot you work in (used in the prompt below)
1949     if [[ $GRMLPROMPT -gt 0 ]] ; then
1950         PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D
1951 ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
1952     else
1953         # This assembles the primary prompt string
1954         if (( EUID != 0 )); then
1955             PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_0_}'"%# "
1956         else
1957             PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_0_}'"%# "
1958         fi
1959     fi
1960 fi
1961
1962 # if we are inside a grml-chroot set a specific prompt theme
1963 if [[ -n "$GRML_CHROOT" ]] ; then
1964     PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# "
1965 fi
1966 # }}}
1967
1968 # {{{ 'hash' some often used directories
1969 #d# start
1970 hash -d deb=/var/cache/apt/archives
1971 hash -d doc=/usr/share/doc
1972 hash -d linux=/lib/modules/$(command uname -r)/build/
1973 hash -d log=/var/log
1974 hash -d slog=/var/log/syslog
1975 hash -d src=/usr/src
1976 hash -d templ=/usr/share/doc/grml-templates
1977 hash -d tt=/usr/share/doc/texttools-doc
1978 hash -d www=/var/www
1979 #d# end
1980 # }}}
1981
1982 # {{{ some aliases
1983 if [[ $UID -eq 0 ]] ; then
1984     [[ -r /etc/grml/screenrc ]] && alias screen='/usr/bin/screen -c /etc/grml/screenrc'
1985 elif [[ -r $HOME/.screenrc ]] ; then
1986     alias screen="/usr/bin/screen -c $HOME/.screenrc"
1987 else
1988     [[ -r /etc/grml/screenrc_grml ]] && alias screen='/usr/bin/screen -c /etc/grml/screenrc_grml'
1989 fi
1990
1991 # do we have GNU ls with color-support?
1992 if ls --help 2>/dev/null | grep -- --color= >/dev/null && [[ "$TERM" != dumb ]] ; then
1993     #a1# execute \kbd{@a@}:\quad ls with colors
1994     alias ls='ls -b -CF --color=auto'
1995     #a1# execute \kbd{@a@}:\quad list all files, with colors
1996     alias la='ls -la --color=auto'
1997     #a1# long colored list, without dotfiles (@a@)
1998     alias ll='ls -l --color=auto'
1999     #a1# long colored list, human readable sizes (@a@)
2000     alias lh='ls -hAl --color=auto'
2001     #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
2002     alias l='ls -lF --color=auto'
2003 else
2004     alias ls='ls -b -CF'
2005     alias la='ls -la'
2006     alias ll='ls -l'
2007     alias lh='ls -hAl'
2008     alias l='ls -lF'
2009 fi
2010
2011 alias mdstat='cat /proc/mdstat'
2012 alias ...='cd ../../'
2013
2014 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
2015 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
2016     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
2017 fi
2018
2019 alias cp='nocorrect cp'         # no spelling correction on cp
2020 alias mkdir='nocorrect mkdir'   # no spelling correction on mkdir
2021 alias mv='nocorrect mv'         # no spelling correction on mv
2022 alias rm='nocorrect rm'         # no spelling correction on rm
2023
2024 #a1# Execute \kbd{rmdir}
2025 alias rd='rmdir'
2026 #a1# Execute \kbd{rmdir}
2027 alias md='mkdir'
2028
2029 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
2030 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
2031 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
2032
2033 # make sure it is not assigned yet
2034 [[ $(whence -w utf2iso &>/dev/null) == 'utf2iso: alias' ]] && unalias utf2iso
2035
2036 utf2iso() {
2037     if isutfenv ; then
2038         for ENV in $(env | command grep -i '.utf') ; do
2039             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
2040         done
2041     fi
2042 }
2043
2044 # make sure it is not assigned yet
2045 [[ $(whence -w iso2utf &>/dev/null) == 'iso2utf: alias' ]] && unalias iso2utf
2046 iso2utf() {
2047     if ! isutfenv ; then
2048         for ENV in $(env | command grep -i '\.iso') ; do
2049             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
2050         done
2051     fi
2052 }
2053
2054 # set up software synthesizer via speakup
2055 swspeak() {
2056     aumix -w 90 -v 90 -p 90 -m 90
2057     if ! [[ -r /dev/softsynth ]] ; then
2058         flite -o play -t "Sorry, software synthesizer not available. Did you boot with swspeak bootoption?"
2059         return 1
2060     else
2061         setopt singlelinezle
2062         unsetopt prompt_cr
2063         export PS1="%m%# "
2064         nice -n -20 speechd-up
2065         sleep 2
2066         flite -o play -t "Finished setting up software synthesizer"
2067     fi
2068 }
2069
2070 # I like clean prompt, so provide simple way to get that
2071 check_com 0 || alias 0='return 0'
2072
2073 # for really lazy people like mika:
2074 check_com S &>/dev/null || alias S='screen'
2075 check_com s &>/dev/null || alias s='ssh'
2076
2077 # get top 10 shell commands:
2078 alias top10='print -l ? ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
2079
2080 # truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i'
2081 if check_com -c truecrypt ; then
2082     if isutfenv ; then
2083         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" '
2084     else
2085         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" '
2086     fi
2087 fi
2088
2089 #f1# Hints for the use of zsh on grml
2090 zsh-help() {
2091     print "$bg[white]$fg[black]
2092 zsh-help - hints for use of zsh on grml
2093 =======================================$reset_color"
2094
2095     print '
2096 Main configuration of zsh happens in /etc/zsh/zshrc (global)
2097 and /etc/skel/.zshrc which is copied to $HOME/.zshrc once.
2098 The files are part of the package grml-etc-core, if you want to
2099 use them on a non-grml-system just get the tar.gz from
2100 http://deb.grml.org/ or get the files from the mercurial
2101 repository:
2102
2103   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/skel/.zshrc
2104   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/zsh/zshrc
2105
2106 If you want to stay in sync with zsh configuration of grml
2107 run '\''ln -sf /etc/skel/.zshrc $HOME/.zshrc'\'' and configure
2108 your own stuff in $HOME/.zshrc.local. System wide configuration
2109 without touching configuration files of grml can take place
2110 in /etc/zsh/zshrc.local.
2111
2112 If you want to use the configuration of user grml also when
2113 running as user root just run '\''zshskel'\'' which will source
2114 the file /etc/skel/.zshrc.
2115
2116 For information regarding zsh start at http://grml.org/zsh/
2117
2118 Take a look at grml'\''s zsh refcard:
2119 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
2120
2121 Check out the main zsh refcard:
2122 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
2123
2124 And of course visit the zsh-lovers:
2125 % man zsh-lovers
2126
2127 You can adjust some options through environment variables when
2128 invoking zsh without having to edit configuration files.
2129 Basically meant for bash users who are not used to the power of
2130 the zsh yet. :)
2131
2132   "NOCOR=1    zsh" => deactivate automatic correction
2133   "NOMENU=1   zsh" => do not use auto menu completion (note: use ctrl-d for completion instead!)
2134   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
2135   "BATTERY=1  zsh" => activate battery status (via acpi) on right side of prompt
2136
2137 A value greater than 0 is enables a feature; a value equal to zero
2138 disables it. If you like one or the other of these settings, you can
2139 add them to ~/.zshenv to ensure they are set when sourcing grml'\''s
2140 zshrc.'
2141
2142     print "
2143 $bg[white]$fg[black]
2144 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
2145 Enjoy your grml system with the zsh!$reset_color"
2146 }
2147
2148 # debian stuff
2149 if [[ -r /etc/debian_version ]] ; then
2150     #a3# Execute \kbd{apt-cache search}
2151     alias acs='apt-cache search'
2152     #a3# Execute \kbd{apt-cache show}
2153     alias acsh='apt-cache show'
2154     #a3# Execute \kbd{apt-cache policy}
2155     alias acp='apt-cache policy'
2156     #a3# Execute \kbd{apt-get dist-upgrade}
2157     salias adg="apt-get dist-upgrade"
2158     #a3# Execute \kbd{apt-get install}
2159     salias agi="apt-get install"
2160     #a3# Execute \kbd{aptitude install}
2161     salias ati="aptitude install"
2162     #a3# Execute \kbd{apt-get upgrade}
2163     salias ag="apt-get upgrade"
2164     #a3# Execute \kbd{apt-get update}
2165     salias au="apt-get update"
2166     #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
2167     salias -a up="aptitude update ; aptitude safe-upgrade"
2168     #a3# Execute \kbd{dpkg-buildpackage}
2169     alias dbp='dpkg-buildpackage'
2170     #a3# Execute \kbd{grep-excuses}
2171     alias ge='grep-excuses'
2172
2173     # debian upgrade
2174     #f3# Execute \kbd{apt-get update \&\& }\\&\quad \kbd{apt-get dist-upgrade}
2175     upgrade() {
2176         if [[ -z "$1" ]] ; then
2177             $SUDO apt-get update
2178             $SUDO apt-get -u upgrade
2179         else
2180             ssh $1 $SUDO apt-get update
2181             # ask before the upgrade
2182             local dummy
2183             ssh $1 $SUDO apt-get --no-act upgrade
2184             echo -n 'Process the upgrade?'
2185             read -q dummy
2186             if [[ $dummy == "y" ]] ; then
2187                 ssh $1 $SUDO apt-get -u upgrade --yes
2188             fi
2189         fi
2190     }
2191
2192     # get a root shell as normal user in live-cd mode:
2193     if isgrmlcd && [[ $UID -ne 0 ]] ; then
2194        alias su="sudo su"
2195      fi
2196
2197     #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
2198     alias llog="$PAGER /var/log/syslog"     # take a look at the syslog
2199     #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
2200     alias tlog="tail -f /var/log/syslog"    # follow the syslog
2201     #a1# (Re)-source \kbd{/etc/skel/.zshrc}
2202     alias zshskel="source /etc/skel/.zshrc" # source skeleton zshrc
2203 fi
2204
2205 # sort installed Debian-packages by size
2206 if check_com -c grep-status ; then
2207     #a3# List installed Debian-packages sorted by size
2208     alias debs-by-size='grep-status -FStatus -sInstalled-Size,Package -n "install ok installed" | paste -sd "  \n" | sort -rn'
2209 fi
2210
2211 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
2212 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord ; then
2213     if check_com -c wodim ; then
2214         alias cdrecord="echo 'cdrecord is not provided under its original name by Debian anymore.
2215 See #377109 in the BTS of Debian for more details.
2216
2217 Please use the wodim binary instead' ; return 1"
2218     fi
2219 fi
2220
2221 # get_tw_cli has been renamed into get_3ware
2222 if check_com -c get_3ware ; then
2223     get_tw_cli() {
2224         echo 'Warning: get_tw_cli has been renamed into get_3ware. Invoking get_3ware for you.'>&2
2225         get_3ware
2226     }
2227 fi
2228
2229 # I hate lacking backward compatibility, so provide an alternative therefore
2230 if ! check_com -c apache2-ssl-certificate ; then
2231
2232     apache2-ssl-certificate() {
2233
2234     print 'Debian does not ship apache2-ssl-certificate anymore (see #398520). :('
2235     print 'You might want to take a look at Debian the package ssl-cert as well.'
2236     print 'To generate a certificate for use with apache2 follow the instructions:'
2237
2238     echo '
2239
2240 export RANDFILE=/dev/random
2241 mkdir /etc/apache2/ssl/
2242 openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem
2243 chmod 600 /etc/apache2/ssl/apache.pem
2244
2245 Run "grml-tips ssl-certificate" if you need further instructions.
2246 '
2247     }
2248 fi
2249 # }}}
2250
2251 # {{{ Use hard limits, except for a smaller stack and no core dumps
2252 unlimit
2253 is425 && limit stack 8192
2254 isgrmlcd && limit core 0 # important for a live-cd-system
2255 limit -s
2256 # }}}
2257
2258 # {{{ completion system
2259
2260 # called later (via is4 && grmlcomp)
2261 # notice: use 'zstyle' for getting current settings
2262 #         press ^Xh (control-x h) for getting tags in context; ^X? (control-x ?) to run complete_debug with trace output
2263 grmlcomp() {
2264     # TODO: This could use some additional information
2265
2266     # allow one error for every three characters typed in approximate completer
2267     zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
2268
2269     # don't complete backup files as executables
2270     zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
2271
2272     # start menu completion only if it could find no unambiguous initial string
2273     zstyle ':completion:*:correct:*'       insert-unambiguous true
2274     zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
2275     zstyle ':completion:*:correct:*'       original true
2276
2277     # activate color-completion
2278     zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}
2279
2280     # format on completion
2281     zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
2282
2283     # complete 'cd -<tab>' with menu
2284     zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
2285
2286     # insert all expansions for expand completer
2287     zstyle ':completion:*:expand:*'        tag-order all-expansions
2288     zstyle ':completion:*:history-words'   list false
2289
2290     # activate menu
2291     zstyle ':completion:*:history-words'   menu yes
2292
2293     # ignore duplicate entries
2294     zstyle ':completion:*:history-words'   remove-all-dups yes
2295     zstyle ':completion:*:history-words'   stop yes
2296
2297     # match uppercase from lowercase
2298     zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'
2299
2300     # separate matches into groups
2301     zstyle ':completion:*:matches'         group 'yes'
2302     zstyle ':completion:*'                 group-name ''
2303
2304     if [[ "$NOMENU" -eq 0 ]] ; then
2305         # if there are more than 5 options allow selecting from a menu
2306         zstyle ':completion:*'               menu select=5
2307     else
2308         # don't use any menus at all
2309         setopt no_auto_menu
2310     fi
2311
2312     zstyle ':completion:*:messages'        format '%d'
2313     zstyle ':completion:*:options'         auto-description '%d'
2314
2315     # describe options in full
2316     zstyle ':completion:*:options'         description 'yes'
2317
2318     # on processes completion complete all user processes
2319     zstyle ':completion:*:processes'       command 'ps -au$USER'
2320
2321     # offer indexes before parameters in subscripts
2322     zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
2323
2324     # provide verbose completion information
2325     zstyle ':completion:*'                 verbose true
2326
2327     # recent (as of Dec 2007) zsh versions are able to provide descriptions
2328     # for commands (read: 1st word in the line) that it will list for the user
2329     # to choose from. The following disables that, because it's not exactly fast.
2330     zstyle ':completion:*:-command-:*:'    verbose false
2331
2332     # set format for warnings
2333     zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
2334
2335     # define files to ignore for zcompile
2336     zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
2337     zstyle ':completion:correct:'          prompt 'correct to: %e'
2338
2339     # Ignore completion functions for commands you don't have:
2340     zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
2341
2342     # Provide more processes in completion of programs like killall:
2343     zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'
2344
2345     # complete manual by their section
2346     zstyle ':completion:*:manuals'    separate-sections true
2347     zstyle ':completion:*:manuals.*'  insert-sections   true
2348     zstyle ':completion:*:man:*'      menu yes select
2349
2350     # run rehash on completion so new installed program are found automatically:
2351     _force_rehash() {
2352         (( CURRENT == 1 )) && rehash
2353         return 1
2354     }
2355
2356     ## correction
2357     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
2358     if [[ "$NOCOR" -gt 0 ]] ; then
2359         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
2360         setopt nocorrect
2361     else
2362         # try to be smart about when to use what completer...
2363         setopt correct
2364         zstyle -e ':completion:*' completer '
2365             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
2366                 _last_try="$HISTNO$BUFFER$CURSOR"
2367                 reply=(_complete _match _ignored _prefix _files)
2368             else
2369                 if [[ $words[1] == (rm|mv) ]] ; then
2370                     reply=(_complete _files)
2371                 else
2372                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
2373                 fi
2374             fi'
2375     fi
2376
2377     # zstyle ':completion:*' completer _complete _correct _approximate
2378     # zstyle ':completion:*' expand prefix suffix
2379
2380     # complete shell aliases
2381     # zstyle ':completion:*' completer _expand_alias _complete _approximate
2382
2383     # command for process lists, the local web server details and host completion
2384     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
2385
2386     # caching
2387     [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
2388                             zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
2389
2390     # host completion /* add brackets as vim can't parse zsh's complex cmdlines 8-) {{{ */
2391     if is42 ; then
2392         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
2393         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
2394     else
2395         _ssh_hosts=()
2396         _etc_hosts=()
2397     fi
2398     hosts=(
2399         $(hostname)
2400         "$_ssh_hosts[@]"
2401         "$_etc_hosts[@]"
2402         grml.org
2403         localhost
2404     )
2405     zstyle ':completion:*:hosts' hosts $hosts
2406     #  zstyle '*' hosts $hosts
2407
2408     # specify your logins:
2409     # my_accounts=(
2410     #  {grml,grml1}@foo.invalid
2411     #  grml-devel@bar.invalid
2412     # )
2413     # other_accounts=(
2414     #  {fred,root}@foo.invalid
2415     #  vera@bar.invalid
2416     # )
2417     # zstyle ':completion:*:my-accounts' users-hosts $my_accounts
2418     # zstyle ':completion:*:other-accounts' users-hosts $other_accounts
2419
2420     # specify specific port/service settings:
2421     #  telnet_users_hosts_ports=(
2422     #    user1@host1:
2423     #    user2@host2:
2424     #    @mail-server:{smtp,pop3}
2425     #    @news-server:nntp
2426     #    @proxy-server:8000
2427     #  )
2428     # zstyle ':completion:*:*:telnet:*' users-hosts-ports $telnet_users_hosts_ports
2429
2430     # use generic completion system for programs not yet defined; (_gnu_generic works
2431     # with commands that provide a --help option with "standard" gnu-like output.)
2432     compdef _gnu_generic tail head feh cp mv df stow uname ipacsum fetchipac
2433
2434     # see upgrade function in this file
2435     compdef _hosts upgrade
2436 }
2437 # }}}
2438
2439 # {{{ grmlstuff
2440 grmlstuff() {
2441 # people should use 'grml-x'!
2442     startx() {
2443         if [[ -e /etc/X11/xorg.conf ]] ; then
2444             [[ -x /usr/bin/startx ]] && /usr/bin/startx "$@" || /usr/X11R6/bin/startx "$@"
2445         else
2446             echo "Please use the script \"grml-x\" for starting the X Window System
2447 because there does not exist /etc/X11/xorg.conf yet.
2448 If you want to use startx anyway please call \"/usr/bin/startx\"."
2449             return -1
2450         fi
2451     }
2452
2453     xinit() {
2454         if [[ -e /etc/X11/xorg.conf ]] ; then
2455             [[ -x /usr/bin/xinit ]] && /usr/bin/xinit || /usr/X11R6/bin/xinit
2456         else
2457             echo "Please use the script \"grml-x\" for starting the X Window System.
2458 because there does not exist /etc/X11/xorg.conf yet.
2459 If you want to use xinit anyway please call \"/usr/bin/xinit\"."
2460             return -1
2461         fi
2462     }
2463
2464     if check_com -c 915resolution ; then
2465         alias 855resolution='echo -e "Please use 915resolution as resolution modify tool for Intel graphic chipset."; return -1'
2466     fi
2467
2468     #a1# Output version of running grml
2469     alias grml-version='cat /etc/grml_version'
2470
2471     if check_com -c rebuildfstab ; then
2472         #a1# Rebuild /etc/fstab
2473         alias grml-rebuildfstab='rebuildfstab -v -r -config'
2474     fi
2475
2476     if check_com -c grml-debootstrap ; then
2477         alias debian2hd='print "Installing debian to harddisk is possible via using grml-debootstrap." ; return 1'
2478     fi
2479 }
2480 # }}}
2481
2482 # {{{ now run the functions
2483 isgrml && checkhome
2484 is4    && isgrml    && grmlstuff
2485 is4    && grmlcomp
2486 # }}}
2487
2488 # {{{ keephack
2489 is4 && xsource "/etc/zsh/keephack"
2490 # }}}
2491
2492 # {{{ wonderful idea of using "e" glob qualifier by Peter Stephenson
2493 # You use it as follows:
2494 # $ NTREF=/reference/file
2495 # $ ls -l *(e:nt:)
2496 # This lists all the files in the current directory newer than the reference file.
2497 # You can also specify the reference file inline; note quotes:
2498 # $ ls -l *(e:'nt ~/.zshenv':)
2499 is4 && nt() {
2500     if [[ -n $1 ]] ; then
2501         local NTREF=${~1}
2502     fi
2503     [[ $REPLY -nt $NTREF ]]
2504 }
2505 # }}}
2506
2507 # shell functions {{{
2508
2509 #f1# Provide csh compatibility
2510 setenv()  { typeset -x "${1}${1:+=}${(@)argv[2,$#]}" }  # csh compatibility
2511
2512 #f1# Reload an autoloadable function
2513 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2514
2515 #f1# Reload zsh setup
2516 reload() {
2517     if [[ "$#*" -eq 0 ]] ; then
2518         [[ -r ~/.zshrc ]] && . ~/.zshrc
2519     else
2520         local fn
2521         for fn in "$@"; do
2522             unfunction $fn
2523             autoload -U $fn
2524         done
2525     fi
2526 }
2527 compdef _functions reload freload
2528
2529 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
2530 sll() {
2531     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
2532     for i in "$@" ; do
2533         file=$i
2534         while [[ -h "$file" ]] ; do
2535             ls -l $file
2536             file=$(readlink "$file")
2537         done
2538     done
2539 }
2540
2541 # fast manual access
2542 if check_com qma ; then
2543     #f1# View the zsh manual
2544     manzsh()  { qma zshall "$1" }
2545     compdef _man qma
2546 else
2547     manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
2548     # manzsh()  { /usr/bin/man zshall |  most +/"$1" ; }
2549     # [[ -f ~/.terminfo/m/mostlike ]] && MYLESS='LESS=C TERMINFO=~/.terminfo TERM=mostlike less' || MYLESS='less'
2550     # manzsh()  { man zshall | $MYLESS -p $1 ; }
2551 fi
2552
2553 if check_com -c $PAGER ; then
2554     #f1# View Debian's changelog of a given package
2555     dchange() {
2556         if [[ -r /usr/share/doc/${1}/changelog.Debian.gz ]] ; then
2557             $PAGER /usr/share/doc/${1}/changelog.Debian.gz
2558         elif [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
2559             $PAGER /usr/share/doc/${1}/changelog.gz
2560         else
2561             if check_com -c aptitude ; then
2562                 echo "No changelog for package $1 found, using aptitude to retrieve it."
2563                 if isgrml ; then
2564                     aptitude -t unstable changelog ${1}
2565                 else
2566                     aptitude changelog ${1}
2567                 fi
2568             else
2569                 echo "No changelog for package $1 found, sorry."
2570                 return 1
2571             fi
2572         fi
2573     }
2574     _dchange() { _files -W /usr/share/doc -/ }
2575     compdef _dchange dchange
2576
2577     #f1# View Debian's NEWS of a given package
2578     dnews() {
2579         if [[ -r /usr/share/doc/${1}/NEWS.Debian.gz ]] ; then
2580             $PAGER /usr/share/doc/${1}/NEWS.Debian.gz
2581         else
2582             if [[ -r /usr/share/doc/${1}/NEWS.gz ]] ; then
2583                 $PAGER /usr/share/doc/${1}/NEWS.gz
2584             else
2585                 echo "No NEWS file for package $1 found, sorry."
2586                 return 1
2587             fi
2588         fi
2589     }
2590     _dnews() { _files -W /usr/share/doc -/ }
2591     compdef _dnews dnews
2592
2593     #f1# View upstream's changelog of a given package
2594     uchange() {
2595         if [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
2596             $PAGER /usr/share/doc/${1}/changelog.gz
2597         else
2598             echo "No changelog for package $1 found, sorry."
2599             return 1
2600         fi
2601     }
2602     _uchange() { _files -W /usr/share/doc -/ }
2603     compdef _uchange uchange
2604 fi
2605
2606 # zsh profiling
2607 profile() {
2608     ZSH_PROFILE_RC=1 $SHELL "$@"
2609 }
2610
2611 #f1# Edit an alias via zle
2612 edalias() {
2613     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
2614 }
2615 compdef _aliases edalias
2616
2617 #f1# Edit a function via zle
2618 edfunc() {
2619     [[ -z "$1" ]] && { echo "Usage: edfun <function_to_edit>" ; return 1 } || zed -f "$1" ;
2620 }
2621 compdef _functions edfunc
2622
2623 # use it e.g. via 'Restart apache2'
2624 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
2625 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
2626 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
2627 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
2628 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
2629 if [[ -d /etc/init.d || -d /etc/service ]] ; then
2630     __start_stop() {
2631         local action_="${1:l}"  # e.g Start/Stop/Restart
2632         local service_="$2"
2633         local param_="$3"
2634
2635         local service_target_="$(readlink /etc/init.d/$service_)"
2636         if [[ $service_target_ == "/usr/bin/sv" ]]; then
2637             # runit
2638             case "${action_}" in
2639                 start) if [[ ! -e /etc/service/$service_ ]]; then
2640                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
2641                        else
2642                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2643                        fi ;;
2644                 # there is no reload in runits sysv emulation
2645                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
2646                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
2647             esac
2648         else
2649             # sysvinit
2650             $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2651         fi
2652     }
2653
2654     for i in Start Restart Stop Force-Reload Reload ; do
2655         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
2656     done
2657 fi
2658
2659 #f1# Provides useful information on globbing
2660 H-Glob() {
2661     echo -e "
2662     /      directories
2663     .      plain files
2664     @      symbolic links
2665     =      sockets
2666     p      named pipes (FIFOs)
2667     *      executable plain files (0100)
2668     %      device files (character or block special)
2669     %b     block special files
2670     %c     character special files
2671     r      owner-readable files (0400)
2672     w      owner-writable files (0200)
2673     x      owner-executable files (0100)
2674     A      group-readable files (0040)
2675     I      group-writable files (0020)
2676     E      group-executable files (0010)
2677     R      world-readable files (0004)
2678     W      world-writable files (0002)
2679     X      world-executable files (0001)
2680     s      setuid files (04000)
2681     S      setgid files (02000)
2682     t      files with the sticky bit (01000)
2683
2684   print *(m-1)          # Files modified up to a day ago
2685   print *(a1)           # Files accessed a day ago
2686   print *(@)            # Just symlinks
2687   print *(Lk+50)        # Files bigger than 50 kilobytes
2688   print *(Lk-50)        # Files smaller than 50 kilobytes
2689   print **/*.c          # All *.c files recursively starting in \$PWD
2690   print **/*.c~file.c   # Same as above, but excluding 'file.c'
2691   print (foo|bar).*     # Files starting with 'foo' or 'bar'
2692   print *~*.*           # All Files that do not contain a dot
2693   chmod 644 *(.^x)      # make all plain non-executable files publically readable
2694   print -l *(.c|.h)     # Lists *.c and *.h
2695   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
2696   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
2697 }
2698 alias help-zshglob=H-Glob
2699
2700 check_com -c qma && alias ?='qma zshall'
2701
2702 # grep for running process, like: 'any vim'
2703 any() {
2704     if [[ -z "$1" ]] ; then
2705         echo "any - grep for process(es) by keyword" >&2
2706         echo "Usage: any <keyword>" >&2 ; return 1
2707     else
2708         local STRING=$1
2709         local LENGTH=$(expr length $STRING)
2710         local FIRSCHAR=$(echo $(expr substr $STRING 1 1))
2711         local REST=$(echo $(expr substr $STRING 2 $LENGTH))
2712         ps xauwww| grep "[$FIRSCHAR]$REST"
2713     fi
2714 }
2715
2716 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
2717 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
2718 [[ -r /proc/1/maps ]] && \
2719 deswap() {
2720     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
2721     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
2722     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
2723 }
2724
2725 # print hex value of a number
2726 hex() {
2727     [[ -n "$1" ]] && printf "%x\n" $1 || { print 'Usage: hex <number-to-convert>' ; return 1 }
2728 }
2729
2730 # calculate (or eval at all ;-)) with perl => p[erl-]eval
2731 # hint: also take a look at zcalc -> 'autoload zcalc' -> 'man zshmodules | less -p MATHFUNC'
2732 peval() {
2733     [[ -n "$1" ]] && CALC="$*" || print "Usage: calc [expression]"
2734     perl -e "print eval($CALC),\"\n\";"
2735 }
2736 functions peval &>/dev/null && alias calc=peval
2737
2738 # brltty seems to have problems with utf8 environment and/or font Uni3-Terminus16 under
2739 # certain circumstances, so work around it, no matter which environment we have
2740 brltty() {
2741     if [[ -z "$DISPLAY" ]] ; then
2742         consolechars -f /usr/share/consolefonts/default8x16.psf.gz
2743         command brltty "$@"
2744     else
2745         command brltty "$@"
2746     fi
2747 }
2748
2749 # just press 'asdf' keys to toggle between dvorak and us keyboard layout
2750 aoeu() {
2751     echo -n 'Switching to us keyboard layout: '
2752     [[ -z "$DISPLAY" ]] && $SUDO loadkeys us &>/dev/null || setxkbmap us &>/dev/null
2753     echo 'Done'
2754 }
2755 asdf() {
2756     echo -n 'Switching to dvorak keyboard layout: '
2757     [[ -z "$DISPLAY" ]] && $SUDO loadkeys dvorak &>/dev/null || setxkbmap dvorak &>/dev/null
2758     echo 'Done'
2759 }
2760 # just press 'asdf' key to toggle from neon layout to us keyboard layout
2761 uiae() {
2762     echo -n 'Switching to us keyboard layout: '
2763     setxkbmap us && echo 'Done' || echo 'Failed'
2764 }
2765
2766 # set up an ipv6 tunnel
2767 ipv6-tunnel() {
2768     case $1 in
2769         start)
2770             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2771                 print 'ipv6 tunnel already set up, nothing to be done.'
2772                 print 'execute: "ifconfig sit1 down ; ifconfig sit0 down" to remove ipv6-tunnel.' ; return 1
2773             else
2774                 [[ -n "$PUBLIC_IP" ]] || \
2775                     local PUBLIC_IP=$(ifconfig $(route -n | awk '/^0\.0\.0\.0/{print $8; exit}') | \
2776                                       awk '/inet addr:/ {print $2}' | tr -d 'addr:')
2777
2778                 [[ -n "$PUBLIC_IP" ]] || { print 'No $PUBLIC_IP set and could not determine default one.' ; return 1 }
2779                 local IPV6ADDR=$(printf "2002:%02x%02x:%02x%02x:1::1" $(print ${PUBLIC_IP//./ }))
2780                 print -n "Setting up ipv6 tunnel $IPV6ADDR via ${PUBLIC_IP}: "
2781                 ifconfig sit0 tunnel ::192.88.99.1 up
2782                 ifconfig sit1 add "$IPV6ADDR" && print done || print failed
2783             fi
2784             ;;
2785         status)
2786             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2787                 print 'ipv6 tunnel available' ; return 0
2788             else
2789                 print 'ipv6 tunnel not available' ; return 1
2790             fi
2791             ;;
2792         stop)
2793             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2794                 print -n 'Stopping ipv6 tunnel (sit0 + sit1): '
2795                 ifconfig sit1 down ; ifconfig sit0 down && print done || print failed
2796             else
2797                 print 'No ipv6 tunnel found, nothing to be done.' ; return 1
2798             fi
2799             ;;
2800         *)
2801             print "Usage: ipv6-tunnel [start|stop|status]">&2 ; return 1
2802             ;;
2803     esac
2804 }
2805
2806 # run dhclient for wireless device
2807 iwclient() {
2808     salias dhclient "$(wavemon -d | awk '/device/{print $2}')"
2809 }
2810
2811 # spawn a minimally set up ksh - useful if you want to umount /usr/.
2812 minimal-shell() {
2813     exec env -i ENV="/etc/minimal-shellrc" HOME="$HOME" TERM="$TERM" ksh
2814 }
2815
2816 # make a backup of a file
2817 bk() {
2818     cp -a "$1" "${1}_$(date --iso-8601=seconds)"
2819 }
2820
2821 # Switching shell safely and efficiently? http://www.zsh.org/mla/workers/2001/msg02410.html
2822 # bash() {
2823 #  NO_SWITCH="yes" command bash "$@"
2824 # }
2825 # restart () {
2826 #  exec $SHELL $SHELL_ARGS "$@"
2827 # }
2828
2829 # }}}
2830
2831 # log out? set timeout in seconds {{{
2832 # TMOUT=1800
2833 # do not log out in some specific terminals:
2834 #  if [[ "${TERM}" == ([Exa]term*|rxvt|dtterm|screen*) ]] ; then
2835 #    unset TMOUT
2836 #  fi
2837 # }}}
2838
2839 # {{{ make sure our environment is clean regarding colors
2840 for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
2841 # }}}
2842
2843 # source another config file if present {{{
2844 xsource "/etc/zsh/zshrc.local"
2845 xsource "${HOME}/.zshenv"
2846 # }}}
2847
2848 # "persistent history" {{{
2849 # just write important commands you always need to ~/.important_commands
2850 if [[ -r ~/.important_commands ]] ; then
2851     fc -R ~/.important_commands
2852 fi
2853 # }}}
2854
2855 ## genrefcard.pl settings {{{
2856 ### example: split functions-search 8,16,24,32
2857 #@# split functions-search 8
2858 ## }}}
2859
2860 # add variable to be able to check whether the file has been read {{{
2861 ZSHRC_GLOBAL_HAS_BEEN_READ=1
2862 # }}}
2863
2864 ## END OF FILE #################################################################
2865 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4