Naposledy aktivní 1765272910

Modified .zshrc files based on Grml's defaults

Revize 454f6e1966351ddeca4d577ba9ad0538d4f06934

.zshrc Raw
1# Filename: /etc/zsh/zshrc
2# Purpose: config file for zsh (z shell)
3# Authors: grml-team (grml.org), (c) Michael Prokop <[email protected]>
4# Bug-Reports: see http://grml.org/bugs/
5# License: This file is licensed under the GPL v2.
6################################################################################
7# This file is sourced only for interactive shells. It
8# should contain commands to set up aliases, functions,
9# options, key bindings, etc.
10#
11# Global Order: zshenv, zprofile, zshrc, zlogin
12################################################################################
13
14# USAGE
15# If you are using this file as your ~/.zshrc file, please use ~/.zshrc.pre
16# and ~/.zshrc.local for your own customisations. The former file is read
17# before ~/.zshrc, the latter is read after it. Also, consider reading the
18# refcard and the reference manual for this setup, both available from:
19# <http://grml.org/zsh/>
20
21# Contributing:
22# If you want to help to improve grml's zsh setup, clone the grml-etc-core
23# repository from git.grml.org:
24# git clone git://git.grml.org/grml-etc-core.git
25#
26# Make your changes, commit them; use 'git format-patch' to create a series
27# of patches and send those to the following address via 'git send-email':
28# [email protected]
29#
30# Doing so makes sure the right people get your patches for review and
31# possibly inclusion.
32
33# zsh-refcard-tag documentation:
34# You may notice strange looking comments in this file.
35# These are there for a purpose. grml's zsh-refcard can now be
36# automatically generated from the contents of the actual configuration
37# file. However, we need a little extra information on which comments
38# and what lines of code to take into account (and for what purpose).
39#
40# Here is what they mean:
41#
42# List of tags (comment types) used:
43# #a# Next line contains an important alias, that should
44# be included in the grml-zsh-refcard.
45# (placement tag: @@INSERT-aliases@@)
46# #f# Next line contains the beginning of an important function.
47# (placement tag: @@INSERT-functions@@)
48# #v# Next line contains an important variable.
49# (placement tag: @@INSERT-variables@@)
50# #k# Next line contains an important keybinding.
51# (placement tag: @@INSERT-keybindings@@)
52# #d# Hashed directories list generation:
53# start denotes the start of a list of 'hash -d'
54# definitions.
55# end denotes its end.
56# (placement tag: @@INSERT-hasheddirs@@)
57# #A# Abbreviation expansion list generation:
58# start denotes the beginning of abbreviations.
59# end denotes their end.
60# Lines within this section that end in '#d .*' provide
61# extra documentation to be included in the refcard.
62# (placement tag: @@INSERT-abbrev@@)
63# #m# This tag allows you to manually generate refcard entries
64# for code lines that are hard/impossible to parse.
65# Example:
66# #m# k ESC-h Call the run-help function
67# That would add a refcard entry in the keybindings table
68# for 'ESC-h' with the given comment.
69# So the syntax is: #m# <section> <argument> <comment>
70# #o# This tag lets you insert entries to the 'other' hash.
71# Generally, this should not be used. It is there for
72# things that cannot be done easily in another way.
73# (placement tag: @@INSERT-other-foobar@@)
74#
75# All of these tags (except for m and o) take two arguments, the first
76# within the tag, the other after the tag:
77#
78# #<tag><section># <comment>
79#
80# Where <section> is really just a number, which are defined by the
81# @secmap array on top of 'genrefcard.pl'. The reason for numbers
82# instead of names is, that for the reader, the tag should not differ
83# much from a regular comment. For zsh, it is a regular comment indeed.
84# The numbers have got the following meanings:
85# 0 -> "default"
86# 1 -> "system"
87# 2 -> "user"
88# 3 -> "debian"
89# 4 -> "search"
90# 5 -> "shortcuts"
91# 6 -> "services"
92#
93# So, the following will add an entry to the 'functions' table in the
94# 'system' section, with a (hopefully) descriptive comment:
95# #f1# Edit an alias via zle
96# edalias() {
97#
98# It will then show up in the @@INSERT-aliases-system@@ replacement tag
99# that can be found in 'grml-zsh-refcard.tex.in'.
100# If the section number is omitted, the 'default' section is assumed.
101# Furthermore, in 'grml-zsh-refcard.tex.in' @@INSERT-aliases@@ is
102# exactly the same as @@INSERT-aliases-default@@. If you want a list of
103# *all* aliases, for example, use @@INSERT-aliases-all@@.
104
105# zsh profiling
106# just execute 'ZSH_PROFILE_RC=1 zsh' and run 'zprof' to get the details
107if [[ $ZSH_PROFILE_RC -gt 0 ]] ; then
108 zmodload zsh/zprof
109fi
110
111typeset -A GRML_STATUS_FEATURES
112
113function grml_status_feature () {
114 emulate -L zsh
115 local f=$1
116 local -i success=$2
117 if (( success == 0 )); then
118 GRML_STATUS_FEATURES[$f]=success
119 else
120 GRML_STATUS_FEATURES[$f]=failure
121 fi
122 return 0
123}
124
125function grml_status_features () {
126 emulate -L zsh
127 local mode=${1:-+-}
128 local this
129 if [[ $mode == -h ]] || [[ $mode == --help ]]; then
130 cat <<EOF
131grml_status_features [-h|--help|-|+|+-|FEATURE]
132
133Prints a summary of features the grml setup is trying to load. The
134result of loading a feature is recorded. This function lets you query
135the result.
136
137The function takes one argument: "-h" or "--help" to display this help
138text, "+" to display a list of all successfully loaded features, "-" for
139a list of all features that failed to load. "+-" to show a list of all
140features with their statuses.
141
142Any other word is considered to by a feature and prints its status.
143
144The default mode is "+-".
145EOF
146 return 0
147 fi
148 if [[ $mode != - ]] && [[ $mode != + ]] && [[ $mode != +- ]]; then
149 this="${GRML_STATUS_FEATURES[$mode]}"
150 if [[ -z $this ]]; then
151 printf 'unknown\n'
152 return 1
153 else
154 printf '%s\n' $this
155 fi
156 return 0
157 fi
158 for key in ${(ok)GRML_STATUS_FEATURES}; do
159 this="${GRML_STATUS_FEATURES[$key]}"
160 if [[ $this == success ]] && [[ $mode == *+* ]]; then
161 printf '%-16s %s\n' $key $this
162 fi
163 if [[ $this == failure ]] && [[ $mode == *-* ]]; then
164 printf '%-16s %s\n' $key $this
165 fi
166 done
167 return 0
168}
169
170# load .zshrc.pre to give the user the chance to overwrite the defaults
171[[ -r ${ZDOTDIR:-${HOME}}/.zshrc.pre ]] && source ${ZDOTDIR:-${HOME}}/.zshrc.pre
172
173# check for version/system
174# check for versions (compatibility reasons)
175function is51 () {
176 [[ $ZSH_VERSION == 5.<1->* ]] && return 0
177 return 1
178}
179
180function is4 () {
181 [[ $ZSH_VERSION == <4->* ]] && return 0
182 return 1
183}
184
185function is41 () {
186 [[ $ZSH_VERSION == 4.<1->* || $ZSH_VERSION == <5->* ]] && return 0
187 return 1
188}
189
190function is42 () {
191 [[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
192 return 1
193}
194
195function is425 () {
196 [[ $ZSH_VERSION == 4.2.<5->* || $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
197 return 1
198}
199
200function is43 () {
201 [[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
202 return 1
203}
204
205function is433 () {
206 [[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == 4.<4->* \
207 || $ZSH_VERSION == <5->* ]] && return 0
208 return 1
209}
210
211function is437 () {
212 [[ $ZSH_VERSION == 4.3.<7->* || $ZSH_VERSION == 4.<4->* \
213 || $ZSH_VERSION == <5->* ]] && return 0
214 return 1
215}
216
217function is439 () {
218 [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* \
219 || $ZSH_VERSION == <5->* ]] && return 0
220 return 1
221}
222
223#f1# Checks whether or not you're running grml
224function isgrml () {
225 [[ -f /etc/grml_version ]] && return 0
226 return 1
227}
228
229#f1# Checks whether or not you're running a grml cd
230function isgrmlcd () {
231 [[ -f /etc/grml_cd ]] && return 0
232 return 1
233}
234
235if isgrml ; then
236#f1# Checks whether or not you're running grml-small
237 function isgrmlsmall () {
238 if [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]]; then
239 return 0
240 fi
241 return 1
242 }
243else
244 function isgrmlsmall () { return 1 }
245fi
246
247GRML_OSTYPE=$(uname -s)
248
249function islinux () {
250 [[ $GRML_OSTYPE == "Linux" ]]
251}
252
253function isdarwin () {
254 [[ $GRML_OSTYPE == "Darwin" ]]
255}
256
257function isfreebsd () {
258 [[ $GRML_OSTYPE == "FreeBSD" ]]
259}
260
261function isopenbsd () {
262 [[ $GRML_OSTYPE == "OpenBSD" ]]
263}
264
265function issolaris () {
266 [[ $GRML_OSTYPE == "SunOS" ]]
267}
268
269#f1# are we running within an utf environment?
270function isutfenv () {
271 case "$LANG $CHARSET $LANGUAGE" in
272 *utf*) return 0 ;;
273 *UTF*) return 0 ;;
274 *) return 1 ;;
275 esac
276}
277
278# check for user, if not running as root set $SUDO to sudo
279(( EUID != 0 )) && SUDO='sudo' || SUDO=''
280
281# change directory to home on first invocation of zsh
282# important for rungetty -> autologin
283# Thanks go to Bart Schaefer!
284isgrml && function checkhome () {
285 if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
286 export ALREADY_DID_CD_HOME=$HOME
287 cd
288 fi
289}
290
291# check for zsh v3.1.7+
292
293if ! [[ ${ZSH_VERSION} == 3.1.<7->* \
294 || ${ZSH_VERSION} == 3.<2->.<->* \
295 || ${ZSH_VERSION} == <4->.<->* ]] ; then
296
297 printf '-!-\n'
298 printf '-!- In this configuration we try to make use of features, that only\n'
299 printf '-!- require version 3.1.7 of the shell; That way this setup can be\n'
300 printf '-!- used with a wide range of zsh versions, while using fairly\n'
301 printf '-!- advanced features in all supported versions.\n'
302 printf '-!-\n'
303 printf '-!- However, you are running zsh version %s.\n' "$ZSH_VERSION"
304 printf '-!-\n'
305 printf '-!- While this *may* work, it might as well fail.\n'
306 printf '-!- Please consider updating to at least version 3.1.7 of zsh.\n'
307 printf '-!-\n'
308 printf '-!- DO NOT EXPECT THIS TO WORK FLAWLESSLY!\n'
309 printf '-!- If it does today, you'\''ve been lucky.\n'
310 printf '-!-\n'
311 printf '-!- Ye been warned!\n'
312 printf '-!-\n'
313
314 function zstyle () { : }
315fi
316
317# autoload wrapper - use this one instead of autoload directly
318# We need to define this function as early as this, because autoloading
319# 'is-at-least()' needs it.
320function zrcautoload () {
321 emulate -L zsh
322 setopt extended_glob
323 local fdir ffile
324 local -i ffound
325
326 ffile=$1
327 (( ffound = 0 ))
328 for fdir in ${fpath} ; do
329 [[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
330 done
331
332 (( ffound == 0 )) && return 1
333 if [[ $ZSH_VERSION == 3.1.<6-> || $ZSH_VERSION == <4->* ]] ; then
334 autoload -U ${ffile} || return 1
335 else
336 autoload ${ffile} || return 1
337 fi
338 return 0
339}
340
341# The following is the ‘add-zsh-hook’ function from zsh upstream. It is
342# included here to make the setup work with older versions of zsh (prior to
343# 4.3.7) in which this function had a bug that triggers annoying errors during
344# shell startup. This is exactly upstreams code from f0068edb4888a4d8fe94def,
345# with just a few adjustments in coding style to make the function look more
346# compact. This definition can be removed as soon as we raise the minimum
347# version requirement to 4.3.7 or newer.
348function add-zsh-hook () {
349 # Add to HOOK the given FUNCTION.
350 # HOOK is one of chpwd, precmd, preexec, periodic, zshaddhistory,
351 # zshexit, zsh_directory_name (the _functions subscript is not required).
352 #
353 # With -d, remove the function from the hook instead; delete the hook
354 # variable if it is empty.
355 #
356 # -D behaves like -d, but pattern characters are active in the function
357 # name, so any matching function will be deleted from the hook.
358 #
359 # Without -d, the FUNCTION is marked for autoload; -U is passed down to
360 # autoload if that is given, as are -z and -k. (This is harmless if the
361 # function is actually defined inline.)
362 emulate -L zsh
363 local -a hooktypes
364 hooktypes=(
365 chpwd precmd preexec periodic zshaddhistory zshexit
366 zsh_directory_name
367 )
368 local usage="Usage: $0 hook function\nValid hooks are:\n $hooktypes"
369 local opt
370 local -a autoopts
371 integer del list help
372 while getopts "dDhLUzk" opt; do
373 case $opt in
374 (d) del=1 ;;
375 (D) del=2 ;;
376 (h) help=1 ;;
377 (L) list=1 ;;
378 ([Uzk]) autoopts+=(-$opt) ;;
379 (*) return 1 ;;
380 esac
381 done
382 shift $(( OPTIND - 1 ))
383 if (( list )); then
384 typeset -mp "(${1:-${(@j:|:)hooktypes}})_functions"
385 return $?
386 elif (( help || $# != 2 || ${hooktypes[(I)$1]} == 0 )); then
387 print -u$(( 2 - help )) $usage
388 return $(( 1 - help ))
389 fi
390 local hook="${1}_functions"
391 local fn="$2"
392 if (( del )); then
393 # delete, if hook is set
394 if (( ${(P)+hook} )); then
395 if (( del == 2 )); then
396 set -A $hook ${(P)hook:#${~fn}}
397 else
398 set -A $hook ${(P)hook:#$fn}
399 fi
400 # unset if no remaining entries --- this can give better
401 # performance in some cases
402 if (( ! ${(P)#hook} )); then
403 unset $hook
404 fi
405 fi
406 else
407 if (( ${(P)+hook} )); then
408 if (( ${${(P)hook}[(I)$fn]} == 0 )); then
409 set -A $hook ${(P)hook} $fn
410 fi
411 else
412 set -A $hook $fn
413 fi
414 autoload $autoopts -- $fn
415 fi
416}
417
418# Load is-at-least() for more precise version checks Note that this test will
419# *always* fail, if the is-at-least function could not be marked for
420# autoloading.
421zrcautoload is-at-least || function is-at-least () { return 1 }
422
423# set some important options (as early as possible)
424
425# append history list to the history file; this is the default but we make sure
426# because it's required for share_history.
427setopt append_history
428
429# import new commands from the history file also in other zsh-session
430is4 && setopt share_history
431
432# save each command's beginning timestamp and the duration to the history file
433setopt extended_history
434
435# remove command lines from the history list when the first character on the
436# line is a space
437setopt histignorespace
438
439# if a command is issued that can't be executed as a normal command, and the
440# command is the name of a directory, perform the cd command to that directory.
441setopt auto_cd
442
443# in order to use #, ~ and ^ for filename generation grep word
444# *~(*.gz|*.bz|*.bz2|*.zip|*.Z) -> searches for word not in compressed files
445# don't forget to quote '^', '~' and '#'!
446setopt extended_glob
447
448# display PID when suspending processes as well
449setopt longlistjobs
450
451# report the status of backgrounds jobs immediately
452setopt notify
453
454# whenever a command completion is attempted, make sure the entire command path
455# is hashed first.
456setopt hash_list_all
457
458# not just at the end
459setopt completeinword
460
461# Don't send SIGHUP to background processes when the shell exits.
462setopt nohup
463
464# make cd push the old directory onto the directory stack.
465setopt auto_pushd
466
467# avoid "beep"ing
468setopt nobeep
469
470# don't push the same dir twice.
471setopt pushd_ignore_dups
472
473# * shouldn't match dotfiles. ever.
474setopt noglobdots
475
476# use zsh style word splitting
477setopt noshwordsplit
478
479# don't error out when unset parameters are used
480setopt unset
481
482# setting some default values
483NOCOR=${NOCOR:-0}
484NOETCHOSTS=${NOETCHOSTS:-0}
485NOMENU=${NOMENU:-0}
486NOPRECMD=${NOPRECMD:-0}
487COMMAND_NOT_FOUND=${COMMAND_NOT_FOUND:-0}
488GRML_ZSH_CNF_HANDLER=${GRML_ZSH_CNF_HANDLER:-/usr/share/command-not-found/command-not-found}
489GRML_DISPLAY_BATTERY=${GRML_DISPLAY_BATTERY:-${BATTERY:-0}}
490GRMLSMALL_SPECIFIC=${GRMLSMALL_SPECIFIC:-1}
491ZSH_NO_DEFAULT_LOCALE=${ZSH_NO_DEFAULT_LOCALE:-0}
492
493typeset -ga ls_options
494typeset -ga grep_options
495
496# Colors on GNU ls(1)
497if ls --color=auto / >/dev/null 2>&1; then
498 ls_options+=( --color=auto )
499# Colors on FreeBSD and OSX ls(1)
500elif ls -G / >/dev/null 2>&1; then
501 ls_options+=( -G )
502fi
503
504# Natural sorting order on GNU ls(1)
505# OSX and IllumOS have a -v option that is not natural sorting
506if ls --version |& grep -q 'GNU' >/dev/null 2>&1 && ls -v / >/dev/null 2>&1; then
507 ls_options+=( -v )
508fi
509
510# Color on GNU and FreeBSD grep(1)
511if grep --color=auto -q "a" <<< "a" >/dev/null 2>&1; then
512 grep_options+=( --color=auto )
513fi
514
515# utility functions
516# this function checks if a command exists and returns either true
517# or false. This avoids using 'which' and 'whence', which will
518# avoid problems with aliases for which on certain weird systems. :-)
519# Usage: check_com [-c|-g] word
520# -c only checks for external commands
521# -g does the usual tests and also checks for global aliases
522function check_com () {
523 emulate -L zsh
524 local -i comonly gatoo
525 comonly=0
526 gatoo=0
527
528 if [[ $1 == '-c' ]] ; then
529 comonly=1
530 shift 1
531 elif [[ $1 == '-g' ]] ; then
532 gatoo=1
533 shift 1
534 fi
535
536 if (( ${#argv} != 1 )) ; then
537 printf 'usage: check_com [-c|-g] <command>\n' >&2
538 return 1
539 fi
540
541 if (( comonly > 0 )) ; then
542 (( ${+commands[$1]} )) && return 0
543 return 1
544 fi
545
546 if (( ${+commands[$1]} )) \
547 || (( ${+functions[$1]} )) \
548 || (( ${+aliases[$1]} )) \
549 || (( ${+reswords[(r)$1]} )) ; then
550 return 0
551 fi
552
553 if (( gatoo > 0 )) && (( ${+galiases[$1]} )) ; then
554 return 0
555 fi
556
557 return 1
558}
559
560# creates an alias and precedes the command with
561# sudo if $EUID is not zero.
562function salias () {
563 emulate -L zsh
564 local only=0 ; local multi=0
565 local key val
566 while getopts ":hao" opt; do
567 case $opt in
568 o) only=1 ;;
569 a) multi=1 ;;
570 h)
571 printf 'usage: salias [-hoa] <alias-expression>\n'
572 printf ' -h shows this help text.\n'
573 printf ' -a replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
574 printf ' be careful using this option.\n'
575 printf ' -o only sets an alias if a preceding sudo would be needed.\n'
576 return 0
577 ;;
578 *) salias -h >&2; return 1 ;;
579 esac
580 done
581 shift "$((OPTIND-1))"
582
583 if (( ${#argv} > 1 )) ; then
584 printf 'Too many arguments %s\n' "${#argv}"
585 return 1
586 fi
587
588 key="${1%%\=*}" ; val="${1#*\=}"
589 if (( EUID == 0 )) && (( only == 0 )); then
590 alias -- "${key}=${val}"
591 elif (( EUID > 0 )) ; then
592 (( multi > 0 )) && val="${val// ; / ; sudo }"
593 alias -- "${key}=sudo ${val}"
594 fi
595
596 return 0
597}
598
599# Check if we can read given files and source those we can.
600function xsource () {
601 if (( ${#argv} < 1 )) ; then
602 printf 'usage: xsource FILE(s)...\n' >&2
603 return 1
604 fi
605
606 while (( ${#argv} > 0 )) ; do
607 [[ -r "$1" ]] && source "$1"
608 shift
609 done
610 return 0
611}
612
613# Check if we can read a given file and 'cat(1)' it.
614function xcat () {
615 emulate -L zsh
616 if (( ${#argv} != 1 )) ; then
617 printf 'usage: xcat FILE\n' >&2
618 return 1
619 fi
620
621 [[ -r $1 ]] && cat $1
622 return 0
623}
624
625# Remove these functions again, they are of use only in these
626# setup files. This should be called at the end of .zshrc.
627function xunfunction () {
628 emulate -L zsh
629 local -a funcs
630 local func
631 funcs=(salias xcat xsource xunfunction zrcautoload zrcautozle)
632 for func in $funcs ; do
633 [[ -n ${functions[$func]} ]] \
634 && unfunction $func
635 done
636 return 0
637}
638
639# this allows us to stay in sync with grml's zshrc and put own
640# modifications in ~/.zshrc.local
641function zrclocal () {
642 xsource "/etc/zsh/zshrc.local"
643 xsource "${ZDOTDIR:-${HOME}}/.zshrc.local"
644 return 0
645}
646
647# locale setup
648if (( ZSH_NO_DEFAULT_LOCALE == 0 )); then
649 xsource "/etc/default/locale"
650fi
651
652for var in LANG LC_ALL LC_MESSAGES ; do
653 [[ -n ${(P)var} ]] && export $var
654done
655builtin unset -v var
656
657# set some variables
658if check_com -c vim ; then
659#v#
660 export EDITOR=${EDITOR:-vim}
661else
662 export EDITOR=${EDITOR:-vi}
663fi
664
665#v#
666export PAGER=${PAGER:-less}
667
668#v#
669export MAIL=${MAIL:-/var/mail/$USER}
670
671# color setup for ls:
672check_com -c dircolors && eval $(dircolors -b)
673# color setup for ls on OS X / FreeBSD:
674isdarwin && export CLICOLOR=1
675isfreebsd && export CLICOLOR=1
676
677# do MacPorts setup on darwin
678if isdarwin && [[ -d /opt/local ]]; then
679 # Note: PATH gets set in /etc/zprofile on Darwin, so this can't go into
680 # zshenv.
681 PATH="/opt/local/bin:/opt/local/sbin:$PATH"
682 MANPATH="/opt/local/share/man:$MANPATH"
683fi
684# do Fink setup on darwin
685isdarwin && xsource /sw/bin/init.sh
686
687# load our function and completion directories
688for fdir in /usr/share/grml/zsh/completion /usr/share/grml/zsh/functions; do
689 fpath=( ${fdir} ${fdir}/**/*(/N) ${fpath} )
690done
691typeset -aU ffiles
692ffiles=(/usr/share/grml/zsh/functions/**/[^_]*[^~](N.:t))
693(( ${#ffiles} > 0 )) && autoload -U "${ffiles[@]}"
694unset -v fdir ffiles
695
696# support colors in less
697export LESS_TERMCAP_mb=$'\E[01;31m'
698export LESS_TERMCAP_md=$'\E[01;31m'
699export LESS_TERMCAP_me=$'\E[0m'
700export LESS_TERMCAP_se=$'\E[0m'
701export LESS_TERMCAP_so=$'\E[01;44;33m'
702export LESS_TERMCAP_ue=$'\E[0m'
703export LESS_TERMCAP_us=$'\E[01;32m'
704
705# mailchecks
706MAILCHECK=30
707
708# report about cpu-/system-/user-time of command if running longer than
709# 5 seconds
710REPORTTIME=5
711
712# watch for everyone but me and root
713watch=(notme root)
714
715# automatically remove duplicates from these arrays
716typeset -U path PATH cdpath CDPATH fpath FPATH manpath MANPATH
717
718# Load a few modules
719is4 && \
720for mod in parameter complist deltochar mathfunc ; do
721 zmodload -i zsh/${mod} 2>/dev/null
722 grml_status_feature mod:$mod $?
723done && builtin unset -v mod
724
725# autoload zsh modules when they are referenced
726if is4 ; then
727 zmodload -a zsh/stat zstat
728 zmodload -a zsh/zpty zpty
729 zmodload -ap zsh/mapfile mapfile
730fi
731
732# completion system
733COMPDUMPFILE=${COMPDUMPFILE:-${ZDOTDIR:-${HOME}}/.zcompdump}
734if zrcautoload compinit ; then
735 typeset -a tmp
736 zstyle -a ':grml:completion:compinit' arguments tmp
737 compinit -d ${COMPDUMPFILE} "${tmp[@]}"
738 grml_status_feature compinit $?
739 unset tmp
740else
741 grml_status_feature compinit 1
742 function compdef { }
743fi
744
745# completion system
746
747# called later (via is4 && grmlcomp)
748# note: use 'zstyle' for getting current settings
749# press ^xh (control-x h) for getting tags in context; ^x? (control-x ?) to run complete_debug with trace output
750function grmlcomp () {
751 # TODO: This could use some additional information
752
753 # Make sure the completion system is initialised
754 (( ${+_comps} )) || return 1
755
756 # allow one error for every three characters typed in approximate completer
757 zstyle ':completion:*:approximate:' max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'
758
759 # don't complete backup files as executables
760 zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'
761
762 # start menu completion only if it could find no unambiguous initial string
763 zstyle ':completion:*:correct:*' insert-unambiguous true
764 zstyle ':completion:*:corrections' format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
765 zstyle ':completion:*:correct:*' original true
766
767 # activate color-completion
768 zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
769
770 # format on completion
771 zstyle ':completion:*:descriptions' format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'
772
773 # automatically complete 'cd -<tab>' and 'cd -<ctrl-d>' with menu
774 # zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
775
776 # insert all expansions for expand completer
777 zstyle ':completion:*:expand:*' tag-order all-expansions
778 zstyle ':completion:*:history-words' list false
779
780 # activate menu
781 zstyle ':completion:*:history-words' menu yes
782
783 # ignore duplicate entries
784 zstyle ':completion:*:history-words' remove-all-dups yes
785 zstyle ':completion:*:history-words' stop yes
786
787 # match uppercase from lowercase
788 zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
789
790 # separate matches into groups
791 zstyle ':completion:*:matches' group 'yes'
792 zstyle ':completion:*' group-name ''
793
794 if [[ "$NOMENU" -eq 0 ]] ; then
795 # if there are more than 5 options allow selecting from a menu
796 zstyle ':completion:*' menu select=5
797 else
798 # don't use any menus at all
799 setopt no_auto_menu
800 fi
801
802 zstyle ':completion:*:messages' format '%d'
803 zstyle ':completion:*:options' auto-description '%d'
804
805 # describe options in full
806 zstyle ':completion:*:options' description 'yes'
807
808 # on processes completion complete all user processes
809 zstyle ':completion:*:processes' command 'ps -au$USER'
810
811 # offer indexes before parameters in subscripts
812 zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
813
814 # provide verbose completion information
815 zstyle ':completion:*' verbose true
816
817 # recent (as of Dec 2007) zsh versions are able to provide descriptions
818 # for commands (read: 1st word in the line) that it will list for the user
819 # to choose from. The following disables that, because it's not exactly fast.
820 zstyle ':completion:*:-command-:*:' verbose false
821
822 # set format for warnings
823 zstyle ':completion:*:warnings' format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'
824
825 # define files to ignore for zcompile
826 zstyle ':completion:*:*:zcompile:*' ignored-patterns '(*~|*.zwc)'
827 zstyle ':completion:correct:' prompt 'correct to: %e'
828
829 # Ignore completion functions for commands you don't have:
830 zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'
831
832 # Provide more processes in completion of programs like killall:
833 zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'
834
835 # complete manual by their section
836 zstyle ':completion:*:manuals' separate-sections true
837 zstyle ':completion:*:manuals.*' insert-sections true
838 zstyle ':completion:*:man:*' menu yes select
839
840 # Search path for sudo completion
841 zstyle ':completion:*:sudo:*' command-path /usr/local/sbin \
842 /usr/local/bin \
843 /usr/sbin \
844 /usr/bin \
845 /sbin \
846 /bin \
847 /usr/X11R6/bin
848
849 # provide .. as a completion
850 zstyle ':completion:*' special-dirs ..
851
852 # run rehash on completion so new installed program are found automatically:
853 function _force_rehash () {
854 (( CURRENT == 1 )) && rehash
855 return 1
856 }
857
858 ## correction
859 # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
860 if [[ "$NOCOR" -gt 0 ]] ; then
861 zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
862 setopt nocorrect
863 else
864 # try to be smart about when to use what completer...
865 setopt correct
866 zstyle -e ':completion:*' completer '
867 if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
868 _last_try="$HISTNO$BUFFER$CURSOR"
869 reply=(_complete _match _ignored _prefix _files)
870 else
871 if [[ $words[1] == (rm|mv) ]] ; then
872 reply=(_complete _files)
873 else
874 reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
875 fi
876 fi'
877 fi
878
879 # command for process lists, the local web server details and host completion
880 zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
881
882 # Some functions, like _apt and _dpkg, are very slow. We can use a cache in
883 # order to speed things up
884 if [[ ${GRML_COMP_CACHING:-yes} == yes ]]; then
885 GRML_COMP_CACHE_DIR=${GRML_COMP_CACHE_DIR:-${ZDOTDIR:-$HOME}/.cache}
886 if [[ ! -d ${GRML_COMP_CACHE_DIR} ]]; then
887 command mkdir -p "${GRML_COMP_CACHE_DIR}"
888 fi
889 zstyle ':completion:*' use-cache yes
890 zstyle ':completion:*:complete:*' cache-path "${GRML_COMP_CACHE_DIR}"
891 fi
892
893 # host completion
894 _etc_hosts=()
895 _ssh_config_hosts=()
896 _ssh_hosts=()
897 if is42 ; then
898 if [[ -r ~/.ssh/config ]] ; then
899 _ssh_config_hosts=(${${(s: :)${(ps:\t:)${${(@M)${(f)"$(<$HOME/.ssh/config)"}:#Host *}#Host }}}:#*[*?]*})
900 fi
901
902 if [[ -r ~/.ssh/known_hosts ]] ; then
903 _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*})
904 fi
905
906 if [[ -r /etc/hosts ]] && [[ "$NOETCHOSTS" -eq 0 ]] ; then
907 : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(grep -v '^0\.0\.0\.0\|^127\.0\.0\.1\|^::1 ' /etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}}
908 fi
909 fi
910
911 local localname
912 localname="$(uname -n)"
913 hosts=(
914 "${localname}"
915 "$_ssh_config_hosts[@]"
916 "$_ssh_hosts[@]"
917 "$_etc_hosts[@]"
918 localhost
919 )
920 zstyle ':completion:*:hosts' hosts $hosts
921 # TODO: so, why is this here?
922 # zstyle '*' hosts $hosts
923
924 # use generic completion system for programs not yet defined; (_gnu_generic works
925 # with commands that provide a --help option with "standard" gnu-like output.)
926 for compcom in cp deborphan df feh fetchipac gpasswd head hnb ipacsum mv \
927 pal stow uname ; do
928 [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
929 done; unset compcom
930
931 # see upgrade function in this file
932 compdef _hosts upgrade
933}
934
935# Keyboard setup: The following is based on the same code, we wrote for
936# debian's setup. It ensures the terminal is in the right mode, when zle is
937# active, so the values from $terminfo are valid. Therefore, this setup should
938# work on all systems, that have support for `terminfo'. It also requires the
939# zsh in use to have the `zsh/terminfo' module built.
940#
941# If you are customising your `zle-line-init()' or `zle-line-finish()'
942# functions, make sure you call the following utility functions in there:
943#
944# - zle-line-init(): zle-smkx
945# - zle-line-finish(): zle-rmkx
946
947# Use emacs-like key bindings by default:
948bindkey -e
949
950# Custom widgets:
951
952## beginning-of-line OR beginning-of-buffer OR beginning of history
953## by: Bart Schaefer <[email protected]>, Bernhard Tittelbach
954function beginning-or-end-of-somewhere () {
955 local hno=$HISTNO
956 if [[ ( "${LBUFFER[-1]}" == $'\n' && "${WIDGET}" == beginning-of* ) || \
957 ( "${RBUFFER[1]}" == $'\n' && "${WIDGET}" == end-of* ) ]]; then
958 zle .${WIDGET:s/somewhere/buffer-or-history/} "$@"
959 else
960 zle .${WIDGET:s/somewhere/line-hist/} "$@"
961 if (( HISTNO != hno )); then
962 zle .${WIDGET:s/somewhere/buffer-or-history/} "$@"
963 fi
964 fi
965}
966zle -N beginning-of-somewhere beginning-or-end-of-somewhere
967zle -N end-of-somewhere beginning-or-end-of-somewhere
968
969# add a command line to the shells history without executing it
970function commit-to-history () {
971 print -rs ${(z)BUFFER}
972 zle send-break
973}
974zle -N commit-to-history
975
976# only slash should be considered as a word separator:
977function slash-backward-kill-word () {
978 local WORDCHARS="${WORDCHARS:s@/@}"
979 # zle backward-word
980 zle backward-kill-word
981}
982zle -N slash-backward-kill-word
983
984# a generic accept-line wrapper
985
986# This widget can prevent unwanted autocorrections from command-name
987# to _command-name, rehash automatically on enter and call any number
988# of builtin and user-defined widgets in different contexts.
989#
990# For a broader description, see:
991# <http://bewatermyfriend.org/posts/2007/12-26.11-50-38-tooltime.html>
992#
993# The code is imported from the file 'zsh/functions/accept-line' from
994# <http://ft.bewatermyfriend.org/comp/zsh/zsh-dotfiles.tar.bz2>, which
995# distributed under the same terms as zsh itself.
996
997# A newly added command will may not be found or will cause false
998# correction attempts, if you got auto-correction set. By setting the
999# following style, we force accept-line() to rehash, if it cannot
1000# find the first word on the command line in the $command[] hash.
1001zstyle ':acceptline:*' rehash true
1002
1003function Accept-Line () {
1004 setopt localoptions noksharrays
1005 local -a subs
1006 local -xi aldone
1007 local sub
1008 local alcontext=${1:-$alcontext}
1009
1010 zstyle -a ":acceptline:${alcontext}" actions subs
1011
1012 (( ${#subs} < 1 )) && return 0
1013
1014 (( aldone = 0 ))
1015 for sub in ${subs} ; do
1016 [[ ${sub} == 'accept-line' ]] && sub='.accept-line'
1017 zle ${sub}
1018
1019 (( aldone > 0 )) && break
1020 done
1021}
1022
1023function Accept-Line-getdefault () {
1024 emulate -L zsh
1025 local default_action
1026
1027 zstyle -s ":acceptline:${alcontext}" default_action default_action
1028 case ${default_action} in
1029 ((accept-line|))
1030 printf ".accept-line"
1031 ;;
1032 (*)
1033 printf ${default_action}
1034 ;;
1035 esac
1036}
1037
1038function Accept-Line-HandleContext () {
1039 zle Accept-Line
1040
1041 default_action=$(Accept-Line-getdefault)
1042 zstyle -T ":acceptline:${alcontext}" call_default \
1043 && zle ${default_action}
1044}
1045
1046function accept-line () {
1047 setopt localoptions noksharrays
1048 local -a cmdline
1049 local -x alcontext
1050 local buf com fname format msg default_action
1051
1052 alcontext='default'
1053 buf="${BUFFER}"
1054 cmdline=(${(z)BUFFER})
1055 com="${cmdline[1]}"
1056 fname="_${com}"
1057
1058 Accept-Line 'preprocess'
1059
1060 zstyle -t ":acceptline:${alcontext}" rehash \
1061 && [[ -z ${commands[$com]} ]] \
1062 && rehash
1063
1064 if [[ -n ${com} ]] \
1065 && [[ -n ${reswords[(r)$com]} ]] \
1066 || [[ -n ${aliases[$com]} ]] \
1067 || [[ -n ${functions[$com]} ]] \
1068 || [[ -n ${builtins[$com]} ]] \
1069 || [[ -n ${commands[$com]} ]] ; then
1070
1071 # there is something sensible to execute, just do it.
1072 alcontext='normal'
1073 Accept-Line-HandleContext
1074
1075 return
1076 fi
1077
1078 if [[ -o correct ]] \
1079 || [[ -o correctall ]] \
1080 && [[ -n ${functions[$fname]} ]] ; then
1081
1082 # nothing there to execute but there is a function called
1083 # _command_name; a completion widget. Makes no sense to
1084 # call it on the commandline, but the correct{,all} options
1085 # will ask for it nevertheless, so warn the user.
1086 if [[ ${LASTWIDGET} == 'accept-line' ]] ; then
1087 # Okay, we warned the user before, he called us again,
1088 # so have it his way.
1089 alcontext='force'
1090 Accept-Line-HandleContext
1091
1092 return
1093 fi
1094
1095 if zstyle -t ":acceptline:${alcontext}" nocompwarn ; then
1096 alcontext='normal'
1097 Accept-Line-HandleContext
1098 else
1099 # prepare warning message for the user, configurable via zstyle.
1100 zstyle -s ":acceptline:${alcontext}" compwarnfmt msg
1101
1102 if [[ -z ${msg} ]] ; then
1103 msg="%c will not execute and completion %f exists."
1104 fi
1105
1106 zformat -f msg "${msg}" "c:${com}" "f:${fname}"
1107
1108 zle -M -- "${msg}"
1109 fi
1110 return
1111 elif [[ -n ${buf//[$' \t\n']##/} ]] ; then
1112 # If we are here, the commandline contains something that is not
1113 # executable, which is neither subject to _command_name correction
1114 # and is not empty. might be a variable assignment
1115 alcontext='misc'
1116 Accept-Line-HandleContext
1117
1118 return
1119 fi
1120
1121 # If we got this far, the commandline only contains whitespace, or is empty.
1122 alcontext='empty'
1123 Accept-Line-HandleContext
1124}
1125
1126zle -N accept-line
1127zle -N Accept-Line
1128zle -N Accept-Line-HandleContext
1129
1130# power completion / abbreviation expansion / buffer expansion
1131# see http://zshwiki.org/home/examples/zleiab for details
1132# less risky than the global aliases but powerful as well
1133# just type the abbreviation key and afterwards 'ctrl-x .' to expand it
1134declare -A abk
1135setopt extendedglob
1136setopt interactivecomments
1137abk=(
1138# key # value (#d additional doc string)
1139#A# start
1140 '...' '../..'
1141 '....' '../../..'
1142 'BG' '& exit'
1143 'C' '| wc -l'
1144 'G' '|& grep '${grep_options:+"${grep_options[*]}"}
1145 'H' '| head'
1146 'Hl' ' --help |& less -r' #d (Display help in pager)
1147 'L' '| less'
1148 'LL' '|& less -r'
1149 'M' '| most'
1150 'N' '&>/dev/null' #d (No Output)
1151 'R' '| tr A-z N-za-m' #d (ROT13)
1152 'SL' '| sort | less'
1153 'S' '| sort -u'
1154 'T' '| tail'
1155 'V' '|& vim -'
1156#A# end
1157 'co' './configure && make && sudo make install'
1158)
1159
1160function zleiab () {
1161 emulate -L zsh
1162 setopt extendedglob
1163 local MATCH
1164
1165 LBUFFER=${LBUFFER%%(#m)[.\-+:|_a-zA-Z0-9]#}
1166 LBUFFER+=${abk[$MATCH]:-$MATCH}
1167}
1168
1169zle -N zleiab
1170
1171function help-show-abk () {
1172 zle -M "$(print "Available abbreviations for expansion:"; print -a -C 2 ${(kv)abk})"
1173}
1174
1175zle -N help-show-abk
1176
1177# press "ctrl-x d" to insert the actual date in the form yyyy-mm-dd
1178function insert-datestamp () { LBUFFER+=${(%):-'%D{%Y-%m-%d}'}; }
1179zle -N insert-datestamp
1180
1181# press esc-m for inserting last typed word again (thanks to caphuso!)
1182function insert-last-typed-word () { zle insert-last-word -- 0 -1 };
1183zle -N insert-last-typed-word;
1184
1185function grml-zsh-fg () {
1186 if (( ${#jobstates} )); then
1187 zle .push-input
1188 [[ -o hist_ignore_space ]] && BUFFER=' ' || BUFFER=''
1189 BUFFER="${BUFFER}fg"
1190 zle .accept-line
1191 else
1192 zle -M 'No background jobs. Doing nothing.'
1193 fi
1194}
1195zle -N grml-zsh-fg
1196
1197# run command line as user root via sudo:
1198function sudo-command-line () {
1199 [[ -z $BUFFER ]] && zle up-history
1200 local cmd="sudo "
1201 if [[ ${BUFFER} == ${cmd}* ]]; then
1202 CURSOR=$(( CURSOR-${#cmd} ))
1203 BUFFER="${BUFFER#$cmd}"
1204 else
1205 BUFFER="${cmd}${BUFFER}"
1206 CURSOR=$(( CURSOR+${#cmd} ))
1207 fi
1208 zle reset-prompt
1209}
1210zle -N sudo-command-line
1211
1212### jump behind the first word on the cmdline.
1213### useful to add options.
1214function jump_after_first_word () {
1215 local words
1216 words=(${(z)BUFFER})
1217
1218 if (( ${#words} <= 1 )) ; then
1219 CURSOR=${#BUFFER}
1220 else
1221 CURSOR=${#${words[1]}}
1222 fi
1223}
1224zle -N jump_after_first_word
1225
1226#f5# Create directory under cursor or the selected area
1227function inplaceMkDirs () {
1228 # Press ctrl-xM to create the directory under the cursor or the selected area.
1229 # To select an area press ctrl-@ or ctrl-space and use the cursor.
1230 # Use case: you type "mv abc ~/testa/testb/testc/" and remember that the
1231 # directory does not exist yet -> press ctrl-XM and problem solved
1232 local PATHTOMKDIR
1233 if ((REGION_ACTIVE==1)); then
1234 local F=$MARK T=$CURSOR
1235 if [[ $F -gt $T ]]; then
1236 F=${CURSOR}
1237 T=${MARK}
1238 fi
1239 # get marked area from buffer and eliminate whitespace
1240 PATHTOMKDIR=${BUFFER[F+1,T]%%[[:space:]]##}
1241 PATHTOMKDIR=${PATHTOMKDIR##[[:space:]]##}
1242 else
1243 local bufwords iword
1244 bufwords=(${(z)LBUFFER})
1245 iword=${#bufwords}
1246 bufwords=(${(z)BUFFER})
1247 PATHTOMKDIR="${(Q)bufwords[iword]}"
1248 fi
1249 [[ -z "${PATHTOMKDIR}" ]] && return 1
1250 PATHTOMKDIR=${~PATHTOMKDIR}
1251 if [[ -e "${PATHTOMKDIR}" ]]; then
1252 zle -M " path already exists, doing nothing"
1253 else
1254 zle -M "$(mkdir -p -v "${PATHTOMKDIR}")"
1255 zle end-of-line
1256 fi
1257}
1258
1259zle -N inplaceMkDirs
1260
1261#v1# set number of lines to display per page
1262HELP_LINES_PER_PAGE=20
1263#v1# set location of help-zle cache file
1264HELP_ZLE_CACHE_FILE=~/.cache/zsh_help_zle_lines.zsh
1265# helper function for help-zle, actually generates the help text
1266function help_zle_parse_keybindings () {
1267 emulate -L zsh
1268 setopt extendedglob
1269 unsetopt ksharrays #indexing starts at 1
1270
1271 #v1# choose files that help-zle will parse for keybindings
1272 ((${+HELPZLE_KEYBINDING_FILES})) || HELPZLE_KEYBINDING_FILES=( /etc/zsh/zshrc ~/.zshrc.pre ~/.zshrc ~/.zshrc.local )
1273
1274 if [[ -r $HELP_ZLE_CACHE_FILE ]]; then
1275 local load_cache=0
1276 local f
1277 for f ($HELPZLE_KEYBINDING_FILES) [[ $f -nt $HELP_ZLE_CACHE_FILE ]] && load_cache=1
1278 [[ $load_cache -eq 0 ]] && . $HELP_ZLE_CACHE_FILE && return
1279 fi
1280
1281 #fill with default keybindings, possibly to be overwritten in a file later
1282 #Note that due to zsh inconsistency on escaping assoc array keys, we encase the key in '' which we will remove later
1283 local -A help_zle_keybindings
1284 help_zle_keybindings['<Ctrl>@']="set MARK"
1285 help_zle_keybindings['<Ctrl>x<Ctrl>j']="vi-join lines"
1286 help_zle_keybindings['<Ctrl>x<Ctrl>b']="jump to matching brace"
1287 help_zle_keybindings['<Ctrl>x<Ctrl>u']="undo"
1288 help_zle_keybindings['<Ctrl>_']="undo"
1289 help_zle_keybindings['<Ctrl>x<Ctrl>f<c>']="find <c> in cmdline"
1290 help_zle_keybindings['<Ctrl>a']="goto beginning of line"
1291 help_zle_keybindings['<Ctrl>e']="goto end of line"
1292 help_zle_keybindings['<Ctrl>t']="transpose charaters"
1293 help_zle_keybindings['<Alt>t']="transpose words"
1294 help_zle_keybindings['<Alt>s']="spellcheck word"
1295 help_zle_keybindings['<Ctrl>k']="backward kill buffer"
1296 help_zle_keybindings['<Ctrl>u']="forward kill buffer"
1297 help_zle_keybindings['<Ctrl>y']="insert previously killed word/string"
1298 help_zle_keybindings["<Alt>'"]="quote line"
1299 help_zle_keybindings['<Alt>"']="quote from mark to cursor"
1300 help_zle_keybindings['<Alt><arg>']="repeat next cmd/char <arg> times (<Alt>-<Alt>1<Alt>0a -> -10 times 'a')"
1301 help_zle_keybindings['<Alt>u']="make next word Uppercase"
1302 help_zle_keybindings['<Alt>l']="make next word lowercase"
1303 help_zle_keybindings['<Ctrl>xG']="preview expansion under cursor"
1304 help_zle_keybindings['<Alt>q']="push current CL into background, freeing it. Restore on next CL"
1305 help_zle_keybindings['<Alt>.']="insert (and interate through) last word from prev CLs"
1306 help_zle_keybindings['<Alt>,']="complete word from newer history (consecutive hits)"
1307 help_zle_keybindings['<Alt>m']="repeat last typed word on current CL"
1308 help_zle_keybindings['<Ctrl>v']="insert next keypress symbol literally (e.g. for bindkey)"
1309 help_zle_keybindings['!!:n*<Tab>']="insert last n arguments of last command"
1310 help_zle_keybindings['!!:n-<Tab>']="insert arguments n..N-2 of last command (e.g. mv s s d)"
1311 help_zle_keybindings['<Alt>h']="show help/manpage for current command"
1312
1313 #init global variables
1314 unset help_zle_lines help_zle_sln
1315 typeset -g -a help_zle_lines
1316 typeset -g help_zle_sln=1
1317
1318 local k v f cline
1319 local lastkeybind_desc contents #last description starting with #k# that we found
1320 local num_lines_elapsed=0 #number of lines between last description and keybinding
1321 #search config files in the order they a called (and thus the order in which they overwrite keybindings)
1322 for f in $HELPZLE_KEYBINDING_FILES; do
1323 [[ -r "$f" ]] || continue #not readable ? skip it
1324 contents="$(<$f)"
1325 for cline in "${(f)contents}"; do
1326 #zsh pattern: matches lines like: #k# ..............
1327 if [[ "$cline" == (#s)[[:space:]]#\#k\#[[:space:]]##(#b)(*)[[:space:]]#(#e) ]]; then
1328 lastkeybind_desc="$match[*]"
1329 num_lines_elapsed=0
1330 #zsh pattern: matches lines that set a keybinding using bind2map, bindkey or compdef -k
1331 # ignores lines that are commentend out
1332 # grabs first in '' or "" enclosed string with length between 1 and 6 characters
1333 elif [[ "$cline" == [^#]#(bind2maps[[:space:]](*)-s|bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*) ]]; then
1334 #description previously found ? description not more than 2 lines away ? keybinding not empty ?
1335 if [[ -n $lastkeybind_desc && $num_lines_elapsed -lt 2 && -n $match[1] ]]; then
1336 #substitute keybinding string with something readable
1337 k=${${${${${${${match[1]/\\e\^h/<Alt><BS>}/\\e\^\?/<Alt><BS>}/\\e\[5~/<PageUp>}/\\e\[6~/<PageDown>}//(\\e|\^\[)/<Alt>}//\^/<Ctrl>}/3~/<Alt><Del>}
1338 #put keybinding in assoc array, possibly overwriting defaults or stuff found in earlier files
1339 #Note that we are extracting the keybinding-string including the quotes (see Note at beginning)
1340 help_zle_keybindings[${k}]=$lastkeybind_desc
1341 fi
1342 lastkeybind_desc=""
1343 else
1344 ((num_lines_elapsed++))
1345 fi
1346 done
1347 done
1348 unset contents
1349 #calculate length of keybinding column
1350 local kstrlen=0
1351 for k (${(k)help_zle_keybindings[@]}) ((kstrlen < ${#k})) && kstrlen=${#k}
1352 #convert the assoc array into preformated lines, which we are able to sort
1353 for k v in ${(kv)help_zle_keybindings[@]}; do
1354 #pad keybinding-string to kstrlen chars and remove outermost characters (i.e. the quotes)
1355 help_zle_lines+=("${(r:kstrlen:)k[2,-2]}${v}")
1356 done
1357 #sort lines alphabetically
1358 help_zle_lines=("${(i)help_zle_lines[@]}")
1359 [[ -d ${HELP_ZLE_CACHE_FILE:h} ]] || mkdir -p "${HELP_ZLE_CACHE_FILE:h}"
1360 echo "help_zle_lines=(${(q)help_zle_lines[@]})" >| $HELP_ZLE_CACHE_FILE
1361 zcompile $HELP_ZLE_CACHE_FILE
1362}
1363typeset -g help_zle_sln
1364typeset -g -a help_zle_lines
1365
1366# Provides (partially autogenerated) help on keybindings and the zsh line editor
1367function help-zle () {
1368 emulate -L zsh
1369 unsetopt ksharrays #indexing starts at 1
1370 #help lines already generated ? no ? then do it
1371 [[ ${+functions[help_zle_parse_keybindings]} -eq 1 ]] && {help_zle_parse_keybindings && unfunction help_zle_parse_keybindings}
1372 #already displayed all lines ? go back to the start
1373 [[ $help_zle_sln -gt ${#help_zle_lines} ]] && help_zle_sln=1
1374 local sln=$help_zle_sln
1375 #note that help_zle_sln is a global var, meaning we remember the last page we viewed
1376 help_zle_sln=$((help_zle_sln + HELP_LINES_PER_PAGE))
1377 zle -M "${(F)help_zle_lines[sln,help_zle_sln-1]}"
1378}
1379zle -N help-zle
1380
1381## complete word from currently visible Screen or Tmux buffer.
1382if check_com -c screen || check_com -c tmux; then
1383 function _complete_screen_display () {
1384
1385 local TMPFILE=$(mktemp)
1386 local -U -a _screen_display_wordlist
1387 trap "rm -f $TMPFILE" EXIT
1388
1389 # fill array with contents from screen hardcopy
1390 if ((${+TMUX})); then
1391 #works, but crashes tmux below version 1.4
1392 #luckily tmux -V option to ask for version, was also added in 1.4
1393 tmux -V &>/dev/null || return
1394 tmux -q capture-pane -b 0 \; save-buffer -b 0 $TMPFILE \; delete-buffer -b 0
1395 else
1396 [[ "$TERM" != "screen" ]] && return
1397 screen -X hardcopy $TMPFILE
1398 # screen sucks, it dumps in latin1, apparently always. so recode it
1399 # to system charset
1400 check_com recode && recode latin1 $TMPFILE
1401 fi
1402 _screen_display_wordlist=( ${(QQ)$(<$TMPFILE)} )
1403 # remove PREFIX to be completed from that array
1404 _screen_display_wordlist[${_screen_display_wordlist[(i)$PREFIX]}]=""
1405 compadd -a _screen_display_wordlist
1406 }
1407 #m# k CTRL-x\,\,\,S Complete word from GNU screen buffer
1408 bindkey -r "^xS"
1409 compdef -k _complete_screen_display complete-word '^xS'
1410fi
1411
1412# Load a few more functions and tie them to widgets, so they can be bound:
1413
1414function zrcautozle () {
1415 emulate -L zsh
1416 local fnc=$1
1417 zrcautoload $fnc && zle -N $fnc
1418}
1419
1420function zrcgotwidget () {
1421 (( ${+widgets[$1]} ))
1422}
1423
1424function zrcgotkeymap () {
1425 [[ -n ${(M)keymaps:#$1} ]]
1426}
1427
1428zrcautozle insert-files
1429zrcautozle edit-command-line
1430zrcautozle insert-unicode-char
1431if zrcautoload history-search-end; then
1432 zle -N history-beginning-search-backward-end history-search-end
1433 zle -N history-beginning-search-forward-end history-search-end
1434fi
1435zle -C hist-complete complete-word _generic
1436zstyle ':completion:hist-complete:*' completer _history
1437
1438# The actual terminal setup hooks and bindkey-calls:
1439
1440# An array to note missing features to ease diagnosis in case of problems.
1441typeset -ga grml_missing_features
1442
1443function zrcbindkey () {
1444 if (( ARGC )) && zrcgotwidget ${argv[-1]}; then
1445 bindkey "$@"
1446 fi
1447}
1448
1449function bind2maps () {
1450 local i sequence widget
1451 local -a maps
1452
1453 while [[ "$1" != "--" ]]; do
1454 maps+=( "$1" )
1455 shift
1456 done
1457 shift
1458
1459 if [[ "$1" == "-s" ]]; then
1460 shift
1461 sequence="$1"
1462 else
1463 sequence="${key[$1]}"
1464 fi
1465 widget="$2"
1466
1467 [[ -z "$sequence" ]] && return 1
1468
1469 for i in "${maps[@]}"; do
1470 zrcbindkey -M "$i" "$sequence" "$widget"
1471 done
1472}
1473
1474if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
1475 function zle-smkx () {
1476 emulate -L zsh
1477 printf '%s' ${terminfo[smkx]}
1478 }
1479 function zle-rmkx () {
1480 emulate -L zsh
1481 printf '%s' ${terminfo[rmkx]}
1482 }
1483 function zle-line-init () {
1484 zle-smkx
1485 }
1486 function zle-line-finish () {
1487 zle-rmkx
1488 }
1489 zle -N zle-line-init
1490 zle -N zle-line-finish
1491else
1492 for i in {s,r}mkx; do
1493 (( ${+terminfo[$i]} )) || grml_missing_features+=($i)
1494 done
1495 unset i
1496fi
1497
1498typeset -A key
1499key=(
1500 Home "${terminfo[khome]}"
1501 End "${terminfo[kend]}"
1502 Insert "${terminfo[kich1]}"
1503 Delete "${terminfo[kdch1]}"
1504 Up "${terminfo[kcuu1]}"
1505 Down "${terminfo[kcud1]}"
1506 Left "${terminfo[kcub1]}"
1507 Right "${terminfo[kcuf1]}"
1508 PageUp "${terminfo[kpp]}"
1509 PageDown "${terminfo[knp]}"
1510 BackTab "${terminfo[kcbt]}"
1511)
1512
1513# Guidelines for adding key bindings:
1514#
1515# - Do not add hardcoded escape sequences, to enable non standard key
1516# combinations such as Ctrl-Meta-Left-Cursor. They are not easily portable.
1517#
1518# - Adding Ctrl characters, such as '^b' is okay; note that '^b' and '^B' are
1519# the same key.
1520#
1521# - All keys from the $key[] mapping are obviously okay.
1522#
1523# - Most terminals send "ESC x" when Meta-x is pressed. Thus, sequences like
1524# '\ex' are allowed in here as well.
1525
1526bind2maps emacs -- Home beginning-of-somewhere
1527bind2maps viins vicmd -- Home vi-beginning-of-line
1528bind2maps emacs -- End end-of-somewhere
1529bind2maps viins vicmd -- End vi-end-of-line
1530bind2maps emacs viins -- Insert overwrite-mode
1531bind2maps vicmd -- Insert vi-insert
1532bind2maps emacs -- Delete delete-char
1533bind2maps viins vicmd -- Delete vi-delete-char
1534bind2maps emacs viins vicmd -- Up up-line-or-search
1535bind2maps emacs viins vicmd -- Down down-line-or-search
1536bind2maps emacs -- Left backward-char
1537bind2maps viins vicmd -- Left vi-backward-char
1538bind2maps emacs -- Right forward-char
1539bind2maps viins vicmd -- Right vi-forward-char
1540#k# Perform abbreviation expansion
1541bind2maps emacs viins -- -s '^x.' zleiab
1542#k# Display list of abbreviations that would expand
1543bind2maps emacs viins -- -s '^xb' help-show-abk
1544#k# mkdir -p <dir> from string under cursor or marked area
1545bind2maps emacs viins -- -s '^xM' inplaceMkDirs
1546#k# display help for keybindings and ZLE
1547bind2maps emacs viins -- -s '^xz' help-zle
1548#k# Insert files and test globbing
1549bind2maps emacs viins -- -s "^xf" insert-files
1550#k# Edit the current line in \kbd{\$EDITOR}
1551bind2maps emacs viins -- -s '\ee' edit-command-line
1552#k# search history backward for entry beginning with typed text
1553bind2maps emacs viins -- -s '^xp' history-beginning-search-backward-end
1554#k# search history forward for entry beginning with typed text
1555bind2maps emacs viins -- -s '^xP' history-beginning-search-forward-end
1556#k# search history backward for entry beginning with typed text
1557bind2maps emacs viins -- PageUp history-beginning-search-backward-end
1558#k# search history forward for entry beginning with typed text
1559bind2maps emacs viins -- PageDown history-beginning-search-forward-end
1560bind2maps emacs viins -- -s "^x^h" commit-to-history
1561#k# Kill left-side word or everything up to next slash
1562bind2maps emacs viins -- -s '\ev' slash-backward-kill-word
1563#k# Kill left-side word or everything up to next slash
1564bind2maps emacs viins -- -s '\e^h' slash-backward-kill-word
1565#k# Kill left-side word or everything up to next slash
1566bind2maps emacs viins -- -s '\e^?' slash-backward-kill-word
1567# Do history expansion on space:
1568bind2maps emacs viins -- -s ' ' magic-space
1569#k# Trigger menu-complete
1570bind2maps emacs viins -- -s '\ei' menu-complete # menu completion via esc-i
1571#k# Insert a timestamp on the command line (yyyy-mm-dd)
1572bind2maps emacs viins -- -s '^xd' insert-datestamp
1573#k# Insert last typed word
1574bind2maps emacs viins -- -s "\em" insert-last-typed-word
1575#k# A smart shortcut for \kbd{fg<enter>}
1576bind2maps emacs viins -- -s '^z' grml-zsh-fg
1577#k# prepend the current command with "sudo"
1578bind2maps emacs viins -- -s "^os" sudo-command-line
1579#k# jump to after first word (for adding options)
1580bind2maps emacs viins -- -s '^x1' jump_after_first_word
1581#k# complete word from history with menu
1582bind2maps emacs viins -- -s "^x^x" hist-complete
1583
1584# insert unicode character
1585# usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an §
1586# See for example http://unicode.org/charts/ for unicode characters code
1587#k# Insert Unicode character
1588bind2maps emacs viins -- -s '^xi' insert-unicode-char
1589
1590# use the new *-pattern-* widgets for incremental history search
1591if zrcgotwidget history-incremental-pattern-search-backward; then
1592 for seq wid in '^r' history-incremental-pattern-search-backward \
1593 '^s' history-incremental-pattern-search-forward
1594 do
1595 bind2maps emacs viins vicmd -- -s $seq $wid
1596 done
1597 builtin unset -v seq wid
1598fi
1599
1600if zrcgotkeymap menuselect; then
1601 #m# k Shift-tab Perform backwards menu completion
1602 bind2maps menuselect -- BackTab reverse-menu-complete
1603
1604 #k# menu selection: pick item but stay in the menu
1605 bind2maps menuselect -- -s '\e^M' accept-and-menu-complete
1606 # also use + and INSERT since it's easier to press repeatedly
1607 bind2maps menuselect -- -s '+' accept-and-menu-complete
1608 bind2maps menuselect -- Insert accept-and-menu-complete
1609
1610 # accept a completion and try to complete again by using menu
1611 # completion; very useful with completing directories
1612 # by using 'undo' one's got a simple file browser
1613 bind2maps menuselect -- -s '^o' accept-and-infer-next-history
1614fi
1615
1616# Finally, here are still a few hardcoded escape sequences; Special sequences
1617# like Ctrl-<Cursor-key> etc do suck a fair bit, because they are not
1618# standardised and most of the time are not available in a terminals terminfo
1619# entry.
1620#
1621# While we do not encourage adding bindings like these, we will keep these for
1622# backward compatibility.
1623
1624## use Ctrl-left-arrow and Ctrl-right-arrow for jumping to word-beginnings on
1625## the command line.
1626# URxvt sequences:
1627bind2maps emacs viins vicmd -- -s '\eOc' forward-word
1628bind2maps emacs viins vicmd -- -s '\eOd' backward-word
1629# These are for xterm:
1630bind2maps emacs viins vicmd -- -s '\e[1;5C' forward-word
1631bind2maps emacs viins vicmd -- -s '\e[1;5D' backward-word
1632## the same for alt-left-arrow and alt-right-arrow
1633# URxvt again:
1634bind2maps emacs viins vicmd -- -s '\e\e[C' forward-word
1635bind2maps emacs viins vicmd -- -s '\e\e[D' backward-word
1636# Xterm again:
1637bind2maps emacs viins vicmd -- -s '^[[1;3C' forward-word
1638bind2maps emacs viins vicmd -- -s '^[[1;3D' backward-word
1639# Also try ESC Left/Right:
1640bind2maps emacs viins vicmd -- -s '\e'${key[Right]} forward-word
1641bind2maps emacs viins vicmd -- -s '\e'${key[Left]} backward-word
1642
1643# autoloading
1644
1645zrcautoload zmv
1646zrcautoload zed
1647
1648# we don't want to quote/espace URLs on our own...
1649# if autoload -U url-quote-magic ; then
1650# zle -N self-insert url-quote-magic
1651# zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}='
1652# else
1653# print 'Notice: no url-quote-magic available :('
1654# fi
1655if is51 ; then
1656 # url-quote doesn't work without bracketed-paste-magic since Zsh 5.1
1657 alias url-quote='autoload -U bracketed-paste-magic url-quote-magic;
1658 zle -N bracketed-paste bracketed-paste-magic; zle -N self-insert url-quote-magic'
1659else
1660 alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic'
1661fi
1662
1663#m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
1664alias run-help >&/dev/null && unalias run-help
1665for rh in run-help{,-git,-ip,-openssl,-p4,-sudo,-svk,-svn}; do
1666 zrcautoload $rh
1667done; unset rh
1668
1669# command not found handling
1670
1671(( ${COMMAND_NOT_FOUND} == 1 )) &&
1672function command_not_found_handler () {
1673 emulate -L zsh
1674 if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then
1675 ${GRML_ZSH_CNF_HANDLER} $1
1676 fi
1677 return 1
1678}
1679
1680# history
1681
1682#v#
1683HISTFILE=${HISTFILE:-${ZDOTDIR:-${HOME}}/.zsh_history}
1684isgrmlcd && HISTSIZE=500 || HISTSIZE=5000
1685isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
1686
1687# dirstack handling
1688
1689DIRSTACKSIZE=${DIRSTACKSIZE:-20}
1690DIRSTACKFILE=${DIRSTACKFILE:-${ZDOTDIR:-${HOME}}/.zdirs}
1691
1692if zstyle -T ':grml:chpwd:dirstack' enable; then
1693 typeset -gaU GRML_PERSISTENT_DIRSTACK
1694 function grml_dirstack_filter () {
1695 local -a exclude
1696 local filter entry
1697 if zstyle -s ':grml:chpwd:dirstack' filter filter; then
1698 $filter $1 && return 0
1699 fi
1700 if zstyle -a ':grml:chpwd:dirstack' exclude exclude; then
1701 for entry in "${exclude[@]}"; do
1702 [[ $1 == ${~entry} ]] && return 0
1703 done
1704 fi
1705 return 1
1706 }
1707
1708 function chpwd () {
1709 (( ZSH_SUBSHELL )) && return
1710 (( $DIRSTACKSIZE <= 0 )) && return
1711 [[ -z $DIRSTACKFILE ]] && return
1712 grml_dirstack_filter $PWD && return
1713 GRML_PERSISTENT_DIRSTACK=(
1714 $PWD "${(@)GRML_PERSISTENT_DIRSTACK[1,$DIRSTACKSIZE]}"
1715 )
1716 builtin print -l ${GRML_PERSISTENT_DIRSTACK} >! ${DIRSTACKFILE}
1717 }
1718
1719 if [[ -f ${DIRSTACKFILE} ]]; then
1720 # Enabling NULL_GLOB via (N) weeds out any non-existing
1721 # directories from the saved dir-stack file.
1722 dirstack=( ${(f)"$(< $DIRSTACKFILE)"}(N) )
1723 # "cd -" won't work after login by just setting $OLDPWD, so
1724 [[ -d $dirstack[1] ]] && cd -q $dirstack[1] && cd -q $OLDPWD
1725 fi
1726
1727 if zstyle -t ':grml:chpwd:dirstack' filter-on-load; then
1728 for i in "${dirstack[@]}"; do
1729 if ! grml_dirstack_filter "$i"; then
1730 GRML_PERSISTENT_DIRSTACK=(
1731 "${GRML_PERSISTENT_DIRSTACK[@]}"
1732 $i
1733 )
1734 fi
1735 done
1736 else
1737 GRML_PERSISTENT_DIRSTACK=( "${dirstack[@]}" )
1738 fi
1739fi
1740
1741# directory based profiles
1742
1743if is433 ; then
1744
1745# chpwd_profiles(): Directory Profiles, Quickstart:
1746#
1747# In .zshrc.local:
1748#
1749# zstyle ':chpwd:profiles:/usr/src/grml(|/|/*)' profile grml
1750# zstyle ':chpwd:profiles:/usr/src/debian(|/|/*)' profile debian
1751# chpwd_profiles
1752#
1753# For details see the `grmlzshrc.5' manual page.
1754function chpwd_profiles () {
1755 local profile context
1756 local -i reexecute
1757
1758 context=":chpwd:profiles:$PWD"
1759 zstyle -s "$context" profile profile || profile='default'
1760 zstyle -T "$context" re-execute && reexecute=1 || reexecute=0
1761
1762 if (( ${+parameters[CHPWD_PROFILE]} == 0 )); then
1763 typeset -g CHPWD_PROFILE
1764 local CHPWD_PROFILES_INIT=1
1765 (( ${+functions[chpwd_profiles_init]} )) && chpwd_profiles_init
1766 elif [[ $profile != $CHPWD_PROFILE ]]; then
1767 (( ${+functions[chpwd_leave_profile_$CHPWD_PROFILE]} )) \
1768 && chpwd_leave_profile_${CHPWD_PROFILE}
1769 fi
1770 if (( reexecute )) || [[ $profile != $CHPWD_PROFILE ]]; then
1771 (( ${+functions[chpwd_profile_$profile]} )) && chpwd_profile_${profile}
1772 fi
1773
1774 CHPWD_PROFILE="${profile}"
1775 return 0
1776}
1777
1778chpwd_functions=( ${chpwd_functions} chpwd_profiles )
1779
1780fi # is433
1781
1782# Prompt setup for grml:
1783
1784# set colors for use in prompts (modern zshs allow for the use of %F{red}foo%f
1785# in prompts to get a red "foo" embedded, but it's good to keep these for
1786# backwards compatibility).
1787if is437; then
1788 BLUE="%F{blue}"
1789 RED="%F{red}"
1790 GREEN="%F{green}"
1791 CYAN="%F{cyan}"
1792 MAGENTA="%F{magenta}"
1793 YELLOW="%F{yellow}"
1794 WHITE="%F{white}"
1795 NO_COLOR="%f"
1796elif zrcautoload colors && colors 2>/dev/null ; then
1797 BLUE="%{${fg[blue]}%}"
1798 RED="%{${fg_bold[red]}%}"
1799 GREEN="%{${fg[green]}%}"
1800 CYAN="%{${fg[cyan]}%}"
1801 MAGENTA="%{${fg[magenta]}%}"
1802 YELLOW="%{${fg[yellow]}%}"
1803 WHITE="%{${fg[white]}%}"
1804 NO_COLOR="%{${reset_color}%}"
1805else
1806 BLUE=$'%{\e[1;34m%}'
1807 RED=$'%{\e[1;31m%}'
1808 GREEN=$'%{\e[1;32m%}'
1809 CYAN=$'%{\e[1;36m%}'
1810 WHITE=$'%{\e[1;37m%}'
1811 MAGENTA=$'%{\e[1;35m%}'
1812 YELLOW=$'%{\e[1;33m%}'
1813 NO_COLOR=$'%{\e[0m%}'
1814fi
1815
1816# First, the easy ones: PS2..4:
1817
1818# secondary prompt, printed when the shell needs more information to complete a
1819# command.
1820PS2='\`%_> '
1821# selection prompt used within a select loop.
1822PS3='?# '
1823# the execution trace prompt (setopt xtrace). default: '+%N:%i>'
1824PS4='+%N:%i:%_> '
1825
1826# Some additional features to use with our prompt:
1827#
1828# - battery status
1829# - debian_chroot
1830# - vcs_info setup and version specific fixes
1831
1832# display battery status on right side of prompt using 'GRML_DISPLAY_BATTERY=1' in .zshrc.pre
1833
1834function battery () {
1835if [[ $GRML_DISPLAY_BATTERY -gt 0 ]] ; then
1836 if islinux ; then
1837 batterylinux
1838 elif isopenbsd ; then
1839 batteryopenbsd
1840 elif isfreebsd ; then
1841 batteryfreebsd
1842 elif isdarwin ; then
1843 batterydarwin
1844 else
1845 #not yet supported
1846 GRML_DISPLAY_BATTERY=0
1847 fi
1848fi
1849}
1850
1851function batterylinux () {
1852GRML_BATTERY_LEVEL=''
1853local batteries bat capacity
1854batteries=( /sys/class/power_supply/BAT*(N) )
1855if (( $#batteries > 0 )) ; then
1856 for bat in $batteries ; do
1857 if [[ -e $bat/capacity ]]; then
1858 capacity=$(< $bat/capacity)
1859 else
1860 typeset -F energy_full=$(< $bat/energy_full)
1861 typeset -F energy_now=$(< $bat/energy_now)
1862 typeset -i capacity=$(( 100 * $energy_now / $energy_full))
1863 fi
1864 case $(< $bat/status) in
1865 Charging)
1866 GRML_BATTERY_LEVEL+=" ^"
1867 ;;
1868 Discharging)
1869 if (( capacity < 20 )) ; then
1870 GRML_BATTERY_LEVEL+=" !v"
1871 else
1872 GRML_BATTERY_LEVEL+=" v"
1873 fi
1874 ;;
1875 *) # Full, Unknown
1876 GRML_BATTERY_LEVEL+=" ="
1877 ;;
1878 esac
1879 GRML_BATTERY_LEVEL+="${capacity}%%"
1880 done
1881fi
1882}
1883
1884function batteryopenbsd () {
1885GRML_BATTERY_LEVEL=''
1886local bat batfull batwarn batnow num
1887for num in 0 1 ; do
1888 bat=$(sysctl -n hw.sensors.acpibat${num} 2>/dev/null)
1889 if [[ -n $bat ]]; then
1890 batfull=${"$(sysctl -n hw.sensors.acpibat${num}.amphour0)"%% *}
1891 batwarn=${"$(sysctl -n hw.sensors.acpibat${num}.amphour1)"%% *}
1892 batnow=${"$(sysctl -n hw.sensors.acpibat${num}.amphour3)"%% *}
1893 case "$(sysctl -n hw.sensors.acpibat${num}.raw0)" in
1894 *" discharging"*)
1895 if (( batnow < batwarn )) ; then
1896 GRML_BATTERY_LEVEL+=" !v"
1897 else
1898 GRML_BATTERY_LEVEL+=" v"
1899 fi
1900 ;;
1901 *" charging"*)
1902 GRML_BATTERY_LEVEL+=" ^"
1903 ;;
1904 *)
1905 GRML_BATTERY_LEVEL+=" ="
1906 ;;
1907 esac
1908 GRML_BATTERY_LEVEL+="${$(( 100 * batnow / batfull ))%%.*}%%"
1909 fi
1910done
1911}
1912
1913function batteryfreebsd () {
1914GRML_BATTERY_LEVEL=''
1915local num
1916local -A table
1917for num in 0 1 ; do
1918 table=( ${=${${${${${(M)${(f)"$(acpiconf -i $num 2>&1)"}:#(State|Remaining capacity):*}%%( ##|%)}//:[ $'\t']##/@}// /-}//@/ }} )
1919 if [[ -n $table ]] && [[ $table[State] != "not-present" ]] ; then
1920 case $table[State] in
1921 *discharging*)
1922 if (( $table[Remaining-capacity] < 20 )) ; then
1923 GRML_BATTERY_LEVEL+=" !v"
1924 else
1925 GRML_BATTERY_LEVEL+=" v"
1926 fi
1927 ;;
1928 *charging*)
1929 GRML_BATTERY_LEVEL+=" ^"
1930 ;;
1931 *)
1932 GRML_BATTERY_LEVEL+=" ="
1933 ;;
1934 esac
1935 GRML_BATTERY_LEVEL+="$table[Remaining-capacity]%%"
1936 fi
1937done
1938}
1939
1940function batterydarwin () {
1941GRML_BATTERY_LEVEL=''
1942local -a table
1943table=( ${$(pmset -g ps)[(w)8,9]%%(\%|);} )
1944if [[ -n $table[2] ]] ; then
1945 case $table[2] in
1946 charging)
1947 GRML_BATTERY_LEVEL+=" ^"
1948 ;;
1949 discharging)
1950 if (( $table[1] < 20 )) ; then
1951 GRML_BATTERY_LEVEL+=" !v"
1952 else
1953 GRML_BATTERY_LEVEL+=" v"
1954 fi
1955 ;;
1956 *)
1957 GRML_BATTERY_LEVEL+=" ="
1958 ;;
1959 esac
1960 GRML_BATTERY_LEVEL+="$table[1]%%"
1961fi
1962}
1963
1964# set variable debian_chroot if running in a chroot with /etc/debian_chroot
1965if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
1966 debian_chroot=$(</etc/debian_chroot)
1967fi
1968
1969# gather version control information for inclusion in a prompt
1970
1971if zrcautoload vcs_info; then
1972 # `vcs_info' in zsh versions 4.3.10 and below have a broken `_realpath'
1973 # function, which can cause a lot of trouble with our directory-based
1974 # profiles. So:
1975 if [[ ${ZSH_VERSION} == 4.3.<-10> ]] ; then
1976 function VCS_INFO_realpath () {
1977 setopt localoptions NO_shwordsplit chaselinks
1978 ( builtin cd -q $1 2> /dev/null && pwd; )
1979 }
1980 fi
1981
1982 zstyle ':vcs_info:*' max-exports 2
1983
1984 if [[ -o restricted ]]; then
1985 zstyle ':vcs_info:*' enable NONE
1986 fi
1987fi
1988
1989typeset -A grml_vcs_coloured_formats
1990typeset -A grml_vcs_plain_formats
1991
1992grml_vcs_plain_formats=(
1993 format "(%s%)-[%b] " "zsh: %r"
1994 actionformat "(%s%)-[%b|%a] " "zsh: %r"
1995 rev-branchformat "%b:%r"
1996)
1997
1998grml_vcs_coloured_formats=(
1999 format "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOR} "
2000 actionformat "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOR} "
2001 rev-branchformat "%b${RED}:${YELLOW}%r"
2002)
2003
2004typeset GRML_VCS_COLOUR_MODE=xxx
2005
2006function grml_vcs_info_toggle_colour () {
2007 emulate -L zsh
2008 if [[ $GRML_VCS_COLOUR_MODE == plain ]]; then
2009 grml_vcs_info_set_formats coloured
2010 else
2011 grml_vcs_info_set_formats plain
2012 fi
2013 return 0
2014}
2015
2016function grml_vcs_info_set_formats () {
2017 emulate -L zsh
2018 #setopt localoptions xtrace
2019 local mode=$1 AF F BF
2020 if [[ $mode == coloured ]]; then
2021 AF=${grml_vcs_coloured_formats[actionformat]}
2022 F=${grml_vcs_coloured_formats[format]}
2023 BF=${grml_vcs_coloured_formats[rev-branchformat]}
2024 GRML_VCS_COLOUR_MODE=coloured
2025 else
2026 AF=${grml_vcs_plain_formats[actionformat]}
2027 F=${grml_vcs_plain_formats[format]}
2028 BF=${grml_vcs_plain_formats[rev-branchformat]}
2029 GRML_VCS_COLOUR_MODE=plain
2030 fi
2031
2032 zstyle ':vcs_info:*' actionformats "$AF" "zsh: %r"
2033 zstyle ':vcs_info:*' formats "$F" "zsh: %r"
2034 zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "$BF"
2035 return 0
2036}
2037
2038# Change vcs_info formats for the grml prompt. The 2nd format sets up
2039# $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title.
2040if [[ "$TERM" == dumb ]] ; then
2041 grml_vcs_info_set_formats plain
2042else
2043 grml_vcs_info_set_formats coloured
2044fi
2045
2046# Now for the fun part: The grml prompt themes in `promptsys' mode of operation
2047
2048# This actually defines three prompts:
2049#
2050# - grml
2051# - grml-large
2052# - grml-chroot
2053#
2054# They all share the same code and only differ with respect to which items they
2055# contain. The main source of documentation is the `prompt_grml_help' function
2056# below, which gets called when the user does this: prompt -h grml
2057
2058function prompt_grml_help () {
2059 <<__EOF0__
2060 prompt grml
2061
2062 This is the prompt as used by the grml-live system <http://grml.org>. It is
2063 a rather simple one-line prompt, that by default looks something like this:
2064
2065 <user>@<host> <current-working-directory>[ <vcs_info-data>]%
2066
2067 The prompt itself integrates with zsh's prompt themes system (as you are
2068 witnessing right now) and is configurable to a certain degree. In
2069 particular, these aspects are customisable:
2070
2071 - The items used in the prompt (e.g. you can remove \`user' from
2072 the list of activated items, which will cause the user name to
2073 be omitted from the prompt string).
2074
2075 - The attributes used with the items are customisable via strings
2076 used before and after the actual item.
2077
2078 The available items are: at, battery, change-root, date, grml-chroot,
2079 history, host, jobs, newline, path, percent, rc, rc-always, sad-smiley,
2080 shell-level, time, user, vcs
2081
2082 The actual configuration is done via zsh's \`zstyle' mechanism. The
2083 context, that is used while looking up styles is:
2084
2085 ':prompt:grml:<left-or-right>:<subcontext>'
2086
2087 Here <left-or-right> is either \`left' or \`right', signifying whether the
2088 style should affect the left or the right prompt. <subcontext> is either
2089 \`setup' or 'items:<item>', where \`<item>' is one of the available items.
2090
2091 The styles:
2092
2093 - use-rprompt (boolean): If \`true' (the default), print a sad smiley
2094 in $RPROMPT if the last command a returned non-successful error code.
2095 (This in only valid if <left-or-right> is "right"; ignored otherwise)
2096
2097 - items (list): The list of items used in the prompt. If \`vcs' is
2098 present in the list, the theme's code invokes \`vcs_info'
2099 accordingly. Default (left): rc change-root user at host path vcs
2100 percent; Default (right): sad-smiley
2101
2102 - strip-sensitive-characters (boolean): If the \`prompt_subst' option
2103 is active in zsh, the shell performs lots of expansions on prompt
2104 variable strings, including command substitution. So if you don't
2105 control where some of your prompt strings is coming from, this is
2106 an exploitable weakness. Grml's zsh setup does not set this option
2107 and it is off in the shell in zsh-mode by default. If it *is* turned
2108 on however, this style becomes active, and there are two flavours of
2109 it: On per default is a global variant in the '*:setup' context. This
2110 strips characters after the whole prompt string was constructed. There
2111 is a second variant in the '*:items:<item>', that is off by default.
2112 It allows fine grained control over which items' data is stripped.
2113 The characters that are stripped are: \$ and \`.
2114
2115 Available styles in 'items:<item>' are: pre, post. These are strings that
2116 are inserted before (pre) and after (post) the item in question. Thus, the
2117 following would cause the user name to be printed in red instead of the
2118 default blue:
2119
2120 zstyle ':prompt:grml:*:items:user' pre '%F{red}'
2121
2122 Note, that the \`post' style may remain at its default value, because its
2123 default value is '%f', which turns the foreground text attribute off (which
2124 is exactly, what is still required with the new \`pre' value).
2125__EOF0__
2126}
2127
2128function prompt_grml-chroot_help () {
2129 <<__EOF0__
2130 prompt grml-chroot
2131
2132 This is a variation of the grml prompt, see: prompt -h grml
2133
2134 The main difference is the default value of the \`items' style. The rest
2135 behaves exactly the same. Here are the defaults for \`grml-chroot':
2136
2137 - left: grml-chroot user at host path percent
2138 - right: (empty list)
2139__EOF0__
2140}
2141
2142function prompt_grml-large_help () {
2143 <<__EOF0__
2144 prompt grml-large
2145
2146 This is a variation of the grml prompt, see: prompt -h grml
2147
2148 The main difference is the default value of the \`items' style. In
2149 particular, this theme uses _two_ lines instead of one with the plain
2150 \`grml' theme. The rest behaves exactly the same. Here are the defaults
2151 for \`grml-large':
2152
2153 - left: rc jobs history shell-level change-root time date newline user
2154 at host path vcs percent
2155 - right: sad-smiley
2156__EOF0__
2157}
2158
2159function grml_prompt_setup () {
2160 emulate -L zsh
2161 autoload -Uz vcs_info
2162 # The following autoload is disabled for now, since this setup includes a
2163 # static version of the ‘add-zsh-hook’ function above. It needs to be
2164 # re-enabled as soon as that static definition is removed again.
2165 #autoload -Uz add-zsh-hook
2166 add-zsh-hook precmd prompt_$1_precmd
2167}
2168
2169function prompt_grml_setup () {
2170 grml_prompt_setup grml
2171}
2172
2173function prompt_grml-chroot_setup () {
2174 grml_prompt_setup grml-chroot
2175}
2176
2177function prompt_grml-large_setup () {
2178 grml_prompt_setup grml-large
2179}
2180
2181# These maps define default tokens and pre-/post-decoration for items to be
2182# used within the themes. All defaults may be customised in a context sensitive
2183# matter by using zsh's `zstyle' mechanism.
2184typeset -gA grml_prompt_pre_default \
2185 grml_prompt_post_default \
2186 grml_prompt_token_default \
2187 grml_prompt_token_function
2188
2189grml_prompt_pre_default=(
2190 at ''
2191 battery ' '
2192 change-root ''
2193 date '%F{blue}'
2194 grml-chroot '%F{red}'
2195 history '%F{green}'
2196 host ''
2197 jobs '%F{cyan}'
2198 newline ''
2199 path '%B'
2200 percent ''
2201 rc '%B%F{red}'
2202 rc-always ''
2203 sad-smiley ''
2204 shell-level '%F{red}'
2205 time '%F{blue}'
2206 user '%B%F{blue}'
2207 vcs ''
2208)
2209
2210grml_prompt_post_default=(
2211 at ''
2212 battery ''
2213 change-root ''
2214 date '%f'
2215 grml-chroot '%f '
2216 history '%f'
2217 host ''
2218 jobs '%f'
2219 newline ''
2220 path '%b'
2221 percent ''
2222 rc '%f%b'
2223 rc-always ''
2224 sad-smiley ''
2225 shell-level '%f'
2226 time '%f'
2227 user '%f%b'
2228 vcs ''
2229)
2230
2231grml_prompt_token_default=(
2232 at '@'
2233 battery 'GRML_BATTERY_LEVEL'
2234 change-root 'debian_chroot'
2235 date '%D{%Y-%m-%d}'
2236 grml-chroot 'GRML_CHROOT'
2237 history '{history#%!} '
2238 host '%m '
2239 jobs '[%j running job(s)] '
2240 newline $'\n'
2241 path '%40<..<%~%<< '
2242 percent '%# '
2243 rc '%(?..%? )'
2244 rc-always '%?'
2245 sad-smiley '%(?..:()'
2246 shell-level '%(3L.+ .)'
2247 time '%D{%H:%M:%S} '
2248 user '%n'
2249 vcs '0'
2250)
2251
2252function grml_theme_has_token () {
2253 if (( ARGC != 1 )); then
2254 printf 'usage: grml_theme_has_token <name>\n'
2255 return 1
2256 fi
2257 (( ${+grml_prompt_token_default[$1]} ))
2258}
2259
2260function GRML_theme_add_token_usage () {
2261 <<__EOF0__
2262 Usage: grml_theme_add_token <name> [-f|-i] <token/function> [<pre> <post>]
2263
2264 <name> is the name for the newly added token. If the \`-f' or \`-i' options
2265 are used, <token/function> is the name of the function (see below for
2266 details). Otherwise it is the literal token string to be used. <pre> and
2267 <post> are optional.
2268
2269 Options:
2270
2271 -f <function> Use a function named \`<function>' each time the token
2272 is to be expanded.
2273
2274 -i <function> Use a function named \`<function>' to initialise the
2275 value of the token _once_ at runtime.
2276
2277 The functions are called with one argument: the token's new name. The
2278 return value is expected in the \$REPLY parameter. The use of these
2279 options is mutually exclusive.
2280
2281 There is a utility function \`grml_theme_has_token', which you can use
2282 to test if a token exists before trying to add it. This can be a guard
2283 for situations in which a \`grml_theme_add_token' call may happen more
2284 than once.
2285
2286 Example:
2287
2288 To add a new token \`day' that expands to the current weekday in the
2289 current locale in green foreground colour, use this:
2290
2291 grml_theme_add_token day '%D{%A}' '%F{green}' '%f'
2292
2293 Another example would be support for \$VIRTUAL_ENV:
2294
2295 function virtual_env_prompt () {
2296 REPLY=\${VIRTUAL_ENV+\${VIRTUAL_ENV:t} }
2297 }
2298 grml_theme_add_token virtual-env -f virtual_env_prompt
2299
2300 After that, you will be able to use a changed \`items' style to
2301 assemble your prompt.
2302__EOF0__
2303}
2304
2305function grml_theme_add_token () {
2306 emulate -L zsh
2307 local name token pre post
2308 local -i init funcall
2309
2310 if (( ARGC == 0 )); then
2311 GRML_theme_add_token_usage
2312 return 0
2313 fi
2314
2315 init=0
2316 funcall=0
2317 pre=''
2318 post=''
2319 name=$1
2320 shift
2321 if [[ $1 == '-f' ]]; then
2322 funcall=1
2323 shift
2324 elif [[ $1 == '-i' ]]; then
2325 init=1
2326 shift
2327 fi
2328
2329 if (( ARGC == 0 )); then
2330 printf '
2331grml_theme_add_token: No token-string/function-name provided!\n\n'
2332 GRML_theme_add_token_usage
2333 return 1
2334 fi
2335 token=$1
2336 shift
2337 if (( ARGC != 0 && ARGC != 2 )); then
2338 printf '
2339grml_theme_add_token: <pre> and <post> need to by specified _both_!\n\n'
2340 GRML_theme_add_token_usage
2341 return 1
2342 fi
2343 if (( ARGC )); then
2344 pre=$1
2345 post=$2
2346 shift 2
2347 fi
2348
2349 if grml_theme_has_token $name; then
2350 printf '
2351grml_theme_add_token: Token `%s'\'' exists! Giving up!\n\n' $name
2352 GRML_theme_add_token_usage
2353 return 2
2354 fi
2355 if (( init )); then
2356 REPLY=''
2357 $token $name
2358 token=$REPLY
2359 fi
2360 grml_prompt_pre_default[$name]=$pre
2361 grml_prompt_post_default[$name]=$post
2362 if (( funcall )); then
2363 grml_prompt_token_function[$name]=$token
2364 grml_prompt_token_default[$name]=23
2365 else
2366 grml_prompt_token_default[$name]=$token
2367 fi
2368}
2369
2370function grml_wrap_reply () {
2371 emulate -L zsh
2372 local target="$1"
2373 local new="$2"
2374 local left="$3"
2375 local right="$4"
2376
2377 if (( ${+parameters[$new]} )); then
2378 REPLY="${left}${(P)new}${right}"
2379 else
2380 REPLY=''
2381 fi
2382}
2383
2384function grml_prompt_addto () {
2385 emulate -L zsh
2386 local target="$1"
2387 local lr it apre apost new v REPLY
2388 local -a items
2389 shift
2390
2391 [[ $target == PS1 ]] && lr=left || lr=right
2392 zstyle -a ":prompt:${grmltheme}:${lr}:setup" items items || items=( "$@" )
2393 typeset -g "${target}="
2394 for it in "${items[@]}"; do
2395 zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" pre apre \
2396 || apre=${grml_prompt_pre_default[$it]}
2397 zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" post apost \
2398 || apost=${grml_prompt_post_default[$it]}
2399 zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
2400 || new=${grml_prompt_token_default[$it]}
2401 if (( ${+grml_prompt_token_function[$it]} )); then
2402 REPLY=''
2403 ${grml_prompt_token_function[$it]} $it
2404 else
2405 case $it in
2406 battery)
2407 grml_wrap_reply $target $new '' ''
2408 ;;
2409 change-root)
2410 grml_wrap_reply $target $new '(' ')'
2411 ;;
2412 grml-chroot)
2413 if [[ -n ${(P)new} ]]; then
2414 REPLY="$CHROOT"
2415 else
2416 REPLY=''
2417 fi
2418 ;;
2419 vcs)
2420 v="vcs_info_msg_${new}_"
2421 if (( ! vcscalled )); then
2422 vcs_info
2423 vcscalled=1
2424 fi
2425 if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
2426 REPLY="${(P)v}"
2427 else
2428 REPLY=''
2429 fi
2430 ;;
2431 *) REPLY="$new" ;;
2432 esac
2433 fi
2434 # Strip volatile characters per item. This is off by default. See the
2435 # global stripping code a few lines below for details.
2436 if [[ -o prompt_subst ]] && zstyle -t ":prompt:${grmltheme}:${lr}:items:$it" \
2437 strip-sensitive-characters
2438 then
2439 REPLY="${REPLY//[$\`]/}"
2440 fi
2441 typeset -g "${target}=${(P)target}${apre}${REPLY}${apost}"
2442 done
2443
2444 # Per default, strip volatile characters (in the prompt_subst case)
2445 # globally. If the option is off, the style has no effect. For more
2446 # control, this can be turned off and stripping can be configured on a
2447 # per-item basis (see above).
2448 if [[ -o prompt_subst ]] && zstyle -T ":prompt:${grmltheme}:${lr}:setup" \
2449 strip-sensitive-characters
2450 then
2451 typeset -g "${target}=${${(P)target}//[$\`]/}"
2452 fi
2453}
2454
2455function prompt_grml_precmd () {
2456 emulate -L zsh
2457 local grmltheme=grml
2458 local -a left_items right_items
2459 left_items=(rc change-root user at host path vcs percent)
2460 right_items=(sad-smiley)
2461
2462 prompt_grml_precmd_worker
2463}
2464
2465function prompt_grml-chroot_precmd () {
2466 emulate -L zsh
2467 local grmltheme=grml-chroot
2468 local -a left_items right_items
2469 left_items=(grml-chroot user at host path percent)
2470 right_items=()
2471
2472 prompt_grml_precmd_worker
2473}
2474
2475function prompt_grml-large_precmd () {
2476 emulate -L zsh
2477 local grmltheme=grml-large
2478 local -a left_items right_items
2479 left_items=(rc jobs history shell-level change-root time date newline
2480 user at host path vcs percent)
2481 right_items=(sad-smiley)
2482
2483 prompt_grml_precmd_worker
2484}
2485
2486function prompt_grml_precmd_worker () {
2487 emulate -L zsh
2488 local -i vcscalled=0
2489
2490 grml_prompt_addto PS1 "${left_items[@]}"
2491 if zstyle -T ":prompt:${grmltheme}:right:setup" use-rprompt; then
2492 grml_prompt_addto RPS1 "${right_items[@]}"
2493 fi
2494}
2495
2496function grml_prompt_fallback () {
2497 setopt prompt_subst
2498 local p0 p1
2499
2500 p0="${RED}%(?..%? )${WHITE}${debian_chroot:+($debian_chroot)}"
2501 p1="${BLUE}%n${NO_COLOR}@%m %40<...<%B%~%b%<< "'${vcs_info_msg_0_}'"%# "
2502 if (( EUID == 0 )); then
2503 PROMPT="${BLUE}${p0}${RED}${p1}"
2504 else
2505 PROMPT="${RED}${p0}${BLUE}${p1}"
2506 fi
2507}
2508
2509if zrcautoload promptinit && promptinit 2>/dev/null ; then
2510 grml_status_feature promptinit 0
2511 # Since we define the required functions in here and not in files in
2512 # $fpath, we need to stick the theme's name into `$prompt_themes'
2513 # ourselves, since promptinit does not pick them up otherwise.
2514 prompt_themes+=( grml grml-chroot grml-large )
2515 # Also, keep the array sorted...
2516 prompt_themes=( "${(@on)prompt_themes}" )
2517else
2518 grml_status_feature promptinit 1
2519 grml_prompt_fallback
2520 function precmd () { (( ${+functions[vcs_info]} )) && vcs_info; }
2521fi
2522
2523if is437; then
2524 # The prompt themes use modern features of zsh, that require at least
2525 # version 4.3.7 of the shell. Use the fallback otherwise.
2526 if [[ $GRML_DISPLAY_BATTERY -gt 0 ]]; then
2527 zstyle ':prompt:grml:right:setup' items sad-smiley battery
2528 add-zsh-hook precmd battery
2529 fi
2530 if [[ "$TERM" == dumb ]] ; then
2531 zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" pre ''
2532 zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" post ' '
2533 for i in rc user path jobs history date time shell-level; do
2534 zstyle ":prompt:grml(|-large|-chroot):*:items:$i" pre ''
2535 zstyle ":prompt:grml(|-large|-chroot):*:items:$i" post ''
2536 done
2537 unset i
2538 zstyle ':prompt:grml(|-large|-chroot):right:setup' use-rprompt false
2539 elif (( EUID == 0 )); then
2540 zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%B%F{red}'
2541 fi
2542
2543 # Finally enable one of the prompts.
2544 if [[ -n $GRML_CHROOT ]]; then
2545 prompt grml-chroot
2546 elif [[ $GRMLPROMPT -gt 0 ]]; then
2547 prompt grml-large
2548 else
2549 prompt grml
2550 fi
2551else
2552 grml_prompt_fallback
2553 function precmd () { (( ${+functions[vcs_info]} )) && vcs_info; }
2554fi
2555
2556# make sure to use right prompt only when not running a command
2557is41 && setopt transient_rprompt
2558
2559# Terminal-title wizardry
2560
2561function ESC_print () {
2562 info_print $'\ek' $'\e\\' "$@"
2563}
2564function set_title () {
2565 info_print $'\e]0;' $'\a' "$@"
2566}
2567
2568function info_print () {
2569 local esc_begin esc_end
2570 esc_begin="$1"
2571 esc_end="$2"
2572 shift 2
2573 printf '%s' ${esc_begin}
2574 printf '%s' "$*"
2575 printf '%s' "${esc_end}"
2576}
2577
2578function grml_reset_screen_title () {
2579 # adjust title of xterm
2580 # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
2581 [[ ${NOTITLE:-} -gt 0 ]] && return 0
2582 case $TERM in
2583 (xterm*|rxvt*|alacritty|foot)
2584 set_title ${(%):-"%n@%m: %~"}
2585 ;;
2586 esac
2587}
2588
2589function grml_vcs_to_screen_title () {
2590 if [[ $TERM == screen* ]] ; then
2591 if [[ -n ${vcs_info_msg_1_} ]] ; then
2592 ESC_print ${vcs_info_msg_1_}
2593 else
2594 ESC_print "zsh"
2595 fi
2596 fi
2597}
2598
2599function grml_maintain_name () {
2600 local localname
2601 localname="$(uname -n)"
2602
2603 # set hostname if not running on local machine
2604 if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != "${localname}" ]] ; then
2605 NAME="@$HOSTNAME"
2606 fi
2607}
2608
2609function grml_cmd_to_screen_title () {
2610 # get the name of the program currently running and hostname of local
2611 # machine set screen window title if running in a screen
2612 if [[ "$TERM" == screen* ]] ; then
2613 local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME"
2614 ESC_print ${CMD}
2615 fi
2616}
2617
2618function grml_control_xterm_title () {
2619 case $TERM in
2620 (xterm*|rxvt*|alacritty|foot)
2621 set_title "${(%):-"%n@%m:"}" "$2"
2622 ;;
2623 esac
2624}
2625
2626# The following autoload is disabled for now, since this setup includes a
2627# static version of the ‘add-zsh-hook’ function above. It needs to be
2628# re-enabled as soon as that static definition is removed again.
2629#zrcautoload add-zsh-hook || add-zsh-hook () { :; }
2630if [[ $NOPRECMD -eq 0 ]]; then
2631 add-zsh-hook precmd grml_reset_screen_title
2632 add-zsh-hook precmd grml_vcs_to_screen_title
2633 add-zsh-hook preexec grml_maintain_name
2634 add-zsh-hook preexec grml_cmd_to_screen_title
2635 if [[ $NOTITLE -eq 0 ]]; then
2636 add-zsh-hook preexec grml_control_xterm_title
2637 fi
2638fi
2639
2640# 'hash' some often used directories
2641#d# start
2642hash -d deb=/var/cache/apt/archives
2643hash -d doc=/usr/share/doc
2644hash -d linux=/lib/modules/$(command uname -r)/build/
2645hash -d log=/var/log
2646hash -d slog=/var/log/syslog
2647hash -d src=/usr/src
2648hash -d www=/var/www
2649#d# end
2650
2651# some aliases
2652if check_com -c screen ; then
2653 if [[ $UID -eq 0 ]] ; then
2654 if [[ -r /etc/grml/screenrc ]]; then
2655 alias screen='screen -c /etc/grml/screenrc'
2656 fi
2657 elif [[ ! -r $HOME/.screenrc ]] ; then
2658 if [[ -r /etc/grml/screenrc_grml ]]; then
2659 alias screen='screen -c /etc/grml/screenrc_grml'
2660 else
2661 if [[ -r /etc/grml/screenrc ]]; then
2662 alias screen='screen -c /etc/grml/screenrc'
2663 fi
2664 fi
2665 fi
2666fi
2667
2668# do we have GNU ls with color-support?
2669if [[ "$TERM" != dumb ]]; then
2670 #a1# List files with colors (\kbd{ls \ldots})
2671 alias ls="command ls ${ls_options:+${ls_options[*]}}"
2672 #a1# List all files, with colors (\kbd{ls -la \ldots})
2673 alias la="command ls -la ${ls_options:+${ls_options[*]}}"
2674 #a1# List files with long colored list, without dotfiles (\kbd{ls -l \ldots})
2675 alias ll="command ls -l ${ls_options:+${ls_options[*]}}"
2676 #a1# List files with long colored list, human readable sizes (\kbd{ls -hAl \ldots})
2677 alias lh="command ls -hAl ${ls_options:+${ls_options[*]}}"
2678 #a1# List files with long colored list, append qualifier to filenames (\kbd{ls -l \ldots})\\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
2679 alias l="command ls -l ${ls_options:+${ls_options[*]}}"
2680else
2681 alias la='command ls -la'
2682 alias ll='command ls -l'
2683 alias lh='command ls -hAl'
2684 alias l='command ls -l'
2685fi
2686
2687# use ip from iproute2 with color support
2688if ip -color=auto addr show dev lo >/dev/null 2>&1; then
2689 alias ip='command ip -color=auto'
2690fi
2691
2692if [[ -r /proc/mdstat ]]; then
2693 alias mdstat='cat /proc/mdstat'
2694fi
2695
2696alias ...='cd ../../'
2697
2698# generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
2699if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then
2700 alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)""
2701fi
2702
2703# see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details
2704alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'"
2705alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'"
2706
2707# make sure it is not assigned yet
2708[[ -n ${aliases[utf2iso]} ]] && unalias utf2iso
2709function utf2iso () {
2710 if isutfenv ; then
2711 local ENV
2712 for ENV in $(env | command grep -i '.utf') ; do
2713 eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
2714 done
2715 fi
2716}
2717
2718# make sure it is not assigned yet
2719[[ -n ${aliases[iso2utf]} ]] && unalias iso2utf
2720function iso2utf () {
2721 if ! isutfenv ; then
2722 local ENV
2723 for ENV in $(env | command grep -i '\.iso') ; do
2724 eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
2725 done
2726 fi
2727}
2728
2729# especially for roadwarriors using GNU screen and ssh:
2730if ! check_com asc &>/dev/null ; then
2731 function asc () { autossh -t "$@" 'screen -RdU' }
2732 compdef asc=ssh
2733fi
2734
2735#f1# Hints for the use of zsh on grml
2736function zsh-help () {
2737 print "$bg[white]$fg[black]
2738zsh-help - hints for use of zsh on grml
2739=======================================$reset_color"
2740
2741 print '
2742Main configuration of zsh happens in /etc/zsh/zshrc.
2743That file is part of the package grml-etc-core, if you want to
2744use them on a non-grml-system just get the tar.gz from
2745http://deb.grml.org/ or (preferably) get it from the git repository:
2746
2747 http://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
2748
2749This version of grml'\''s zsh setup does not use skel/.zshrc anymore.
2750The file is still there, but it is empty for backwards compatibility.
2751
2752For your own changes use these two files:
2753 $HOME/.zshrc.pre
2754 $HOME/.zshrc.local
2755
2756The former is sourced very early in our zshrc, the latter is sourced
2757very lately.
2758
2759System wide configuration without touching configuration files of grml
2760can take place in /etc/zsh/zshrc.local.
2761
2762For information regarding zsh start at http://grml.org/zsh/
2763
2764Take a look at grml'\''s zsh refcard:
2765% xpdf =(zcat /usr/share/doc/grml-docs/zsh/grml-zsh-refcard.pdf.gz)
2766
2767Check out the main zsh refcard:
2768% '$BROWSER' http://www.bash2zsh.com/zsh_refcard/refcard.pdf
2769
2770And of course visit the zsh-lovers:
2771% man zsh-lovers
2772
2773You can adjust some options through environment variables when
2774invoking zsh without having to edit configuration files.
2775Basically meant for bash users who are not used to the power of
2776the zsh yet. :)
2777
2778 "NOCOR=1 zsh" => deactivate automatic correction
2779 "NOMENU=1 zsh" => do not use auto menu completion
2780 (note: use ctrl-d for completion instead!)
2781 "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title)
2782 "NOTITLE=1 zsh" => disable setting the title of xterms without disabling
2783 preexec() and precmd() completely
2784 "GRML_DISPLAY_BATTERY=1 zsh"
2785 => activate battery status on right side of prompt (WIP)
2786 "COMMAND_NOT_FOUND=1 zsh"
2787 => Enable a handler if an external command was not found
2788 The command called in the handler can be altered by setting
2789 the GRML_ZSH_CNF_HANDLER variable, the default is:
2790 "/usr/share/command-not-found/command-not-found"
2791
2792A value greater than 0 is enables a feature; a value equal to zero
2793disables it. If you like one or the other of these settings, you can
2794add them to ~/.zshrc.pre to ensure they are set when sourcing grml'\''s
2795zshrc.'
2796
2797 print "
2798$bg[white]$fg[black]
2799Please report wishes + bugs to the grml-team: http://grml.org/bugs/
2800Enjoy your grml system with the zsh!$reset_color"
2801}
2802
2803# debian stuff
2804if [[ -r /etc/debian_version ]] ; then
2805 if [[ -z "$GRML_NO_APT_ALIASES" ]]; then
2806 #a3# Execute \kbd{apt-cache policy}
2807 alias acp='apt-cache policy'
2808 if check_com -c apt ; then
2809 #a3# Execute \kbd{apt search}
2810 alias acs='apt search'
2811 #a3# Execute \kbd{apt show}
2812 alias acsh='apt show'
2813 #a3# Execute \kbd{apt dist-upgrade}
2814 salias adg="apt dist-upgrade"
2815 #a3# Execute \kbd{apt upgrade}
2816 salias ag="apt upgrade"
2817 #a3# Execute \kbd{apt install}
2818 salias agi="apt install"
2819 #a3# Execute \kbd{apt update}
2820 salias au="apt update"
2821 else
2822 alias acs='apt-cache search'
2823 alias acsh='apt-cache show'
2824 salias adg="apt-get dist-upgrade"
2825 salias ag="apt-get upgrade"
2826 salias agi="apt-get install"
2827 salias au="apt-get update"
2828 fi
2829 #a3# Execute \kbd{aptitude install}
2830 salias ati="aptitude install"
2831 #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
2832 salias -a up="aptitude update ; aptitude safe-upgrade"
2833 #a3# Execute \kbd{dpkg-buildpackage}
2834 alias dbp='dpkg-buildpackage'
2835 #a3# Execute \kbd{grep-excuses}
2836 alias ge='grep-excuses'
2837 fi
2838
2839 # get a root shell as normal user in live-cd mode:
2840 if isgrmlcd && [[ $UID -ne 0 ]] ; then
2841 alias su="sudo su"
2842 fi
2843
2844fi
2845
2846# use /var/log/syslog iff present, fallback to journalctl otherwise
2847if [ -e /var/log/syslog ] ; then
2848 #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog || journalctl}
2849 salias llog="$PAGER /var/log/syslog" # take a look at the syslog
2850 #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog || journalctl}
2851 salias tlog="tail --follow=name /var/log/syslog" # follow the syslog
2852elif check_com -c journalctl ; then
2853 salias llog="journalctl"
2854 salias tlog="journalctl -f"
2855fi
2856
2857# sort installed Debian-packages by size
2858if check_com -c dpkg-query ; then
2859 #a3# List installed Debian-packages sorted by size
2860 alias debs-by-size="dpkg-query -Wf 'x \${Installed-Size} \${Package} \${Status}\n' | sed -ne '/^x /d' -e '/^x \(.*\) install ok installed$/s//\1/p' | sort -nr"
2861fi
2862
2863# if cdrecord is a symlink (to wodim) or isn't present at all warn:
2864if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord; then
2865 if check_com -c wodim; then
2866 function cdrecord () {
2867 <<__EOF0__
2868cdrecord is not provided under its original name by Debian anymore.
2869See #377109 in the BTS of Debian for more details.
2870
2871Please use the wodim binary instead
2872__EOF0__
2873 return 1
2874 }
2875 fi
2876fi
2877
2878if isgrmlcd; then
2879 # No core dumps: important for a live-cd-system
2880 limit -s core 0
2881fi
2882
2883# grmlstuff
2884function grmlstuff () {
2885# people should use 'grml-x'!
2886 if check_com -c 915resolution; then
2887 function 855resolution () {
2888 echo "Please use 915resolution as resolution modifying tool for Intel \
2889graphic chipset."
2890 return -1
2891 }
2892 fi
2893
2894 #a1# Output version of running grml
2895 alias grml-version='cat /etc/grml_version'
2896
2897 if check_com -c grml-debootstrap ; then
2898 function debian2hd () {
2899 echo "Installing debian to harddisk is possible by using grml-debootstrap."
2900 return 1
2901 }
2902 fi
2903
2904 if check_com -c tmate && check_com -c qrencode ; then
2905 function grml-remote-support() {
2906 tmate -L grml-remote-support new -s grml-remote-support -d
2907 tmate -L grml-remote-support wait tmate-ready
2908 tmate -L grml-remote-support display -p '#{tmate_ssh}' | qrencode -t ANSI
2909 echo "tmate session: $(tmate -L grml-remote-support display -p '#{tmate_ssh}')"
2910 echo
2911 echo "Scan this QR code and send it to your support team."
2912 }
2913 fi
2914}
2915
2916# now run the functions
2917isgrml && checkhome
2918is4 && isgrml && grmlstuff
2919is4 && grmlcomp
2920
2921# keephack
2922is4 && xsource "/etc/zsh/keephack"
2923
2924# wonderful idea of using "e" glob qualifier by Peter Stephenson
2925# You use it as follows:
2926# $ NTREF=/reference/file
2927# $ ls -l *(e:nt:)
2928# This lists all the files in the current directory newer than the reference file.
2929# You can also specify the reference file inline; note quotes:
2930# $ ls -l *(e:'nt ~/.zshenv':)
2931is4 && function nt () {
2932 if [[ -n $1 ]] ; then
2933 local NTREF=${~1}
2934 fi
2935 [[ $REPLY -nt $NTREF ]]
2936}
2937
2938# shell functions
2939
2940#f1# Reload an autoloadable function
2941function freload () { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
2942compdef _functions freload
2943
2944#
2945# Usage:
2946#
2947# e.g.: a -> b -> c -> d ....
2948#
2949# sll a
2950#
2951#
2952# if parameter is given with leading '=', lookup $PATH for parameter and resolve that
2953#
2954# sll =java
2955#
2956# Note: limit for recursive symlinks on linux:
2957# http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/namei.c?id=refs/heads/master#l808
2958# This limits recursive symlink follows to 8,
2959# while limiting consecutive symlinks to 40.
2960#
2961# When resolving and displaying information about symlinks, no check is made
2962# that the displayed information does make any sense on your OS.
2963# We leave that decission to the user.
2964#
2965# The zstat module is used to detect symlink loops. zstat is available since zsh4.
2966# With an older zsh you will need to abort with <C-c> in that case.
2967# When a symlink loop is detected, a warning ist printed and further processing is stopped.
2968#
2969# Module zstat is loaded by default in grml zshrc, no extra action needed for that.
2970#
2971# Known bugs:
2972# If you happen to come across a symlink that points to a destination on another partition
2973# with the same inode number, that will be marked as symlink loop though it is not.
2974# Two hints for this situation:
2975# I) Play lottery the same day, as you seem to be rather lucky right now.
2976# II) Send patches.
2977#
2978# return status:
2979# 0 upon success
2980# 1 file/dir not accesible
2981# 2 symlink loop detected
2982#
2983#f1# List symlinks in detail (more detailed version of 'readlink -f', 'whence -s' and 'namei -l')
2984function sll () {
2985 if [[ -z ${1} ]] ; then
2986 printf 'Usage: %s <symlink(s)>\n' "${0}"
2987 return 1
2988 fi
2989
2990 local file jumpd curdir
2991 local -i 10 RTN LINODE i
2992 local -a SEENINODES
2993 curdir="${PWD}"
2994 RTN=0
2995
2996 for file in "${@}" ; do
2997 SEENINODES=()
2998 ls -l "${file:a}" || RTN=1
2999
3000 while [[ -h "$file" ]] ; do
3001 if is4 ; then
3002 LINODE=$(zstat -L +inode "${file}")
3003 for i in ${SEENINODES} ; do
3004 if (( ${i} == ${LINODE} )) ; then
3005 builtin cd -q "${curdir}"
3006 print 'link loop detected, aborting!'
3007 return 2
3008 fi
3009 done
3010 SEENINODES+=${LINODE}
3011 fi
3012 jumpd="${file:h}"
3013 file="${file:t}"
3014
3015 if [[ -d ${jumpd} ]] ; then
3016 builtin cd -q "${jumpd}" || RTN=1
3017 fi
3018 file=$(readlink "$file")
3019
3020 jumpd="${file:h}"
3021 file="${file:t}"
3022
3023 if [[ -d ${jumpd} ]] ; then
3024 builtin cd -q "${jumpd}" || RTN=1
3025 fi
3026
3027 ls -l "${PWD}/${file}" || RTN=1
3028 done
3029 shift 1
3030 if (( ${#} >= 1 )) ; then
3031 print ""
3032 fi
3033 builtin cd -q "${curdir}"
3034 done
3035 return ${RTN}
3036}
3037
3038if check_com -c $PAGER ; then
3039 #f3# View Debian's changelog of given package(s)
3040 function dchange () {
3041 emulate -L zsh
3042 [[ -z "$1" ]] && printf 'Usage: %s <package_name(s)>\n' "$0" && return 1
3043
3044 local package
3045
3046 # `less` as $PAGER without e.g. `|lesspipe %s` inside $LESSOPEN can't properly
3047 # read *.gz files, try to detect this to use vi instead iff available
3048 local viewer
3049
3050 if [[ ${$(typeset -p PAGER)[2]} = -a ]] ; then
3051 viewer=($PAGER) # support PAGER=(less -Mr) but leave array untouched
3052 else
3053 viewer=(${=PAGER}) # support PAGER='less -Mr'
3054 fi
3055
3056 if [[ ${viewer[1]:t} = less ]] && [[ -z "${LESSOPEN}" ]] && check_com vi ; then
3057 viewer='vi'
3058 fi
3059
3060 for package in "$@" ; do
3061 if [[ -r /usr/share/doc/${package}/changelog.Debian.gz ]] ; then
3062 $viewer /usr/share/doc/${package}/changelog.Debian.gz
3063 elif [[ -r /usr/share/doc/${package}/changelog.gz ]] ; then
3064 $viewer /usr/share/doc/${package}/changelog.gz
3065 elif [[ -r /usr/share/doc/${package}/changelog ]] ; then
3066 $viewer /usr/share/doc/${package}/changelog
3067 else
3068 if check_com -c aptitude ; then
3069 echo "No changelog for package $package found, using aptitude to retrieve it."
3070 aptitude changelog "$package"
3071 elif check_com -c apt-get ; then
3072 echo "No changelog for package $package found, using apt-get to retrieve it."
3073 apt-get changelog "$package"
3074 else
3075 echo "No changelog for package $package found, sorry."
3076 fi
3077 fi
3078 done
3079 }
3080 function _dchange () { _files -W /usr/share/doc -/ }
3081 compdef _dchange dchange
3082
3083 #f3# View Debian's NEWS of a given package
3084 function dnews () {
3085 emulate -L zsh
3086 if [[ -r /usr/share/doc/$1/NEWS.Debian.gz ]] ; then
3087 $PAGER /usr/share/doc/$1/NEWS.Debian.gz
3088 else
3089 if [[ -r /usr/share/doc/$1/NEWS.gz ]] ; then
3090 $PAGER /usr/share/doc/$1/NEWS.gz
3091 else
3092 echo "No NEWS file for package $1 found, sorry."
3093 return 1
3094 fi
3095 fi
3096 }
3097 function _dnews () { _files -W /usr/share/doc -/ }
3098 compdef _dnews dnews
3099
3100 #f3# View Debian's copyright of a given package
3101 function dcopyright () {
3102 emulate -L zsh
3103 if [[ -r /usr/share/doc/$1/copyright ]] ; then
3104 $PAGER /usr/share/doc/$1/copyright
3105 else
3106 echo "No copyright file for package $1 found, sorry."
3107 return 1
3108 fi
3109 }
3110 function _dcopyright () { _files -W /usr/share/doc -/ }
3111 compdef _dcopyright dcopyright
3112
3113 #f3# View upstream's changelog of a given package
3114 function uchange () {
3115 emulate -L zsh
3116 if [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
3117 $PAGER /usr/share/doc/$1/changelog.gz
3118 else
3119 echo "No changelog for package $1 found, sorry."
3120 return 1
3121 fi
3122 }
3123 function _uchange () { _files -W /usr/share/doc -/ }
3124 compdef _uchange uchange
3125fi
3126
3127# zsh profiling
3128function profile () {
3129 ZSH_PROFILE_RC=1 zsh "$@"
3130}
3131
3132#f1# Edit an alias via zle
3133function edalias () {
3134 [[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
3135}
3136compdef _aliases edalias
3137
3138#f1# Edit a function via zle
3139function edfunc () {
3140 [[ -z "$1" ]] && { echo "Usage: edfunc <function_to_edit>" ; return 1 } || zed -f "$1" ;
3141}
3142compdef _functions edfunc
3143
3144# use it e.g. via 'Restart apache2'
3145#m# f6 Start() \kbd{service \em{process}}\quad\kbd{start}
3146#m# f6 Restart() \kbd{service \em{process}}\quad\kbd{restart}
3147#m# f6 Stop() \kbd{service \em{process}}\quad\kbd{stop}
3148#m# f6 Reload() \kbd{service \em{process}}\quad\kbd{reload}
3149#m# f6 Force-Reload() \kbd{service \em{process}}\quad\kbd{force-reload}
3150#m# f6 Status() \kbd{service \em{process}}\quad\kbd{status}
3151if [[ -d /etc/init.d || -d /etc/service ]] ; then
3152 function __start_stop () {
3153 local action_="${1:l}" # e.g Start/Stop/Restart
3154 local service_="$2"
3155 local param_="$3"
3156
3157 local service_target_="$(readlink /etc/init.d/$service_)"
3158 if [[ $service_target_ == "/usr/bin/sv" ]]; then
3159 # runit
3160 case "${action_}" in
3161 start) if [[ ! -e /etc/service/$service_ ]]; then
3162 $SUDO ln -s "/etc/sv/$service_" "/etc/service/"
3163 else
3164 $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
3165 fi ;;
3166 # there is no reload in runits sysv emulation
3167 reload) $SUDO "/etc/init.d/$service_" "force-reload" "$param_" ;;
3168 *) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
3169 esac
3170 else
3171 # sysv/sysvinit-utils, upstart
3172 if check_com -c service ; then
3173 $SUDO service "$service_" "${action_}" "$param_"
3174 else
3175 $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
3176 fi
3177 fi
3178 }
3179
3180 function _grmlinitd () {
3181 local -a scripts
3182 scripts=( /etc/init.d/*(x:t) )
3183 _describe "service startup script" scripts
3184 }
3185
3186 for i in Start Restart Stop Force-Reload Reload Status ; do
3187 eval "function $i () { __start_stop $i \"\$1\" \"\$2\" ; }"
3188 compdef _grmlinitd $i
3189 done
3190 builtin unset -v i
3191fi
3192
3193#f1# Provides useful information on globbing
3194function H-Glob () {
3195 echo -e "
3196 / directories
3197 . plain files
3198 @ symbolic links
3199 = sockets
3200 p named pipes (FIFOs)
3201 * executable plain files (0100)
3202 % device files (character or block special)
3203 %b block special files
3204 %c character special files
3205 r owner-readable files (0400)
3206 w owner-writable files (0200)
3207 x owner-executable files (0100)
3208 A group-readable files (0040)
3209 I group-writable files (0020)
3210 E group-executable files (0010)
3211 R world-readable files (0004)
3212 W world-writable files (0002)
3213 X world-executable files (0001)
3214 s setuid files (04000)
3215 S setgid files (02000)
3216 t files with the sticky bit (01000)
3217
3218 print *(m-1) # Files modified up to a day ago
3219 print *(a1) # Files accessed a day ago
3220 print *(@) # Just symlinks
3221 print *(Lk+50) # Files bigger than 50 kilobytes
3222 print *(Lk-50) # Files smaller than 50 kilobytes
3223 print **/*.c # All *.c files recursively starting in \$PWD
3224 print **/*.c~file.c # Same as above, but excluding 'file.c'
3225 print (foo|bar).* # Files starting with 'foo' or 'bar'
3226 print *~*.* # All Files that do not contain a dot
3227 chmod 644 *(.^x) # make all plain non-executable files publically readable
3228 print -l *(.c|.h) # Lists *.c and *.h
3229 print **/*(g:users:) # Recursively match all files that are owned by group 'users'
3230 echo /proc/*/cwd(:h:t:s/self//) # Analogous to >ps ax | awk '{print $1}'<"
3231}
3232alias help-zshglob=H-Glob
3233
3234# grep for running process, like: 'any vim'
3235function any () {
3236 emulate -L zsh
3237 unsetopt KSH_ARRAYS
3238 if [[ -z "$1" ]] ; then
3239 echo "any - grep for process(es) by keyword" >&2
3240 echo "Usage: any <keyword>" >&2 ; return 1
3241 else
3242 ps xauwww | grep -i "${grep_options[@]}" "[${1[1]}]${1[2,-1]}"
3243 fi
3244}
3245
3246
3247# After resuming from suspend, system is paging heavily, leading to very bad interactivity.
3248# taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
3249[[ -r /proc/1/maps ]] && \
3250function deswap () {
3251 print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
3252 cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/') > /dev/null
3253 print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
3254}
3255
3256# a wrapper for vim, that deals with title setting
3257# VIM_OPTIONS
3258# set this array to a set of options to vim you always want
3259# to have set when calling vim (in .zshrc.local), like:
3260# VIM_OPTIONS=( -p )
3261# This will cause vim to send every file given on the
3262# commandline to be send to it's own tab (needs vim7).
3263if check_com vim; then
3264 function vim () {
3265 VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
3266 }
3267fi
3268
3269ssl_hashes=( sha512 sha256 sha1 md5 )
3270
3271for sh in ${ssl_hashes}; do
3272 eval 'ssl-cert-'${sh}'() {
3273 emulate -L zsh
3274 if [[ -z $1 ]] ; then
3275 printf '\''usage: %s <file>\n'\'' "ssh-cert-'${sh}'"
3276 return 1
3277 fi
3278 openssl x509 -noout -fingerprint -'${sh}' -in $1
3279 }'
3280done; unset sh
3281
3282function ssl-cert-fingerprints () {
3283 emulate -L zsh
3284 local i
3285 if [[ -z $1 ]] ; then
3286 printf 'usage: ssl-cert-fingerprints <file>\n'
3287 return 1
3288 fi
3289 for i in ${ssl_hashes}
3290 do ssl-cert-$i $1;
3291 done
3292}
3293
3294function ssl-cert-info () {
3295 emulate -L zsh
3296 if [[ -z $1 ]] ; then
3297 printf 'usage: ssl-cert-info <file>\n'
3298 return 1
3299 fi
3300 openssl x509 -noout -text -in $1
3301 ssl-cert-fingerprints $1
3302}
3303
3304# make sure our environment is clean regarding colors
3305builtin unset -v BLUE RED GREEN CYAN YELLOW MAGENTA WHITE NO_COLOR
3306
3307# "persistent history"
3308# just write important commands you always need to $GRML_IMPORTANT_COMMANDS
3309# defaults for backward compatibility to ~/.important_commands
3310if [[ -r ~/.important_commands ]] ; then
3311 GRML_IMPORTANT_COMMANDS=~/.important_commands
3312else
3313 GRML_IMPORTANT_COMMANDS=${GRML_IMPORTANT_COMMANDS:-${ZDOTDIR:-${HOME}}/.important_commands}
3314fi
3315[[ -r ${GRML_IMPORTANT_COMMANDS} ]] && builtin fc -R ${GRML_IMPORTANT_COMMANDS}
3316
3317# load the lookup subsystem if it's available on the system
3318zrcautoload lookupinit && lookupinit
3319
3320# variables
3321
3322# set terminal property (used e.g. by msgid-chooser)
3323case "${COLORTERM}" in
3324 truecolor)
3325 # do not overwrite
3326 ;;
3327 *)
3328 export COLORTERM="yes"
3329 ;;
3330esac
3331
3332# aliases
3333
3334# general
3335#a2# Execute \kbd{du -sch}
3336[[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias da='du -sch'
3337
3338# listing stuff
3339#a2# Execute \kbd{ls -lSrah}
3340alias dir="command ls -lSrah"
3341#a2# Only show dot-directories
3342alias lad='command ls -d .*(/)'
3343#a2# Only show dot-files
3344alias lsa='command ls -a .*(.)'
3345#a2# Only files with setgid/setuid/sticky flag
3346alias lss='command ls -l *(s,S,t)'
3347#a2# Only show symlinks
3348alias lsl='command ls -l *(@)'
3349#a2# Display only executables
3350alias lsx='command ls -l *(*)'
3351#a2# Display world-{readable,writable,executable} files
3352alias lsw='command ls -ld *(R,W,X.^ND/)'
3353#a2# Display the ten biggest files
3354alias lsbig="command ls -flh *(.OL[1,10])"
3355#a2# Only show directories
3356alias lsd='command ls -d *(/)'
3357#a2# Only show empty directories
3358alias lse='command ls -d *(/^F)'
3359#a2# Display the ten newest files
3360alias lsnew="command ls -rtlh *(D.om[1,10])"
3361#a2# Display the ten oldest files
3362alias lsold="command ls -rtlh *(D.Om[1,10])"
3363#a2# Display the ten smallest files
3364alias lssmall="command ls -Srl *(.oL[1,10])"
3365#a2# Display the ten newest directories and ten newest .directories
3366alias lsnewdir="command ls -rthdl *(/om[1,10]) .*(D/om[1,10])"
3367#a2# Display the ten oldest directories and ten oldest .directories
3368alias lsolddir="command ls -rthdl *(/Om[1,10]) .*(D/Om[1,10])"
3369
3370# some useful aliases
3371#a2# Remove current empty directory. Execute \kbd{cd ..; rmdir \$OLDCWD}
3372alias rmcdir='cd ..; rmdir $OLDPWD || cd $OLDPWD'
3373
3374#a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3375alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3376#a2# scp with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
3377alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
3378
3379# work around non utf8 capable software in utf environment via $LANG and luit
3380if check_com isutfenv && check_com luit ; then
3381 if check_com -c mrxvt ; then
3382 isutfenv && [[ -n "$LANG" ]] && \
3383 alias mrxvt="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit mrxvt"
3384 fi
3385
3386 if check_com -c aterm ; then
3387 isutfenv && [[ -n "$LANG" ]] && \
3388 alias aterm="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit aterm"
3389 fi
3390
3391 if check_com -c centericq ; then
3392 isutfenv && [[ -n "$LANG" ]] && \
3393 alias centericq="LANG=${LANG/(#b)(*)[.@]*/$match[1].iso885915} luit centericq"
3394 fi
3395fi
3396
3397# useful functions
3398
3399#f5# Backup \kbd{file_or_folder {\rm to} file_or_folder\_timestamp}
3400function bk () {
3401 emulate -L zsh
3402 local current_date=$(date -u "+%Y%m%dT%H%M%SZ")
3403 local clean keep move verbose result all to_bk
3404 setopt extended_glob
3405 keep=1
3406 while getopts ":hacmrv" opt; do
3407 case $opt in
3408 a) (( all++ ));;
3409 c) unset move clean && (( ++keep ));;
3410 m) unset keep clean && (( ++move ));;
3411 r) unset move keep && (( ++clean ));;
3412 v) verbose="-v";;
3413 h) <<__EOF0__
3414bk [-hcmv] FILE [FILE ...]
3415bk -r [-av] [FILE [FILE ...]]
3416Backup a file or folder in place and append the timestamp
3417Remove backups of a file or folder, or all backups in the current directory
3418
3419Usage:
3420-h Display this help text
3421-c Keep the file/folder as is, create a copy backup using cp(1) (default)
3422-m Move the file/folder, using mv(1)
3423-r Remove backups of the specified file or directory, using rm(1). If none
3424 is provided, remove all backups in the current directory.
3425-a Remove all (even hidden) backups.
3426-v Verbose
3427
3428The -c, -r and -m options are mutually exclusive. If specified at the same time,
3429the last one is used.
3430
3431The return code is the sum of all cp/mv/rm return codes.
3432__EOF0__
3433return 0;;
3434 \?) bk -h >&2; return 1;;
3435 esac
3436 done
3437 shift "$((OPTIND-1))"
3438 if (( keep > 0 )); then
3439 if islinux || isfreebsd; then
3440 for to_bk in "$@"; do
3441 cp $verbose -a "${to_bk%/}" "${to_bk%/}_$current_date"
3442 (( result += $? ))
3443 done
3444 else
3445 for to_bk in "$@"; do
3446 cp $verbose -pR "${to_bk%/}" "${to_bk%/}_$current_date"
3447 (( result += $? ))
3448 done
3449 fi
3450 elif (( move > 0 )); then
3451 while (( $# > 0 )); do
3452 mv $verbose "${1%/}" "${1%/}_$current_date"
3453 (( result += $? ))
3454 shift
3455 done
3456 elif (( clean > 0 )); then
3457 if (( $# > 0 )); then
3458 for to_bk in "$@"; do
3459 rm $verbose -rf "${to_bk%/}"_[0-9](#c8)T([0-1][0-9]|2[0-3])([0-5][0-9])(#c2)Z
3460 (( result += $? ))
3461 done
3462 else
3463 if (( all > 0 )); then
3464 rm $verbose -rf *_[0-9](#c8)T([0-1][0-9]|2[0-3])([0-5][0-9])(#c2)Z(D)
3465 else
3466 rm $verbose -rf *_[0-9](#c8)T([0-1][0-9]|2[0-3])([0-5][0-9])(#c2)Z
3467 fi
3468 (( result += $? ))
3469 fi
3470 fi
3471 return $result
3472}
3473
3474#f5# cd to directory and list files
3475function cl () {
3476 emulate -L zsh
3477 cd $1 && ls -a
3478}
3479
3480# smart cd function, allows switching to /etc when running 'cd /etc/fstab'
3481function cd () {
3482 if (( ${#argv} == 1 )) && [[ -f ${1} ]]; then
3483 [[ ! -e ${1:h} ]] && return 1
3484 print "Correcting ${1} to ${1:h}"
3485 builtin cd ${1:h}
3486 else
3487 builtin cd "$@"
3488 fi
3489}
3490
3491#f5# Create Directory and \kbd{cd} to it
3492function mkcd () {
3493 if (( ARGC != 1 )); then
3494 printf 'usage: mkcd <new-directory>\n'
3495 return 1;
3496 fi
3497 if [[ ! -d "$1" ]]; then
3498 command mkdir -p "$1"
3499 else
3500 printf '`%s'\'' already exists: cd-ing.\n' "$1"
3501 fi
3502 builtin cd "$1"
3503}
3504
3505#f5# Create temporary directory and \kbd{cd} to it
3506function cdt () {
3507 builtin cd "$(mktemp -d)"
3508 builtin pwd
3509}
3510
3511#f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
3512function accessed () {
3513 emulate -L zsh
3514 print -l -- *(a-${1:-1})
3515}
3516
3517#f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
3518function changed () {
3519 emulate -L zsh
3520 print -l -- *(c-${1:-1})
3521}
3522
3523#f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
3524function modified () {
3525 emulate -L zsh
3526 print -l -- *(m-${1:-1})
3527}
3528# modified() was named new() in earlier versions, add an alias for backwards compatibility
3529check_com new || alias new=modified
3530
3531# use colors when GNU grep with color-support
3532if (( $#grep_options > 0 )); then
3533 o=${grep_options:+"${grep_options[*]}"}
3534 #a2# Execute \kbd{grep -{}-color=auto}
3535 alias grep='grep '$o
3536 alias egrep='egrep '$o
3537 unset o
3538fi
3539
3540# Translate DE<=>EN
3541# 'translate' looks up a word in a file with language-to-language
3542# translations (field separator should be " : "). A typical wordlist looks
3543# like the following:
3544# | english-word : german-translation
3545# It's also only possible to translate english to german but not reciprocal.
3546# Use the following oneliner to reverse the sort order:
3547# $ awk -F ':' '{ print $2" : "$1" "$3 }' \
3548# /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
3549#f5# Translates a word
3550function trans () {
3551 emulate -L zsh
3552 case "$1" in
3553 -[dD]*)
3554 translate -l de-en $2
3555 ;;
3556 -[eE]*)
3557 translate -l en-de $2
3558 ;;
3559 *)
3560 echo "Usage: $0 { -D | -E }"
3561 echo " -D == German to English"
3562 echo " -E == English to German"
3563 esac
3564}
3565
3566# Usage: simple-extract <file>
3567# Using option -d deletes the original archive file.
3568#f5# Smart archive extractor
3569function simple-extract () {
3570 emulate -L zsh
3571 setopt extended_glob noclobber
3572 local ARCHIVE DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
3573 local RC=0
3574 zparseopts -D -E "d=DELETE_ORIGINAL"
3575 for ARCHIVE in "${@}"; do
3576 case $ARCHIVE in
3577 *(tar.bz2|tbz2|tbz))
3578 DECOMP_CMD="tar -xvjf -"
3579 USES_STDIN=true
3580 USES_STDOUT=false
3581 ;;
3582 *(tar.gz|tgz))
3583 DECOMP_CMD="tar -xvzf -"
3584 USES_STDIN=true
3585 USES_STDOUT=false
3586 ;;
3587 *(tar.xz|txz|tar.lzma))
3588 DECOMP_CMD="tar -xvJf -"
3589 USES_STDIN=true
3590 USES_STDOUT=false
3591 ;;
3592 *tar.zst)
3593 DECOMP_CMD="tar --zstd -xvf -"
3594 USES_STDIN=true
3595 USES_STDOUT=false
3596 ;;
3597 *tar.lrz)
3598 DECOMP_CMD="lrzuntar"
3599 USES_STDIN=false
3600 USES_STDOUT=false
3601 ;;
3602 *tar)
3603 DECOMP_CMD="tar -xvf -"
3604 USES_STDIN=true
3605 USES_STDOUT=false
3606 ;;
3607 *rar)
3608 DECOMP_CMD="unrar x"
3609 USES_STDIN=false
3610 USES_STDOUT=false
3611 ;;
3612 *lzh)
3613 DECOMP_CMD="lha x"
3614 USES_STDIN=false
3615 USES_STDOUT=false
3616 ;;
3617 *7z)
3618 DECOMP_CMD="7z x"
3619 USES_STDIN=false
3620 USES_STDOUT=false
3621 ;;
3622 *(zip|jar))
3623 DECOMP_CMD="unzip"
3624 USES_STDIN=false
3625 USES_STDOUT=false
3626 ;;
3627 *deb)
3628 DECOMP_CMD="ar -x"
3629 USES_STDIN=false
3630 USES_STDOUT=false
3631 ;;
3632 *bz2)
3633 DECOMP_CMD="bzip2 -d -c -"
3634 USES_STDIN=true
3635 USES_STDOUT=true
3636 ;;
3637 *(gz|Z))
3638 DECOMP_CMD="gzip -d -c -"
3639 USES_STDIN=true
3640 USES_STDOUT=true
3641 ;;
3642 *(xz|lzma))
3643 DECOMP_CMD="xz -d -c -"
3644 USES_STDIN=true
3645 USES_STDOUT=true
3646 ;;
3647 *zst)
3648 DECOMP_CMD="zstd -d -c -"
3649 USES_STDIN=true
3650 USES_STDOUT=true
3651 ;;
3652 *lrz)
3653 DECOMP_CMD="lrunzip -"
3654 USES_STDIN=true
3655 USES_STDOUT=true
3656 ;;
3657 *)
3658 print "ERROR: '$ARCHIVE' has unrecognized archive type." >&2
3659 RC=$((RC+1))
3660 continue
3661 ;;
3662 esac
3663
3664 if ! check_com ${DECOMP_CMD[(w)1]}; then
3665 echo "ERROR: ${DECOMP_CMD[(w)1]} not installed." >&2
3666 RC=$((RC+2))
3667 continue
3668 fi
3669
3670 GZTARGET="${ARCHIVE:t:r}"
3671 if [[ -f $ARCHIVE ]] ; then
3672
3673 print "Extracting '$ARCHIVE' ..."
3674 if $USES_STDIN; then
3675 if $USES_STDOUT; then
3676 ${=DECOMP_CMD} < "$ARCHIVE" > $GZTARGET
3677 else
3678 ${=DECOMP_CMD} < "$ARCHIVE"
3679 fi
3680 else
3681 if $USES_STDOUT; then
3682 ${=DECOMP_CMD} "$ARCHIVE" > $GZTARGET
3683 else
3684 ${=DECOMP_CMD} "$ARCHIVE"
3685 fi
3686 fi
3687 [[ $? -eq 0 && -n "$DELETE_ORIGINAL" ]] && rm -f "$ARCHIVE"
3688
3689 elif [[ "$ARCHIVE" == (#s)(https|http|ftp)://* ]] ; then
3690 if check_com curl; then
3691 WGET_CMD="curl -L -s -o -"
3692 elif check_com wget; then
3693 WGET_CMD="wget -q -O -"
3694 elif check_com fetch; then
3695 WGET_CMD="fetch -q -o -"
3696 else
3697 print "ERROR: neither wget, curl nor fetch is installed" >&2
3698 RC=$((RC+4))
3699 continue
3700 fi
3701 print "Downloading and Extracting '$ARCHIVE' ..."
3702 if $USES_STDIN; then
3703 if $USES_STDOUT; then
3704 ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD} > $GZTARGET
3705 RC=$((RC+$?))
3706 else
3707 ${=WGET_CMD} "$ARCHIVE" | ${=DECOMP_CMD}
3708 RC=$((RC+$?))
3709 fi
3710 else
3711 if $USES_STDOUT; then
3712 ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE") > $GZTARGET
3713 else
3714 ${=DECOMP_CMD} =(${=WGET_CMD} "$ARCHIVE")
3715 fi
3716 fi
3717
3718 else
3719 print "ERROR: '$ARCHIVE' is neither a valid file nor a supported URI." >&2
3720 RC=$((RC+8))
3721 fi
3722 done
3723 return $RC
3724}
3725
3726function __archive_or_uri () {
3727 _alternative \
3728 'files:Archives:_files -g "*.(#l)(tar.bz2|tbz2|tbz|tar.gz|tgz|tar.xz|txz|tar.lzma|tar|rar|lzh|7z|zip|jar|deb|bz2|gz|Z|xz|lzma)"' \
3729 '_urls:Remote Archives:_urls'
3730}
3731
3732function _simple_extract () {
3733 _arguments \
3734 '-d[delete original archivefile after extraction]' \
3735 '*:Archive Or Uri:__archive_or_uri'
3736}
3737compdef _simple_extract simple-extract
3738[[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias se=simple-extract
3739
3740#f5# Change the xterm title from within GNU-screen
3741function xtrename () {
3742 emulate -L zsh
3743 if [[ $1 != "-f" ]] ; then
3744 if [[ -z ${DISPLAY} ]] ; then
3745 printf 'xtrename only makes sense in X11.\n'
3746 return 1
3747 fi
3748 else
3749 shift
3750 fi
3751 if [[ -z $1 ]] ; then
3752 printf 'usage: xtrename [-f] "title for xterm"\n'
3753 printf ' renames the title of xterm from _within_ screen.\n'
3754 printf ' also works without screen.\n'
3755 printf ' will not work if DISPLAY is unset, use -f to override.\n'
3756 return 0
3757 fi
3758 print -n "\eP\e]0;${1}\C-G\e\\"
3759 return 0
3760}
3761
3762# Create small urls via http://goo.gl using curl(1).
3763# API reference: https://code.google.com/apis/urlshortener/
3764function zurl () {
3765 emulate -L zsh
3766 setopt extended_glob
3767
3768 if [[ -z $1 ]]; then
3769 print "USAGE: zurl <URL>"
3770 return 1
3771 fi
3772
3773 local PN url prog api json contenttype item
3774 local -a data
3775 PN=$0
3776 url=$1
3777
3778 # Prepend 'http://' to given URL where necessary for later output.
3779 if [[ ${url} != http(s|)://* ]]; then
3780 url='http://'${url}
3781 fi
3782
3783 if check_com -c curl; then
3784 prog=curl
3785 else
3786 print "curl is not available, but mandatory for ${PN}. Aborting."
3787 return 1
3788 fi
3789 api='https://www.googleapis.com/urlshortener/v1/url'
3790 contenttype="Content-Type: application/json"
3791 json="{\"longUrl\": \"${url}\"}"
3792 data=(${(f)"$($prog --silent -H ${contenttype} -d ${json} $api)"})
3793 # Parse the response
3794 for item in "${data[@]}"; do
3795 case "$item" in
3796 ' '#'"id":'*)
3797 item=${item#*: \"}
3798 item=${item%\",*}
3799 printf '%s\n' "$item"
3800 return 0
3801 ;;
3802 esac
3803 done
3804 return 1
3805}
3806
3807#f2# Find history events by search pattern and list them by date.
3808function whatwhen () {
3809 emulate -L zsh
3810 local usage help ident format_l format_s first_char remain first last
3811 usage='USAGE: whatwhen [options] <searchstring> <search range>'
3812 help='Use `whatwhen -h'\'' for further explanations.'
3813 ident=${(l,${#${:-Usage: }},, ,)}
3814 format_l="${ident}%s\t\t\t%s\n"
3815 format_s="${format_l//(\\t)##/\\t}"
3816 # Make the first char of the word to search for case
3817 # insensitive; e.g. [aA]
3818 first_char=[${(L)1[1]}${(U)1[1]}]
3819 remain=${1[2,-1]}
3820 # Default search range is `-100'.
3821 first=${2:-\-100}
3822 # Optional, just used for `<first> <last>' given.
3823 last=$3
3824 case $1 in
3825 ("")
3826 printf '%s\n\n' 'ERROR: No search string specified. Aborting.'
3827 printf '%s\n%s\n\n' ${usage} ${help} && return 1
3828 ;;
3829 (-h)
3830 printf '%s\n\n' ${usage}
3831 print 'OPTIONS:'
3832 printf $format_l '-h' 'show help text'
3833 print '\f'
3834 print 'SEARCH RANGE:'
3835 printf $format_l "'0'" 'the whole history,'
3836 printf $format_l '-<n>' 'offset to the current history number; (default: -100)'
3837 printf $format_s '<[-]first> [<last>]' 'just searching within a give range'
3838 printf '\n%s\n' 'EXAMPLES:'
3839 printf ${format_l/(\\t)/} 'whatwhen grml' '# Range is set to -100 by default.'
3840 printf $format_l 'whatwhen zsh -250'
3841 printf $format_l 'whatwhen foo 1 99'
3842 ;;
3843 (\?)
3844 printf '%s\n%s\n\n' ${usage} ${help} && return 1
3845 ;;
3846 (*)
3847 # -l list results on stout rather than invoking $EDITOR.
3848 # -i Print dates as in YYYY-MM-DD.
3849 # -m Search for a - quoted - pattern within the history.
3850 fc -li -m "*${first_char}${remain}*" $first $last
3851 ;;
3852 esac
3853}
3854
3855# mercurial related stuff
3856if check_com -c hg ; then
3857 # gnu like diff for mercurial
3858 # http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
3859 #f5# GNU like diff for mercurial
3860 function hgdi () {
3861 emulate -L zsh
3862 local i
3863 for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
3864 }
3865
3866 # build debian package
3867 #a2# Alias for \kbd{hg-buildpackage}
3868 alias hbp='hg-buildpackage'
3869
3870 # execute commands on the versioned patch-queue from the current repos
3871 [[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
3872
3873 # diffstat for specific version of a mercurial repository
3874 # hgstat => display diffstat between last revision and tip
3875 # hgstat 1234 => display diffstat between revision 1234 and tip
3876 #f5# Diffstat for specific version of a mercurial repos
3877 function hgstat () {
3878 emulate -L zsh
3879 [[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
3880 }
3881
3882fi # end of check whether we have the 'hg'-executable
3883
3884# disable bracketed paste mode for dumb terminals
3885[[ "$TERM" == dumb ]] && unset zle_bracketed_paste
3886
3887# grml-small cleanups and workarounds
3888
3889# The following is used to remove zsh-config-items that do not work
3890# in grml-small by default.
3891# If you do not want these adjustments (for whatever reason), set
3892# $GRMLSMALL_SPECIFIC to 0 in your .zshrc.pre file (which this configuration
3893# sources if it is there).
3894
3895if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
3896
3897 # Clean up
3898
3899 unset "abk[V]"
3900 unalias 'V' &> /dev/null
3901 unfunction vman &> /dev/null
3902 unfunction viless &> /dev/null
3903 unfunction 2html &> /dev/null
3904
3905 # manpages are not in grmlsmall
3906 unfunction manzsh &> /dev/null
3907 unfunction man2 &> /dev/null
3908
3909 # Workarounds
3910
3911 # See https://github.com/grml/grml/issues/56
3912 if ! [[ -x ${commands[dig]} ]]; then
3913 function dig_after_all () {
3914 unfunction dig
3915 unfunction _dig
3916 autoload -Uz _dig
3917 unfunction dig_after_all
3918 }
3919 function dig () {
3920 if [[ -x ${commands[dig]} ]]; then
3921 dig_after_all
3922 command dig "$@"
3923 return "$!"
3924 fi
3925 printf 'This installation does not include `dig'\'' for size reasons.\n'
3926 printf 'Try `drill'\'' as a light weight alternative.\n'
3927 return 0
3928 }
3929 function _dig () {
3930 if [[ -x ${commands[dig]} ]]; then
3931 dig_after_all
3932 zle -M 'Found `dig'\'' installed. '
3933 else
3934 zle -M 'Try `drill'\'' instead of `dig'\''.'
3935 fi
3936 }
3937 compdef _dig dig
3938 fi
3939fi
3940
3941zrclocal
3942
3943unfunction grml_status_feature
3944
3945## genrefcard.pl settings
3946
3947### doc strings for external functions from files
3948#m# f5 grml-wallpaper() Sets a wallpaper (try completion for possible values)
3949
3950### example: split functions-search 8,16,24,32
3951#@# split functions-search 8
3952
3953## END OF FILE #################################################################
3954# vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
3955# Local variables:
3956# mode: sh
3957# End:
3958
3959# Make Flatpaks accessible via the shell
3960export PATH="$PATH:/var/lib/flatpak/exports/bin"
3961
3962# Reset prompt to default
3963prompt default
3964PROMPT='%# '
3965
3966# Load Headline ZSH theme
3967source ~/.config/headline.zsh-theme