Add support for ${HOME}/.zshenv; set $PATH on Solaris/SunOS
[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: Sam Mai 17 22:52:34 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 is43(){
113     [[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
114     return 1
115 }
116
117 #f1# Checks whether or not you're running grml
118 isgrml(){
119     [[ -f /etc/grml_version ]] && return 0
120     return 1
121 }
122
123 #f1# Checks whether or not you're running a grml cd
124 isgrmlcd(){
125     [[ -f /etc/grml_cd ]] && return 0
126     return 1
127 }
128
129 if isgrml ; then
130 #f1# Checks whether or not you're running grml-small
131     isgrmlsmall() {
132         [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
133     }
134 else
135     isgrmlsmall() { return 1 }
136 fi
137
138 #f1# are we running within an utf environment?
139 isutfenv() {
140     case "$LANG $CHARSET $LANGUAGE" in
141         *utf*) return 0 ;;
142         *UTF*) return 0 ;;
143         *)     return 1 ;;
144     esac
145 }
146
147 # check for user, if not running as root set $SUDO to sudo
148 (( EUID != 0 )) && SUDO='sudo' || SUDO=''
149
150 # change directory to home on first invocation of zsh
151 # important for rungetty -> autologin
152 # Thanks go to Bart Schaefer!
153 isgrml && checkhome() {
154     if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
155         export ALREADY_DID_CD_HOME=$HOME
156         cd
157     fi
158 }
159
160 # check for zsh v3.1.7+
161
162 if ! [[ ${ZSH_VERSION} == 3.1.<7->*      \
163      || ${ZSH_VERSION} == 3.<2->.<->*    \
164      || ${ZSH_VERSION} == <4->.<->*   ]] ; then
165
166     printf '-!-\n'
167     printf '-!- In this configuration we try to make use of features, that only\n'
168     printf '-!- require version 3.1.7 of the shell; That way this setup can be\n'
169     printf '-!- used with a wide range of zsh versions, while using fairly\n'
170     printf '-!- advanced features in all supported versions.\n'
171     printf '-!-\n'
172     printf '-!- However, you are running zsh version %s.\n' "$ZSH_VERSION"
173     printf '-!-\n'
174     printf '-!- While this *may* work, it might as well fail.\n'
175     printf '-!- Please consider updating to at least version 3.1.7 of zsh.\n'
176     printf '-!-\n'
177     printf '-!- DO NOT EXPECT THIS TO WORK FLAWLESSLY!\n'
178     printf '-!- If it does today, you'\''ve been lucky.\n'
179     printf '-!-\n'
180     printf '-!- Ye been warned!\n'
181     printf '-!-\n'
182
183     function zstyle() { : }
184 fi
185
186 # }}}
187
188 # utility functions {{{
189 # this function checks if a command exists and returns either true
190 # or false. This avoids using 'which' and 'whence', which will
191 # avoid problems with aliases for which on certain weird systems. :-)
192 check_com() {
193     local -i comonly
194
195     if [[ ${1} == '-c' ]] ; then
196         (( comonly = 1 ))
197         shift
198     else
199         (( comonly = 0 ))
200     fi
201
202     if (( ${#argv} != 1 )) ; then
203         printf 'usage: check_com [-c] <command>\n' >&2
204         return 1
205     fi
206
207     if (( comonly > 0 )) ; then
208         [[ -n ${commands[$1]}  ]] && return 0
209         return 1
210     fi
211
212     if   [[ -n ${commands[$1]}    ]] \
213       || [[ -n ${functions[$1]}   ]] \
214       || [[ -n ${aliases[$1]}     ]] \
215       || [[ -n ${reswords[(r)$1]} ]] ; then
216
217         return 0
218     fi
219
220     return 1
221 }
222
223 # creates an alias and precedes the command with
224 # sudo if $EUID is not zero.
225 salias() {
226     local only=0 ; local multi=0
227     while [[ ${1} == -* ]] ; do
228         case ${1} in
229             (-o) only=1 ;;
230             (-a) multi=1 ;;
231             (--) shift ; break ;;
232             (-h)
233                 printf 'usage: salias [-h|-o|-a] <alias-expression>\n'
234                 printf '  -h      shows this help text.\n'
235                 printf '  -a      replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
236                 printf '          be careful using this option.\n'
237                 printf '  -o      only sets an alias if a preceding sudo would be needed.\n'
238                 return 0
239                 ;;
240             (*) printf "unkown option: '%s'\n" "${1}" ; return 1 ;;
241         esac
242         shift
243     done
244
245     if (( ${#argv} > 1 )) ; then
246         printf 'Too many arguments %s\n' "${#argv}"
247         return 1
248     fi
249
250     key="${1%%\=*}" ;  val="${1#*\=}"
251     if (( EUID == 0 )) && (( only == 0 )); then
252         alias -- "${key}=${val}"
253     elif (( EUID > 0 )) ; then
254         (( multi > 0 )) && val="${val// ; / ; sudo }"
255         alias -- "${key}=sudo ${val}"
256     fi
257
258     return 0
259 }
260
261 # a "print -l ${(u)foo}"-workaround for pre-4.2.0 shells
262 # usage: uprint foo
263 #   Where foo is the *name* of the parameter you want printed.
264 #   Note that foo is no typo; $foo would be wrong here!
265 if ! is42 ; then
266     uprint () {
267         local -a u
268         local w
269         local parameter=${1}
270
271         if [[ -z ${parameter} ]] ; then
272             printf 'usage: uprint <parameter>\n'
273             return 1
274         fi
275
276         for w in ${(P)parameter} ; do
277             [[ -z ${(M)u:#${w}} ]] && u=( ${u} ${w} )
278         done
279
280         builtin print -l ${u}
281     }
282 fi
283
284 # Check if we can read given files and source those we can.
285 xsource() {
286     if (( ${#argv} < 1 )) ; then
287         printf 'usage: xsource FILE(s)...\n' >&2
288         return 1
289     fi
290
291     while (( ${#argv} > 0 )) ; do
292         [[ -r ${1} ]] && source ${1}
293         shift
294     done
295     return 0
296 }
297
298 # Check if we can read a given file and 'cat(1)' it.
299 xcat() {
300     if (( ${#argv} != 1 )) ; then
301         printf 'usage: xcat FILE\n' >&2
302         return 1
303     fi
304
305     [[ -r ${1} ]] && cat ${1}
306     return 0
307 }
308
309 # Remove these functions again, they are of use only in these
310 # setup files. This should be called at the end of .zshrc.
311 xunfunction() {
312     local -a funcs
313     funcs=(salias xcat xsource xunfunction zrcautoload)
314
315     for func in $funcs ; do
316         [[ -n ${functions[$func]} ]] \
317             && unfunction $func
318     done
319     return 0
320 }
321
322 # autoload wrapper - use this one instead of autoload directly
323 function zrcautoload() {
324     setopt local_options extended_glob
325     local fdir ffile
326     local -i ffound
327
328     ffile=${1}
329     (( found = 0 ))
330     for fdir in ${fpath} ; do
331         [[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
332     done
333
334     (( ffound == 0 )) && return 1
335     if [[ $ZSH_VERSION == 3.1.<6-> || $ZSH_VERSION == <4->* ]] ; then
336         autoload -U ${ffile} || return 1
337     else
338         autoload ${ffile} || return 1
339     fi
340     return 0
341 }
342
343 #}}}
344
345 # Load is-at-least() for more precise version checks {{{
346
347 # Note that this test will *always* fail, if the is-at-least
348 # function could not be marked for autoloading.
349 zrcautoload is-at-least || is-at-least() { return 1 }
350
351 # }}}
352
353 # locale setup {{{
354 if [[ -z "$LANG" ]] ; then
355    xsource "/etc/default/locale"
356 fi
357
358 export LANG=${LANG:-en_US.iso885915}
359 for var in LC_ALL LC_MESSAGES ; do
360     [[ -n ${(P)var} ]] && export $var
361 done
362
363 xsource "/etc/sysconfig/keyboard"
364
365 TZ=$(xcat /etc/timezone)
366 # }}}
367
368 # check for potentially old files in 'completion.d' {{{
369 setopt extendedglob
370 xof=(/etc/zsh/completion.d/*~/etc/zsh/completion.d/_*(N))
371 if (( ${#xof} > 0 )) ; then
372     printf '\n -!- INFORMATION\n\n'
373     printf ' -!- %s file(s) not starting with an underscore (_) found in\n' ${#xof}
374     printf ' -!- /etc/zsh/completion.d/.\n\n'
375     printf ' -!- While this has been the case in old versions of grml-etc-core,\n'
376     printf ' -!- recent versions of the grml-zsh-setup have all these files rewritten\n'
377     printf ' -!- and renamed. Furthermore, the grml-zsh-setup will *only* add files\n'
378     printf ' -!- named _* to that directory.\n\n'
379     printf ' -!- If you added functions to completion.d yourself, please consider\n'
380     printf ' -!- moving them to /etc/zsh/functions.d/. Files in that directory, not\n'
381     printf ' -!- starting with an underscore are marked for automatic loading\n'
382     printf ' -!- by default (so that is quite convenient).\n\n'
383     printf ' -!- If there are files *not* starting with an underscore from an older\n'
384     printf ' -!- grml-etc-core in completion.d, you may safely remove them.\n\n'
385     printf ' -!- Delete the files for example via running:\n\n'
386     printf "      rm ${xof}\n\n"
387     printf ' -!- Note, that this message will *not* go away, unless you yourself\n'
388     printf ' -!- resolve the situation manually.\n\n'
389     BROKEN_COMPLETION_DIR=1
390 fi
391 unset xof
392 # }}}
393
394 # {{{ set some variables
395 if check_com -c vim ; then
396 #v#
397     export EDITOR=${EDITOR:-vim}
398 else
399     export EDITOR=${EDITOR:-vi}
400 fi
401
402 #v#
403 export PAGER=${PAGER:-less}
404
405 #v#
406 export MAIL=${MAIL:-/var/mail/$USER}
407
408 # if we don't set $SHELL then aterm, rxvt,.. will use /bin/sh or /bin/bash :-/
409 export SHELL='/bin/zsh'
410
411 # color setup for ls:
412 check_com -c dircolors && eval $(dircolors -b)
413
414 # set width of man pages to 80 for more convenient reading
415 # export MANWIDTH=${MANWIDTH:-80}
416
417 # Search path for the cd command
418 #  cdpath=(.. ~)
419
420 # completion functions go to /etc/zsh/completion.d
421 # function files may be put into /etc/zsh/functions.d, from where they
422 # will be automatically autoloaded.
423 if [[ -n "$BROKEN_COMPLETION_DIR" ]] ; then
424     print 'Warning: not setting completion directories because broken files have been found.' >&2
425 else
426     [[ -d /etc/zsh/completion.d ]] && fpath=( $fpath /etc/zsh/completion.d )
427     if [[ -d /etc/zsh/functions.d ]] ; then
428         fpath+=( /etc/zsh/functions.d )
429         for func in /etc/zsh/functions.d/[^_]*[^~] ; do
430             zrcautoload -U ${func:t}
431         done
432     fi
433 fi
434
435 # automatically remove duplicates from these arrays
436 typeset -U path cdpath fpath manpath
437 # }}}
438
439 # {{{ keybindings
440 if [[ "$TERM" != emacs ]] ; then
441     [[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
442     [[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
443     [[ -z "$terminfo[kend]"  ]] || bindkey -M emacs "$terminfo[kend]"  end-of-line
444     [[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
445     [[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
446     [[ -z "$terminfo[kend]"  ]] || bindkey -M vicmd "$terminfo[kend]"  vi-end-of-line
447     [[ -z "$terminfo[cuu1]"  ]] || bindkey -M viins "$terminfo[cuu1]"  vi-up-line-or-history
448     [[ -z "$terminfo[cuf1]"  ]] || bindkey -M viins "$terminfo[cuf1]"  vi-forward-char
449     [[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
450     [[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
451     [[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
452     [[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char
453     # ncurses stuff:
454     [[ "$terminfo[kcuu1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
455     [[ "$terminfo[kcud1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
456     [[ "$terminfo[kcuf1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
457     [[ "$terminfo[kcub1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
458     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
459     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M viins "${terminfo[kend]/O/[}"  end-of-line
460     [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
461     [[ "$terminfo[kend]"  == $'\eO'* ]] && bindkey -M emacs "${terminfo[kend]/O/[}"  end-of-line
462 fi
463
464 ## keybindings (run 'bindkeys' for details, more details via man zshzle)
465 # use emacs style per default:
466 bindkey -e
467 # use vi style:
468 # bindkey -v
469
470 #if [[ "$TERM" == screen ]] ; then
471 bindkey '\e[1~' beginning-of-line       # home
472 bindkey '\e[4~' end-of-line             # end
473 bindkey '\e[A'  up-line-or-search       # cursor up
474 bindkey '\e[B'  down-line-or-search     # <ESC>-
475
476 bindkey '^xp'   history-beginning-search-backward
477 bindkey '^xP'   history-beginning-search-forward
478 # bindkey -s '^L' "|less\n"             # ctrl-L pipes to less
479 # bindkey -s '^B' " &\n"                # ctrl-B runs it in the background
480 # if terminal type is set to 'rxvt':
481 bindkey '\e[7~' beginning-of-line       # home
482 bindkey '\e[8~' end-of-line             # end
483 #fi
484
485 # insert unicode character
486 # usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an Â§
487 # See for example http://unicode.org/charts/ for unicode characters code
488 zrcautoload insert-unicode-char
489 zle -N insert-unicode-char
490 #k# Insert Unicode character
491 bindkey '^Xi' insert-unicode-char
492
493 # just type 'cd ...' to get 'cd ../..'
494 #  rationalise-dot() {
495 #  if [[ $LBUFFER == *.. ]] ; then
496 #    LBUFFER+=/..
497 #  else
498 #    LBUFFER+=.
499 #  fi
500 #  }
501 #  zle -N rationalise-dot
502 #  bindkey . rationalise-dot
503
504 #  bindkey '\eq' push-line-or-edit
505 # }}}
506
507 # a generic accept-line wrapper {{{
508
509 # This widget can prevent unwanted autocorrections from command-name
510 # to _command-name, rehash automatically on enter and call any number
511 # of builtin and user-defined widgets in different contexts.
512 #
513 # For a broader description, see:
514 # <http://bewatermyfriend.org/posts/2007/12-26.11-50-38-tooltime.html>
515 #
516 # The code is imported from the file 'zsh/functions/accept-line' from
517 # <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>, which
518 # distributed under the same terms as zsh itself.
519
520 # A newly added command will may not be found or will cause false
521 # correction attempts, if you got auto-correction set. By setting the
522 # following style, we force accept-line() to rehash, if it cannot
523 # find the first word on the command line in the $command[] hash.
524 zstyle ':acceptline:*' rehash true
525
526 function Accept-Line() {
527     setopt localoptions noksharrays
528     local -a subs
529     local -xi aldone
530     local sub
531
532     zstyle -a ":acceptline:${alcontext}" actions subs
533
534     (( ${#subs} < 1 )) && return 0
535
536     (( aldone = 0 ))
537     for sub in ${subs} ; do
538         [[ ${sub} == 'accept-line' ]] && sub='.accept-line'
539         zle ${sub}
540
541         (( aldone > 0 )) && break
542     done
543 }
544
545 function Accept-Line-getdefault() {
546     local default_action
547
548     zstyle -s ":acceptline:${alcontext}" default_action default_action
549     case ${default_action} in
550         ((accept-line|))
551             printf ".accept-line"
552             ;;
553         (*)
554             printf ${default_action}
555             ;;
556     esac
557 }
558
559 function accept-line() {
560     setopt localoptions noksharrays
561     local -a cmdline
562     local -x alcontext
563     local buf com fname format msg default_action
564
565     alcontext='default'
566     buf="${BUFFER}"
567     cmdline=(${(z)BUFFER})
568     com="${cmdline[1]}"
569     fname="_${com}"
570
571     zstyle -t ":acceptline:${alcontext}" rehash \
572         && [[ -z ${commands[$com]} ]]           \
573         && rehash
574
575     if    [[ -n ${reswords[(r)$com]} ]] \
576        || [[ -n ${aliases[$com]}     ]] \
577        || [[ -n ${functions[$com]}   ]] \
578        || [[ -n ${builtins[$com]}    ]] \
579        || [[ -n ${commands[$com]}    ]] ; then
580
581         # there is something sensible to execute, just do it.
582         alcontext='normal'
583         zle Accept-Line
584
585         default_action=$(Accept-Line-getdefault)
586         zstyle -T ":acceptline:${alcontext}" call_default \
587             && zle ${default_action}
588         return
589     fi
590
591     if    [[ -o correct              ]] \
592        || [[ -o correctall           ]] \
593        && [[ -n ${functions[$fname]} ]] ; then
594
595         # nothing there to execute but there is a function called
596         # _command_name; a completion widget. Makes no sense to
597         # call it on the commandline, but the correct{,all} options
598         # will ask for it nevertheless, so warn the user.
599         if [[ ${LASTWIDGET} == 'accept-line' ]] ; then
600             # Okay, we warned the user before, he called us again,
601             # so have it his way.
602             alcontext='force'
603             zle Accept-Line
604
605             default_action=$(Accept-Line-getdefault)
606             zstyle -T ":acceptline:${alcontext}" call_default \
607                 && zle ${default_action}
608             return
609         fi
610
611         # prepare warning message for the user, configurable via zstyle.
612         zstyle -s ":acceptline:${alcontext}" compwarnfmt msg
613
614         if [[ -z ${msg} ]] ; then
615             msg="%c will not execute and completion %f exists."
616         fi
617
618         zformat -f msg "${msg}" "c:${com}" "f:${fname}"
619
620         zle -M -- "${msg}"
621         return
622     elif [[ -n ${buf//[$' \t\n']##/} ]] ; then
623         # If we are here, the commandline contains something that is not
624         # executable, which is neither subject to _command_name correction
625         # and is not empty. might be a variable assignment
626         alcontext='misc'
627         zle Accept-Line
628
629         default_action=$(Accept-Line-getdefault)
630         zstyle -T ":acceptline:${alcontext}" call_default \
631             && zle ${default_action}
632         return
633     fi
634
635     # If we got this far, the commandline only contains whitespace, or is empty.
636     alcontext='empty'
637     zle Accept-Line
638
639     default_action=$(Accept-Line-getdefault)
640     zstyle -T ":acceptline:${alcontext}" call_default \
641         && zle ${default_action}
642 }
643
644 zle -N accept-line
645 zle -N Accept-Line
646
647 # }}}
648
649 # power completion - abbreviation expansion {{{
650 # power completion / abbreviation expansion / buffer expansion
651 # see http://zshwiki.org/home/examples/zleiab for details
652 # less risky than the global aliases but powerful as well
653 # just type the abbreviation key and afterwards ',.' to expand it
654 declare -A abk
655 setopt extendedglob
656 setopt interactivecomments
657 abk=(
658 # key  # value                (#d additional doc string)
659 #A# start
660     '...' '../..'
661     '....' '../../..'
662     'BG' '& exit'
663     'C' '| wc -l'
664     'G' '|& grep --color=auto'
665     'H' '| head'
666     'Hl' ' --help |& less -r'      #d (Display help in pager)
667     'L' '| less'
668     'LL' '|& less -r'
669     'M' '| most'
670     'N' '&>/dev/null'              #d (No Output)
671     'R' '| tr A-z N-za-m'          #d (ROT13)
672     'SL' '| sort | less'
673     'S' '| sort -u'
674     'T' '| tail'
675     'V' '|& vim -'
676 #A# end
677     'hide' "echo -en '\033]50;nil2\007'"
678     'tiny' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"'
679     'small' 'echo -en "\033]50;6x10\007"'
680     'medium' 'echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"'
681     'default' 'echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"'
682     'large' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"'
683     'huge' 'echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"'
684     'smartfont' 'echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"'
685     'semifont' 'echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"'
686     'da' 'du -sch'
687     'j' 'jobs -l'
688     'u' 'translate -i'
689     'co' "./configure && make && sudo make install"
690     'CH' "./configure --help"
691     'conkeror' 'firefox -chrome chrome://conkeror/content'
692     'dir' 'ls -lSrah'
693     'lad' $'ls -d .*(/)\n# only show dot-directories'
694     'lsa' $'ls -a .*(.)\n# only show dot-files'
695     'lss' $'ls -l *(s,S,t)\n# only files with setgid/setuid/sticky flag'
696     'lsl' $'ls -l *(@[1,10])\n# only symlinks'
697     'lsx' $'ls -l *(*[1,10])\n# only executables'
698     'lsw' $'ls -ld *(R,W,X.^ND/)\n# world-{readable,writable,executable} files'
699     'lsbig' $'ls -flh *(.OL[1,10])\n# display the biggest files'
700     'lsd' $'ls -d *(/)\n# only show directories'
701     'lse' $'ls -d *(/^F)\n# only show empty directories'
702     'lsnew' $'ls -rl *(D.om[1,10])\n# display the newest files'
703     'lsold' $'ls -rtlh *(D.om[-11,-1])\n # display the oldest files'
704     'lssmall' $'ls -Srl *(.oL[1,10])\n# display the smallest files'
705     'rw-' 'chmod 600'
706     '600' 'chmod u+rw-x,g-rwx,o-rwx'
707     'rwx' 'chmod u+rwx'
708     '700' 'chmod u+rwx,g-rwx,o-rwx'
709     'r--' 'chmod u+r-wx,g-rwx,o-rwx'
710     '644' $'chmod u+rw-x,g+r-wx,o+r-wx\n # 4=r,2=w,1=x'
711     '755' 'chmod u+rwx,g+r-w+x,o+r-w+x'
712     'md' 'mkdir -p '
713     'cmplayer' 'mplayer -vo -fs -zoom fbdev'
714     'fbmplayer' 'mplayer -vo -fs -zoom fbdev'
715     'fblinks' 'links2 -driver fb'
716     'insecssh' 'ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
717     'insecscp' 'scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
718     'fori' 'for i ({..}) { }'
719     'cx' 'chmod +x'
720     'e'  'print -l'
721     'se' 'setopt interactivecomments'
722     'va' 'valac --vapidir=../vapi/ --pkg=gtk+-2.0 gtktest.vala'
723     'fb2' '=mplayer -vo fbdev -fs -zoom 1>/dev/null -xy 2'
724     'fb3' '=mplayer -vo fbdev -fs  -zoom 1>/dev/null -xy 3'
725     'ci' 'centericq'
726     'D'  'export DISPLAY=:0.0'
727     'mp' 'mplayer -vo xv -fs -zoom'
728 )
729
730 globalias() {
731     local MATCH
732     matched_chars='[.-|_a-zA-Z0-9]#'
733     LBUFFER=${LBUFFER%%(#m)[.-|_a-zA-Z0-9]#}
734     LBUFFER+=${abk[$MATCH]:-$MATCH}
735 }
736
737 zle -N globalias
738 bindkey ",." globalias
739 # }}}
740
741 # {{{ autoloading
742 zrcautoload zmv    # who needs mmv or rename?
743 zrcautoload history-search-end
744
745 # we don't want to quote/espace URLs on our own...
746 # if autoload -U url-quote-magic ; then
747 #    zle -N self-insert url-quote-magic
748 #    zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}='
749 # else
750 #    print 'Notice: no url-quote-magic available :('
751 # fi
752 alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic'
753
754 #m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
755 alias run-help >&/dev/null && unalias run-help
756 zrcautoload run-help # use via 'esc-h'
757
758 # completion system
759 if zrcautoload compinit && compinit 2>/dev/null ; then
760     compinit 2>/dev/null || print 'Notice: no compinit available :('
761 else
762     print 'Notice: no compinit available :('
763     function zstyle { }
764     function compdef { }
765 fi
766
767 is4 && zrcautoload zed # use ZLE editor to edit a file or function
768
769 is4 && \
770 for mod in complist deltochar mathfunc ; do
771     zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
772 done
773
774 # autoload zsh modules when they are referenced
775 if is4 ; then
776     tmpargs=(
777         a   stat
778         a   zpty
779         ap  zprof
780         ap  mapfile
781     )
782
783     while (( ${#tmpargs} > 0 )) ; do
784         zmodload -${tmpargs[1]} zsh/${tmpargs[2]} ${tmpargs[2]}
785         shift 2 tmpargs
786     done
787     unset tmpargs
788 fi
789
790 if is4 && zrcautoload insert-files && zle -N insert-files ; then
791     #k# Insert files
792     bindkey "^Xf" insert-files # C-x-f
793 fi
794
795 bindkey ' '   magic-space    # also do history expansion on space
796 #k# Trigger menu-complete
797 bindkey '\ei' menu-complete  # menu completion via esc-i
798
799 # press esc-e for editing command line in $EDITOR or $VISUAL
800 if is4 && zrcautoload edit-command-line && zle -N edit-command-line ; then
801     #k# Edit the current line in \kbd{\$EDITOR}
802     bindkey '\ee' edit-command-line
803 fi
804
805 if is4 && [[ -n ${(k)modules[zsh/complist]} ]] ; then
806     #k# menu selection: pick item but stay in the menu
807     bindkey -M menuselect '\e^M' accept-and-menu-complete
808
809     # use the vi navigation keys (hjkl) besides cursor keys in menu completion
810     #bindkey -M menuselect 'h' vi-backward-char        # left
811     #bindkey -M menuselect 'k' vi-up-line-or-history   # up
812     #bindkey -M menuselect 'l' vi-forward-char         # right
813     #bindkey -M menuselect 'j' vi-down-line-or-history # bottom
814
815     # accept a completion and try to complete again by using menu
816     # completion; very useful with completing directories
817     # by using 'undo' one's got a simple file browser
818     bindkey -M menuselect '^o' accept-and-infer-next-history
819 fi
820
821 # press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
822 _bkdate() { BUFFER="$BUFFER$(date '+%F')"; CURSOR=$#BUFFER; }
823 zle -N _bkdate
824
825 #k# Insert a timestamp on the command line (yyyy-mm-dd)
826 bindkey '^Ed' _bkdate
827
828 # press esc-m for inserting last typed word again (thanks to caphuso!)
829 insert-last-typed-word() { zle insert-last-word -- 0 -1 };
830 zle -N insert-last-typed-word;
831
832 #k# Insert last typed word
833 bindkey "\em" insert-last-typed-word
834
835 # set command prediction from history, see 'man 1 zshcontrib'
836 #  is4 && zrcautoload predict-on && \
837 #  zle -N predict-on         && \
838 #  zle -N predict-off        && \
839 #  bindkey "^X^Z" predict-on && \
840 #  bindkey "^Z" predict-off
841
842 #k# Shortcut for \kbd{fg<enter>}
843 bindkey -s '^z' "fg\n"
844
845 # press ctrl-q to quote line:
846 #  mquote () {
847 #        zle beginning-of-line
848 #        zle forward-word
849 #        # RBUFFER="'$RBUFFER'"
850 #        RBUFFER=${(q)RBUFFER}
851 #        zle end-of-line
852 #  }
853 #  zle -N mquote && bindkey '^q' mquote
854
855 # run command line as user root via sudo:
856 sudo-command-line() {
857     [[ -z $BUFFER ]] && zle up-history
858     [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
859 }
860 zle -N sudo-command-line
861
862 #k# Put the current command line into a \kbd{sudo} call
863 bindkey "^Os" sudo-command-line
864
865 ### jump behind the first word on the cmdline.
866 ### useful to add options.
867 function jump_after_first_word() {
868     local words
869     words=(${(z)BUFFER})
870
871     if (( ${#words} <= 1 )) ; then
872         CURSOR=${#BUFFER}
873     else
874         CURSOR=${#${words[1]}}
875     fi
876 }
877 zle -N jump_after_first_word
878
879 bindkey '^x1' jump_after_first_word
880
881 # }}}
882
883 # {{{ set some important options
884 # Please update these tags, if you change the umask settings below.
885 #o# r_umask     002
886 #o# r_umaskstr  rwxrwxr-x
887 #o# umask       022
888 #o# umaskstr    rwxr-xr-x
889 (( EUID != 0 )) && umask 002 || umask 022
890
891 # history:
892 setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
893 is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
894 setopt extended_history     # save each command's beginning timestamp and the duration to the history file
895 is4 && setopt histignorealldups # If  a  new  command  line being added to the history
896                             # list duplicates an older one, the older command is removed from the list
897 setopt histignorespace      # remove command lines from the history list when
898                             # the first character on the line is a space
899 #  setopt histallowclobber    # add `|' to output redirections in the history
900 #  setopt NO_clobber          # warning if file exists ('cat /dev/null > ~/.zshrc')
901 setopt auto_cd              # if a command is issued that can't be executed as a normal command,
902                             # and the command is the name of a directory, perform the cd command to that directory
903 setopt extended_glob        # in order to use #, ~ and ^ for filename generation
904                             # grep word *~(*.gz|*.bz|*.bz2|*.zip|*.Z) ->
905                             # -> searches for word not in compressed files
906                             # don't forget to quote '^', '~' and '#'!
907 setopt longlistjobs         # display PID when suspending processes as well
908 setopt notify               # report the status of backgrounds jobs immediately
909 setopt hash_list_all        # Whenever a command completion is attempted, make sure \
910                             # the entire command path is hashed first.
911 setopt completeinword       # not just at the end
912 # setopt nocheckjobs          # don't warn me about bg processes when exiting
913 setopt nohup                # and don't kill them, either
914 # setopt printexitvalue       # alert me if something failed
915 # setopt dvorak               # with spelling correction, assume dvorak kb
916 setopt auto_pushd           # make cd push the old directory onto the directory stack.
917 setopt nonomatch            # try to avoid the 'zsh: no matches found...'
918 setopt nobeep               # avoid "beep"ing
919 setopt pushd_ignore_dups    # don't push the same dir twice.
920
921 MAILCHECK=30       # mailchecks
922 REPORTTIME=5       # report about cpu-/system-/user-time of command if running longer than 5 seconds
923 watch=(notme root) # watch for everyone but me and root
924
925 # define word separators (for stuff like backward-word, forward-word, backward-kill-word,..)
926 #  WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' # the default
927 #  WORDCHARS=.
928 #  WORDCHARS='*?_[]~=&;!#$%^(){}'
929 #  WORDCHARS='${WORDCHARS:s@/@}'
930
931 # only slash should be considered as a word separator:
932 slash-backward-kill-word() {
933     local WORDCHARS="${WORDCHARS:s@/@}"
934     # zle backward-word
935     zle backward-kill-word
936 }
937 zle -N slash-backward-kill-word
938
939 #k# Kill everything in a word up to its last \kbd{/}
940 bindkey '\ev' slash-backward-kill-word
941
942 # }}}
943
944 # {{{ history
945
946 ZSHDIR=$HOME/.zsh
947
948 #v#
949 HISTFILE=$HOME/.zsh_history
950 isgrmlcd && HISTSIZE=500  || HISTSIZE=5000
951 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
952
953 # }}}
954
955 # dirstack handling {{{
956
957 DIRSTACKSIZE=${DIRSTACKSIZE:-20}
958 DIRSTACKFILE=${DIRSTACKFILE:-${HOME}/.zdirs}
959
960 if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
961     dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
962     # "cd -" won't work after login by just setting $OLDPWD, so
963     [[ -d $dirstack[0] ]] && cd $dirstack[0] && cd $OLDPWD
964 fi
965
966 chpwd() {
967     if is42 ; then
968         builtin print -l ${(u)dirstack} >! ${DIRSTACKFILE}
969     else
970         uprint dirstack >! ${DIRSTACKFILE}
971     fi
972 }
973
974 # }}}
975
976 # {{{ display battery status on right side of prompt via running 'BATTERY=1 zsh'
977 if [[ -n "$BATTERY" ]] ; then
978     if check_com -c acpi ; then
979         PERCENT="${(C)${(s| |)$(acpi 2>/dev/null)}[4]}"
980         [[ -z "$PERCENT" ]] && PERCENT='acpi not present'
981
982         if [[ "${PERCENT%%%}" -lt 20 ]] ; then
983             PERCENT="warning: ${PERCENT}%"
984         fi
985     fi
986 fi
987 # }}}
988
989 # display version control information on right side of prompt if $VCS is set {{{
990 # based on Mike Hommey's http://web.glandium.org/blog/?p=170
991 __vcs_dir() {
992     local vcs base_dir sub_dir ref
993
994     sub_dir() {
995       local sub_dir
996       sub_dir=$(readlink -f "${PWD}")
997       sub_dir=${sub_dir#$1}
998       echo ${sub_dir#/}
999     }
1000
1001     git_dir() {
1002       base_dir=$(git-rev-parse --show-cdup 2>/dev/null) || return 1
1003       base_dir=$(readlink -f "$base_dir/..")
1004       sub_dir=$(git-rev-parse --show-prefix)
1005       sub_dir=${sub_dir%/}
1006       ref=$(git-symbolic-ref -q HEAD || git-name-rev --name-only HEAD 2>/dev/null)
1007       ref=${ref#refs/heads/}
1008       vcs="git"
1009     }
1010
1011     svn_dir() {
1012       [[ -d ".svn" ]] || return 1
1013       base_dir="."
1014       while [[ -d "$base_dir/../.svn" ]]; do base_dir="$base_dir/.."; done
1015       base_dir=$(readlink -f "$base_dir")
1016       sub_dir=$(sub_dir "${base_dir}")
1017       ref=$(svn info "$base_dir" | awk '/^URL/ { sub(".*/","",$0); r=$0 } /^Revision/ { sub("[^0-9]*","",$0); print r":"$0 }')
1018       vcs="svn"
1019     }
1020
1021     svk_dir() {
1022         [[ -f ~/.svk/config ]] || return 1
1023         base_dir=$(awk '/: *$/ { sub(/^ */,"",$0); sub(/: *$/,"",$0); if (match("'${PWD}'", $0"(/|$)")) { print $0; d=1; } } /depotpath/ && d == 1 { sub(".*/","",$0); r=$0 } /revision/ && d == 1 { print r ":" $2; exit 1 }' ~/.svk/config) && return 1
1024         ref=${base_dir##*
1025   }
1026         base_dir=${base_dir%%
1027   *}
1028         sub_dir=$(sub_dir "${base_dir}")
1029         vcs="svk"
1030     }
1031
1032     hg_dir() {
1033         base_dir="."
1034         while [[ ! -d "$base_dir/.hg" ]]; do
1035             base_dir="$base_dir/.."
1036             [[ $(readlink -f "${base_dir}") = "/" ]] && return 1
1037         done
1038         base_dir=$(readlink -f "$base_dir")
1039         sub_dir=$(sub_dir "${base_dir}")
1040         ref=$(< "${base_dir}/.hg/branch")
1041         vcs="hg"
1042     }
1043
1044     hg_dir  ||
1045     git_dir ||
1046     svn_dir ||
1047     svk_dir # ||
1048   #  base_dir="$PWD"
1049   #  echo "${vcs:+($vcs)}${base_dir/$HOME/~}${vcs:+[$ref]${sub_dir}}"
1050     echo "${vcs:+($vcs)}${base_dir}${vcs:+[$ref]${sub_dir}}"
1051 }
1052 # }}}
1053
1054 # {{{ set prompt
1055 if zrcautoload promptinit && promptinit 2>/dev/null ; then
1056     promptinit # people should be able to use their favourite prompt
1057 else
1058     print 'Notice: no promptinit available :('
1059 fi
1060
1061
1062 # precmd() => a function which is executed just before each prompt
1063 # use 'NOPRECMD=1' to disable the precmd + preexec commands
1064
1065 # precmd () { setopt promptsubst; [[ -o interactive ]] && jobs -l;
1066
1067 # make sure to use right prompt only when not running a command
1068 is41 && setopt transient_rprompt
1069
1070 is4 && [[ -z $NOPRECMD ]] && precmd () {
1071     [[ -n $NOPRECMD ]] && return 0
1072     # allow manual overwriting of RPROMPT
1073     if [[ -n $RPROMPT ]] ; then
1074         [[ $TERM == screen* ]] && echo -n $'\ekzsh\e\\'
1075         # return 0
1076     fi
1077     # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
1078     if [[ -z $DONTSETRPROMPT ]] ; then
1079         if [[ -n $BATTERY ]] ; then
1080             RPROMPT="%(?..:()% ${PERCENT}${SCREENTITLE}"
1081             # RPROMPT="${PERCENT}${SCREENTITLE}"
1082         elif [[ -n $VCS ]] ; then
1083             RPROMPT="%(?..:()% $(__vcs_dir)${SCREENTITLE}"
1084         else
1085             RPROMPT="%(?..:()% ${SCREENTITLE}"
1086             # RPROMPT="${SCREENTITLE}"
1087         fi
1088     fi
1089     # adjust title of xterm
1090     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
1091     case $TERM in
1092         (xterm*|rxvt)
1093             print -Pn "\e]0;%n@%m: %~\a"
1094             ;;
1095     esac
1096 }
1097
1098 # chpwd () => a function which is executed whenever the directory is changed
1099
1100 # preexec() => a function running before every command
1101 is4 && [[ -z $NOPRECMD ]] && \
1102 preexec () {
1103     [[ -n $NOPRECMD ]] && return 0
1104 # set hostname if not running on host with name 'grml'
1105     if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
1106        NAME="@$HOSTNAME"
1107     fi
1108 # get the name of the program currently running and hostname of local machine
1109 # set screen window title if running in a screen
1110     if [[ "$TERM" == screen* ]] ; then
1111         # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]}       # don't use hostname
1112         local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname
1113         echo -ne "\ek$CMD\e\\"
1114     fi
1115 # set the screen title to "zsh" when sitting at the command prompt:
1116     if [[ "$TERM" == screen* ]] ; then
1117         SCREENTITLE=$'%{\ekzsh\e\\%}'
1118     else
1119         SCREENTITLE=''
1120     fi
1121 # adjust title of xterm
1122     case $TERM in
1123         (xterm*|rxvt)
1124             print -Pn "\e]0;%n@%m: $1\a"
1125             ;;
1126     esac
1127 }
1128
1129 # set colors
1130 if zrcautoload colors && colors 2>/dev/null ; then
1131     BLUE="%{${fg[blue]}%}"
1132     RED="%{${fg_bold[red]}%}"
1133     GREEN="%{${fg[green]}%}"
1134     CYAN="%{${fg[cyan]}%}"
1135     WHITE="%{${fg[white]}%}"
1136     NO_COLOUR="%{${reset_color}%}"
1137 else
1138     BLUE=$'%{\e[1;34m%}'
1139     RED=$'%{\e[1;31m%}'
1140     GREEN=$'%{\e[1;32m%}'
1141     CYAN=$'%{\e[1;36m%}'
1142     WHITE=$'%{\e[1;37m%}'
1143     NO_COLOUR=$'%{\e[0m%}'
1144 fi
1145
1146 EXITCODE="%(?..%?%1v )"
1147 PS2='`%_> '       # secondary prompt, printed when the shell needs more information to complete a command.
1148 PS3='?# '         # selection prompt used within a select loop.
1149 PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
1150
1151 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
1152 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
1153     debian_chroot=$(cat /etc/debian_chroot)
1154 fi
1155
1156 # don't use colors on dumb terminals (like emacs):
1157 if [[ "$TERM" == dumb ]] ; then
1158     PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< %# "
1159 else
1160     # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt
1161     # set variable identifying the chroot you work in (used in the prompt below)
1162     if [[ -n $GRMLPROMPT ]] ; then
1163         PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D
1164 ${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# "
1165     else
1166         if (( EUID != 0 )); then
1167             PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# " # primary prompt string
1168         else
1169             PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< %# " # primary prompt string
1170         fi
1171     fi
1172 fi
1173
1174 # if we are inside a grml-chroot set a specific prompt theme
1175 if [[ -n "$GRML_CHROOT" ]] ; then
1176     PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# "
1177 fi
1178 # }}}
1179
1180 # {{{ 'hash' some often used directories
1181 #d# start
1182 hash -d deb=/var/cache/apt/archives
1183 hash -d doc=/usr/share/doc
1184 hash -d linux=/lib/modules/$(command uname -r)/build/
1185 hash -d log=/var/log
1186 hash -d slog=/var/log/syslog
1187 hash -d src=/usr/src
1188 hash -d templ=/usr/share/doc/grml-templates
1189 hash -d tt=/usr/share/doc/texttools-doc
1190 hash -d www=/var/www
1191 #d# end
1192 # }}}
1193
1194 # {{{ some aliases
1195 if [[ $UID -eq 0 ]] ; then
1196     [[ -r /etc/grml/screenrc ]] && alias screen='/usr/bin/screen -c /etc/grml/screenrc'
1197 elif [[ -r $HOME/.screenrc ]] ; then
1198     alias screen="/usr/bin/screen -c $HOME/.screenrc"
1199 else
1200     [[ -r /etc/grml/screenrc_grml ]] && alias screen='/usr/bin/screen -c /etc/grml/screenrc_grml'
1201 fi
1202
1203 # do we have GNU ls with color-support?
1204 if ls --help 2>/dev/null | grep -- --color= >/dev/null && [[ "$TERM" != dumb ]] ; then
1205     #a1# execute \kbd{@a@}:\quad ls with colors
1206     alias ls='ls -b -CF --color=auto'
1207     #a1# execute \kbd{@a@}:\quad list all files, with colors
1208     alias la='ls -la --color=auto'
1209     #a1# long colored list, without dotfiles (@a@)
1210     alias ll='ls -l --color=auto'
1211     #a1# long colored list, human readable sizes (@a@)
1212     alias lh='ls -hAl --color=auto'
1213     #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
1214     alias l='ls -lF --color=auto'
1215 else
1216     alias ls='ls -b -CF'
1217     alias la='ls -la'
1218     alias ll='ls -l'
1219     alias lh='ls -hAl'
1220     alias l='ls -lF'
1221 fi
1222
1223 alias mdstat='cat /proc/mdstat'
1224 alias ...='cd ../../'
1225
1226 # generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
1227 if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
1228     alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
1229 fi
1230
1231 alias cp='nocorrect cp'         # no spelling correction on cp
1232 alias mkdir='nocorrect mkdir'   # no spelling correction on mkdir
1233 alias mv='nocorrect mv'         # no spelling correction on mv
1234 alias rm='nocorrect rm'         # no spelling correction on rm
1235
1236 #a1# Execute \kbd{rmdir}
1237 alias rd='rmdir'
1238 #a1# Execute \kbd{rmdir}
1239 alias md='mkdir'
1240
1241 # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
1242 alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
1243 alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
1244
1245 # make sure it is not assigned yet
1246 [[ $(whence -w utf2iso &>/dev/null) == 'utf2iso: alias' ]] && unalias utf2iso
1247
1248 utf2iso() {
1249     if isutfenv ; then
1250         for ENV in $(env | command grep -i '.utf') ; do
1251             eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
1252         done
1253     fi
1254 }
1255
1256 # make sure it is not assigned yet
1257 [[ $(whence -w iso2utf &>/dev/null) == 'iso2utf: alias' ]] && unalias iso2utf
1258 iso2utf() {
1259     if ! isutfenv ; then
1260         for ENV in $(env | command grep -i '\.iso') ; do
1261             eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
1262         done
1263     fi
1264 }
1265
1266 # set up software synthesizer via speakup
1267 swspeak() {
1268     aumix -w 90 -v 90 -p 90 -m 90
1269     if ! [[ -r /dev/softsynth ]] ; then
1270         flite -o play -t "Sorry, software synthesizer not available. Did you boot with swspeak bootoption?"
1271         return 1
1272     else
1273         setopt singlelinezle
1274         unsetopt prompt_cr
1275         export PS1="%m%# "
1276         nice -n -20 speechd-up
1277         sleep 2
1278         flite -o play -t "Finished setting up software synthesizer"
1279     fi
1280 }
1281
1282 # I like clean prompt, so provide simple way to get that
1283 check_com 0 || alias 0='return 0'
1284
1285 # for really lazy people like mika:
1286 check_com S &>/dev/null || alias S='screen'
1287 check_com s &>/dev/null || alias s='ssh'
1288
1289 # get top 10 shell commands:
1290 alias top10='print -l ? ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
1291
1292 # truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i'
1293 if check_com -c truecrypt ; then
1294     if isutfenv ; then
1295         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" '
1296     else
1297         alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" '
1298     fi
1299 fi
1300
1301 #f1# Hints for the use of zsh on grml
1302 zsh-help() {
1303     print "$bg[white]$fg[black]
1304 zsh-help - hints for use of zsh on grml
1305 =======================================$reset_color"
1306
1307     print '
1308 Main configuration of zsh happens in /etc/zsh/zshrc (global)
1309 and /etc/skel/.zshrc which is copied to $HOME/.zshrc once.
1310 The files are part of the package grml-etc-core, if you want to
1311 use them on a non-grml-system just get the tar.gz from
1312 http://deb.grml.org/ or get the files from the mercurial
1313 repository:
1314
1315   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/skel/.zshrc
1316   http://hg.grml.org/grml-etc-core/raw-file/tip/etc/zsh/zshrc
1317
1318 If you want to stay in sync with zsh configuration of grml
1319 run '\''ln -sf /etc/skel/.zshrc $HOME/.zshrc'\'' and configure
1320 your own stuff in $HOME/.zshrc.local. System wide configuration
1321 without touching configuration files of grml can take place
1322 in /etc/zsh/zshrc.local.
1323
1324 If you want to use the configuration of user grml also when
1325 running as user root just run '\''zshskel'\'' which will source
1326 the file /etc/skel/.zshrc.
1327
1328 For information regarding zsh start at http://grml.org/zsh/
1329
1330 Take a look at grml'\''s zsh refcard:
1331 % xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
1332
1333 Check out the main zsh refcard:
1334 % '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
1335
1336 And of course visit the zsh-lovers:
1337 % man zsh-lovers
1338
1339 You can adjust some options through environment variables when
1340 invoking zsh without having to edit configuration files.
1341 Basically meant for bash users who are not used to the power of
1342 the zsh yet. :)
1343
1344   "NOCOR=1    zsh" => deactivate automatic correction
1345   "NOMENU=1   zsh" => do not use menu completion (note: use strg-d for completion instead!)
1346   "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
1347   "BATTERY=1  zsh" => activate battery status (via acpi) on right side of prompt'
1348
1349     print "
1350 $bg[white]$fg[black]
1351 Please report wishes + bugs to the grml-team: http://grml.org/bugs/
1352 Enjoy your grml system with the zsh!$reset_color"
1353 }
1354
1355 # debian stuff
1356 if [[ -r /etc/debian_version ]] ; then
1357     #a3# Execute \kbd{apt-cache search}
1358     alias acs='apt-cache search'
1359     #a3# Execute \kbd{apt-cache show}
1360     alias acsh='apt-cache show'
1361     #a3# Execute \kbd{apt-cache policy}
1362     alias acp='apt-cache policy'
1363     #a3# Execute \kbd{apt-get dist-upgrade}
1364     salias adg="apt-get dist-upgrade"
1365     #a3# Execute \kbd{apt-get install}
1366     salias agi="apt-get install"
1367     #a3# Execute \kbd{aptitude install}
1368     salias ati="aptitude install"
1369     #a3# Execute \kbd{apt-get upgrade}
1370     salias ag="apt-get upgrade"
1371     #a3# Execute \kbd{apt-get update}
1372     salias au="apt-get update"
1373     #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
1374     salias -a up="aptitude update ; aptitude safe-upgrade"
1375     #a3# Execute \kbd{dpkg-buildpackage}
1376     alias dbp='dpkg-buildpackage'
1377     #a3# Execute \kbd{grep-excuses}
1378     alias ge='grep-excuses'
1379
1380     # debian upgrade
1381     #f3# Execute \kbd{apt-get update \&\& }\\&\quad \kbd{apt-get dist-upgrade}
1382     upgrade() {
1383         if [[ -z "$1" ]] ; then
1384             $SUDO apt-get update
1385             $SUDO apt-get -u upgrade
1386         else
1387             ssh $1 $SUDO apt-get update
1388             # ask before the upgrade
1389             local dummy
1390             ssh $1 $SUDO apt-get --no-act upgrade
1391             echo -n 'Process the upgrade?'
1392             read -q dummy
1393             if [[ $dummy == "y" ]] ; then
1394                 ssh $1 $SUDO apt-get -u upgrade --yes
1395             fi
1396         fi
1397     }
1398
1399     # get a root shell as normal user in live-cd mode:
1400     if isgrmlcd && [[ $UID -ne 0 ]] ; then
1401        alias su="sudo su"
1402      fi
1403
1404     #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
1405     alias llog="$PAGER /var/log/syslog"     # take a look at the syslog
1406     #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
1407     alias tlog="tail -f /var/log/syslog"    # follow the syslog
1408     #a1# (Re)-source \kbd{/etc/skel/.zshrc}
1409     alias zshskel="source /etc/skel/.zshrc" # source skeleton zshrc
1410 fi
1411
1412 # sort installed Debian-packages by size
1413 if check_com -c grep-status ; then
1414     #a3# List installed Debian-packages sorted by size
1415     alias debs-by-size='grep-status -FStatus -sInstalled-Size,Package -n "install ok installed" | paste -sd "  \n" | sort -rn'
1416 fi
1417
1418 # if cdrecord is a symlink (to wodim) or isn't present at all warn:
1419 if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord ; then
1420     if check_com -c wodim ; then
1421         alias cdrecord="echo 'cdrecord is not provided under its original name by Debian anymore.
1422 See #377109 in the BTS of Debian for more details.
1423
1424 Please use the wodim binary instead' ; return 1"
1425     fi
1426 fi
1427
1428 # get_tw_cli has been renamed into get_3ware
1429 if check_com -c get_3ware ; then
1430     get_tw_cli() {
1431         echo 'Warning: get_tw_cli has been renamed into get_3ware. Invoking get_3ware for you.'>&2
1432         get_3ware
1433     }
1434 fi
1435
1436 # I hate lacking backward compatibility, so provide an alternative therefore
1437 if ! check_com -c apache2-ssl-certificate ; then
1438
1439     apache2-ssl-certificate() {
1440
1441     print 'Debian does not ship apache2-ssl-certificate anymore (see #398520). :('
1442     print 'You might want to take a look at Debian the package ssl-cert as well.'
1443     print 'To generate a certificate for use with apache2 follow the instructions:'
1444
1445     echo '
1446
1447 export RANDFILE=/dev/random
1448 mkdir /etc/apache2/ssl/
1449 openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem
1450 chmod 600 /etc/apache2/ssl/apache.pem
1451
1452 Run "grml-tips ssl-certificate" if you need further instructions.
1453 '
1454     }
1455 fi
1456 # }}}
1457
1458 # {{{ Use hard limits, except for a smaller stack and no core dumps
1459 unlimit
1460 is4 && limit stack 8192
1461 isgrmlcd && limit core 0 # important for a live-cd-system
1462 limit -s
1463 # }}}
1464
1465 # {{{ completion system
1466
1467 # called later (via is4 && grmlcomp)
1468 # notice: use 'zstyle' for getting current settings
1469 #         press ^Xh (control-x h) for getting tags in context; ^X? (control-x ?) to run complete_debug with trace output
1470 grmlcomp() {
1471     # TODO: This could use some additional information
1472
1473     # allow one error for every three characters typed in approximate completer
1474     zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
1475
1476     # don't complete backup files as executables
1477     zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
1478
1479     # start menu completion only if it could find no unambiguous initial string
1480     zstyle ':completion:*:correct:*'       insert-unambiguous true
1481     zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
1482     zstyle ':completion:*:correct:*'       original true
1483
1484     # activate color-completion
1485     zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}
1486
1487     # format on completion
1488     zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
1489
1490     # complete 'cd -<tab>' with menu
1491     zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
1492
1493     # insert all expansions for expand completer
1494     zstyle ':completion:*:expand:*'        tag-order all-expansions
1495     zstyle ':completion:*:history-words'   list false
1496
1497     # activate menu
1498     zstyle ':completion:*:history-words'   menu yes
1499
1500     # ignore duplicate entries
1501     zstyle ':completion:*:history-words'   remove-all-dups yes
1502     zstyle ':completion:*:history-words'   stop yes
1503
1504     # match uppercase from lowercase
1505     zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'
1506
1507     # separate matches into groups
1508     zstyle ':completion:*:matches'         group 'yes'
1509     zstyle ':completion:*'                 group-name ''
1510
1511     if [[ -z "$NOMENU" ]] ; then
1512         # if there are more than 5 options allow selecting from a menu
1513         zstyle ':completion:*'               menu select=5
1514     else
1515         # don't use any menus at all
1516         setopt no_auto_menu
1517     fi
1518
1519     zstyle ':completion:*:messages'        format '%d'
1520     zstyle ':completion:*:options'         auto-description '%d'
1521
1522     # describe options in full
1523     zstyle ':completion:*:options'         description 'yes'
1524
1525     # on processes completion complete all user processes
1526     zstyle ':completion:*:processes'       command 'ps -au$USER'
1527
1528     # offer indexes before parameters in subscripts
1529     zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
1530
1531     # provide verbose completion information
1532     zstyle ':completion:*'                 verbose true
1533
1534     # recent (as of Dec 2007) zsh versions are able to provide descriptions
1535     # for commands (read: 1st word in the line) that it will list for the user
1536     # to choose from. The following disables that, because it's not exactly fast.
1537     zstyle ':completion:*:-command-:*:'    verbose false
1538
1539     # set format for warnings
1540     zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
1541
1542     # define files to ignore for zcompile
1543     zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
1544     zstyle ':completion:correct:'          prompt 'correct to: %e'
1545
1546     # Ignore completion functions for commands you don't have:
1547     zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
1548
1549     # complete manual by their section
1550     zstyle ':completion:*:manuals'    separate-sections true
1551     zstyle ':completion:*:manuals.*'  insert-sections   true
1552     zstyle ':completion:*:man:*'      menu yes select
1553
1554     # run rehash on completion so new installed program are found automatically:
1555     _force_rehash() {
1556         (( CURRENT == 1 )) && rehash
1557         return 1
1558     }
1559
1560     ## correction
1561     # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
1562     if [[ -n "$NOCOR" ]] ; then
1563         zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
1564         setopt nocorrect
1565     else
1566         # try to be smart about when to use what completer...
1567         setopt correct
1568         zstyle -e ':completion:*' completer '
1569             if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
1570                 _last_try="$HISTNO$BUFFER$CURSOR"
1571                 reply=(_complete _match _ignored _prefix _files)
1572             else
1573                 if [[ $words[1] == (rm|mv) ]] ; then
1574                     reply=(_complete _files)
1575                 else
1576                     reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
1577                 fi
1578             fi'
1579     fi
1580
1581     # zstyle ':completion:*' completer _complete _correct _approximate
1582     # zstyle ':completion:*' expand prefix suffix
1583
1584     # command for process lists, the local web server details and host completion
1585     zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
1586
1587     # caching
1588     [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
1589                             zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
1590
1591     # host completion /* add brackets as vim can't parse zsh's complex cmdlines 8-) {{{ */
1592     if is42 ; then
1593         [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
1594         [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
1595     else
1596         _ssh_hosts=()
1597         _etc_hosts=()
1598     fi
1599     hosts=(
1600         $(hostname)
1601         "$_ssh_hosts[@]"
1602         "$_etc_hosts[@]"
1603         grml.org
1604         localhost
1605     )
1606     zstyle ':completion:*:hosts' hosts $hosts
1607     #  zstyle '*' hosts $hosts
1608
1609     # specify your logins:
1610     # my_accounts=(
1611     #  {grml,grml1}@foo.invalid
1612     #  grml-devel@bar.invalid
1613     # )
1614     # other_accounts=(
1615     #  {fred,root}@foo.invalid
1616     #  vera@bar.invalid
1617     # )
1618     # zstyle ':completion:*:my-accounts' users-hosts $my_accounts
1619     # zstyle ':completion:*:other-accounts' users-hosts $other_accounts
1620
1621     # specify specific port/service settings:
1622     #  telnet_users_hosts_ports=(
1623     #    user1@host1:
1624     #    user2@host2:
1625     #    @mail-server:{smtp,pop3}
1626     #    @news-server:nntp
1627     #    @proxy-server:8000
1628     #  )
1629     # zstyle ':completion:*:*:telnet:*' users-hosts-ports $telnet_users_hosts_ports
1630
1631     # use generic completion system for programs not yet defined; (_gnu_generic works
1632     # with commands that provide a --help option with "standard" gnu-like output.)
1633     compdef _gnu_generic tail head feh cp mv df stow uname ipacsum fetchipac
1634
1635     # see upgrade function in this file
1636     compdef _hosts upgrade
1637 }
1638 # }}}
1639
1640 # {{{ grmlstuff
1641 grmlstuff() {
1642 # people should use 'grml-x'!
1643     startx() {
1644         if [[ -e /etc/X11/xorg.conf ]] ; then
1645             [[ -x /usr/bin/startx ]] && /usr/bin/startx "$@" || /usr/X11R6/bin/startx "$@"
1646         else
1647             echo "Please use the script \"grml-x\" for starting the X Window System
1648 because there does not exist /etc/X11/xorg.conf yet.
1649 If you want to use startx anyway please call \"/usr/bin/startx\"."
1650             return -1
1651         fi
1652     }
1653
1654     xinit() {
1655         if [[ -e /etc/X11/xorg.conf ]] ; then
1656             [[ -x /usr/bin/xinit ]] && /usr/bin/xinit || /usr/X11R6/bin/xinit
1657         else
1658             echo "Please use the script \"grml-x\" for starting the X Window System.
1659 because there does not exist /etc/X11/xorg.conf yet.
1660 If you want to use xinit anyway please call \"/usr/bin/xinit\"."
1661             return -1
1662         fi
1663     }
1664
1665     if check_com -c 915resolution ; then
1666         alias 855resolution='echo -e "Please use 915resolution as resolution modify tool for Intel graphic chipset."; return -1'
1667     fi
1668
1669     #a1# Output version of running grml
1670     alias grml-version='cat /etc/grml_version'
1671
1672     if check_com -c rebuildfstab ; then
1673         #a1# Rebuild /etc/fstab
1674         alias grml-rebuildfstab='rebuildfstab -v -r -config'
1675     fi
1676
1677     if check_com -c grml-debootstrap ; then
1678         alias debian2hd='print "Installing debian to harddisk is possible via using grml-debootstrap." ; return 1'
1679     fi
1680 }
1681 # }}}
1682
1683 # {{{ now run the functions
1684 isgrml && checkhome
1685 is4    && isgrml    && grmlstuff
1686 is4    && grmlcomp
1687 # }}}
1688
1689 # {{{ keephack
1690 is4 && xsource "/etc/zsh/keephack"
1691 # }}}
1692
1693 # {{{ wonderful idea of using "e" glob qualifier by Peter Stephenson
1694 # You use it as follows:
1695 # $ NTREF=/reference/file
1696 # $ ls -l *(e:nt:)
1697 # This lists all the files in the current directory newer than the reference file.
1698 # You can also specify the reference file inline; note quotes:
1699 # $ ls -l *(e:'nt ~/.zshenv':)
1700 is4 && nt() {
1701     if [[ -n $1 ]] ; then
1702         local NTREF=${~1}
1703     fi
1704     [[ $REPLY -nt $NTREF ]]
1705 }
1706 # }}}
1707
1708 # shell functions {{{
1709
1710 #f1# Provide csh compatibility
1711 setenv()  { typeset -x "${1}${1:+=}${(@)argv[2,$#]}" }  # csh compatibility
1712
1713 #f1# Reload an autoloadable function
1714 freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
1715
1716 #f1# Reload zsh setup
1717 reload() {
1718     if [[ "$#*" -eq 0 ]] ; then
1719         [[ -r ~/.zshrc ]] && . ~/.zshrc
1720     else
1721         local fn
1722         for fn in "$@"; do
1723             unfunction $fn
1724             autoload -U $fn
1725         done
1726     fi
1727 }
1728 compdef _functions reload freload
1729
1730 #f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
1731 sll() {
1732     [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
1733     for i in "$@" ; do
1734         file=$i
1735         while [[ -h "$file" ]] ; do
1736             ls -l $file
1737             file=$(readlink "$file")
1738         done
1739     done
1740 }
1741
1742 # fast manual access
1743 if check_com qma ; then
1744     #f1# View the zsh manual
1745     manzsh()  { qma zshall "$1" }
1746     compdef _man qma
1747 else
1748     manzsh()  { /usr/bin/man zshall |  vim -c "se ft=man| se hlsearch" +/"$1" - ; }
1749     # manzsh()  { /usr/bin/man zshall |  most +/"$1" ; }
1750     # [[ -f ~/.terminfo/m/mostlike ]] && MYLESS='LESS=C TERMINFO=~/.terminfo TERM=mostlike less' || MYLESS='less'
1751     # manzsh()  { man zshall | $MYLESS -p $1 ; }
1752 fi
1753
1754 if check_com -c $PAGER ; then
1755     #f1# View Debian's changelog of a given package
1756     dchange() {
1757         if [[ -r /usr/share/doc/${1}/changelog.Debian.gz ]] ; then
1758             $PAGER /usr/share/doc/${1}/changelog.Debian.gz
1759         elif [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
1760             $PAGER /usr/share/doc/${1}/changelog.gz
1761         else
1762             if check_com -c aptitude ; then
1763                 echo "No changelog for package $1 found, using aptitude to retrieve it."
1764                 if isgrml ; then
1765                     aptitude -t unstable changelog ${1}
1766                 else
1767                     aptitude changelog ${1}
1768                 fi
1769             else
1770                 echo "No changelog for package $1 found, sorry."
1771                 return 1
1772             fi
1773         fi
1774     }
1775     _dchange() { _files -W /usr/share/doc -/ }
1776     compdef _dchange dchange
1777
1778     #f1# View Debian's NEWS of a given package
1779     dnews() {
1780         if [[ -r /usr/share/doc/${1}/NEWS.Debian.gz ]] ; then
1781             $PAGER /usr/share/doc/${1}/NEWS.Debian.gz
1782         else
1783             if [[ -r /usr/share/doc/${1}/NEWS.gz ]] ; then
1784                 $PAGER /usr/share/doc/${1}/NEWS.gz
1785             else
1786                 echo "No NEWS file for package $1 found, sorry."
1787                 return 1
1788             fi
1789         fi
1790     }
1791     _dnews() { _files -W /usr/share/doc -/ }
1792     compdef _dnews dnews
1793
1794     #f1# View upstream's changelog of a given package
1795     uchange() {
1796         if [[ -r /usr/share/doc/${1}/changelog.gz ]] ; then
1797             $PAGER /usr/share/doc/${1}/changelog.gz
1798         else
1799             echo "No changelog for package $1 found, sorry."
1800             return 1
1801         fi
1802     }
1803     _uchange() { _files -W /usr/share/doc -/ }
1804     compdef _uchange uchange
1805 fi
1806
1807 # zsh profiling
1808 profile() {
1809     ZSH_PROFILE_RC=1 $SHELL "$@"
1810 }
1811
1812 #f1# Edit an alias via zle
1813 edalias() {
1814     [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
1815 }
1816 compdef _aliases edalias
1817
1818 #f1# Edit a function via zle
1819 edfunc() {
1820     [[ -z "$1" ]] && { echo "Usage: edfun <function_to_edit>" ; return 1 } || zed -f "$1" ;
1821 }
1822 compdef _functions edfunc
1823
1824 # use it e.g. via 'Restart apache2'
1825 #m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
1826 #m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
1827 #m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
1828 #m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
1829 #m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
1830 if [[ -d /etc/init.d ]] ; then
1831     for i in Start Restart Stop Force-Reload Reload ; do
1832         eval "$i() { $SUDO /etc/init.d/\$1 ${i:l} \$2 ; }"
1833     done
1834 fi
1835
1836 #f1# Provides useful information on globbing
1837 H-Glob() {
1838     echo -e "
1839     /      directories
1840     .      plain files
1841     @      symbolic links
1842     =      sockets
1843     p      named pipes (FIFOs)
1844     *      executable plain files (0100)
1845     %      device files (character or block special)
1846     %b     block special files
1847     %c     character special files
1848     r      owner-readable files (0400)
1849     w      owner-writable files (0200)
1850     x      owner-executable files (0100)
1851     A      group-readable files (0040)
1852     I      group-writable files (0020)
1853     E      group-executable files (0010)
1854     R      world-readable files (0004)
1855     W      world-writable files (0002)
1856     X      world-executable files (0001)
1857     s      setuid files (04000)
1858     S      setgid files (02000)
1859     t      files with the sticky bit (01000)
1860
1861   print *(m-1)          # Files modified up to a day ago
1862   print *(a1)           # Files accessed a day ago
1863   print *(@)            # Just symlinks
1864   print *(Lk+50)        # Files bigger than 50 kilobytes
1865   print *(Lk-50)        # Files smaller than 50 kilobytes
1866   print **/*.c          # All *.c files recursively starting in \$PWD
1867   print **/*.c~file.c   # Same as above, but excluding 'file.c'
1868   print (foo|bar).*     # Files starting with 'foo' or 'bar'
1869   print *~*.*           # All Files that do not contain a dot
1870   chmod 644 *(.^x)      # make all plain non-executable files publically readable
1871   print -l *(.c|.h)     # Lists *.c and *.h
1872   print **/*(g:users:)  # Recursively match all files that are owned by group 'users'
1873   echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
1874 }
1875 alias help-zshglob=H-Glob
1876
1877 check_com -c qma && alias ?='qma zshall'
1878
1879 # grep for running process, like: 'any vim'
1880 any() {
1881     if [[ -z "$1" ]] ; then
1882         echo "any - grep for process(es) by keyword" >&2
1883         echo "Usage: any <keyword>" >&2 ; return 1
1884     else
1885         local STRING=$1
1886         local LENGTH=$(expr length $STRING)
1887         local FIRSCHAR=$(echo $(expr substr $STRING 1 1))
1888         local REST=$(echo $(expr substr $STRING 2 $LENGTH))
1889         ps xauwww| grep "[$FIRSCHAR]$REST"
1890     fi
1891 }
1892
1893 # After resuming from suspend, system is paging heavily, leading to very bad interactivity.
1894 # taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
1895 [[ -r /proc/1/maps ]] && \
1896 deswap() {
1897     print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
1898     cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/')  > /dev/null
1899     print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
1900 }
1901
1902 # print hex value of a number
1903 hex() {
1904     [[ -n "$1" ]] && printf "%x\n" $1 || { print 'Usage: hex <number-to-convert>' ; return 1 }
1905 }
1906
1907 # calculate (or eval at all ;-)) with perl => p[erl-]eval
1908 # hint: also take a look at zcalc -> 'autoload zcalc' -> 'man zshmodules | less -p MATHFUNC'
1909 peval() {
1910     [[ -n "$1" ]] && CALC="$*" || print "Usage: calc [expression]"
1911     perl -e "print eval($CALC),\"\n\";"
1912 }
1913 functions peval &>/dev/null && alias calc=peval
1914
1915 # brltty seems to have problems with utf8 environment and/or font Uni3-Terminus16 under
1916 # certain circumstances, so work around it, no matter which environment we have
1917 brltty() {
1918     if [[ -z "$DISPLAY" ]] ; then
1919         consolechars -f /usr/share/consolefonts/default8x16.psf.gz
1920         command brltty "$@"
1921     else
1922         command brltty "$@"
1923     fi
1924 }
1925
1926 # just press 'asdf' keys to toggle between dvorak and us keyboard layout
1927 aoeu() {
1928     echo -n 'Switching to us keyboard layout: '
1929     [[ -z "$DISPLAY" ]] && $SUDO loadkeys us &>/dev/null || setxkbmap us &>/dev/null
1930     echo 'Done'
1931 }
1932 asdf() {
1933     echo -n 'Switching to dvorak keyboard layout: '
1934     [[ -z "$DISPLAY" ]] && $SUDO loadkeys dvorak &>/dev/null || setxkbmap dvorak &>/dev/null
1935     echo 'Done'
1936 }
1937 # just press 'asdf' key to toggle from neon layout to us keyboard layout
1938 uiae() {
1939     echo -n 'Switching to us keyboard layout: '
1940     setxkbmap us && echo 'Done' || echo 'Failed'
1941 }
1942
1943 # set up an ipv6 tunnel
1944 ipv6-tunnel() {
1945     case $1 in
1946         start)
1947             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
1948                 print 'ipv6 tunnel already set up, nothing to be done.'
1949                 print 'execute: "ifconfig sit1 down ; ifconfig sit0 down" to remove ipv6-tunnel.' ; return 1
1950             else
1951                 [[ -n "$PUBLIC_IP" ]] || \
1952                     local PUBLIC_IP=$(ifconfig $(route -n | awk '/^0\.0\.0\.0/{print $8; exit}') | \
1953                                       awk '/inet addr:/ {print $2}' | tr -d 'addr:')
1954
1955                 [[ -n "$PUBLIC_IP" ]] || { print 'No $PUBLIC_IP set and could not determine default one.' ; return 1 }
1956                 local IPV6ADDR=$(printf "2002:%02x%02x:%02x%02x:1::1" $(print ${PUBLIC_IP//./ }))
1957                 print -n "Setting up ipv6 tunnel $IPV6ADDR via ${PUBLIC_IP}: "
1958                 ifconfig sit0 tunnel ::192.88.99.1 up
1959                 ifconfig sit1 add "$IPV6ADDR" && print done || print failed
1960             fi
1961             ;;
1962         status)
1963             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
1964                 print 'ipv6 tunnel available' ; return 0
1965             else
1966                 print 'ipv6 tunnel not available' ; return 1
1967             fi
1968             ;;
1969         stop)
1970             if ifconfig sit1 2>/dev/null | grep -q 'inet6 addr: 2002:.*:1::1' ; then
1971                 print -n 'Stopping ipv6 tunnel (sit0 + sit1): '
1972                 ifconfig sit1 down ; ifconfig sit0 down && print done || print failed
1973             else
1974                 print 'No ipv6 tunnel found, nothing to be done.' ; return 1
1975             fi
1976             ;;
1977         *)
1978             print "Usage: ipv6-tunnel [start|stop|status]">&2 ; return 1
1979             ;;
1980     esac
1981 }
1982
1983 # run dhclient for wireless device
1984 iwclient() {
1985     salias dhclient "$(wavemon -d | awk '/device/{print $2}')"
1986 }
1987
1988 # spawn a minimally set up ksh - useful if you want to umount /usr/.
1989 minimal-shell() {
1990     exec env -i ENV="/etc/minimal-shellrc" HOME="$HOME" TERM="$TERM" ksh
1991 }
1992
1993 # make a backup of a file
1994 bk() {
1995     cp -a "$1" "${1}_$(date --iso-8601=seconds)"
1996 }
1997
1998 # Switching shell safely and efficiently? http://www.zsh.org/mla/workers/2001/msg02410.html
1999 # bash() {
2000 #  NO_SWITCH="yes" command bash "$@"
2001 # }
2002 # restart () {
2003 #  exec $SHELL $SHELL_ARGS "$@"
2004 # }
2005
2006 # }}}
2007
2008 # log out? set timeout in seconds {{{
2009 # TMOUT=1800
2010 # do not log out in some specific terminals:
2011 #  if [[ "${TERM}" == ([Exa]term*|rxvt|dtterm|screen*) ]] ; then
2012 #    unset TMOUT
2013 #  fi
2014 # }}}
2015
2016 # {{{ make sure our environment is clean regarding colors
2017 for color in BLUE RED GREEN CYAN WHITE ; unset $color
2018 # }}}
2019
2020 # source another config file if present {{{
2021 xsource "/etc/zsh/zshrc.local"
2022 xsource "${HOME}/.zshenv"
2023 # }}}
2024
2025 # "persistent history" {{{
2026 # just write important commands you always need to ~/.important_commands
2027 if [[ -r ~/.important_commands ]] ; then
2028     fc -R ~/.important_commands
2029 fi
2030 # }}}
2031
2032 ## genrefcard.pl settings {{{
2033 ### example: split functions-search 8,16,24,32
2034 #@# split functions-search 8
2035 ## }}}
2036
2037 # add variable to be able to check whether the file has been read {{{
2038 ZSHRC_GLOBAL_HAS_BEEN_READ=1
2039 # }}}
2040
2041 ## END OF FILE #################################################################
2042 # vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4