zshrc: Fixing $PS2
[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 [[ -n $ZSH_PROFILE_RC ]] ; 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/[^_]*[^~] ; 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  zprof
809         ap  mapfile
810     )
811
812     while (( ${#tmpargs} > 0 )) ; do
813         zmodload -${tmpargs[1]} zsh/${tmpargs[2]} ${tmpargs[2]}
814         shift 2 tmpargs
815     done
816     unset tmpargs
817 fi
818
819 if is4 && zrcautoload insert-files && zle -N insert-files ; then
820     #k# Insert files
821     bindkey "^Xf" insert-files # C-x-f
822 fi
823
824 bindkey ' '   magic-space    # also do history expansion on space
825 #k# Trigger menu-complete
826 bindkey '\ei' menu-complete  # menu completion via esc-i
827
828 # press esc-e for editing command line in $EDITOR or $VISUAL
829 if is4 && zrcautoload edit-command-line && zle -N edit-command-line ; then
830     #k# Edit the current line in \kbd{\$EDITOR}
831     bindkey '\ee' edit-command-line
832 fi
833
834 if is4 && [[ -n ${(k)modules[zsh/complist]} ]] ; then
835     #k# menu selection: pick item but stay in the menu
836     bindkey -M menuselect '\e^M' accept-and-menu-complete
837
838     # use the vi navigation keys (hjkl) besides cursor keys in menu completion
839     #bindkey -M menuselect 'h' vi-backward-char        # left
840     #bindkey -M menuselect 'k' vi-up-line-or-history   # up
841     #bindkey -M menuselect 'l' vi-forward-char         # right
842     #bindkey -M menuselect 'j' vi-down-line-or-history # bottom
843
844     # accept a completion and try to complete again by using menu
845     # completion; very useful with completing directories
846     # by using 'undo' one's got a simple file browser
847     bindkey -M menuselect '^o' accept-and-infer-next-history
848 fi
849
850 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
851 _bkdate() { BUFFER="$BUFFER$(date '+%F')"; CURSOR=$#BUFFER; }
852 zle -N _bkdate
853
854 #k# Insert a timestamp on the command line (yyyy-mm-dd)
855 bindkey '^Ed' _bkdate
856
857 # press esc-m for inserting last typed word again (thanks to caphuso!)
858 insert-last-typed-word() { zle insert-last-word -- 0 -1 };
859 zle -N insert-last-typed-word;
860
861 #k# Insert last typed word
862 bindkey "\em" insert-last-typed-word
863
864 # set command prediction from history, see 'man 1 zshcontrib'
865 #  is4 && zrcautoload predict-on && \
866 #  zle -N predict-on         && \
867 #  zle -N predict-off        && \
868 #  bindkey "^X^Z" predict-on && \
869 #  bindkey "^Z" predict-off
870
871 #k# Shortcut for \kbd{fg<enter>}
872 bindkey -s '^z' "fg\n"
873
874 # press ctrl-q to quote line:
875 #  mquote () {
876 #        zle beginning-of-line
877 #        zle forward-word
878 #        # RBUFFER="'$RBUFFER'"
879 #        RBUFFER=${(q)RBUFFER}
880 #        zle end-of-line
881 #  }
882 #  zle -N mquote && bindkey '^q' mquote
883
884 # run command line as user root via sudo:
885 sudo-command-line() {
886     [[ -z $BUFFER ]] && zle up-history
887     [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
888 }
889 zle -N sudo-command-line
890
891 #k# Put the current command line into a \kbd{sudo} call
892 bindkey "^Os" sudo-command-line
893
894 ### jump behind the first word on the cmdline.
895 ### useful to add options.
896 function jump_after_first_word() {
897     local words
898     words=(${(z)BUFFER})
899
900     if (( ${#words} <= 1 )) ; then
901         CURSOR=${#BUFFER}
902     else
903         CURSOR=${#${words[1]}}
904     fi
905 }
906 zle -N jump_after_first_word
907
908 bindkey '^x1' jump_after_first_word
909
910 # }}}
911
912 # {{{ set some important options
913 # Please update these tags, if you change the umask settings below.
914 #o# r_umask     002
915 #o# r_umaskstr  rwxrwxr-x
916 #o# umask       022
917 #o# umaskstr    rwxr-xr-x
918 (( EUID != 0 )) && umask 002 || umask 022
919
920 # history:
921 setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
922 is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
923 setopt extended_history     # save each command's beginning timestamp and the duration to the history file
924 is4 && setopt histignorealldups # If  a  new  command  line being added to the history
925                             # list duplicates an older one, the older command is removed from the list
926 setopt histignorespace      # remove command lines from the history list when
927                             # the first character on the line is a space
928 #  setopt histallowclobber    # add `|' to output redirections in the history
929 #  setopt NO_clobber          # warning if file exists ('cat /dev/null > ~/.zshrc')
930 setopt auto_cd              # if a command is issued that can't be executed as a normal command,
931                             # and the command is the name of a directory, perform the cd command to that directory
932 setopt extended_glob        # in order to use #, ~ and ^ for filename generation
933                             # grep word *~(*.gz|*.bz|*.bz2|*.zip|*.Z) ->
934                             # -> searches for word not in compressed files
935                             # don't forget to quote '^', '~' and '#'!
936 setopt longlistjobs         # display PID when suspending processes as well
937 setopt notify               # report the status of backgrounds jobs immediately
938 setopt hash_list_all        # Whenever a command completion is attempted, make sure \
939                             # the entire command path is hashed first.
940 setopt completeinword       # not just at the end
941 # setopt nocheckjobs          # don't warn me about bg processes when exiting
942 setopt nohup                # and don't kill them, either
943 # setopt printexitvalue       # alert me if something failed
944 # setopt dvorak               # with spelling correction, assume dvorak kb
945 setopt auto_pushd           # make cd push the old directory onto the directory stack.
946 setopt nonomatch            # try to avoid the 'zsh: no matches found...'
947 setopt nobeep               # avoid "beep"ing
948 setopt pushd_ignore_dups    # don't push the same dir twice.
949
950 MAILCHECK=30       # mailchecks
951 REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 seconds
952 watch=(notme root) # watch for everyone but me and root
953
954 # define word separators (for stuff like backward-word, forward-word, backward-kill-word,..)
955 #  WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' # the default
956 #  WORDCHARS=.
957 #  WORDCHARS='*?_[]~=&;!#$%^(){}'
958 #  WORDCHARS='${WORDCHARS:s@/@}'
959
960 # only slash should be considered as a word separator:
961 slash-backward-kill-word() {
962     local WORDCHARS="${WORDCHARS:s@/@}"
963     # zle backward-word
964     zle backward-kill-word
965 }
966 zle -N slash-backward-kill-word
967
968 #k# Kill everything in a word up to its last \kbd{/}
969 bindkey '\ev' slash-backward-kill-word
970
971 # }}}
972
973 # {{{ history
974
975 ZSHDIR=$HOME/.zsh
976
977 #v#
978 HISTFILE=$HOME/.zsh_history
979 isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
980 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
981
982 # }}}
983
984 # dirstack handling {{{
985
986 DIRSTACKSIZE=${DIRSTACKSIZE:-20}
987 DIRSTACKFILE=${DIRSTACKFILE:-${HOME}/.zdirs}
988
989 if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
990     dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
991     # "cd -" won't work after login by just setting $OLDPWD, so
992     [[ -d $dirstack[0] ]] && cd $dirstack[0] && cd $OLDPWD
993 fi
994
995 chpwd() {
996     if is42 ; then
997         builtin print -l ${(u)dirstack} >! ${DIRSTACKFILE}
998     else
999         uprint dirstack >! ${DIRSTACKFILE}
1000     fi
1001 }
1002
1003 # }}}
1004
1005 # {{{ display battery status on right side of prompt via running 'BATTERY=1 zsh'
1006 if [[ -n "$BATTERY" ]] ; then
1007     if check_com -c acpi ; then
1008         PERCENT="${(C)${(s| |)$(acpi 2>/dev/null)}[4]}"
1009         [[ -z "$PERCENT" ]] && PERCENT='acpi not present'
1010
1011         if [[ "${PERCENT%%%}" -lt 20 ]] ; then
1012             PERCENT="warning: ${PERCENT}%"
1013         fi
1014     fi
1015 fi
1016 # }}}
1017
1018 # set colors for use in prompts {{{
1019 if zrcautoload colors && colors 2>/dev/null ; then
1020     BLUE="%{${fg[blue]}%}"
1021     RED="%{${fg_bold[red]}%}"
1022     GREEN="%{${fg[green]}%}"
1023     CYAN="%{${fg[cyan]}%}"
1024     MAGENTA="%{${fg[magenta]}%}"
1025     YELLOW="%{${fg[yellow]}%}"
1026     WHITE="%{${fg[white]}%}"
1027     NO_COLOUR="%{${reset_color}%}"
1028 else
1029     BLUE=$'%{\e[1;34m%}'
1030     RED=$'%{\e[1;31m%}'
1031     GREEN=$'%{\e[1;32m%}'
1032     CYAN=$'%{\e[1;36m%}'
1033     WHITE=$'%{\e[1;37m%}'
1034     MAGENTA=$'%{\e[1;35m%}'
1035     YELLOW=$'%{\e[1;33m%}'
1036     NO_COLOUR=$'%{\e[0m%}'
1037 fi
1038
1039 # }}}
1040
1041 # gather version control information for inclusion in a prompt {{{
1042
1043 # vcs_info() documentation: {{{
1044 #
1045 # This functionality requires zsh version >= 4.1.*.
1046 # To load vcs_info(), copy this file to your $fpath[] and do:
1047 #   % autoload -Uz vcs_info && vcs_info
1048 #
1049 # The vcs_info() feature can be configured via zstyle:
1050 #   First, the context in which we are working:
1051 #       :vcs_info:<user-context>:<vcs-string>
1052 #   ...where <vcs-string> is one of:
1053 #       - git, git-svn, hg, darcs, bzr, mtn, svn, cvs or svk
1054 #   ...and <user-context> is a freely configurable string, assignable
1055 #   by the user as the first argument to vcs_info().
1056 #
1057 # There is one special value for <vcs-string> named 'init', that
1058 # is in effect as long as there was no decision what vcs backend to use.
1059 #
1060 # There are two pre-defined values for <user-context>:
1061 #   default  - the one used if none is specified
1062 #   command  - used by vcs_info_lastmsg to lookup its styles.
1063 # You may *not* use 'print_systems_' as a user-context string,
1064 # because it is used internally.
1065 #
1066 # You can of course use ':vcs_info:*' to match all VCSs in all
1067 # user-contexts at once.
1068 #
1069 # Another special context is 'formats', it is used by the
1070 # vcs_info_lastmsg() utility function (see below).
1071 #
1072 #
1073 # This is a description of all styles, that are looked up:
1074 #   format              - Used in most circumstances.
1075 #   actionformat        - Used if a there is a special action going on;
1076 #                         (like an interactive rebase or a merge conflict)
1077 #   branchformat        - Some backends replace %b in the format and
1078 #                         actionformat styles above, not only by a branch
1079 #                         name but also by a revision number. This style
1080 #                         let's you modify how that string should look like.
1081 #   enable              - Check in the 'init' context. If set to false,
1082 #                         vcs_info() will do nothing.
1083 #   disable             - Provide a list of systems, you don't want
1084 #                         the vcs_info() to check for repositories
1085 #                         (checked in the 'init' context, too).
1086 #   use-simple          - If there are two different ways of gathering
1087 #                         information, you can select the simpler one
1088 #                         by setting this style to true; the default
1089 #                         is to use the not-that-simple code, which is
1090 #                         potentially a lot slower but might be more
1091 #                         accurate in all possible cases.
1092 #   use-prompt-escapes  - determines if we assume that the assembled
1093 #                         string from vcs_info() includes prompt escapes.
1094 #                         (Used by vcs_info_lastmsg().
1095 #
1096 # The use-simple style is currently only available for the bzr backend.
1097 #
1098 # The default values for these in all contexts are:
1099 #   format              " (%s)-[%b|%a]-"
1100 #   actionformat        " (%s)-[%b]-"
1101 #   branchformat        "%b:%r" (for bzr, svn and svk)
1102 #   enable              true
1103 #   disable             (empty list)
1104 #   use-simple          false
1105 #   use-prompt-escapes  true
1106 #
1107 #
1108 # In format and actionformat, the following replacements are done:
1109 #   %s  - The vcs in use (git, hg, svn etc.)
1110 #   %b  - Information about the current branch.
1111 #   %a  - An identifier, that describes the action.
1112 #         Only makes sense in actionformat.
1113 #   %R  - base directory of the repository.
1114 #   %r  - repository name
1115 #         If %R is '/foo/bar/repoXY', %r is 'repoXY'.
1116 #
1117 #
1118 # In branchformat these replacements are done:
1119 #   %b  - the branch name
1120 #   %r  - the current revision number
1121 #
1122 # Not all vcs backends have to support all replacements.
1123 #
1124 #
1125 # Function descriptions:
1126 #   vcs_info()
1127 #       The main function, that runs all backends and assembles
1128 #       all data into ${VCS_INFO_message_}. This is the function
1129 #       you want to call from precmd() if you want to include
1130 #       up-to-date information in your prompt (see Variable
1131 #       description, too if you are interested in this).
1132 #
1133 #   vcs_info_printsys()
1134 #       Prints a list of all supported version control systems.
1135 #       Useful to find out possible contexts or values for the
1136 #       'disable' style.
1137 #
1138 #   vcs_info_lastmsg()
1139 #       Outputs the last ${VCS_INFO_message_} value. Takes into account
1140 #       the value of the use-prompt-escapes style in ':vcs_info:formats'.
1141 #
1142 #
1143 # Variable description:
1144 #   ${VCS_INFO_message_}    (Note the trailing underscore)
1145 #       This is the storage for the message the last vcs_info()
1146 #       call has assembled.
1147 #
1148 #
1149 # Examples:
1150 #   Don't use vcs_info at all (even though it's in your prompt):
1151 #   % zstyle ':vcs_info:*' enable false
1152 #
1153 #   Disable the backends for bzr and svk:
1154 #   % zstyle ':vcs_info:*' disable bzr svk
1155 #
1156 #   Provide a special format for git:
1157 #   % zstyle ':vcs_info:*:git' format       ' GIT, BABY! [%b]'
1158 #   % zstyle ':vcs_info:*:git' actionformat ' GIT ACTION! [%b|%a]'
1159 #
1160 #   Use the quicker bzr backend (if you do, please report if it does
1161 #   the-right-thing[tm] - thanks):
1162 #   % zstyle ':vcs_info:*:bzr' use-simple true
1163 #
1164 #   Display the revision number in yellow for bzr and svn:
1165 #   % zstyle ':vcs_info:*:(svn|bzr)' branchformat '%b%{'${fg[yellow]}'%}:%r'
1166 #
1167 # If you want colors, make sure you enclose the color codes in %{...%},
1168 # if you want to use the string provided by vcs_info() in prompts.
1169 #
1170 # Here is an example of how to include vcs_info in PS1 (*requires*
1171 # 'setopt prompt_subst'):
1172 #
1173 #       PS1='%(?..[%?]-)%3~%${VCS_INFO_message_}#'
1174 #       precmd () { vcs_info; }
1175 #
1176 # Here is how to print the vcs infomation as a command:
1177 #       alias vcsi='vcs_info command; vcs_info_lastmsg'
1178 #
1179 #   This way, you can even define different formats for output via
1180 #   vcs_info_lastmsg() in the ':vcs_info:command:*' namespace.
1181 #
1182 # }}}
1183 VCS_INFO_adjust () { #{{{
1184     [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
1185     return 0
1186 }
1187 # }}}
1188 VCS_INFO_check_com () { #{{{
1189     (( ${+commands[$1]} )) && [[ -x ${commands[$1]} ]] && return 0
1190     return 1
1191 }
1192 # }}}
1193 VCS_INFO_format () { # {{{
1194     local msg
1195
1196     if [[ -n ${1} ]] ; then
1197         zstyle -s ":vcs_info:${usercontext}:${vcs}" actionformat msg
1198         [[ -z ${msg} ]] && msg=' (%s)-[%b|%a]-'
1199     else
1200         zstyle -s ":vcs_info:${usercontext}:${vcs}" format msg
1201         [[ -z ${msg} ]] && msg=' (%s)-[%b]-'
1202     fi
1203     printf '%s' ${msg}
1204 }
1205 # }}}
1206 VCS_INFO_realpath () { #{{{
1207     # replacing 'readlink -f', which is really not portable.
1208     # forcing a subshell, to ensure chpwd() is not removed
1209     # from the calling shell (if VCS_INFO_realpath() is called
1210     # manually).
1211     (
1212         (( ${+functions[chpwd]} )) && unfunction chpwd
1213         setopt chaselinks
1214         cd $1 2>/dev/null && pwd
1215     )
1216 }
1217 # }}}
1218 VCS_INFO_git_getaction () { #{{{
1219     local gitaction='' gitdir=${1}
1220     local tmp
1221
1222     for tmp in "${gitdir}/rebase-apply" \
1223                "${gitdir}/rebase"       \
1224                "${gitdir}/../.dotest" ; do
1225         if [[ -d ${tmp} ]] ; then
1226             if   [[ -f "${tmp}/rebasing" ]] ; then
1227                 gitaction="rebase"
1228             elif [[ -f "${tmp}/applying" ]] ; then
1229                 gitaction="am"
1230             else
1231                 gitaction="am/rebase"
1232             fi
1233             printf '%s' ${gitaction}
1234             return 0
1235         fi
1236     done
1237
1238     for tmp in "${gitdir}/rebase-merge/interactive" \
1239                "${gitdir}/.dotest-merge/interactive" ; do
1240         if [[ -f "${tmp}" ]] ; then
1241             printf '%s' "rebase-i"
1242             return 0
1243         fi
1244     done
1245
1246     for tmp in "${gitdir}/rebase-merge" \
1247                "${gitdir}/.dotest-merge" ; do
1248         if [[ -d "${tmp}" ]] ; then
1249             printf '%s' "rebase-m"
1250             return 0
1251         fi
1252     done
1253
1254     if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1255         printf '%s' "merge"
1256     else
1257         if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
1258             printf '%s' "bisect"
1259         fi
1260     fi
1261
1262     return 1
1263 }
1264 # }}}
1265 VCS_INFO_git_getbranch () { #{{{
1266     local gitbranch gitdir=${1}
1267     local gitsymref='git symbolic-ref HEAD'
1268
1269     if    [[ -d "${gitdir}/rebase-apply" ]] \
1270        || [[ -d "${gitdir}/rebase" ]]       \
1271        || [[ -d "${gitdir}/../.dotest" ]]   \
1272        || [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
1273         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1274         [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/rebase-apply/head-name)"
1275
1276     elif   [[ -f "${gitdir}/rebase-merge/interactive" ]] \
1277         || [[ -d "${gitdir}/rebase-merge" ]] ; then
1278         gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
1279
1280     elif   [[ -f "${gitdir}/.dotest-merge/interactive" ]] \
1281         || [[ -d "${gitdir}/.dotest-merge" ]] ; then
1282         gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
1283
1284     else
1285         gitbranch="$(${(z)gitsymref} 2> /dev/null)"
1286
1287         if [[ $? -ne 0 ]] ; then
1288             gitbranch="$(git describe --exact-match HEAD 2>/dev/null)"
1289
1290             if [[ $? -ne 0 ]] ; then
1291                 gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
1292             fi
1293         fi
1294     fi
1295
1296     printf '%s' "${gitbranch##refs/heads/}"
1297 }
1298 # }}}
1299 VCS_INFO_git_get_data () { # {{{
1300     setopt localoptions extendedglob
1301     local gitdir gitbase gitbranch gitaction msg
1302
1303     gitdir=${vcs_comm[gitdir]}
1304     gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"
1305
1306     if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
1307         return
1308     fi
1309
1310     VCS_INFO_adjust
1311     gitaction="$(VCS_INFO_git_getaction ${gitdir})"
1312     msg=$(VCS_INFO_format ${gitaction})
1313
1314     gitbase=${PWD%/${$(git rev-parse --show-prefix)%/##}}
1315
1316     zformat -f msg "${msg}" "a:${gitaction}" "b:${gitbranch}" "s:${vcs}" "r:${gitbase:t}" "R:${gitbase}"
1317     printf '%s' ${msg}
1318 }
1319 # }}}
1320 VCS_INFO_darcs_get_data () { # {{{
1321     local msg darcsbase
1322
1323     darcsbase=${vcs_comm[basedir]}
1324     msg=$(VCS_INFO_format)
1325     zformat -f msg "${msg}" "a:" "b:${darcsbase:t}" "s:${vcs}" "r:${darcsbase:t}" "R:${darcsbase}"
1326     printf '%s' ${msg}
1327 }
1328 # }}}
1329 VCS_INFO_hg_get_data () { # {{{
1330     local msg hgbranch hgbase
1331
1332     hgbase=${vcs_comm[basedir]}
1333     hgbranch=$(< ${hgbase}/.hg/branch)
1334     msg=$(VCS_INFO_format)
1335     zformat -f msg "${msg}" "a:" "b:${hgbranch}" "s:${vcs}" "r:${hgbase:t}" "R:${hgbase}"
1336     printf '%s' ${msg}
1337 }
1338 # }}}
1339 VCS_INFO_mtn_get_data () { # {{{
1340     local msg mtnbranch mtnbase
1341
1342     mtnbase=${vcs_comm[basedir]}
1343     mtnbranch=$(mtn status | awk '/Current branch:/{ sub("Current branch: ", ""); print }')
1344     msg=$(VCS_INFO_format)
1345     zformat -f msg "${msg}" "a:" "b:${mtnbranch}" "s:${vcs}" "r:${mtnbase:t}" "R:${mtnbase}"
1346     printf '%s' ${msg}
1347 }
1348 # }}}
1349 VCS_INFO_svk_get_data () { # {{{
1350     local msg svkbranch svkbase
1351
1352     svkbase=${vcs_comm[basedir]}
1353
1354     zstyle -s ":vcs_info:${usercontext}:${vcs}" branchformat svkbranch || svkbranch="%b:%r"
1355     zformat -f svkbranch "${svkbranch}" "b:${vcs_comm[branch]}" "r:${vcs_comm[revision]}"
1356
1357     msg=$(VCS_INFO_format)
1358     zformat -f msg "${msg}" "a:" "b:${svkbranch}" "s:${vcs}" "r:${svkbase:t}" "R:${svkbase}"
1359     printf '%s' ${msg}
1360 }
1361 # }}}
1362 VCS_INFO_svn_get_data () { # {{{
1363     setopt localoptions noksharrays
1364     local msg svnbase svnbranch
1365     local -a svninfo
1366
1367     svnbase="."
1368     while [[ -d "${svnbase}/../.svn" ]]; do
1369         svnbase="${svnbase}/.."
1370     done
1371     svnbase=$(VCS_INFO_realpath ${svnbase})
1372     svninfo=($(svn info "${svnbase}" | awk '/^URL/ { sub(".*/","",$0); r=$0 } /^Revision/ { sub("[^0-9]*","",$0); print r"\n"$0 }'))
1373
1374     zstyle -s ":vcs_info:${usercontext}:${vcs}" branchformat svnbranch || svnbranch="%b:%r"
1375     zformat -f svnbranch "${svnbranch}" "b:${svninfo[1]}" "r:${svninfo[2]}"
1376
1377     msg=$(VCS_INFO_format)
1378     zformat -f msg "${msg}" "a:" "b:${svnbranch}" "s:${vcs}" "r:${svnbase:t}" "R:${svnbase}"
1379     printf '%s' ${msg}
1380 }
1381 # }}}
1382 VCS_INFO_bzr_get_data () { # {{{
1383     local msg bzrbranch bzrbase bzrrevno bzrbr i j
1384
1385     if zstyle -t ":vcs_info:${usercontext}:${vcs}" "use-simple" ; then
1386         bzrbase=${vcs_comm[basedir]}
1387         bzrbranch=${bzrbase:t}
1388         if [[ -f ${bzrbase}/.bzr/branch/last-revision ]] ; then
1389             bzrrevno=$(< ${bzrbase}/.bzr/branch/last-revision)
1390             bzrrevno=${bzrrevno%% *}
1391         fi
1392     else
1393         bzrbase=$(bzr info 2>/dev/null | sed -rne 's, *branch root: ,,p')
1394         bzrbase=$(VCS_INFO_realpath ${bzrbase})
1395
1396         bzr version-info 2> /dev/null | while read i j; do
1397             case "${i}" in
1398                 revno:)
1399                     bzrrevno=${j} ;;
1400                 branch-nick:)
1401                     bzrbranch=${j} ;;
1402             esac
1403         done
1404     fi
1405
1406     zstyle -s ":vcs_info:${usercontext}:${vcs}" branchformat bzrbr || bzrbr="%b:%r"
1407     zformat -f bzrbr "${bzrbr}" "b:${bzrbranch}" "r:${bzrrevno}"
1408
1409     msg=$(VCS_INFO_format)
1410     zformat -f msg "${msg}" "a:" "b:${bzrbr}" "s:${vcs}" "r:${bzrbase:t}" "R:${bzrbase}"
1411     printf '%s' ${msg}
1412 }
1413 # }}}
1414 VCS_INFO_cvs_get_data () { # {{{
1415     local msg cvsbranch cvsbase basename
1416
1417     cvsbase="."
1418     while [[ -d "${cvsbase}/../CVS" ]]; do
1419         cvsbase="${cvsbase}/.."
1420     done
1421     cvsbase=$(VCS_INFO_realpath ${cvsbase})
1422     cvsbranch=$(< ./CVS/Repository)
1423     basename=${cvsbase:t}
1424     cvsbranch=${cvsbranch##${basename}/}
1425     [[ -z ${cvsbranch} ]] && cvsbranch=${basename}
1426
1427     msg=$(VCS_INFO_format)
1428     zformat -f msg "${msg}" "a:" "b:${cvsbranch}" "s:${vcs}" "r:${basename}" "R:${cvsbase}"
1429     printf '%s' ${msg}
1430 }
1431 # }}}
1432 # VCS_INFO_*_detect () {{{
1433
1434 VCS_INFO_detect_by_dir() {
1435     local dirname=${1}
1436     local basedir="." realbasedir
1437
1438     realbasedir=$(VCS_INFO_realpath ${basedir})
1439     while [[ ${realbasedir} != '/' ]]; do
1440         if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
1441             [[ -d ${basedir}/${dirname} ]] && \
1442             [[ -f ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
1443                 break
1444         else
1445             [[ -d ${basedir}/${dirname} ]] && break
1446         fi
1447
1448         basedir=${basedir}/..
1449         realbasedir=$(VCS_INFO_realpath ${basedir})
1450     done
1451
1452     [[ ${realbasedir} == "/" ]] && return 1
1453     vcs_comm[basedir]=${realbasedir}
1454     return 0
1455 }
1456
1457 VCS_INFO_bzr_detect() {
1458     VCS_INFO_check_com bzr || return 1
1459     vcs_comm[detect_need_file]=branch/format
1460     VCS_INFO_detect_by_dir '.bzr'
1461     return $?
1462 }
1463
1464 VCS_INFO_cvs_detect() {
1465     VCS_INFO_check_com svn || return 1
1466     [[ -d "CVS" ]] && return 0
1467     return 1
1468 }
1469
1470 VCS_INFO_darcs_detect() {
1471     VCS_INFO_check_com darcs || return 1
1472     vcs_comm[detect_need_file]=format
1473     VCS_INFO_detect_by_dir '_darcs'
1474     return $?
1475 }
1476
1477 VCS_INFO_git_detect() {
1478     if VCS_INFO_check_com git && git rev-parse --is-inside-work-tree &> /dev/null ; then
1479         vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
1480         [[ -d ${vcs_comm[gitdir]}/svn ]] && vcs_comm[overwrite_name]='git-svn'
1481         return 0
1482     fi
1483     return 1
1484 }
1485
1486 VCS_INFO_hg_detect() {
1487     VCS_INFO_check_com hg || return 1
1488     vcs_comm[detect_need_file]=branch
1489     VCS_INFO_detect_by_dir '.hg'
1490     return $?
1491 }
1492
1493 VCS_INFO_mtn_detect() {
1494     VCS_INFO_check_com mtn || return 1
1495     vcs_comm[detect_need_file]=revision
1496     VCS_INFO_detect_by_dir '_MTN'
1497     return $?
1498 }
1499
1500 VCS_INFO_svk_detect() {
1501     setopt localoptions noksharrays
1502     local -a info
1503
1504     VCS_INFO_check_com svk || return 1
1505     [[ -f ~/.svk/config ]] || return 1
1506
1507     info=(
1508         $(awk '
1509           /: *$/ {
1510             sub(/^ */,"",$0);
1511             sub(/: *$/,"",$0);
1512             if (match("'${PWD}'", $0"(/|$)")) {
1513               print $0; d=1;
1514             }
1515           }
1516           /depotpath/ && d == 1 {
1517             sub(".*/","",$0);
1518             r=$0
1519           }
1520           /revision/ && d == 1 {
1521             print r "\n" $2;
1522             exit 1
1523           }' ~/.svk/config
1524         )
1525     ) && return 1
1526
1527     vcs_comm[basedir]=${info[1]}
1528     vcs_comm[branch]=${info[2]}
1529     vcs_comm[revision]=${info[3]}
1530     return 0
1531 }
1532
1533 VCS_INFO_svn_detect() {
1534     VCS_INFO_check_com svn || return 1
1535     [[ -d ".svn" ]] && return 0
1536     return 1
1537 }
1538
1539 # }}}
1540 vcs_info_printsys () { # {{{
1541     vcs_info print_systems_
1542 }
1543 # }}}
1544 vcs_info_lastmsg () { # {{{
1545     if zstyle -T ':vcs_info:command:formats' use-prompt-escapes ; then
1546         print -P ${VCS_INFO_message_}
1547     else
1548         print ${VCS_INFO_message_}
1549     fi
1550 }
1551 # }}}
1552 vcs_info () { # {{{
1553     setopt localoptions #xtrace
1554     local string
1555     local -i found
1556     local -a VCSs disabled
1557     local -x vcs usercontext
1558     local -Ax vcs_comm
1559
1560     VCSs=(git hg bzr darcs mtn svn cvs svk)
1561     case ${1} in
1562         (print_systems_)
1563             print -l ${VCSs}
1564             # and the special flavours
1565             print -l '# flavours (cannot be used in the disable style; they' \
1566                      '# are disabled with their master [git-svn -> git]):'   \
1567                      'git-svn'
1568             return 0
1569             ;;
1570         ('')
1571             [[ -t ${usercontext} ]] && usercontext=default
1572             ;;
1573         (*) [[ -t ${usercontext} ]] && usercontext=${1}
1574             ;;
1575     esac
1576
1577     vcs="init"
1578     zstyle -T ":vcs_info:${usercontext}:${vcs}" "enable" || {
1579         typeset -gx VCS_INFO_message_=''
1580         return 0
1581     }
1582     zstyle -a ":vcs_info:${usercontext}:${vcs}" "disable" disabled
1583
1584     (( found = 0 ))
1585     for vcs in ${VCSs} ; do
1586         [[ -n ${(M)disabled:#${vcs}} ]] && continue
1587         vcs_comm=()
1588         VCS_INFO_${vcs}_detect && (( found = 1 )) && break
1589     done
1590
1591     (( found == 0 )) && {
1592         typeset -gx VCS_INFO_message_=''
1593         return 0
1594     }
1595
1596     string=$(VCS_INFO_${vcs}_get_data) || {
1597         typeset -gx VCS_INFO_message_=''
1598         return 1
1599     }
1600
1601     typeset -gx VCS_INFO_message_=${string}
1602     return 0
1603 }
1604
1605 typeset -gx VCS_INFO_message_=''
1606 # }}}
1607
1608 # change vcs_info formats for the grml prompt
1609 if [[ "$TERM" == dumb ]] ; then
1610     zstyle ':vcs_info:*' actionformat "(%s%)-[%b|%a] "
1611     zstyle ':vcs_info:*' format       "(%s%)-[%b] "
1612 else
1613     # these are the same, just with a lot of colours:
1614     zstyle ':vcs_info:*' actionformat "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOUR} "
1615     zstyle ':vcs_info:*' format       "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOUR}%} "
1616     zstyle ':vcs_info:(sv[nk]|bzr)' branchformat "%b${YELLOW}:%r"
1617 fi
1618
1619 # }}}
1620
1621 # {{{ set prompt
1622 if zrcautoload promptinit && promptinit 2>/dev/null ; then
1623     promptinit # people should be able to use their favourite prompt
1624 else
1625     print 'Notice: no promptinit available :('
1626 fi
1627
1628 setopt prompt_subst
1629
1630 # make sure to use right prompt only when not running a command
1631 is41 && setopt transient_rprompt
1632
1633 is4 && [[ -z $NOPRECMD ]] && precmd () {
1634     [[ -n $NOPRECMD ]] && return 0
1635     # update VCS information
1636     vcs_info
1637
1638     # allow manual overwriting of RPROMPT
1639     if [[ -n $RPROMPT ]] ; then
1640         [[ $TERM == screen* ]] && print -nP "\ekzsh\e\\"
1641         # return 0
1642     fi
1643     # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
1644     if [[ -z $DONTSETRPROMPT ]] ; then
1645         if [[ -n $BATTERY ]] ; then
1646             RPROMPT="%(?..:()% ${PERCENT}${SCREENTITLE}"
1647             # RPROMPT="${PERCENT}${SCREENTITLE}"
1648         else
1649             RPROMPT="%(?..:()% ${SCREENTITLE}"
1650             # RPROMPT="${SCREENTITLE}"
1651         fi
1652     fi
1653     # adjust title of xterm
1654     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
1655     case $TERM in
1656         (xterm*|rxvt)
1657             print -Pn "\e]0;%n@%m: %~\a"
1658             ;;
1659     esac
1660 }
1661
1662 # preexec() => a function running before every command
1663 is4 && [[ -z $NOPRECMD ]] && \
1664 preexec () {
1665     [[ -n $NOPRECMD ]] && return 0
1666 # set hostname if not running on host with name 'grml'
1667     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
1668        NAME="@$HOSTNAME"
1669     fi
1670 # get the name of the program currently running and hostname of local machine
1671 # set screen window title if running in a screen
1672     if [[ "$TERM" == screen* ]] ; then
1673         # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]}       # don't use hostname
1674         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname
1675         echo -ne "\ek$CMD\e\\"
1676     fi
1677 # set the screen title to "zsh" when sitting at the command prompt:
1678     if [[ "$TERM" == screen* ]] ; then
1679         SCREENTITLE=$'%{\ekzsh\e\\%}'
1680     else
1681         SCREENTITLE=''
1682     fi
1683 # adjust title of xterm
1684     case $TERM in
1685         (xterm*|rxvt)
1686             print -Pn "\e]0;%n@%m: $1\a"
1687             ;;
1688     esac
1689 }
1690
1691 EXITCODE="%(?..%?%1v )"
1692 PS2='\`%_> '      # secondary prompt, printed when the shell needs more information to complete a command.
1693 PS3='?# '         # selection prompt used within a select loop.
1694 PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
1695
1696 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
1697 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
1698     debian_chroot=$(cat /etc/debian_chroot)
1699 fi
1700
1701 # don't use colors on dumb terminals (like emacs):
1702 if [[ "$TERM" == dumb ]] ; then
1703     PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_}'"%# "
1704 else
1705     # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt
1706     # set variable identifying the chroot you work in (used in the prompt below)
1707     if [[ -n $GRMLPROMPT ]] ; then
1708         PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D
1709 ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
1710     else
1711         # This assembles the primary prompt string
1712         if (( EUID != 0 )); then
1713             PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_}'"%# "
1714         else
1715             PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< "'${VCS_INFO_message_}'"%# "
1716         fi
1717     fi
1718 fi
1719
1720 # if we are inside a grml-chroot set a specific prompt theme
1721 if [[ -n "$GRML_CHROOT" ]] ; then
1722     PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# "
1723 fi
1724 # }}}
1725
1726 # {{{ 'hash' some often used directories
1727 #d# start
1728 hash -d deb=/var/cache/apt/archives
1729 hash -d doc=/usr/share/doc
1730 hash -d linux=/lib/modules/$(command uname -r)/build/
1731 hash -d log=/var/log
1732 hash -d slog=/var/log/syslog
1733 hash -d src=/usr/src
1734 hash -d templ=/usr/share/doc/grml-templates
1735 hash -d tt=/usr/share/doc/texttools-doc
1736 hash -d www=/var/www
1737 #d# end
1738 # }}}
1739
1740 # {{{ some aliases
1741 if [[ $UID -eq 0 ]] ; then
1742     [[ -r /etc/grml/screenrc ]] && alias screen='/usr/bin/screen -c /etc/grml/screenrc'
1743 elif [[ -r $HOME/.screenrc ]] ; then
1744     alias screen="/usr/bin/screen -c $HOME/.screenrc"
1745 else
1746     [[ -r /etc/grml/screenrc_grml ]] && alias screen='/usr/bin/screen -c /etc/grml/screenrc_grml'
1747 fi
1748
1749 # do we have GNU ls with color-support?
1750 if ls --help 2>/dev/null | grep -- --color= >/dev/null && [[ "$TERM" != dumb ]] ; then
1751     #a1# execute \kbd{@a@}:\quad ls with colors
1752     alias ls='ls -b -CF --color=auto'
1753     #a1# execute \kbd{@a@}:\quad list all files, with colors
1754     alias la='ls -la --color=auto'
1755     #a1# long colored list, without dotfiles (@a@)
1756     alias ll='ls -l --color=auto'
1757     #a1# long colored list, human readable sizes (@a@)
1758     alias lh='ls -hAl --color=auto'
1759     #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
1760     alias l='ls -lF --color=auto'
1761 else
1762     alias ls='ls -b -CF'
1763     alias la='ls -la'
1764     alias ll='ls -l'
1765     alias lh='ls -hAl'
1766     alias l='ls -lF'
1767 fi
1768
1769 alias mdstat='cat /proc/mdstat'
1770 alias ...='cd ../../'
1771
1772 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
1773 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
1774     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
1775 fi
1776
1777 alias cp='nocorrect cp'         # no spelling correction on cp
1778 alias mkdir='nocorrect mkdir'   # no spelling correction on mkdir
1779 alias mv='nocorrect mv'         # no spelling correction on mv
1780 alias rm='nocorrect rm'         # no spelling correction on rm
1781
1782 #a1# Execute \kbd{rmdir}
1783 alias rd='rmdir'
1784 #a1# Execute \kbd{rmdir}
1785 alias md='mkdir'
1786
1787 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
1788 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
1789 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
1790
1791 # make sure it is not assigned yet
1792 [[ $(whence -w utf2iso &>/dev/null) == 'utf2iso: alias' ]] && unalias utf2iso
1793
1794 utf2iso() {
1795     if isutfenv ; then
1796         for ENV in $(env | command grep -i '.utf') ; do
1797             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
1798         done
1799     fi
1800 }
1801
1802 # make sure it is not assigned yet
1803 [[ $(whence -w iso2utf &>/dev/null) == 'iso2utf: alias' ]] && unalias iso2utf
1804 iso2utf() {
1805     if ! isutfenv ; then
1806         for ENV in $(env | command grep -i '\.iso') ; do
1807             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
1808         done
1809     fi
1810 }
1811
1812 # set up software synthesizer via speakup
1813 swspeak() {
1814     aumix -w 90 -v 90 -p 90 -m 90
1815     if ! [[ -r /dev/softsynth ]] ; then
1816         flite -o play -t "Sorry, software synthesizer not available. Did you boot with swspeak bootoption?"
1817         return 1
1818     else
1819         setopt singlelinezle
1820         unsetopt prompt_cr
1821         export PS1="%m%# "
1822         nice -n -20 speechd-up
1823         sleep 2
1824         flite -o play -t "Finished setting up software synthesizer"
1825     fi
1826 }
1827
1828 # I like clean prompt, so provide simple way to get that
1829 check_com 0 || alias 0='return 0'
1830
1831 # for really lazy people like mika:
1832 check_com S &>/dev/null || alias S='screen'
1833 check_com s &>/dev/null || alias s='ssh'
1834
1835 # get top 10 shell commands:
1836 alias top10='print -l ? ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
1837
1838 # truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i'
1839 if check_com -c truecrypt ; then
1840     if isutfenv ; then
1841         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" '
1842     else
1843         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" '
1844     fi
1845 fi
1846
1847 #f1# Hints for the use of zsh on grml
1848 zsh-help() {
1849     print "$bg[white]$fg[black]
1850 zsh-help - hints for use of zsh on grml
1851 =======================================$reset_color"
1852
1853     print '
1854 Main configuration of zsh happens in /etc/zsh/zshrc (global)
1855 and /etc/skel/.zshrc which is copied to $HOME/.zshrc once.
1856 The files are part of the package grml-etc-core, if you want to
1857 use them on a non-grml-system just get the tar.gz from
1858 http://deb.grml.org/ or get the files from the mercurial
1859 repository:
1860
1861   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/skel/.zshrc
1862   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/zsh/zshrc
1863
1864 If you want to stay in sync with zsh configuration of grml
1865 run '\''ln -sf /etc/skel/.zshrc $HOME/.zshrc'\'' and configure
1866 your own stuff in $HOME/.zshrc.local. System wide configuration
1867 without touching configuration files of grml can take place
1868 in /etc/zsh/zshrc.local.
1869
1870 If you want to use the configuration of user grml also when
1871 running as user root just run '\''zshskel'\'' which will source
1872 the file /etc/skel/.zshrc.
1873
1874 For information regarding zsh start at http://grml.org/zsh/
1875
1876 Take a look at grml'\''s zsh refcard:
1877 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
1878
1879 Check out the main zsh refcard:
1880 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
1881
1882 And of course visit the zsh-lovers:
1883 % man zsh-lovers
1884
1885 You can adjust some options through environment variables when
1886 invoking zsh without having to edit configuration files.
1887 Basically meant for bash users who are not used to the power of
1888 the zsh yet. :)
1889
1890   "NOCOR=1    zsh" => deactivate automatic correction
1891   "NOMENU=1   zsh" => do not use menu completion (note: use strg-d for completion instead!)
1892   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
1893   "BATTERY=1  zsh" => activate battery status (via acpi) on right side of prompt'
1894
1895     print "
1896 $bg[white]$fg[black]
1897 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
1898 Enjoy your grml system with the zsh!$reset_color"
1899 }
1900
1901 # debian stuff
1902 if [[ -r /etc/debian_version ]] ; then
1903     #a3# Execute \kbd{apt-cache search}
1904     alias acs='apt-cache search'
1905     #a3# Execute \kbd{apt-cache show}
1906     alias acsh='apt-cache show'
1907     #a3# Execute \kbd{apt-cache policy}
1908     alias acp='apt-cache policy'
1909     #a3# Execute \kbd{apt-get dist-upgrade}
1910     salias adg="apt-get dist-upgrade"
1911     #a3# Execute \kbd{apt-get install}
1912     salias agi="apt-get install"
1913     #a3# Execute \kbd{aptitude install}
1914     salias ati="aptitude install"
1915     #a3# Execute \kbd{apt-get upgrade}
1916     salias ag="apt-get upgrade"
1917     #a3# Execute \kbd{apt-get update}
1918     salias au="apt-get update"
1919     #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
1920     salias -a up="aptitude update ; aptitude safe-upgrade"
1921     #a3# Execute \kbd{dpkg-buildpackage}
1922     alias dbp='dpkg-buildpackage'
1923     #a3# Execute \kbd{grep-excuses}
1924     alias ge='grep-excuses'
1925
1926     # debian upgrade
1927     #f3# Execute \kbd{apt-get update \&\& }\\&\quad \kbd{apt-get dist-upgrade}
1928     upgrade() {
1929         if [[ -z "$1" ]] ; then
1930             $SUDO apt-get update
1931             $SUDO apt-get -u upgrade
1932         else
1933             ssh $1 $SUDO apt-get update
1934             # ask before the upgrade
1935             local dummy
1936             ssh $1 $SUDO apt-get --no-act upgrade
1937             echo -n 'Process the upgrade?'
1938             read -q dummy
1939             if [[ $dummy == "y" ]] ; then
1940                 ssh $1 $SUDO apt-get -u upgrade --yes
1941             fi
1942         fi
1943     }
1944
1945     # get a root shell as normal user in live-cd mode:
1946     if isgrmlcd && [[ $UID -ne 0 ]] ; then
1947        alias su="sudo su"
1948      fi
1949
1950     #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
1951     alias llog="$PAGER /var/log/syslog"     # take a look at the syslog
1952     #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
1953     alias tlog="tail -f /var/log/syslog"    # follow the syslog
1954     #a1# (Re)-source \kbd{/etc/skel/.zshrc}
1955     alias zshskel="source /etc/skel/.zshrc" # source skeleton zshrc
1956 fi
1957
1958 # sort installed Debian-packages by size
1959 if check_com -c grep-status ; then
1960     #a3# List installed Debian-packages sorted by size
1961     alias debs-by-size='grep-status -FStatus -sInstalled-Size,Package -n "install ok installed" | paste -sd "  \n" | sort -rn'
1962 fi
1963
1964 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
1965 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord ; then
1966     if check_com -c wodim ; then
1967         alias cdrecord="echo 'cdrecord is not provided under its original name by Debian anymore.
1968 See #377109 in the BTS of Debian for more details.
1969
1970 Please use the wodim binary instead' ; return 1"
1971     fi
1972 fi
1973
1974 # get_tw_cli has been renamed into get_3ware
1975 if check_com -c get_3ware ; then
1976     get_tw_cli() {
1977         echo 'Warning: get_tw_cli has been renamed into get_3ware. Invoking get_3ware for you.'>&2
1978         get_3ware
1979     }
1980 fi
1981
1982 # I hate lacking backward compatibility, so provide an alternative therefore
1983 if ! check_com -c apache2-ssl-certificate ; then
1984
1985     apache2-ssl-certificate() {
1986
1987     print 'Debian does not ship apache2-ssl-certificate anymore (see #398520). :('
1988     print 'You might want to take a look at Debian the package ssl-cert as well.'
1989     print 'To generate a certificate for use with apache2 follow the instructions:'
1990
1991     echo '
1992
1993 export RANDFILE=/dev/random
1994 mkdir /etc/apache2/ssl/
1995 openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem
1996 chmod 600 /etc/apache2/ssl/apache.pem
1997
1998 Run "grml-tips ssl-certificate" if you need further instructions.
1999 '
2000     }
2001 fi
2002 # }}}
2003
2004 # {{{ Use hard limits, except for a smaller stack and no core dumps
2005 unlimit
2006 is425 && limit stack 8192
2007 isgrmlcd && limit core 0 # important for a live-cd-system
2008 limit -s
2009 # }}}
2010
2011 # {{{ completion system
2012
2013 # called later (via is4 && grmlcomp)
2014 # notice: use 'zstyle' for getting current settings
2015 #         press ^Xh (control-x h) for getting tags in context; ^X? (control-x ?) to run complete_debug with trace output
2016 grmlcomp() {
2017     # TODO: This could use some additional information
2018
2019     # allow one error for every three characters typed in approximate completer
2020     zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
2021
2022     # don't complete backup files as executables
2023     zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
2024
2025     # start menu completion only if it could find no unambiguous initial string
2026     zstyle ':completion:*:correct:*'       insert-unambiguous true
2027     zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
2028     zstyle ':completion:*:correct:*'       original true
2029
2030     # activate color-completion
2031     zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}
2032
2033     # format on completion
2034     zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
2035
2036     # complete 'cd -<tab>' with menu
2037     zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
2038
2039     # insert all expansions for expand completer
2040     zstyle ':completion:*:expand:*'        tag-order all-expansions
2041     zstyle ':completion:*:history-words'   list false
2042
2043     # activate menu
2044     zstyle ':completion:*:history-words'   menu yes
2045
2046     # ignore duplicate entries
2047     zstyle ':completion:*:history-words'   remove-all-dups yes
2048     zstyle ':completion:*:history-words'   stop yes
2049
2050     # match uppercase from lowercase
2051     zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'
2052
2053     # separate matches into groups
2054     zstyle ':completion:*:matches'         group 'yes'
2055     zstyle ':completion:*'                 group-name ''
2056
2057     if [[ -z "$NOMENU" ]] ; then
2058         # if there are more than 5 options allow selecting from a menu
2059         zstyle ':completion:*'               menu select=5
2060     else
2061         # don't use any menus at all
2062         setopt no_auto_menu
2063     fi
2064
2065     zstyle ':completion:*:messages'        format '%d'
2066     zstyle ':completion:*:options'         auto-description '%d'
2067
2068     # describe options in full
2069     zstyle ':completion:*:options'         description 'yes'
2070
2071     # on processes completion complete all user processes
2072     zstyle ':completion:*:processes'       command 'ps -au$USER'
2073
2074     # offer indexes before parameters in subscripts
2075     zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
2076
2077     # provide verbose completion information
2078     zstyle ':completion:*'                 verbose true
2079
2080     # recent (as of Dec 2007) zsh versions are able to provide descriptions
2081     # for commands (read: 1st word in the line) that it will list for the user
2082     # to choose from. The following disables that, because it's not exactly fast.
2083     zstyle ':completion:*:-command-:*:'    verbose false
2084
2085     # set format for warnings
2086     zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
2087
2088     # define files to ignore for zcompile
2089     zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
2090     zstyle ':completion:correct:'          prompt 'correct to: %e'
2091
2092     # Ignore completion functions for commands you don't have:
2093     zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
2094
2095     # Provide more processes in completion of programs like killall:
2096     zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'
2097
2098     # complete manual by their section
2099     zstyle ':completion:*:manuals'    separate-sections true
2100     zstyle ':completion:*:manuals.*'  insert-sections   true
2101     zstyle ':completion:*:man:*'      menu yes select
2102
2103     # run rehash on completion so new installed program are found automatically:
2104     _force_rehash() {
2105         (( CURRENT == 1 )) && rehash
2106         return 1
2107     }
2108
2109     ## correction
2110     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
2111     if [[ -n "$NOCOR" ]] ; then
2112         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
2113         setopt nocorrect
2114     else
2115         # try to be smart about when to use what completer...
2116         setopt correct
2117         zstyle -e ':completion:*' completer '
2118             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
2119                 _last_try="$HISTNO$BUFFER$CURSOR"
2120                 reply=(_complete _match _ignored _prefix _files)
2121             else
2122                 if [[ $words[1] == (rm|mv) ]] ; then
2123                     reply=(_complete _files)
2124                 else
2125                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
2126                 fi
2127             fi'
2128     fi
2129
2130     # zstyle ':completion:*' completer _complete _correct _approximate
2131     # zstyle ':completion:*' expand prefix suffix
2132
2133     # complete shell aliases
2134     # zstyle ':completion:*' completer _expand_alias _complete _approximate
2135
2136     # command for process lists, the local web server details and host completion
2137     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
2138
2139     # caching
2140     [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
2141                             zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
2142
2143     # host completion /* add brackets as vim can't parse zsh's complex cmdlines 8-) {{{ */
2144     if is42 ; then
2145         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
2146         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
2147     else
2148         _ssh_hosts=()
2149         _etc_hosts=()
2150     fi
2151     hosts=(
2152         $(hostname)
2153         "$_ssh_hosts[@]"
2154         "$_etc_hosts[@]"
2155         grml.org
2156         localhost
2157     )
2158     zstyle ':completion:*:hosts' hosts $hosts
2159     #  zstyle '*' hosts $hosts
2160
2161     # specify your logins:
2162     # my_accounts=(
2163     #  {grml,grml1}@foo.invalid
2164     #  grml-devel@bar.invalid
2165     # )
2166     # other_accounts=(
2167     #  {fred,root}@foo.invalid
2168     #  vera@bar.invalid
2169     # )
2170     # zstyle ':completion:*:my-accounts' users-hosts $my_accounts
2171     # zstyle ':completion:*:other-accounts' users-hosts $other_accounts
2172
2173     # specify specific port/service settings:
2174     #  telnet_users_hosts_ports=(
2175     #    user1@host1:
2176     #    user2@host2:
2177     #    @mail-server:{smtp,pop3}
2178     #    @news-server:nntp
2179     #    @proxy-server:8000
2180     #  )
2181     # zstyle ':completion:*:*:telnet:*' users-hosts-ports $telnet_users_hosts_ports
2182
2183     # use generic completion system for programs not yet defined; (_gnu_generic works
2184     # with commands that provide a --help option with "standard" gnu-like output.)
2185     compdef _gnu_generic tail head feh cp mv df stow uname ipacsum fetchipac
2186
2187     # see upgrade function in this file
2188     compdef _hosts upgrade
2189 }
2190 # }}}
2191
2192 # {{{ grmlstuff
2193 grmlstuff() {
2194 # people should use 'grml-x'!
2195     startx() {
2196         if [[ -e /etc/X11/xorg.conf ]] ; then
2197             [[ -x /usr/bin/startx ]] && /usr/bin/startx "$@" || /usr/X11R6/bin/startx "$@"
2198         else
2199             echo "Please use the script \"grml-x\" for starting the X Window System
2200 because there does not exist /etc/X11/xorg.conf yet.
2201 If you want to use startx anyway please call \"/usr/bin/startx\"."
2202             return -1
2203         fi
2204     }
2205
2206     xinit() {
2207         if [[ -e /etc/X11/xorg.conf ]] ; then
2208             [[ -x /usr/bin/xinit ]] && /usr/bin/xinit || /usr/X11R6/bin/xinit
2209         else
2210             echo "Please use the script \"grml-x\" for starting the X Window System.
2211 because there does not exist /etc/X11/xorg.conf yet.
2212 If you want to use xinit anyway please call \"/usr/bin/xinit\"."
2213             return -1
2214         fi
2215     }
2216
2217     if check_com -c 915resolution ; then
2218         alias 855resolution='echo -e "Please use 915resolution as resolution modify tool for Intel graphic chipset."; return -1'
2219     fi
2220
2221     #a1# Output version of running grml
2222     alias grml-version='cat /etc/grml_version'
2223
2224     if check_com -c rebuildfstab ; then
2225         #a1# Rebuild /etc/fstab
2226         alias grml-rebuildfstab='rebuildfstab -v -r -config'
2227     fi
2228
2229     if check_com -c grml-debootstrap ; then
2230         alias debian2hd='print "Installing debian to harddisk is possible via using grml-debootstrap." ; return 1'
2231     fi
2232 }
2233 # }}}
2234
2235 # {{{ now run the functions
2236 isgrml && checkhome
2237 is4    && isgrml    && grmlstuff
2238 is4    && grmlcomp
2239 # }}}
2240
2241 # {{{ keephack
2242 is4 && xsource "/etc/zsh/keephack"
2243 # }}}
2244
2245 # {{{ wonderful idea of using "e" glob qualifier by Peter Stephenson
2246 # You use it as follows:
2247 # $ NTREF=/reference/file
2248 # $ ls -l *(e:nt:)
2249 # This lists all the files in the current directory newer than the reference file.
2250 # You can also specify the reference file inline; note quotes:
2251 # $ ls -l *(e:'nt ~/.zshenv':)
2252 is4 && nt() {
2253     if [[ -n $1 ]] ; then
2254         local NTREF=${~1}
2255     fi
2256     [[ $REPLY -nt $NTREF ]]
2257 }
2258 # }}}
2259
2260 # shell functions {{{
2261
2262 #f1# Provide csh compatibility
2263 setenv()  { typeset -x "${1}${1:+=}${(@)argv[2,$#]}" }  # csh compatibility
2264
2265 #f1# Reload an autoloadable function
2266 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2267
2268 #f1# Reload zsh setup
2269 reload() {
2270     if [[ "$#*" -eq 0 ]] ; then
2271         [[ -r ~/.zshrc ]] && . ~/.zshrc
2272     else
2273         local fn
2274         for fn in "$@"; do
2275             unfunction $fn
2276             autoload -U $fn
2277         done
2278     fi
2279 }
2280 compdef _functions reload freload
2281
2282 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
2283 sll() {
2284     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
2285     for i in "$@" ; do
2286         file=$i
2287         while [[ -h "$file" ]] ; do
2288             ls -l $file
2289             file=$(readlink "$file")
2290         done
2291     done
2292 }
2293
2294 # fast manual access
2295 if check_com qma ; then
2296     #f1# View the zsh manual
2297     manzsh()  { qma zshall "$1" }
2298     compdef _man qma
2299 else
2300     manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
2301     # manzsh()  { /usr/bin/man zshall |  most +/"$1" ; }
2302     # [[ -f ~/.terminfo/m/mostlike ]] && MYLESS='LESS=C TERMINFO=~/.terminfo TERM=mostlike less' || MYLESS='less'
2303     # manzsh()  { man zshall | $MYLESS -p $1 ; }
2304 fi
2305
2306 if check_com -c $PAGER ; then
2307     #f1# View Debian's changelog of a given package
2308     dchange() {
2309         if [[ -r /usr/share/doc/${1}/changelog.Debian.gz ]] ; then
2310             $PAGER /usr/share/doc/${1}/changelog.Debian.gz
2311         elif [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
2312             $PAGER /usr/share/doc/${1}/changelog.gz
2313         else
2314             if check_com -c aptitude ; then
2315                 echo "No changelog for package $1 found, using aptitude to retrieve it."
2316                 if isgrml ; then
2317                     aptitude -t unstable changelog ${1}
2318                 else
2319                     aptitude changelog ${1}
2320                 fi
2321             else
2322                 echo "No changelog for package $1 found, sorry."
2323                 return 1
2324             fi
2325         fi
2326     }
2327     _dchange() { _files -W /usr/share/doc -/ }
2328     compdef _dchange dchange
2329
2330     #f1# View Debian's NEWS of a given package
2331     dnews() {
2332         if [[ -r /usr/share/doc/${1}/NEWS.Debian.gz ]] ; then
2333             $PAGER /usr/share/doc/${1}/NEWS.Debian.gz
2334         else
2335             if [[ -r /usr/share/doc/${1}/NEWS.gz ]] ; then
2336                 $PAGER /usr/share/doc/${1}/NEWS.gz
2337             else
2338                 echo "No NEWS file for package $1 found, sorry."
2339                 return 1
2340             fi
2341         fi
2342     }
2343     _dnews() { _files -W /usr/share/doc -/ }
2344     compdef _dnews dnews
2345
2346     #f1# View upstream's changelog of a given package
2347     uchange() {
2348         if [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
2349             $PAGER /usr/share/doc/${1}/changelog.gz
2350         else
2351             echo "No changelog for package $1 found, sorry."
2352             return 1
2353         fi
2354     }
2355     _uchange() { _files -W /usr/share/doc -/ }
2356     compdef _uchange uchange
2357 fi
2358
2359 # zsh profiling
2360 profile() {
2361     ZSH_PROFILE_RC=1 $SHELL "$@"
2362 }
2363
2364 #f1# Edit an alias via zle
2365 edalias() {
2366     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
2367 }
2368 compdef _aliases edalias
2369
2370 #f1# Edit a function via zle
2371 edfunc() {
2372     [[ -z "$1" ]] && { echo "Usage: edfun <function_to_edit>" ; return 1 } || zed -f "$1" ;
2373 }
2374 compdef _functions edfunc
2375
2376 # use it e.g. via 'Restart apache2'
2377 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
2378 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
2379 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
2380 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
2381 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
2382 if [[ -d /etc/init.d || -d /etc/service ]] ; then
2383     __start_stop() {
2384         local action_="${1:l}"  # e.g Start/Stop/Restart
2385         local service_="$2"
2386         local param_="$3"
2387
2388         local service_target_="$(readlink /etc/init.d/$service_)"
2389         if [[ $service_target_ == "/usr/bin/sv" ]]; then
2390             # runit
2391             case "${action_}" in
2392                 start) if [[ ! -e /etc/service/$service_ ]]; then
2393                            $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
2394                        else
2395                            $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2396                        fi ;;
2397                 # there is no reload in runits sysv emulation
2398                 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
2399                 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
2400             esac
2401         else
2402             # sysvinit
2403             $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
2404         fi
2405     }
2406
2407     for i in Start Restart Stop Force-Reload Reload ; do
2408         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
2409     done
2410 fi
2411
2412 #f1# Provides useful information on globbing
2413 H-Glob() {
2414     echo -e "
2415     /      directories
2416     .      plain files
2417     @      symbolic links
2418     =      sockets
2419     p      named pipes (FIFOs)
2420     *      executable plain files (0100)
2421     %      device files (character or block special)
2422     %b     block special files
2423     %c     character special files
2424     r      owner-readable files (0400)
2425     w      owner-writable files (0200)
2426     x      owner-executable files (0100)
2427     A      group-readable files (0040)
2428     I      group-writable files (0020)
2429     E      group-executable files (0010)
2430     R      world-readable files (0004)
2431     W      world-writable files (0002)
2432     X      world-executable files (0001)
2433     s      setuid files (04000)
2434     S      setgid files (02000)
2435     t      files with the sticky bit (01000)
2436
2437   print *(m-1)          # Files modified up to a day ago
2438   print *(a1)           # Files accessed a day ago
2439   print *(@)            # Just symlinks
2440   print *(Lk+50)        # Files bigger than 50 kilobytes
2441   print *(Lk-50)        # Files smaller than 50 kilobytes
2442   print **/*.c          # All *.c files recursively starting in \$PWD
2443   print **/*.c~file.c   # Same as above, but excluding 'file.c'
2444   print (foo|bar).*     # Files starting with 'foo' or 'bar'
2445   print *~*.*           # All Files that do not contain a dot
2446   chmod 644 *(.^x)      # make all plain non-executable files publically readable
2447   print -l *(.c|.h)     # Lists *.c and *.h
2448   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
2449   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
2450 }
2451 alias help-zshglob=H-Glob
2452
2453 check_com -c qma && alias ?='qma zshall'
2454
2455 # grep for running process, like: 'any vim'
2456 any() {
2457     if [[ -z "$1" ]] ; then
2458         echo "any - grep for process(es) by keyword" >&2
2459         echo "Usage: any <keyword>" >&2 ; return 1
2460     else
2461         local STRING=$1
2462         local LENGTH=$(expr length $STRING)
2463         local FIRSCHAR=$(echo $(expr substr $STRING 1 1))
2464         local REST=$(echo $(expr substr $STRING 2 $LENGTH))
2465         ps xauwww| grep "[$FIRSCHAR]$REST"
2466     fi
2467 }
2468
2469 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
2470 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
2471 [[ -r /proc/1/maps ]] && \
2472 deswap() {
2473     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
2474     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
2475     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
2476 }
2477
2478 # print hex value of a number
2479 hex() {
2480     [[ -n "$1" ]] && printf "%x\n" $1 || { print 'Usage: hex <number-to-convert>' ; return 1 }
2481 }
2482
2483 # calculate (or eval at all ;-)) with perl => p[erl-]eval
2484 # hint: also take a look at zcalc -> 'autoload zcalc' -> 'man zshmodules | less -p MATHFUNC'
2485 peval() {
2486     [[ -n "$1" ]] && CALC="$*" || print "Usage: calc [expression]"
2487     perl -e "print eval($CALC),\"\n\";"
2488 }
2489 functions peval &>/dev/null && alias calc=peval
2490
2491 # brltty seems to have problems with utf8 environment and/or font Uni3-Terminus16 under
2492 # certain circumstances, so work around it, no matter which environment we have
2493 brltty() {
2494     if [[ -z "$DISPLAY" ]] ; then
2495         consolechars -f /usr/share/consolefonts/default8x16.psf.gz
2496         command brltty "$@"
2497     else
2498         command brltty "$@"
2499     fi
2500 }
2501
2502 # just press 'asdf' keys to toggle between dvorak and us keyboard layout
2503 aoeu() {
2504     echo -n 'Switching to us keyboard layout: '
2505     [[ -z "$DISPLAY" ]] && $SUDO loadkeys us &>/dev/null || setxkbmap us &>/dev/null
2506     echo 'Done'
2507 }
2508 asdf() {
2509     echo -n 'Switching to dvorak keyboard layout: '
2510     [[ -z "$DISPLAY" ]] && $SUDO loadkeys dvorak &>/dev/null || setxkbmap dvorak &>/dev/null
2511     echo 'Done'
2512 }
2513 # just press 'asdf' key to toggle from neon layout to us keyboard layout
2514 uiae() {
2515     echo -n 'Switching to us keyboard layout: '
2516     setxkbmap us && echo 'Done' || echo 'Failed'
2517 }
2518
2519 # set up an ipv6 tunnel
2520 ipv6-tunnel() {
2521     case $1 in
2522         start)
2523             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2524                 print 'ipv6 tunnel already set up, nothing to be done.'
2525                 print 'execute: "ifconfig sit1 down ; ifconfig sit0 down" to remove ipv6-tunnel.' ; return 1
2526             else
2527                 [[ -n "$PUBLIC_IP" ]] || \
2528                     local PUBLIC_IP=$(ifconfig $(route -n | awk '/^0\.0\.0\.0/{print $8; exit}') | \
2529                                       awk '/inet addr:/ {print $2}' | tr -d 'addr:')
2530
2531                 [[ -n "$PUBLIC_IP" ]] || { print 'No $PUBLIC_IP set and could not determine default one.' ; return 1 }
2532                 local IPV6ADDR=$(printf "2002:%02x%02x:%02x%02x:1::1" $(print ${PUBLIC_IP//./ }))
2533                 print -n "Setting up ipv6 tunnel $IPV6ADDR via ${PUBLIC_IP}: "
2534                 ifconfig sit0 tunnel ::192.88.99.1 up
2535                 ifconfig sit1 add "$IPV6ADDR" && print done || print failed
2536             fi
2537             ;;
2538         status)
2539             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2540                 print 'ipv6 tunnel available' ; return 0
2541             else
2542                 print 'ipv6 tunnel not available' ; return 1
2543             fi
2544             ;;
2545         stop)
2546             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
2547                 print -n 'Stopping ipv6 tunnel (sit0 + sit1): '
2548                 ifconfig sit1 down ; ifconfig sit0 down && print done || print failed
2549             else
2550                 print 'No ipv6 tunnel found, nothing to be done.' ; return 1
2551             fi
2552             ;;
2553         *)
2554             print "Usage: ipv6-tunnel [start|stop|status]">&2 ; return 1
2555             ;;
2556     esac
2557 }
2558
2559 # run dhclient for wireless device
2560 iwclient() {
2561     salias dhclient "$(wavemon -d | awk '/device/{print $2}')"
2562 }
2563
2564 # spawn a minimally set up ksh - useful if you want to umount /usr/.
2565 minimal-shell() {
2566     exec env -i ENV="/etc/minimal-shellrc" HOME="$HOME" TERM="$TERM" ksh
2567 }
2568
2569 # make a backup of a file
2570 bk() {
2571     cp -a "$1" "${1}_$(date --iso-8601=seconds)"
2572 }
2573
2574 # Switching shell safely and efficiently? http://www.zsh.org/mla/workers/2001/msg02410.html
2575 # bash() {
2576 #  NO_SWITCH="yes" command bash "$@"
2577 # }
2578 # restart () {
2579 #  exec $SHELL $SHELL_ARGS "$@"
2580 # }
2581
2582 # }}}
2583
2584 # log out? set timeout in seconds {{{
2585 # TMOUT=1800
2586 # do not log out in some specific terminals:
2587 #  if [[ "${TERM}" == ([Exa]term*|rxvt|dtterm|screen*) ]] ; then
2588 #    unset TMOUT
2589 #  fi
2590 # }}}
2591
2592 # {{{ make sure our environment is clean regarding colors
2593 for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
2594 # }}}
2595
2596 # source another config file if present {{{
2597 xsource "/etc/zsh/zshrc.local"
2598 xsource "${HOME}/.zshenv"
2599 # }}}
2600
2601 # "persistent history" {{{
2602 # just write important commands you always need to ~/.important_commands
2603 if [[ -r ~/.important_commands ]] ; then
2604     fc -R ~/.important_commands
2605 fi
2606 # }}}
2607
2608 ## genrefcard.pl settings {{{
2609 ### example: split functions-search 8,16,24,32
2610 #@# split functions-search 8
2611 ## }}}
2612
2613 # add variable to be able to check whether the file has been read {{{
2614 ZSHRC_GLOBAL_HAS_BEEN_READ=1
2615 # }}}
2616
2617 ## END OF FILE #################################################################
2618 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4