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