# check for version/system
# check for versions (compatibility reasons)
-is4(){
+function is4 () {
[[ $ZSH_VERSION == <4->* ]] && return 0
return 1
}
-is41(){
+function is41 () {
[[ $ZSH_VERSION == 4.<1->* || $ZSH_VERSION == <5->* ]] && return 0
return 1
}
-is42(){
+function is42 () {
[[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
return 1
}
-is425(){
+function is425 () {
[[ $ZSH_VERSION == 4.2.<5->* || $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
return 1
}
-is43(){
+function is43 () {
[[ $ZSH_VERSION == 4.<3->* || $ZSH_VERSION == <5->* ]] && return 0
return 1
}
-is433(){
+function is433 () {
[[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == 4.<4->* \
|| $ZSH_VERSION == <5->* ]] && return 0
return 1
}
-is437(){
+function is437 () {
[[ $ZSH_VERSION == 4.3.<7->* || $ZSH_VERSION == 4.<4->* \
|| $ZSH_VERSION == <5->* ]] && return 0
return 1
}
-is439(){
+function is439 () {
[[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* \
|| $ZSH_VERSION == <5->* ]] && return 0
return 1
}
#f1# Checks whether or not you're running grml
-isgrml(){
+function isgrml () {
[[ -f /etc/grml_version ]] && return 0
return 1
}
#f1# Checks whether or not you're running a grml cd
-isgrmlcd(){
+function isgrmlcd () {
[[ -f /etc/grml_cd ]] && return 0
return 1
}
if isgrml ; then
#f1# Checks whether or not you're running grml-small
- isgrmlsmall() {
+ function isgrmlsmall () {
if [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]]; then
return 0
fi
return 1
}
else
- isgrmlsmall() { return 1 }
+ function isgrmlsmall () { return 1 }
fi
GRML_OSTYPE=$(uname -s)
-islinux(){
+function islinux () {
[[ $GRML_OSTYPE == "Linux" ]]
}
-isdarwin(){
+function isdarwin () {
[[ $GRML_OSTYPE == "Darwin" ]]
}
-isfreebsd(){
+function isfreebsd () {
[[ $GRML_OSTYPE == "FreeBSD" ]]
}
-isopenbsd(){
+function isopenbsd () {
[[ $GRML_OSTYPE == "OpenBSD" ]]
}
+function issolaris () {
+ [[ $GRML_OSTYPE == "SunOS" ]]
+}
+
#f1# are we running within an utf environment?
-isutfenv() {
+function isutfenv () {
case "$LANG $CHARSET $LANGUAGE" in
*utf*) return 0 ;;
*UTF*) return 0 ;;
# change directory to home on first invocation of zsh
# important for rungetty -> autologin
# Thanks go to Bart Schaefer!
-isgrml && checkhome() {
+isgrml && function checkhome () {
if [[ -z "$ALREADY_DID_CD_HOME" ]] ; then
export ALREADY_DID_CD_HOME=$HOME
cd
printf '-!- Ye been warned!\n'
printf '-!-\n'
- function zstyle() { : }
+ function zstyle () { : }
fi
# autoload wrapper - use this one instead of autoload directly
# We need to define this function as early as this, because autoloading
# 'is-at-least()' needs it.
-function zrcautoload() {
+function zrcautoload () {
emulate -L zsh
setopt extended_glob
local fdir ffile
return 0
}
+# The following is the ‘add-zsh-hook’ function from zsh upstream. It is
+# included here to make the setup work with older versions of zsh (prior to
+# 4.3.7) in which this function had a bug that triggers annoying errors during
+# shell startup. This is exactly upstreams code from f0068edb4888a4d8fe94def,
+# with just a few adjustments in coding style to make the function look more
+# compact. This definition can be removed as soon as we raise the minimum
+# version requirement to 4.3.7 or newer.
+function add-zsh-hook () {
+ # Add to HOOK the given FUNCTION.
+ # HOOK is one of chpwd, precmd, preexec, periodic, zshaddhistory,
+ # zshexit, zsh_directory_name (the _functions subscript is not required).
+ #
+ # With -d, remove the function from the hook instead; delete the hook
+ # variable if it is empty.
+ #
+ # -D behaves like -d, but pattern characters are active in the function
+ # name, so any matching function will be deleted from the hook.
+ #
+ # Without -d, the FUNCTION is marked for autoload; -U is passed down to
+ # autoload if that is given, as are -z and -k. (This is harmless if the
+ # function is actually defined inline.)
+ emulate -L zsh
+ local -a hooktypes
+ hooktypes=(
+ chpwd precmd preexec periodic zshaddhistory zshexit
+ zsh_directory_name
+ )
+ local usage="Usage: $0 hook function\nValid hooks are:\n $hooktypes"
+ local opt
+ local -a autoopts
+ integer del list help
+ while getopts "dDhLUzk" opt; do
+ case $opt in
+ (d) del=1 ;;
+ (D) del=2 ;;
+ (h) help=1 ;;
+ (L) list=1 ;;
+ ([Uzk]) autoopts+=(-$opt) ;;
+ (*) return 1 ;;
+ esac
+ done
+ shift $(( OPTIND - 1 ))
+ if (( list )); then
+ typeset -mp "(${1:-${(@j:|:)hooktypes}})_functions"
+ return $?
+ elif (( help || $# != 2 || ${hooktypes[(I)$1]} == 0 )); then
+ print -u$(( 2 - help )) $usage
+ return $(( 1 - help ))
+ fi
+ local hook="${1}_functions"
+ local fn="$2"
+ if (( del )); then
+ # delete, if hook is set
+ if (( ${(P)+hook} )); then
+ if (( del == 2 )); then
+ set -A $hook ${(P)hook:#${~fn}}
+ else
+ set -A $hook ${(P)hook:#$fn}
+ fi
+ # unset if no remaining entries --- this can give better
+ # performance in some cases
+ if (( ! ${(P)#hook} )); then
+ unset $hook
+ fi
+ fi
+ else
+ if (( ${(P)+hook} )); then
+ if (( ${${(P)hook}[(I)$fn]} == 0 )); then
+ set -A $hook ${(P)hook} $fn
+ fi
+ else
+ set -A $hook $fn
+ fi
+ autoload $autoopts -- $fn
+ fi
+}
+
# Load is-at-least() for more precise version checks Note that this test will
# *always* fail, if the is-at-least function could not be marked for
# autoloading.
-zrcautoload is-at-least || is-at-least() { return 1 }
+zrcautoload is-at-least || function is-at-least () { return 1 }
# set some important options (as early as possible)
# display PID when suspending processes as well
setopt longlistjobs
-# try to avoid the 'zsh: no matches found...'
-setopt nonomatch
-
# report the status of backgrounds jobs immediately
setopt notify
typeset -ga ls_options
typeset -ga grep_options
+
+# Colors on GNU ls(1)
if ls --color=auto / >/dev/null 2>&1; then
- ls_options=( --color=auto )
+ ls_options+=( --color=auto )
+# Colors on FreeBSD and OSX ls(1)
elif ls -G / >/dev/null 2>&1; then
- ls_options=( -G )
+ ls_options+=( -G )
+fi
+
+# Natural sorting order on GNU ls(1)
+# OSX and IllumOS have a -v option that is not natural sorting
+if ls --version |& grep -q 'GNU' >/dev/null 2>&1 && ls -v / >/dev/null 2>&1; then
+ ls_options+=( -v )
fi
+
+# Color on GNU and FreeBSD grep(1)
if grep --color=auto -q "a" <<< "a" >/dev/null 2>&1; then
- grep_options=( --color=auto )
+ grep_options+=( --color=auto )
fi
# utility functions
# Usage: check_com [-c|-g] word
# -c only checks for external commands
# -g does the usual tests and also checks for global aliases
-check_com() {
+function check_com () {
emulate -L zsh
local -i comonly gatoo
+ comonly=0
+ gatoo=0
if [[ $1 == '-c' ]] ; then
- (( comonly = 1 ))
- shift
+ comonly=1
+ shift 1
elif [[ $1 == '-g' ]] ; then
- (( gatoo = 1 ))
- else
- (( comonly = 0 ))
- (( gatoo = 0 ))
+ gatoo=1
+ shift 1
fi
if (( ${#argv} != 1 )) ; then
- printf 'usage: check_com [-c] <command>\n' >&2
+ printf 'usage: check_com [-c|-g] <command>\n' >&2
return 1
fi
if (( comonly > 0 )) ; then
- [[ -n ${commands[$1]} ]] && return 0
+ (( ${+commands[$1]} )) && return 0
return 1
fi
- if [[ -n ${commands[$1]} ]] \
- || [[ -n ${functions[$1]} ]] \
- || [[ -n ${aliases[$1]} ]] \
- || [[ -n ${reswords[(r)$1]} ]] ; then
-
+ if (( ${+commands[$1]} )) \
+ || (( ${+functions[$1]} )) \
+ || (( ${+aliases[$1]} )) \
+ || (( ${+reswords[(r)$1]} )) ; then
return 0
fi
- if (( gatoo > 0 )) && [[ -n ${galiases[$1]} ]] ; then
+ if (( gatoo > 0 )) && (( ${+galiases[$1]} )) ; then
return 0
fi
# creates an alias and precedes the command with
# sudo if $EUID is not zero.
-salias() {
+function salias () {
emulate -L zsh
local only=0 ; local multi=0
local key val
- while [[ $1 == -* ]] ; do
- case $1 in
- (-o) only=1 ;;
- (-a) multi=1 ;;
- (--) shift ; break ;;
- (-h)
- printf 'usage: salias [-h|-o|-a] <alias-expression>\n'
+ while getopts ":hao" opt; do
+ case $opt in
+ o) only=1 ;;
+ a) multi=1 ;;
+ h)
+ printf 'usage: salias [-hoa] <alias-expression>\n'
printf ' -h shows this help text.\n'
printf ' -a replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
printf ' be careful using this option.\n'
printf ' -o only sets an alias if a preceding sudo would be needed.\n'
return 0
;;
- (*) printf "unkown option: '%s'\n" "$1" ; return 1 ;;
+ *) salias -h >&2; return 1 ;;
esac
- shift
done
+ shift "$((OPTIND-1))"
if (( ${#argv} > 1 )) ; then
printf 'Too many arguments %s\n' "${#argv}"
return 0
}
-# a "print -l ${(u)foo}"-workaround for pre-4.2.0 shells
-# usage: uprint foo
-# Where foo is the *name* of the parameter you want printed.
-# Note that foo is no typo; $foo would be wrong here!
-if ! is42 ; then
- uprint () {
- emulate -L zsh
- local -a u
- local w
- local parameter=$1
-
- if [[ -z ${parameter} ]] ; then
- printf 'usage: uprint <parameter>\n'
- return 1
- fi
-
- for w in ${(P)parameter} ; do
- [[ -z ${(M)u:#$w} ]] && u=( $u $w )
- done
-
- builtin print -l $u
- }
-fi
-
# Check if we can read given files and source those we can.
-xsource() {
+function xsource () {
if (( ${#argv} < 1 )) ; then
printf 'usage: xsource FILE(s)...\n' >&2
return 1
}
# Check if we can read a given file and 'cat(1)' it.
-xcat() {
+function xcat () {
emulate -L zsh
if (( ${#argv} != 1 )) ; then
printf 'usage: xcat FILE\n' >&2
# Remove these functions again, they are of use only in these
# setup files. This should be called at the end of .zshrc.
-xunfunction() {
+function xunfunction () {
emulate -L zsh
local -a funcs
+ local func
funcs=(salias xcat xsource xunfunction zrcautoload zrcautozle)
for func in $funcs ; do
[[ -n ${functions[$func]} ]] \
# this allows us to stay in sync with grml's zshrc and put own
# modifications in ~/.zshrc.local
-zrclocal() {
+function zrclocal () {
xsource "/etc/zsh/zshrc.local"
xsource "${ZDOTDIR:-${HOME}}/.zshrc.local"
return 0
for var in LANG LC_ALL LC_MESSAGES ; do
[[ -n ${(P)var} ]] && export $var
done
+builtin unset -v var
# set some variables
if check_com -c vim ; then
#v#
export MAIL=${MAIL:-/var/mail/$USER}
-# if we don't set $SHELL then aterm, rxvt,.. will use /bin/sh or /bin/bash :-/
-if [[ -z "$SHELL" ]] ; then
- SHELL="$(which zsh)"
- if [[ -x "$SHELL" ]] ; then
- export SHELL
- fi
-fi
-
# color setup for ls:
check_com -c dircolors && eval $(dircolors -b)
# color setup for ls on OS X / FreeBSD:
# load our function and completion directories
for fdir in /usr/share/grml/zsh/completion /usr/share/grml/zsh/functions; do
fpath=( ${fdir} ${fdir}/**/*(/N) ${fpath} )
- if [[ ${fdir} == '/usr/share/grml/zsh/functions' ]] ; then
- for func in ${fdir}/**/[^_]*[^~](N.) ; do
- zrcautoload ${func:t}
- done
- fi
done
-unset fdir func
+typeset -aU ffiles
+ffiles=(/usr/share/grml/zsh/functions/**/[^_]*[^~](N.:t))
+(( ${#ffiles} > 0 )) && autoload -U "${ffiles[@]}"
+unset -v fdir ffiles
# support colors in less
export LESS_TERMCAP_mb=$'\E[01;31m'
watch=(notme root)
# automatically remove duplicates from these arrays
-typeset -U path cdpath fpath manpath
+typeset -U path PATH cdpath CDPATH fpath FPATH manpath MANPATH
# Load a few modules
is4 && \
for mod in parameter complist deltochar mathfunc ; do
zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :("
-done
+done && builtin unset -v mod
# autoload zsh modules when they are referenced
if is4 ; then
# completion system
COMPDUMPFILE=${COMPDUMPFILE:-${ZDOTDIR:-${HOME}}/.zcompdump}
if zrcautoload compinit ; then
- compinit -d ${COMPDUMPFILE} || print 'Notice: no compinit available :('
+ typeset -a tmp
+ zstyle -a ':grml:completion:compinit' arguments tmp
+ compinit -d ${COMPDUMPFILE} "${tmp[@]}" || print 'Notice: no compinit available :('
+ unset tmp
else
print 'Notice: no compinit available :('
function compdef { }
# called later (via is4 && grmlcomp)
# note: use 'zstyle' for getting current settings
# press ^xh (control-x h) for getting tags in context; ^x? (control-x ?) to run complete_debug with trace output
-grmlcomp() {
+function grmlcomp () {
# TODO: This could use some additional information
# Make sure the completion system is initialised
zstyle ':completion:*' special-dirs ..
# run rehash on completion so new installed program are found automatically:
- _force_rehash() {
+ function _force_rehash () {
(( CURRENT == 1 )) && rehash
return 1
}
# command for process lists, the local web server details and host completion
zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'
- # caching
- [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \
- zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/
+ # Some functions, like _apt and _dpkg, are very slow. We can use a cache in
+ # order to speed things up
+ if [[ ${GRML_COMP_CACHING:-yes} == yes ]]; then
+ GRML_COMP_CACHE_DIR=${GRML_COMP_CACHE_DIR:-${ZDOTDIR:-$HOME}/.cache}
+ if [[ ! -d ${GRML_COMP_CACHE_DIR} ]]; then
+ command mkdir -p "${GRML_COMP_CACHE_DIR}"
+ fi
+ zstyle ':completion:*' use-cache yes
+ zstyle ':completion:*:complete:*' cache-path "${GRML_COMP_CACHE_DIR}"
+ fi
# host completion
if is42 ; then
+ [[ -r ~/.ssh/config ]] && _ssh_config_hosts=(${${(s: :)${(ps:\t:)${${(@M)${(f)"$(<$HOME/.ssh/config)"}:#Host *}#Host }}}:#*[*?]*}) || _ssh_config_hosts=()
[[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
[[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
else
+ _ssh_config_hosts=()
_ssh_hosts=()
_etc_hosts=()
fi
+
+ local localname
+ if check_com hostname ; then
+ localname=$(hostname)
+ elif check_com hostnamectl ; then
+ localname=$(hostnamectl --static)
+ else
+ localname="$(uname -n)"
+ fi
+
hosts=(
- $(hostname)
+ "${localname}"
+ "$_ssh_config_hosts[@]"
"$_ssh_hosts[@]"
"$_etc_hosts[@]"
localhost
# use generic completion system for programs not yet defined; (_gnu_generic works
# with commands that provide a --help option with "standard" gnu-like output.)
for compcom in cp deborphan df feh fetchipac gpasswd head hnb ipacsum mv \
- pal stow tail uname ; do
+ pal stow uname ; do
[[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
done; unset compcom
## beginning-of-line OR beginning-of-buffer OR beginning of history
## by: Bart Schaefer <schaefer@brasslantern.com>, Bernhard Tittelbach
-beginning-or-end-of-somewhere() {
+function beginning-or-end-of-somewhere () {
local hno=$HISTNO
if [[ ( "${LBUFFER[-1]}" == $'\n' && "${WIDGET}" == beginning-of* ) || \
( "${RBUFFER[1]}" == $'\n' && "${WIDGET}" == end-of* ) ]]; then
zle -N end-of-somewhere beginning-or-end-of-somewhere
# add a command line to the shells history without executing it
-commit-to-history() {
- print -s ${(z)BUFFER}
+function commit-to-history () {
+ print -rs ${(z)BUFFER}
zle send-break
}
zle -N commit-to-history
# only slash should be considered as a word separator:
-slash-backward-kill-word() {
+function slash-backward-kill-word () {
local WORDCHARS="${WORDCHARS:s@/@}"
# zle backward-word
zle backward-kill-word
# find the first word on the command line in the $command[] hash.
zstyle ':acceptline:*' rehash true
-function Accept-Line() {
+function Accept-Line () {
setopt localoptions noksharrays
local -a subs
local -xi aldone
done
}
-function Accept-Line-getdefault() {
+function Accept-Line-getdefault () {
emulate -L zsh
local default_action
esac
}
-function Accept-Line-HandleContext() {
+function Accept-Line-HandleContext () {
zle Accept-Line
default_action=$(Accept-Line-getdefault)
&& zle ${default_action}
}
-function accept-line() {
+function accept-line () {
setopt localoptions noksharrays
- local -ax cmdline
+ local -a cmdline
local -x alcontext
local buf com fname format msg default_action
'co' './configure && make && sudo make install'
)
-zleiab() {
+function zleiab () {
emulate -L zsh
setopt extendedglob
local MATCH
zle -N zleiab
-help-show-abk()
-{
+function help-show-abk () {
zle -M "$(print "Available abbreviations for expansion:"; print -a -C 2 ${(kv)abk})"
}
zle -N help-show-abk
-# press "ctrl-e d" to insert the actual date in the form yyyy-mm-dd
-insert-datestamp() { LBUFFER+=${(%):-'%D{%Y-%m-%d}'}; }
+# press "ctrl-x d" to insert the actual date in the form yyyy-mm-dd
+function insert-datestamp () { LBUFFER+=${(%):-'%D{%Y-%m-%d}'}; }
zle -N insert-datestamp
# press esc-m for inserting last typed word again (thanks to caphuso!)
-insert-last-typed-word() { zle insert-last-word -- 0 -1 };
+function insert-last-typed-word () { zle insert-last-word -- 0 -1 };
zle -N insert-last-typed-word;
-function grml-zsh-fg() {
+function grml-zsh-fg () {
if (( ${#jobstates} )); then
zle .push-input
[[ -o hist_ignore_space ]] && BUFFER=' ' || BUFFER=''
zle -N grml-zsh-fg
# run command line as user root via sudo:
-sudo-command-line() {
+function sudo-command-line () {
[[ -z $BUFFER ]] && zle up-history
if [[ $BUFFER != sudo\ * ]]; then
BUFFER="sudo $BUFFER"
### jump behind the first word on the cmdline.
### useful to add options.
-function jump_after_first_word() {
+function jump_after_first_word () {
local words
words=(${(z)BUFFER})
zle -N jump_after_first_word
#f5# Create directory under cursor or the selected area
-inplaceMkDirs() {
+function inplaceMkDirs () {
# Press ctrl-xM to create the directory under the cursor or the selected area.
# To select an area press ctrl-@ or ctrl-space and use the cursor.
# Use case: you type "mv abc ~/testa/testb/testc/" and remember that the
#v1# set location of help-zle cache file
HELP_ZLE_CACHE_FILE=~/.cache/zsh_help_zle_lines.zsh
# helper function for help-zle, actually generates the help text
-help_zle_parse_keybindings()
-{
+function help_zle_parse_keybindings () {
emulate -L zsh
setopt extendedglob
unsetopt ksharrays #indexing starts at 1
if [[ -r $HELP_ZLE_CACHE_FILE ]]; then
local load_cache=0
+ local f
for f ($HELPZLE_KEYBINDING_FILES) [[ $f -nt $HELP_ZLE_CACHE_FILE ]] && load_cache=1
[[ $load_cache -eq 0 ]] && . $HELP_ZLE_CACHE_FILE && return
fi
- #fill with default keybindings, possibly to be overwriten in a file later
+ #fill with default keybindings, possibly to be overwritten in a file later
#Note that due to zsh inconsistency on escaping assoc array keys, we encase the key in '' which we will remove later
local -A help_zle_keybindings
help_zle_keybindings['<Ctrl>@']="set MARK"
help_zle_keybindings['<Alt><arg>']="repeat next cmd/char <arg> times (<Alt>-<Alt>1<Alt>0a -> -10 times 'a')"
help_zle_keybindings['<Alt>u']="make next word Uppercase"
help_zle_keybindings['<Alt>l']="make next word lowercase"
- help_zle_keybindings['<Ctrl>xd']="preview expansion under cursor"
+ help_zle_keybindings['<Ctrl>xG']="preview expansion under cursor"
help_zle_keybindings['<Alt>q']="push current CL into background, freeing it. Restore on next CL"
help_zle_keybindings['<Alt>.']="insert (and interate through) last word from prev CLs"
help_zle_keybindings['<Alt>,']="complete word from newer history (consecutive hits)"
typeset -g -a help_zle_lines
typeset -g help_zle_sln=1
- local k v
+ local k v f cline
local lastkeybind_desc contents #last description starting with #k# that we found
local num_lines_elapsed=0 #number of lines between last description and keybinding
#search config files in the order they a called (and thus the order in which they overwrite keybindings)
# ignores lines that are commentend out
# grabs first in '' or "" enclosed string with length between 1 and 6 characters
elif [[ "$cline" == [^#]#(bind2maps[[:space:]](*)-s|bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*) ]]; then
- #description prevously found ? description not more than 2 lines away ? keybinding not empty ?
+ #description previously found ? description not more than 2 lines away ? keybinding not empty ?
if [[ -n $lastkeybind_desc && $num_lines_elapsed -lt 2 && -n $match[1] ]]; then
#substitute keybinding string with something readable
k=${${${${${${${match[1]/\\e\^h/<Alt><BS>}/\\e\^\?/<Alt><BS>}/\\e\[5~/<PageUp>}/\\e\[6~/<PageDown>}//(\\e|\^\[)/<Alt>}//\^/<Ctrl>}/3~/<Alt><Del>}
typeset -g -a help_zle_lines
# Provides (partially autogenerated) help on keybindings and the zsh line editor
-help-zle()
-{
+function help-zle () {
emulate -L zsh
unsetopt ksharrays #indexing starts at 1
#help lines already generated ? no ? then do it
## complete word from currently visible Screen or Tmux buffer.
if check_com -c screen || check_com -c tmux; then
- _complete_screen_display() {
+ function _complete_screen_display () {
[[ "$TERM" != "screen" ]] && return 1
local TMPFILE=$(mktemp)
# Load a few more functions and tie them to widgets, so they can be bound:
-function zrcautozle() {
+function zrcautozle () {
emulate -L zsh
local fnc=$1
zrcautoload $fnc && zle -N $fnc
}
-function zrcgotwidget() {
+function zrcgotwidget () {
(( ${+widgets[$1]} ))
}
-function zrcgotkeymap() {
+function zrcgotkeymap () {
[[ -n ${(M)keymaps:#$1} ]]
}
# An array to note missing features to ease diagnosis in case of problems.
typeset -ga grml_missing_features
-function zrcbindkey() {
+function zrcbindkey () {
if (( ARGC )) && zrcgotwidget ${argv[-1]}; then
bindkey "$@"
fi
#k# Trigger menu-complete
bind2maps emacs viins -- -s '\ei' menu-complete # menu completion via esc-i
#k# Insert a timestamp on the command line (yyyy-mm-dd)
-bind2maps emacs viins -- -s '^ed' insert-datestamp
+bind2maps emacs viins -- -s '^xd' insert-datestamp
#k# Insert last typed word
bind2maps emacs viins -- -s "\em" insert-last-typed-word
#k# A smart shortcut for \kbd{fg<enter>}
do
bind2maps emacs viins vicmd -- -s $seq $wid
done
+ builtin unset -v seq wid
fi
if zrcgotkeymap menuselect; then
#m# k ESC-h Call \kbd{run-help} for the 1st word on the command line
alias run-help >&/dev/null && unalias run-help
-for rh in run-help{,-git,-svk,-svn}; do
+for rh in run-help{,-git,-ip,-openssl,-p4,-sudo,-svk,-svn}; do
zrcautoload $rh
done; unset rh
# command not found handling
(( ${COMMAND_NOT_FOUND} == 1 )) &&
-function command_not_found_handler() {
+function command_not_found_handler () {
emulate -L zsh
if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then
${GRML_ZSH_CNF_HANDLER} $1
# history
-ZSHDIR=${ZDOTDIR:-${HOME}/.zsh}
-
#v#
-HISTFILE=${ZDOTDIR:-${HOME}}/.zsh_history
+HISTFILE=${HISTFILE:-${ZDOTDIR:-${HOME}}/.zsh_history}
isgrmlcd && HISTSIZE=500 || HISTSIZE=5000
isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history
DIRSTACKSIZE=${DIRSTACKSIZE:-20}
DIRSTACKFILE=${DIRSTACKFILE:-${ZDOTDIR:-${HOME}}/.zdirs}
-if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
- dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
- # "cd -" won't work after login by just setting $OLDPWD, so
- [[ -d $dirstack[1] ]] && cd $dirstack[1] && cd $OLDPWD
-fi
+if zstyle -T ':grml:chpwd:dirstack' enable; then
+ typeset -gaU GRML_PERSISTENT_DIRSTACK
+ function grml_dirstack_filter () {
+ local -a exclude
+ local filter entry
+ if zstyle -s ':grml:chpwd:dirstack' filter filter; then
+ $filter $1 && return 0
+ fi
+ if zstyle -a ':grml:chpwd:dirstack' exclude exclude; then
+ for entry in "${exclude[@]}"; do
+ [[ $1 == ${~entry} ]] && return 0
+ done
+ fi
+ return 1
+ }
-chpwd() {
- if (( $DIRSTACKSIZE <= 0 )) || [[ -z $DIRSTACKFILE ]]; then return; fi
- local -ax my_stack
- my_stack=( ${PWD} ${dirstack} )
- if is42 ; then
- builtin print -l ${(u)my_stack} >! ${DIRSTACKFILE}
+ function chpwd () {
+ (( ZSH_SUBSHELL )) && return
+ (( $DIRSTACKSIZE <= 0 )) && return
+ [[ -z $DIRSTACKFILE ]] && return
+ grml_dirstack_filter $PWD && return
+ GRML_PERSISTENT_DIRSTACK=(
+ $PWD "${(@)GRML_PERSISTENT_DIRSTACK[1,$DIRSTACKSIZE]}"
+ )
+ builtin print -l ${GRML_PERSISTENT_DIRSTACK} >! ${DIRSTACKFILE}
+ }
+
+ if [[ -f ${DIRSTACKFILE} ]]; then
+ # Enabling NULL_GLOB via (N) weeds out any non-existing
+ # directories from the saved dir-stack file.
+ dirstack=( ${(f)"$(< $DIRSTACKFILE)"}(N) )
+ # "cd -" won't work after login by just setting $OLDPWD, so
+ [[ -d $dirstack[1] ]] && cd -q $dirstack[1] && cd -q $OLDPWD
+ fi
+
+ if zstyle -t ':grml:chpwd:dirstack' filter-on-load; then
+ for i in "${dirstack[@]}"; do
+ if ! grml_dirstack_filter "$i"; then
+ GRML_PERSISTENT_DIRSTACK=(
+ "${GRML_PERSISTENT_DIRSTACK[@]}"
+ $i
+ )
+ fi
+ done
else
- uprint my_stack >! ${DIRSTACKFILE}
+ GRML_PERSISTENT_DIRSTACK=( "${dirstack[@]}" )
fi
-}
+fi
# directory based profiles
# chpwd_profiles
#
# For details see the `grmlzshrc.5' manual page.
-function chpwd_profiles() {
+function chpwd_profiles () {
local profile context
local -i reexecute
# display battery status on right side of prompt using 'GRML_DISPLAY_BATTERY=1' in .zshrc.pre
-battery() {
+function battery () {
if [[ $GRML_DISPLAY_BATTERY -gt 0 ]] ; then
if islinux ; then
batterylinux
fi
}
-batterylinux(){
+function batterylinux () {
GRML_BATTERY_LEVEL=''
local batteries bat capacity
batteries=( /sys/class/power_supply/BAT*(N) )
if (( $#batteries > 0 )) ; then
for bat in $batteries ; do
- capacity=$(< $bat/capacity)
+ if [[ -e $bat/capacity ]]; then
+ capacity=$(< $bat/capacity)
+ else
+ typeset -F energy_full=$(< $bat/energy_full)
+ typeset -F energy_now=$(< $bat/energy_now)
+ typeset -i capacity=$(( 100 * $energy_now / $energy_full))
+ fi
case $(< $bat/status) in
Charging)
GRML_BATTERY_LEVEL+=" ^"
fi
}
-batteryopenbsd(){
+function batteryopenbsd () {
GRML_BATTERY_LEVEL=''
local bat batfull batwarn batnow num
for num in 0 1 ; do
done
}
-batteryfreebsd(){
+function batteryfreebsd () {
GRML_BATTERY_LEVEL=''
local num
local -A table
done
}
-batterydarwin(){
+function batterydarwin () {
GRML_BATTERY_LEVEL=''
local -a table
-table=( ${$(pmset -g ps)[(w)7,8]%%(\%|);} )
+table=( ${$(pmset -g ps)[(w)8,9]%%(\%|);} )
if [[ -n $table[2] ]] ; then
case $table[2] in
charging)
typeset GRML_VCS_COLOUR_MODE=xxx
-grml_vcs_info_toggle_colour () {
+function grml_vcs_info_toggle_colour () {
emulate -L zsh
if [[ $GRML_VCS_COLOUR_MODE == plain ]]; then
grml_vcs_info_set_formats coloured
return 0
}
-grml_vcs_info_set_formats () {
+function grml_vcs_info_set_formats () {
emulate -L zsh
#setopt localoptions xtrace
local mode=$1 AF F BF
# below, which gets called when the user does this: prompt -h grml
function prompt_grml_help () {
- cat <<__EOF0__
+ <<__EOF0__
prompt grml
This is the prompt as used by the grml-live system <http://grml.org>. It is
accordingly. Default (left): rc change-root user at host path vcs
percent; Default (right): sad-smiley
+ - strip-sensitive-characters (boolean): If the \`prompt_subst' option
+ is active in zsh, the shell performs lots of expansions on prompt
+ variable strings, including command substitution. So if you don't
+ control where some of your prompt strings is coming from, this is
+ an exploitable weakness. Grml's zsh setup does not set this option
+ and it is off in the shell in zsh-mode by default. If it *is* turned
+ on however, this style becomes active, and there are two flavours of
+ it: On per default is a global variant in the '*:setup' context. This
+ strips characters after the whole prompt string was constructed. There
+ is a second variant in the '*:items:<item>', that is off by default.
+ It allows fine grained control over which items' data is stripped.
+ The characters that are stripped are: \$ and \`.
+
Available styles in 'items:<item>' are: pre, post. These are strings that
are inserted before (pre) and after (post) the item in question. Thus, the
following would cause the user name to be printed in red instead of the
}
function prompt_grml-chroot_help () {
- cat <<__EOF0__
+ <<__EOF0__
prompt grml-chroot
This is a variation of the grml prompt, see: prompt -h grml
}
function prompt_grml-large_help () {
- cat <<__EOF0__
+ <<__EOF0__
prompt grml-large
This is a variation of the grml prompt, see: prompt -h grml
function grml_prompt_setup () {
emulate -L zsh
autoload -Uz vcs_info
- autoload -Uz add-zsh-hook
+ # The following autoload is disabled for now, since this setup includes a
+ # static version of the ‘add-zsh-hook’ function above. It needs to be
+ # re-enabled as soon as that static definition is removed again.
+ #autoload -Uz add-zsh-hook
add-zsh-hook precmd prompt_$1_precmd
}
}
function GRML_theme_add_token_usage () {
- cat <<__EOF__
+ <<__EOF0__
Usage: grml_theme_add_token <name> [-f|-i] <token/function> [<pre> <post>]
<name> is the name for the newly added token. If the \`-f' or \`-i' options
After that, you will be able to use a changed \`items' style to
assemble your prompt.
-__EOF__
+__EOF0__
}
function grml_theme_add_token () {
return 2
fi
if (( init )); then
+ REPLY=''
$token $name
token=$REPLY
fi
fi
}
-function grml_typeset_and_wrap () {
+function grml_wrap_reply () {
emulate -L zsh
local target="$1"
local new="$2"
local right="$4"
if (( ${+parameters[$new]} )); then
- typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
+ REPLY="${left}${(P)new}${right}"
+ else
+ REPLY=''
fi
}
function grml_prompt_addto () {
emulate -L zsh
local target="$1"
- local lr it apre apost new v
+ local lr it apre apost new v REPLY
local -a items
shift
|| apost=${grml_prompt_post_default[$it]}
zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
|| new=${grml_prompt_token_default[$it]}
- typeset -g "${target}=${(P)target}${apre}"
if (( ${+grml_prompt_token_function[$it]} )); then
+ REPLY=''
${grml_prompt_token_function[$it]} $it
- typeset -g "${target}=${(P)target}${REPLY}"
else
case $it in
battery)
- grml_typeset_and_wrap $target $new '' ''
+ grml_wrap_reply $target $new '' ''
;;
change-root)
- grml_typeset_and_wrap $target $new '(' ')'
+ grml_wrap_reply $target $new '(' ')'
;;
grml-chroot)
if [[ -n ${(P)new} ]]; then
- typeset -g "${target}=${(P)target}(CHROOT)"
+ REPLY="$CHROOT"
+ else
+ REPLY=''
fi
;;
vcs)
vcscalled=1
fi
if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
- typeset -g "${target}=${(P)target}${(P)v}"
+ REPLY="${(P)v}"
+ else
+ REPLY=''
fi
;;
- *) typeset -g "${target}=${(P)target}${new}" ;;
+ *) REPLY="$new" ;;
esac
fi
- typeset -g "${target}=${(P)target}${apost}"
+ # Strip volatile characters per item. This is off by default. See the
+ # global stripping code a few lines below for details.
+ if [[ -o prompt_subst ]] && zstyle -t ":prompt:${grmltheme}:${lr}:items:$it" \
+ strip-sensitive-characters
+ then
+ REPLY="${REPLY//[$\`]/}"
+ fi
+ typeset -g "${target}=${(P)target}${apre}${REPLY}${apost}"
done
+
+ # Per default, strip volatile characters (in the prompt_subst case)
+ # globally. If the option is off, the style has no effect. For more
+ # control, this can be turned off and stripping can be configured on a
+ # per-item basis (see above).
+ if [[ -o prompt_subst ]] && zstyle -T ":prompt:${grmltheme}:${lr}:setup" \
+ strip-sensitive-characters
+ then
+ typeset -g "${target}=${${(P)target}//[$\`]/}"
+ fi
}
function prompt_grml_precmd () {
fi
}
-grml_prompt_fallback() {
+function grml_prompt_fallback () {
setopt prompt_subst
- precmd() {
- (( ${+functions[vcs_info]} )) && vcs_info
- }
+ local p0 p1
p0="${RED}%(?..%? )${WHITE}${debian_chroot:+($debian_chroot)}"
p1="${BLUE}%n${NO_COLOR}@%m %40<...<%B%~%b%<< "'${vcs_info_msg_0_}'"%# "
else
PROMPT="${RED}${p0}${BLUE}${p1}"
fi
- unset p0 p1
}
if zrcautoload promptinit && promptinit 2>/dev/null ; then
else
print 'Notice: no promptinit available :('
grml_prompt_fallback
+ function precmd () { (( ${+functions[vcs_info]} )) && vcs_info; }
fi
if is437; then
fi
else
grml_prompt_fallback
+ function precmd () { (( ${+functions[vcs_info]} )) && vcs_info; }
fi
+# make sure to use right prompt only when not running a command
+is41 && setopt transient_rprompt
+
# Terminal-title wizardry
function ESC_print () {
}
function grml_maintain_name () {
- # set hostname if not running on host with name 'grml'
- if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then
+ local localname
+ localname="$(uname -n)"
+
+ # set hostname if not running on local machine
+ if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != "${localname}" ]] ; then
NAME="@$HOSTNAME"
fi
}
function grml_control_xterm_title () {
case $TERM in
(xterm*|rxvt*)
- set_title "${(%):-"%n@%m:"}" "$1"
+ set_title "${(%):-"%n@%m:"}" "$2"
;;
esac
}
-zrcautoload add-zsh-hook || add-zsh-hook () { :; }
+# The following autoload is disabled for now, since this setup includes a
+# static version of the ‘add-zsh-hook’ function above. It needs to be
+# re-enabled as soon as that static definition is removed again.
+#zrcautoload add-zsh-hook || add-zsh-hook () { :; }
if [[ $NOPRECMD -eq 0 ]]; then
add-zsh-hook precmd grml_reset_screen_title
add-zsh-hook precmd grml_vcs_to_screen_title
if check_com -c screen ; then
if [[ $UID -eq 0 ]] ; then
if [[ -r /etc/grml/screenrc ]]; then
- alias screen="${commands[screen]} -c /etc/grml/screenrc"
+ alias screen='screen -c /etc/grml/screenrc'
fi
- elif [[ -r $HOME/.screenrc ]] ; then
- alias screen="${commands[screen]} -c $HOME/.screenrc"
- else
+ elif [[ ! -r $HOME/.screenrc ]] ; then
if [[ -r /etc/grml/screenrc_grml ]]; then
- alias screen="${commands[screen]} -c /etc/grml/screenrc_grml"
+ alias screen='screen -c /etc/grml/screenrc_grml'
else
if [[ -r /etc/grml/screenrc ]]; then
- alias screen="${commands[screen]} -c /etc/grml/screenrc"
+ alias screen='screen -c /etc/grml/screenrc'
fi
fi
fi
# do we have GNU ls with color-support?
if [[ "$TERM" != dumb ]]; then
- #a1# List files with colors (\kbd{ls -F \ldots})
- alias ls='command ls -F '${ls_options:+"${ls_options[*]}"}
+ #a1# List files with colors (\kbd{ls \ldots})
+ alias ls="command ls ${ls_options:+${ls_options[*]}}"
#a1# List all files, with colors (\kbd{ls -la \ldots})
- alias la='command ls -la '${ls_options:+"${ls_options[*]}"}
+ alias la="command ls -la ${ls_options:+${ls_options[*]}}"
#a1# List files with long colored list, without dotfiles (\kbd{ls -l \ldots})
- alias ll='command ls -l '${ls_options:+"${ls_options[*]}"}
+ alias ll="command ls -l ${ls_options:+${ls_options[*]}}"
#a1# List files with long colored list, human readable sizes (\kbd{ls -hAl \ldots})
- alias lh='command ls -hAl '${ls_options:+"${ls_options[*]}"}
- #a1# List files with long colored list, append qualifier to filenames (\kbd{ls -lF \ldots})\\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
- alias l='command ls -lF '${ls_options:+"${ls_options[*]}"}
+ alias lh="command ls -hAl ${ls_options:+${ls_options[*]}}"
+ #a1# List files with long colored list, append qualifier to filenames (\kbd{ls -l \ldots})\\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
+ alias l="command ls -l ${ls_options:+${ls_options[*]}}"
else
- alias ls='command ls -F'
alias la='command ls -la'
alias ll='command ls -l'
alias lh='command ls -hAl'
- alias l='command ls -lF'
+ alias l='command ls -l'
+fi
+
+if [[ -r /proc/mdstat ]]; then
+ alias mdstat='cat /proc/mdstat'
fi
-alias mdstat='cat /proc/mdstat'
alias ...='cd ../../'
# generate alias named "$KERNELVERSION-reboot" so you can use boot with kexec:
# make sure it is not assigned yet
[[ -n ${aliases[utf2iso]} ]] && unalias utf2iso
-utf2iso() {
+function utf2iso () {
if isutfenv ; then
+ local ENV
for ENV in $(env | command grep -i '.utf') ; do
eval export "$(echo $ENV | sed 's/UTF-8/iso885915/ ; s/utf8/iso885915/')"
done
# make sure it is not assigned yet
[[ -n ${aliases[iso2utf]} ]] && unalias iso2utf
-iso2utf() {
+function iso2utf () {
if ! isutfenv ; then
+ local ENV
for ENV in $(env | command grep -i '\.iso') ; do
eval export "$(echo $ENV | sed 's/iso.*/UTF-8/ ; s/ISO.*/UTF-8/')"
done
# especially for roadwarriors using GNU screen and ssh:
if ! check_com asc &>/dev/null ; then
- asc() { autossh -t "$@" 'screen -RdU' }
+ function asc () { autossh -t "$@" 'screen -RdU' }
compdef asc=ssh
fi
#f1# Hints for the use of zsh on grml
-zsh-help() {
+function zsh-help () {
print "$bg[white]$fg[black]
zsh-help - hints for use of zsh on grml
=======================================$reset_color"
# debian stuff
if [[ -r /etc/debian_version ]] ; then
- #a3# Execute \kbd{apt-cache search}
- alias acs='apt-cache search'
- #a3# Execute \kbd{apt-cache show}
- alias acsh='apt-cache show'
- #a3# Execute \kbd{apt-cache policy}
- alias acp='apt-cache policy'
- #a3# Execute \kbd{apt-get dist-upgrade}
- salias adg="apt-get dist-upgrade"
- #a3# Execute \kbd{apt-get install}
- salias agi="apt-get install"
- #a3# Execute \kbd{aptitude install}
- salias ati="aptitude install"
- #a3# Execute \kbd{apt-get upgrade}
- salias ag="apt-get upgrade"
- #a3# Execute \kbd{apt-get update}
- salias au="apt-get update"
- #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
- salias -a up="aptitude update ; aptitude safe-upgrade"
- #a3# Execute \kbd{dpkg-buildpackage}
- alias dbp='dpkg-buildpackage'
- #a3# Execute \kbd{grep-excuses}
- alias ge='grep-excuses'
+ if [[ -z "$GRML_NO_APT_ALIASES" ]]; then
+ #a3# Execute \kbd{apt-cache policy}
+ alias acp='apt-cache policy'
+ if check_com -c apt ; then
+ #a3# Execute \kbd{apt search}
+ alias acs='apt search'
+ #a3# Execute \kbd{apt show}
+ alias acsh='apt show'
+ #a3# Execute \kbd{apt dist-upgrade}
+ salias adg="apt dist-upgrade"
+ #a3# Execute \kbd{apt upgrade}
+ salias ag="apt upgrade"
+ #a3# Execute \kbd{apt install}
+ salias agi="apt install"
+ #a3# Execute \kbd{apt update}
+ salias au="apt update"
+ else
+ alias acs='apt-cache search'
+ alias acsh='apt-cache show'
+ salias adg="apt-get dist-upgrade"
+ salias ag="apt-get upgrade"
+ salias agi="apt-get install"
+ salias au="apt-get update"
+ fi
+ #a3# Execute \kbd{aptitude install}
+ salias ati="aptitude install"
+ #a3# Execute \kbd{aptitude update ; aptitude safe-upgrade}
+ salias -a up="aptitude update ; aptitude safe-upgrade"
+ #a3# Execute \kbd{dpkg-buildpackage}
+ alias dbp='dpkg-buildpackage'
+ #a3# Execute \kbd{grep-excuses}
+ alias ge='grep-excuses'
+ fi
# get a root shell as normal user in live-cd mode:
if isgrmlcd && [[ $UID -ne 0 ]] ; then
alias su="sudo su"
- fi
+ fi
- #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog}
- salias llog="$PAGER /var/log/syslog" # take a look at the syslog
- #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog}
- salias tlog="tail -f /var/log/syslog" # follow the syslog
+fi
+
+# use /var/log/syslog iff present, fallback to journalctl otherwise
+if [ -e /var/log/syslog ] ; then
+ #a1# Take a look at the syslog: \kbd{\$PAGER /var/log/syslog || journalctl}
+ salias llog="$PAGER /var/log/syslog" # take a look at the syslog
+ #a1# Take a look at the syslog: \kbd{tail -f /var/log/syslog || journalctl}
+ salias tlog="tail -f /var/log/syslog" # follow the syslog
+elif check_com -c journalctl ; then
+ salias llog="journalctl"
+ salias tlog="journalctl -f"
fi
# sort installed Debian-packages by size
# if cdrecord is a symlink (to wodim) or isn't present at all warn:
if [[ -L /usr/bin/cdrecord ]] || ! check_com -c cdrecord; then
if check_com -c wodim; then
- cdrecord() {
- cat <<EOMESS
+ function cdrecord () {
+ <<__EOF0__
cdrecord is not provided under its original name by Debian anymore.
See #377109 in the BTS of Debian for more details.
Please use the wodim binary instead
-EOMESS
+__EOF0__
return 1
}
fi
fi
-# Use hard limits, except for a smaller stack and no core dumps
-unlimit
-is425 && limit stack 8192
-isgrmlcd && limit core 0 # important for a live-cd-system
-limit -s
+if isgrmlcd; then
+ # No core dumps: important for a live-cd-system
+ limit -s core 0
+fi
# grmlstuff
-grmlstuff() {
+function grmlstuff () {
# people should use 'grml-x'!
if check_com -c 915resolution; then
- 855resolution() {
+ function 855resolution () {
echo "Please use 915resolution as resolution modifying tool for Intel \
graphic chipset."
return -1
alias grml-version='cat /etc/grml_version'
if check_com -c grml-debootstrap ; then
- debian2hd() {
+ function debian2hd () {
echo "Installing debian to harddisk is possible by using grml-debootstrap."
return 1
}
fi
+
+ if check_com -c tmate && check_com -c qrencode ; then
+ function grml-remote-support() {
+ tmate -L grml-remote-support new -s grml-remote-support -d
+ tmate -L grml-remote-support wait tmate-ready
+ tmate -L grml-remote-support display -p '#{tmate_ssh}' | qrencode -t ANSI
+ echo "tmate session: $(tmate -L grml-remote-support display -p '#{tmate_ssh}')"
+ echo
+ echo "Scan this QR code and send it to your support team."
+ }
+ fi
}
# now run the functions
# This lists all the files in the current directory newer than the reference file.
# You can also specify the reference file inline; note quotes:
# $ ls -l *(e:'nt ~/.zshenv':)
-is4 && nt() {
+is4 && function nt () {
if [[ -n $1 ]] ; then
local NTREF=${~1}
fi
# shell functions
#f1# Reload an autoloadable function
-freload() { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
+function freload () { while (( $# )); do; unfunction $1; autoload -U $1; shift; done }
compdef _functions freload
-#f1# List symlinks in detail (more detailed version of 'readlink -f' and 'whence -s')
-sll() {
- [[ -z "$1" ]] && printf 'Usage: %s <file(s)>\n' "$0" && return 1
- local file
- for file in "$@" ; do
+#
+# Usage:
+#
+# e.g.: a -> b -> c -> d ....
+#
+# sll a
+#
+#
+# if parameter is given with leading '=', lookup $PATH for parameter and resolve that
+#
+# sll =java
+#
+# Note: limit for recursive symlinks on linux:
+# http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/namei.c?id=refs/heads/master#l808
+# This limits recursive symlink follows to 8,
+# while limiting consecutive symlinks to 40.
+#
+# When resolving and displaying information about symlinks, no check is made
+# that the displayed information does make any sense on your OS.
+# We leave that decission to the user.
+#
+# The zstat module is used to detect symlink loops. zstat is available since zsh4.
+# With an older zsh you will need to abort with <C-c> in that case.
+# When a symlink loop is detected, a warning ist printed and further processing is stopped.
+#
+# Module zstat is loaded by default in grml zshrc, no extra action needed for that.
+#
+# Known bugs:
+# If you happen to come across a symlink that points to a destination on another partition
+# with the same inode number, that will be marked as symlink loop though it is not.
+# Two hints for this situation:
+# I) Play lottery the same day, as you seem to be rather lucky right now.
+# II) Send patches.
+#
+# return status:
+# 0 upon success
+# 1 file/dir not accesible
+# 2 symlink loop detected
+#
+#f1# List symlinks in detail (more detailed version of 'readlink -f', 'whence -s' and 'namei -l')
+function sll () {
+ if [[ -z ${1} ]] ; then
+ printf 'Usage: %s <symlink(s)>\n' "${0}"
+ return 1
+ fi
+
+ local file jumpd curdir
+ local -i 10 RTN LINODE i
+ local -a SEENINODES
+ curdir="${PWD}"
+ RTN=0
+
+ for file in "${@}" ; do
+ SEENINODES=()
+ ls -l "${file:a}" || RTN=1
+
while [[ -h "$file" ]] ; do
- ls -l $file
+ if is4 ; then
+ LINODE=$(zstat -L +inode "${file}")
+ for i in ${SEENINODES} ; do
+ if (( ${i} == ${LINODE} )) ; then
+ builtin cd -q "${curdir}"
+ print 'link loop detected, aborting!'
+ return 2
+ fi
+ done
+ SEENINODES+=${LINODE}
+ fi
+ jumpd="${file:h}"
+ file="${file:t}"
+
+ if [[ -d ${jumpd} ]] ; then
+ builtin cd -q "${jumpd}" || RTN=1
+ fi
file=$(readlink "$file")
+
+ jumpd="${file:h}"
+ file="${file:t}"
+
+ if [[ -d ${jumpd} ]] ; then
+ builtin cd -q "${jumpd}" || RTN=1
+ fi
+
+ ls -l "${PWD}/${file}" || RTN=1
done
+ shift 1
+ if (( ${#} >= 1 )) ; then
+ print ""
+ fi
+ builtin cd -q "${curdir}"
done
+ return ${RTN}
}
-# TODO: Is it supported to use pager settings like this?
-# PAGER='less -Mr' - If so, the use of $PAGER here needs fixing
-# with respect to wordsplitting. (ie. ${=PAGER})
if check_com -c $PAGER ; then
#f3# View Debian's changelog of given package(s)
- dchange() {
+ function dchange () {
emulate -L zsh
[[ -z "$1" ]] && printf 'Usage: %s <package_name(s)>\n' "$0" && return 1
local package
+
+ # `less` as $PAGER without e.g. `|lesspipe %s` inside $LESSOPEN can't properly
+ # read *.gz files, try to detect this to use vi instead iff available
+ local viewer
+
+ if [[ ${$(typeset -p PAGER)[2]} = -a ]] ; then
+ viewer=($PAGER) # support PAGER=(less -Mr) but leave array untouched
+ else
+ viewer=(${=PAGER}) # support PAGER='less -Mr'
+ fi
+
+ if [[ ${viewer[1]:t} = less ]] && [[ -z "${LESSOPEN}" ]] && check_com vi ; then
+ viewer='vi'
+ fi
+
for package in "$@" ; do
if [[ -r /usr/share/doc/${package}/changelog.Debian.gz ]] ; then
- $PAGER /usr/share/doc/${package}/changelog.Debian.gz
+ $viewer /usr/share/doc/${package}/changelog.Debian.gz
elif [[ -r /usr/share/doc/${package}/changelog.gz ]] ; then
- $PAGER /usr/share/doc/${package}/changelog.gz
+ $viewer /usr/share/doc/${package}/changelog.gz
elif [[ -r /usr/share/doc/${package}/changelog ]] ; then
- $PAGER /usr/share/doc/${package}/changelog
+ $viewer /usr/share/doc/${package}/changelog
else
if check_com -c aptitude ; then
echo "No changelog for package $package found, using aptitude to retrieve it."
fi
done
}
- _dchange() { _files -W /usr/share/doc -/ }
+ function _dchange () { _files -W /usr/share/doc -/ }
compdef _dchange dchange
#f3# View Debian's NEWS of a given package
- dnews() {
+ function dnews () {
emulate -L zsh
if [[ -r /usr/share/doc/$1/NEWS.Debian.gz ]] ; then
$PAGER /usr/share/doc/$1/NEWS.Debian.gz
fi
fi
}
- _dnews() { _files -W /usr/share/doc -/ }
+ function _dnews () { _files -W /usr/share/doc -/ }
compdef _dnews dnews
#f3# View Debian's copyright of a given package
- dcopyright() {
+ function dcopyright () {
emulate -L zsh
if [[ -r /usr/share/doc/$1/copyright ]] ; then
$PAGER /usr/share/doc/$1/copyright
return 1
fi
}
- _dcopyright() { _files -W /usr/share/doc -/ }
+ function _dcopyright () { _files -W /usr/share/doc -/ }
compdef _dcopyright dcopyright
#f3# View upstream's changelog of a given package
- uchange() {
+ function uchange () {
emulate -L zsh
if [[ -r /usr/share/doc/$1/changelog.gz ]] ; then
$PAGER /usr/share/doc/$1/changelog.gz
return 1
fi
}
- _uchange() { _files -W /usr/share/doc -/ }
+ function _uchange () { _files -W /usr/share/doc -/ }
compdef _uchange uchange
fi
# zsh profiling
-profile() {
- ZSH_PROFILE_RC=1 $SHELL "$@"
+function profile () {
+ ZSH_PROFILE_RC=1 zsh "$@"
}
#f1# Edit an alias via zle
-edalias() {
+function edalias () {
[[ -z "$1" ]] && { echo "Usage: edalias <alias_to_edit>" ; return 1 } || vared aliases'[$1]' ;
}
compdef _aliases edalias
#f1# Edit a function via zle
-edfunc() {
+function edfunc () {
[[ -z "$1" ]] && { echo "Usage: edfunc <function_to_edit>" ; return 1 } || zed -f "$1" ;
}
compdef _functions edfunc
# use it e.g. via 'Restart apache2'
-#m# f6 Start() \kbd{/etc/init.d/\em{process}}\quad\kbd{start}
-#m# f6 Restart() \kbd{/etc/init.d/\em{process}}\quad\kbd{restart}
-#m# f6 Stop() \kbd{/etc/init.d/\em{process}}\quad\kbd{stop}
-#m# f6 Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{reload}
-#m# f6 Force-Reload() \kbd{/etc/init.d/\em{process}}\quad\kbd{force-reload}
-#m# f6 Status() \kbd{/etc/init.d/\em{process}}\quad\kbd{status}
+#m# f6 Start() \kbd{service \em{process}}\quad\kbd{start}
+#m# f6 Restart() \kbd{service \em{process}}\quad\kbd{restart}
+#m# f6 Stop() \kbd{service \em{process}}\quad\kbd{stop}
+#m# f6 Reload() \kbd{service \em{process}}\quad\kbd{reload}
+#m# f6 Force-Reload() \kbd{service \em{process}}\quad\kbd{force-reload}
+#m# f6 Status() \kbd{service \em{process}}\quad\kbd{status}
if [[ -d /etc/init.d || -d /etc/service ]] ; then
- __start_stop() {
+ function __start_stop () {
local action_="${1:l}" # e.g Start/Stop/Restart
local service_="$2"
local param_="$3"
*) $SUDO "/etc/init.d/$service_" "${action_}" "$param_" ;;
esac
else
- # sysvinit
- $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
+ # sysv/sysvinit-utils, upstart
+ if check_com -c service ; then
+ $SUDO service "$service_" "${action_}" "$param_"
+ else
+ $SUDO "/etc/init.d/$service_" "${action_}" "$param_"
+ fi
fi
}
- _grmlinitd() {
+ function _grmlinitd () {
local -a scripts
scripts=( /etc/init.d/*(x:t) )
_describe "service startup script" scripts
}
for i in Start Restart Stop Force-Reload Reload Status ; do
- eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
+ eval "function $i () { __start_stop $i \"\$1\" \"\$2\" ; }"
compdef _grmlinitd $i
done
+ builtin unset -v i
fi
#f1# Provides useful information on globbing
-H-Glob() {
+function H-Glob () {
echo -e "
/ directories
. plain files
alias help-zshglob=H-Glob
# grep for running process, like: 'any vim'
-any() {
+function any () {
emulate -L zsh
unsetopt KSH_ARRAYS
if [[ -z "$1" ]] ; then
# After resuming from suspend, system is paging heavily, leading to very bad interactivity.
# taken from $LINUX-KERNELSOURCE/Documentation/power/swsusp.txt
[[ -r /proc/1/maps ]] && \
-deswap() {
+function deswap () {
print 'Reading /proc/[0-9]*/maps and sending output to /dev/null, this might take a while.'
cat $(sed -ne 's:.* /:/:p' /proc/[0-9]*/maps | sort -u | grep -v '^/dev/') > /dev/null
print 'Finished, running "swapoff -a; swapon -a" may also be useful.'
# This will cause vim to send every file given on the
# commandline to be send to it's own tab (needs vim7).
if check_com vim; then
- vim() {
+ function vim () {
VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@"
}
fi
}'
done; unset sh
-ssl-cert-fingerprints() {
+function ssl-cert-fingerprints () {
emulate -L zsh
local i
if [[ -z $1 ]] ; then
done
}
-ssl-cert-info() {
+function ssl-cert-info () {
emulate -L zsh
if [[ -z $1 ]] ; then
printf 'usage: ssl-cert-info <file>\n'
}
# make sure our environment is clean regarding colors
-for color in BLUE RED GREEN CYAN YELLOW MAGENTA WHITE ; unset $color
+builtin unset -v BLUE RED GREEN CYAN YELLOW MAGENTA WHITE NO_COLOR
# "persistent history"
-# just write important commands you always need to ~/.important_commands
+# just write important commands you always need to $GRML_IMPORTANT_COMMANDS
+# defaults for backward compatibility to ~/.important_commands
if [[ -r ~/.important_commands ]] ; then
- fc -R ~/.important_commands
+ GRML_IMPORTANT_COMMANDS=~/.important_commands
+else
+ GRML_IMPORTANT_COMMANDS=${GRML_IMPORTANT_COMMANDS:-${ZDOTDIR:-${HOME}}/.important_commands}
fi
+[[ -r ${GRML_IMPORTANT_COMMANDS} ]] && builtin fc -R ${GRML_IMPORTANT_COMMANDS}
# load the lookup subsystem if it's available on the system
zrcautoload lookupinit && lookupinit
# general
#a2# Execute \kbd{du -sch}
-alias da='du -sch'
+[[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias da='du -sch'
# listing stuff
#a2# Execute \kbd{ls -lSrah}
# useful functions
#f5# Backup \kbd{file_or_folder {\rm to} file_or_folder\_timestamp}
-bk() {
+function bk () {
emulate -L zsh
- local current_date=$(date -u "+%Y-%m-%dT%H:%M:%SZ")
- local keep move verbose result
- usage() {
- cat << EOT
+ local current_date=$(date -u "+%Y%m%dT%H%M%SZ")
+ local clean keep move verbose result all to_bk
+ setopt extended_glob
+ keep=1
+ while getopts ":hacmrv" opt; do
+ case $opt in
+ a) (( all++ ));;
+ c) unset move clean && (( ++keep ));;
+ m) unset keep clean && (( ++move ));;
+ r) unset move keep && (( ++clean ));;
+ v) verbose="-v";;
+ h) <<__EOF0__
bk [-hcmv] FILE [FILE ...]
+bk -r [-av] [FILE [FILE ...]]
Backup a file or folder in place and append the timestamp
+Remove backups of a file or folder, or all backups in the current directory
Usage:
-h Display this help text
-c Keep the file/folder as is, create a copy backup using cp(1) (default)
-m Move the file/folder, using mv(1)
+-r Remove backups of the specified file or directory, using rm(1). If none
+ is provided, remove all backups in the current directory.
+-a Remove all (even hidden) backups.
-v Verbose
-The -c and -m options can't be used at the same time. If both specified, the
-last one is used.
+The -c, -r and -m options are mutually exclusive. If specified at the same time,
+the last one is used.
-The return code is the sum of all cp/mv return codes.
-EOT
- }
- keep=1
- while getopts ":hcmv" opt; do
- case $opt in
- c) unset move && (( ++keep ));;
- m) unset keep && (( ++move ));;
- v) verbose="-v";;
- h) usage;;
- \?) usage >&2; return 1;;
+The return code is the sum of all cp/mv/rm return codes.
+__EOF0__
+return 0;;
+ \?) bk -h >&2; return 1;;
esac
done
shift "$((OPTIND-1))"
if (( keep > 0 )); then
- while (( $# > 0 )); do
- if islinux || isfreebsd; then
- cp $verbose -a "${1%/}" "${1%/}_$current_date"
- else;
- cp $verbose -pR "${1%/}" "${1%/}_$current_date"
- fi
- (( result += $? ))
- shift
- done
+ if islinux || isfreebsd; then
+ for to_bk in "$@"; do
+ cp $verbose -a "${to_bk%/}" "${to_bk%/}_$current_date"
+ (( result += $? ))
+ done
+ else
+ for to_bk in "$@"; do
+ cp $verbose -pR "${to_bk%/}" "${to_bk%/}_$current_date"
+ (( result += $? ))
+ done
+ fi
elif (( move > 0 )); then
while (( $# > 0 )); do
mv $verbose "${1%/}" "${1%/}_$current_date"
(( result += $? ))
shift
done
+ elif (( clean > 0 )); then
+ if (( $# > 0 )); then
+ for to_bk in "$@"; do
+ rm $verbose -rf "${to_bk%/}"_[0-9](#c8)T([0-1][0-9]|2[0-3])([0-5][0-9])(#c2)Z
+ (( result += $? ))
+ done
+ else
+ if (( all > 0 )); then
+ rm $verbose -rf *_[0-9](#c8)T([0-1][0-9]|2[0-3])([0-5][0-9])(#c2)Z(D)
+ else
+ rm $verbose -rf *_[0-9](#c8)T([0-1][0-9]|2[0-3])([0-5][0-9])(#c2)Z
+ fi
+ (( result += $? ))
+ fi
fi
return $result
}
-#f5# cd to directoy and list files
-cl() {
+#f5# cd to directory and list files
+function cl () {
emulate -L zsh
cd $1 && ls -a
}
# smart cd function, allows switching to /etc when running 'cd /etc/fstab'
-cd() {
+function cd () {
if (( ${#argv} == 1 )) && [[ -f ${1} ]]; then
[[ ! -e ${1:h} ]] && return 1
print "Correcting ${1} to ${1:h}"
fi
}
-#f5# Create Directoy and \kbd{cd} to it
-mkcd() {
+#f5# Create Directory and \kbd{cd} to it
+function mkcd () {
if (( ARGC != 1 )); then
printf 'usage: mkcd <new-directory>\n'
return 1;
}
#f5# Create temporary directory and \kbd{cd} to it
-cdt() {
- local t
- t=$(mktemp -d)
- echo "$t"
- builtin cd "$t"
+function cdt () {
+ builtin cd "$(mktemp -d)"
+ builtin pwd
}
#f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1
-accessed() {
+function accessed () {
emulate -L zsh
print -l -- *(a-${1:-1})
}
#f5# List files which have been changed within the last {\it n} days, {\it n} defaults to 1
-changed() {
+function changed () {
emulate -L zsh
print -l -- *(c-${1:-1})
}
#f5# List files which have been modified within the last {\it n} days, {\it n} defaults to 1
-modified() {
+function modified () {
emulate -L zsh
print -l -- *(m-${1:-1})
}
fi
# Translate DE<=>EN
-# 'translate' looks up fot a word in a file with language-to-language
+# 'translate' looks up a word in a file with language-to-language
# translations (field separator should be " : "). A typical wordlist looks
-# like at follows:
-# | english-word : german-transmission
+# like the following:
+# | english-word : german-translation
# It's also only possible to translate english to german but not reciprocal.
-# Use the following oneliner to turn back the sort order:
+# Use the following oneliner to reverse the sort order:
# $ awk -F ':' '{ print $2" : "$1" "$3 }' \
# /usr/local/lib/words/en-de.ISO-8859-1.vok > ~/.translate/de-en.ISO-8859-1.vok
#f5# Translates a word
-trans() {
+function trans () {
emulate -L zsh
case "$1" in
-[dD]*)
# Usage: simple-extract <file>
# Using option -d deletes the original archive file.
#f5# Smart archive extractor
-simple-extract() {
+function simple-extract () {
emulate -L zsh
setopt extended_glob noclobber
- local DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
+ local ARCHIVE DELETE_ORIGINAL DECOMP_CMD USES_STDIN USES_STDOUT GZTARGET WGET_CMD
local RC=0
zparseopts -D -E "d=DELETE_ORIGINAL"
for ARCHIVE in "${@}"; do
USES_STDIN=true
USES_STDOUT=false
;;
+ *tar.zst)
+ DECOMP_CMD="tar --zstd -xvf -"
+ USES_STDIN=true
+ USES_STDOUT=false
+ ;;
*tar)
DECOMP_CMD="tar -xvf -"
USES_STDIN=true
USES_STDIN=true
USES_STDOUT=true
;;
+ *zst)
+ DECOMP_CMD="zstd -d -c -"
+ USES_STDIN=true
+ USES_STDOUT=true
+ ;;
*)
print "ERROR: '$ARCHIVE' has unrecognized archive type." >&2
RC=$((RC+1))
elif [[ "$ARCHIVE" == (#s)(https|http|ftp)://* ]] ; then
if check_com curl; then
- WGET_CMD="curl -L -k -s -o -"
+ WGET_CMD="curl -L -s -o -"
elif check_com wget; then
- WGET_CMD="wget -q -O - --no-check-certificate"
+ WGET_CMD="wget -q -O -"
+ elif check_com fetch; then
+ WGET_CMD="fetch -q -o -"
else
- print "ERROR: neither wget nor curl is installed" >&2
+ print "ERROR: neither wget, curl nor fetch is installed" >&2
RC=$((RC+4))
continue
fi
return $RC
}
-__archive_or_uri()
-{
+function __archive_or_uri () {
_alternative \
'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)"' \
'_urls:Remote Archives:_urls'
}
-_simple_extract()
-{
+function _simple_extract () {
_arguments \
'-d[delete original archivefile after extraction]' \
'*:Archive Or Uri:__archive_or_uri'
}
compdef _simple_extract simple-extract
-alias se=simple-extract
-
-#f5# Set all ulimit parameters to \kbd{unlimited}
-allulimit() {
- ulimit -c unlimited
- ulimit -d unlimited
- ulimit -f unlimited
- ulimit -l unlimited
- ulimit -n unlimited
- ulimit -s unlimited
- ulimit -t unlimited
-}
+[[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias se=simple-extract
#f5# Change the xterm title from within GNU-screen
-xtrename() {
+function xtrename () {
emulate -L zsh
if [[ $1 != "-f" ]] ; then
if [[ -z ${DISPLAY} ]] ; then
# Create small urls via http://goo.gl using curl(1).
# API reference: https://code.google.com/apis/urlshortener/
-function zurl() {
+function zurl () {
emulate -L zsh
setopt extended_glob
}
#f2# Find history events by search pattern and list them by date.
-whatwhen() {
+function whatwhen () {
emulate -L zsh
local usage help ident format_l format_s first_char remain first last
usage='USAGE: whatwhen [options] <searchstring> <search range>'
# gnu like diff for mercurial
# http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
#f5# GNU like diff for mercurial
- hgdi() {
+ function hgdi () {
emulate -L zsh
+ local i
for i in $(hg status -marn "$@") ; diff -ubwd <(hg cat "$i") "$i"
}
alias hbp='hg-buildpackage'
# execute commands on the versioned patch-queue from the current repos
- alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
+ [[ -n "$GRML_NO_SMALL_ALIASES" ]] || alias mq='hg -R $(readlink -f $(hg root)/.hg/patches)'
# diffstat for specific version of a mercurial repository
# hgstat => display diffstat between last revision and tip
# hgstat 1234 => display diffstat between revision 1234 and tip
#f5# Diffstat for specific version of a mercurial repos
- hgstat() {
+ function hgstat () {
emulate -L zsh
[[ -n "$1" ]] && hg diff -r $1 -r tip | diffstat || hg export tip | diffstat
}
fi # end of check whether we have the 'hg'-executable
-# grml-small cleanups
+# disable bracketed paste mode for dumb terminals
+[[ "$TERM" == dumb ]] && unset zle_bracketed_paste
+
+# grml-small cleanups and workarounds
# The following is used to remove zsh-config-items that do not work
# in grml-small by default.
if (( GRMLSMALL_SPECIFIC > 0 )) && isgrmlsmall ; then
- unset abk[V]
+ # Clean up
+
+ unset "abk[V]"
unalias 'V' &> /dev/null
unfunction vman &> /dev/null
unfunction viless &> /dev/null
unfunction manzsh &> /dev/null
unfunction man2 &> /dev/null
+ # Workarounds
+
+ # See https://github.com/grml/grml/issues/56
+ if ! [[ -x ${commands[dig]} ]]; then
+ function dig_after_all () {
+ unfunction dig
+ unfunction _dig
+ autoload -Uz _dig
+ unfunction dig_after_all
+ }
+ function dig () {
+ if [[ -x ${commands[dig]} ]]; then
+ dig_after_all
+ command dig "$@"
+ return "$!"
+ fi
+ printf 'This installation does not include `dig'\'' for size reasons.\n'
+ printf 'Try `drill'\'' as a light weight alternative.\n'
+ return 0
+ }
+ function _dig () {
+ if [[ -x ${commands[dig]} ]]; then
+ dig_after_all
+ zle -M 'Found `dig'\'' installed. '
+ else
+ zle -M 'Try `drill'\'' instead of `dig'\''.'
+ fi
+ }
+ compdef _dig dig
+ fi
fi
zrclocal