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