X-Git-Url: http://git.grml.org/?a=blobdiff_plain;f=etc%2Fzsh%2Fzshrc;h=a1d868d95e9766fb0c1fc5f6909a2aa6b27cb75a;hb=dfede1a73065b5a648a91b88accef34f1a5e0568;hp=9ba0defcea8106532a0e95862556f7a87c1da731;hpb=0c46c6b42a3f262eef306f7a3694574f50d6215b;p=grml-etc-core.git diff --git a/etc/zsh/zshrc b/etc/zsh/zshrc index 9ba0def..a1d868d 100644 --- a/etc/zsh/zshrc +++ b/etc/zsh/zshrc @@ -109,7 +109,7 @@ if [[ $ZSH_PROFILE_RC -gt 0 ]] ; then fi # load .zshrc.pre to give the user the chance to overwrite the defaults -[[ -r ${HOME}/.zshrc.pre ]] && source ${HOME}/.zshrc.pre +[[ -r ${ZDOTDIR:-${HOME}}/.zshrc.pre ]] && source ${ZDOTDIR:-${HOME}}/.zshrc.pre # check for version/system # check for versions (compatibility reasons) @@ -139,12 +139,20 @@ is43(){ } is433(){ - [[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == 4.<4->* || $ZSH_VERSION == <5->* ]] && return 0 + [[ $ZSH_VERSION == 4.3.<3->* || $ZSH_VERSION == 4.<4->* \ + || $ZSH_VERSION == <5->* ]] && return 0 + return 1 +} + +is437(){ + [[ $ZSH_VERSION == 4.3.<7->* || $ZSH_VERSION == 4.<4->* \ + || $ZSH_VERSION == <5->* ]] && return 0 return 1 } is439(){ - [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* || $ZSH_VERSION == <5->* ]] && return 0 + [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* \ + || $ZSH_VERSION == <5->* ]] && return 0 return 1 } @@ -163,7 +171,10 @@ isgrmlcd(){ if isgrml ; then #f1# Checks whether or not you're running grml-small isgrmlsmall() { - [[ ${${${(f)"$( - # -> searches for word not in compressed files - # don't forget to quote '^', '~' and '#'! -setopt longlistjobs # display PID when suspending processes as well -setopt notify # report the status of backgrounds jobs immediately -setopt hash_list_all # Whenever a command completion is attempted, make sure \ - # the entire command path is hashed first. -setopt completeinword # not just at the end -setopt nohup # and don't kill them, either -setopt auto_pushd # make cd push the old directory onto the directory stack. -setopt nonomatch # try to avoid the 'zsh: no matches found...' -setopt nobeep # avoid "beep"ing -setopt pushd_ignore_dups # don't push the same dir twice. -setopt noglobdots # * shouldn't match dotfiles. ever. -setopt noshwordsplit # use zsh style word splitting -setopt unset # don't error out when unset parameters are used -# setting some default values +# append history list to the history file; this is the default but we make sure +# because it's required for share_history. +setopt append_history + +# import new commands from the history file also in other zsh-session +is4 && setopt share_history + +# save each command's beginning timestamp and the duration to the history file +setopt extended_history + +# If a new command line being added to the history list duplicates an older +# one, the older command is removed from the list +is4 && setopt histignorealldups + +# remove command lines from the history list when the first character on the +# line is a space +setopt histignorespace + +# if a command is issued that can't be executed as a normal command, and the +# command is the name of a directory, perform the cd command to that directory. +setopt auto_cd + +# in order to use #, ~ and ^ for filename generation grep word +# *~(*.gz|*.bz|*.bz2|*.zip|*.Z) -> searches for word not in compressed files +# don't forget to quote '^', '~' and '#'! +setopt extended_glob + +# 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 + +# whenever a command completion is attempted, make sure the entire command path +# is hashed first. +setopt hash_list_all + +# not just at the end +setopt completeinword + +# Don't send SIGHUP to background processes when the shell exits. +setopt nohup + +# make cd push the old directory onto the directory stack. +setopt auto_pushd + +# avoid "beep"ing +setopt nobeep + +# don't push the same dir twice. +setopt pushd_ignore_dups + +# * shouldn't match dotfiles. ever. +setopt noglobdots + +# use zsh style word splitting +setopt noshwordsplit + +# don't error out when unset parameters are used +setopt unset + +# setting some default values NOCOR=${NOCOR:-0} NOMENU=${NOMENU:-0} NOPRECMD=${NOPRECMD:-0} @@ -288,9 +341,20 @@ COMMAND_NOT_FOUND=${COMMAND_NOT_FOUND:-0} GRML_ZSH_CNF_HANDLER=${GRML_ZSH_CNF_HANDLER:-/usr/share/command-not-found/command-not-found} BATTERY=${BATTERY:-0} GRMLSMALL_SPECIFIC=${GRMLSMALL_SPECIFIC:-1} -GRML_ALWAYS_LOAD_ALL=${GRML_ALWAYS_LOAD_ALL:-0} ZSH_NO_DEFAULT_LOCALE=${ZSH_NO_DEFAULT_LOCALE:-0} +typeset -ga ls_options +typeset -ga grep_options +if ls --help 2> /dev/null | grep -q GNU; then + ls_options=( --color=auto ) +elif [[ $OSTYPE == freebsd* ]]; then + ls_options=( -G ) +fi +if grep --help 2> /dev/null | grep -q GNU || \ + [[ $OSTYPE == freebsd* ]]; then + grep_options=( --color=auto ) +fi + # utility functions # this function checks if a command exists and returns either true # or false. This avoids using 'which' and 'whence', which will @@ -342,6 +406,7 @@ check_com() { salias() { emulate -L zsh local only=0 ; local multi=0 + local key val while [[ $1 == -* ]] ; do case $1 in (-o) only=1 ;; @@ -431,8 +496,7 @@ xcat() { xunfunction() { emulate -L zsh local -a funcs - funcs=(salias xcat xsource xunfunction zrcautoload) - + funcs=(salias xcat xsource xunfunction zrcautoload zrcautozle) for func in $funcs ; do [[ -n ${functions[$func]} ]] \ && unfunction $func @@ -444,7 +508,7 @@ xunfunction() { # modifications in ~/.zshrc.local zrclocal() { xsource "/etc/zsh/zshrc.local" - xsource "${HOME}/.zshrc.local" + xsource "${ZDOTDIR:-${HOME}}/.zshrc.local" return 0 } @@ -480,8 +544,9 @@ export SHELL='/bin/zsh' # color setup for ls: check_com -c dircolors && eval $(dircolors -b) -# color setup for ls on OS X: +# color setup for ls on OS X / FreeBSD: isdarwin && export CLICOLOR=1 +isfreebsd && export CLICOLOR=1 # do MacPorts setup on darwin if isdarwin && [[ -d /opt/local ]]; then @@ -496,7 +561,7 @@ isdarwin && xsource /sw/bin/init.sh # 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 [[ ${fpath} == '/usr/share/grml/zsh/functions' ]] ; then + if [[ ${fdir} == '/usr/share/grml/zsh/functions' ]] ; then for func in ${fdir}/**/[^_]*[^~](N.) ; do zrcautoload ${func:t} done @@ -513,43 +578,226 @@ export LESS_TERMCAP_so=$'\E[01;44;33m' export LESS_TERMCAP_ue=$'\E[0m' export LESS_TERMCAP_us=$'\E[01;32m' -MAILCHECK=30 # mailchecks -REPORTTIME=5 # report about cpu-/system-/user-time of command if running longer than 5 seconds -watch=(notme root) # watch for everyone but me and root +# mailchecks +MAILCHECK=30 + +# report about cpu-/system-/user-time of command if running longer than +# 5 seconds +REPORTTIME=5 + +# watch for everyone but me and root +watch=(notme root) # automatically remove duplicates from these arrays typeset -U path cdpath fpath manpath -# keybindings -if [[ "$TERM" != emacs ]] ; then - [[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char - [[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line - [[ -z "$terminfo[kend]" ]] || bindkey -M emacs "$terminfo[kend]" end-of-line - [[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char - [[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line - [[ -z "$terminfo[kend]" ]] || bindkey -M vicmd "$terminfo[kend]" vi-end-of-line - [[ -z "$terminfo[cuu1]" ]] || bindkey -M viins "$terminfo[cuu1]" vi-up-line-or-history - [[ -z "$terminfo[cuf1]" ]] || bindkey -M viins "$terminfo[cuf1]" vi-forward-char - [[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history - [[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history - [[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char - [[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char - # ncurses stuff: - [[ "$terminfo[kcuu1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history - [[ "$terminfo[kcud1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history - [[ "$terminfo[kcuf1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char - [[ "$terminfo[kcub1]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char - [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line - [[ "$terminfo[kend]" == $'\eO'* ]] && bindkey -M viins "${terminfo[kend]/O/[}" end-of-line - [[ "$terminfo[khome]" == $'\eO'* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line - [[ "$terminfo[kend]" == $'\eO'* ]] && bindkey -M emacs "${terminfo[kend]/O/[}" end-of-line +# 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 + +# autoload zsh modules when they are referenced +if is4 ; then + zmodload -a zsh/stat zstat + zmodload -a zsh/zpty zpty + zmodload -ap zsh/mapfile mapfile +fi + +# completion system +if zrcautoload compinit ; then + compinit || print 'Notice: no compinit available :(' +else + print 'Notice: no compinit available :(' + function compdef { } fi -## keybindings (run 'bindkeys' for details, more details via man zshzle) -# use emacs style per default: +# completion system + +# 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() { + # TODO: This could use some additional information + + # Make sure the completion system is initialised + (( ${+_comps} )) || return 1 + + # allow one error for every three characters typed in approximate completer + zstyle ':completion:*:approximate:' max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )' + + # don't complete backup files as executables + zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)' + + # start menu completion only if it could find no unambiguous initial string + zstyle ':completion:*:correct:*' insert-unambiguous true + zstyle ':completion:*:corrections' format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}' + zstyle ':completion:*:correct:*' original true + + # activate color-completion + zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} + + # format on completion + zstyle ':completion:*:descriptions' format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}' + + # automatically complete 'cd -' and 'cd -' with menu + # zstyle ':completion:*:*:cd:*:directory-stack' menu yes select + + # insert all expansions for expand completer + zstyle ':completion:*:expand:*' tag-order all-expansions + zstyle ':completion:*:history-words' list false + + # activate menu + zstyle ':completion:*:history-words' menu yes + + # ignore duplicate entries + zstyle ':completion:*:history-words' remove-all-dups yes + zstyle ':completion:*:history-words' stop yes + + # match uppercase from lowercase + zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' + + # separate matches into groups + zstyle ':completion:*:matches' group 'yes' + zstyle ':completion:*' group-name '' + + if [[ "$NOMENU" -eq 0 ]] ; then + # if there are more than 5 options allow selecting from a menu + zstyle ':completion:*' menu select=5 + else + # don't use any menus at all + setopt no_auto_menu + fi + + zstyle ':completion:*:messages' format '%d' + zstyle ':completion:*:options' auto-description '%d' + + # describe options in full + zstyle ':completion:*:options' description 'yes' + + # on processes completion complete all user processes + zstyle ':completion:*:processes' command 'ps -au$USER' + + # offer indexes before parameters in subscripts + zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters + + # provide verbose completion information + zstyle ':completion:*' verbose true + + # recent (as of Dec 2007) zsh versions are able to provide descriptions + # for commands (read: 1st word in the line) that it will list for the user + # to choose from. The following disables that, because it's not exactly fast. + zstyle ':completion:*:-command-:*:' verbose false + + # set format for warnings + zstyle ':completion:*:warnings' format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d' + + # define files to ignore for zcompile + zstyle ':completion:*:*:zcompile:*' ignored-patterns '(*~|*.zwc)' + zstyle ':completion:correct:' prompt 'correct to: %e' + + # Ignore completion functions for commands you don't have: + zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*' + + # Provide more processes in completion of programs like killall: + zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq' + + # complete manual by their section + zstyle ':completion:*:manuals' separate-sections true + zstyle ':completion:*:manuals.*' insert-sections true + zstyle ':completion:*:man:*' menu yes select + + # Search path for sudo completion + zstyle ':completion:*:sudo:*' command-path /usr/local/sbin \ + /usr/local/bin \ + /usr/sbin \ + /usr/bin \ + /sbin \ + /bin \ + /usr/X11R6/bin + + # provide .. as a completion + zstyle ':completion:*' special-dirs .. + + # run rehash on completion so new installed program are found automatically: + _force_rehash() { + (( CURRENT == 1 )) && rehash + return 1 + } + + ## correction + # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it + if [[ "$NOCOR" -gt 0 ]] ; then + zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored + setopt nocorrect + else + # try to be smart about when to use what completer... + setopt correct + zstyle -e ':completion:*' completer ' + if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then + _last_try="$HISTNO$BUFFER$CURSOR" + reply=(_complete _match _ignored _prefix _files) + else + if [[ $words[1] == (rm|mv) ]] ; then + reply=(_complete _files) + else + reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files) + fi + fi' + fi + + # 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/ + + # host completion + if is42 ; then + [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=() + [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(, Bernhard Tittelbach @@ -568,75 +816,6 @@ beginning-or-end-of-somewhere() { zle -N beginning-of-somewhere beginning-or-end-of-somewhere zle -N end-of-somewhere beginning-or-end-of-somewhere - -#if [[ "$TERM" == screen ]] ; then - -## with HOME/END, move to beginning/end of line (on multiline) on first keypress -## to beginning/end of buffer on second keypress -## and to beginning/end of history on (at most) the third keypress -# terminator & non-debian xterm -bindkey '\eOH' beginning-of-somewhere # home -bindkey '\eOF' end-of-somewhere # end -# freebsd console -bindkey '\e[H' beginning-of-somewhere # home -bindkey '\e[F' end-of-somewhere # end -# xterm,gnome-terminal,quake,etc -bindkey '^[[1~' beginning-of-somewhere # home -bindkey '^[[4~' end-of-somewhere # end -# if terminal type is set to 'rxvt': -bindkey '\e[7~' beginning-of-somewhere # home -bindkey '\e[8~' end-of-somewhere # end -#fi - -bindkey '\e[A' up-line-or-search # cursor up -bindkey '\e[B' down-line-or-search # - - -## alt-backspace is already the default for backwards-delete-word -## let's also set alt-delete for deleting current word (right of cursor) -#k# Kill right-side word -bindkey '^[[3~' delete-word # Modeswitch -bindkey '^[[3;3~' delete-word # Alt_L - -## use Ctrl-left-arrow and Ctrl-right-arrow for jumping to word-beginnings on the CL -bindkey "\e[5C" forward-word -bindkey "\e[5D" backward-word -bindkey "\e[1;5C" forward-word -bindkey "\e[1;5D" backward-word -## the same for alt-left-arrow and alt-right-arrow -bindkey '^[[1;3C' forward-word -bindkey '^[[1;3D' backward-word - -# Search backward in the history for a line beginning with the current -# line up to the cursor and move the cursor to the end of the line then -zle -N history-beginning-search-backward-end history-search-end -zle -N history-beginning-search-forward-end history-search-end -#k# search history backward for entry beginning with typed text -bindkey '^xp' history-beginning-search-backward-end -#k# search history forward for entry beginning with typed text -bindkey '^xP' history-beginning-search-forward-end -#k# search history backward for entry beginning with typed text -bindkey "\e[5~" history-beginning-search-backward-end # PageUp -#k# search history forward for entry beginning with typed text -bindkey "\e[6~" history-beginning-search-forward-end # PageDown - -# bindkey -s '^L' "|less\n" # ctrl-L pipes to less -# bindkey -s '^B' " &\n" # ctrl-B runs it in the background - -# insert unicode character -# usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an § -# See for example http://unicode.org/charts/ for unicode characters code -zrcautoload insert-unicode-char -zle -N insert-unicode-char -#k# Insert Unicode character -bindkey '^Xi' insert-unicode-char - -#m# k Shift-tab Perform backwards menu completion -if [[ -n "$terminfo[kcbt]" ]]; then - bindkey "$terminfo[kcbt]" reverse-menu-complete -elif [[ -n "$terminfo[cbt]" ]]; then # required for GNU screen - bindkey "$terminfo[cbt]" reverse-menu-complete -fi - ## toggle the ,. abbreviation feature on/off # NOABBREVIATION: default abbreviation-state # 0 - enabled (default) @@ -650,9 +829,7 @@ grml_toggle_abbrev() { NOABBREVIATION=1 fi } - zle -N grml_toggle_abbrev -bindkey '^xA' grml_toggle_abbrev # add a command line to the shells history without executing it commit-to-history() { @@ -660,7 +837,6 @@ commit-to-history() { zle send-break } zle -N commit-to-history -bindkey "^x^h" commit-to-history # only slash should be considered as a word separator: slash-backward-kill-word() { @@ -670,19 +846,6 @@ slash-backward-kill-word() { } zle -N slash-backward-kill-word -#k# Kill left-side word or everything up to next slash -bindkey '\ev' slash-backward-kill-word -#k# Kill left-side word or everything up to next slash -bindkey '\e^h' slash-backward-kill-word -#k# Kill left-side word or everything up to next slash -bindkey '\e^?' slash-backward-kill-word - -# use the new *-pattern-* widgets for incremental history search -if is439 ; then - bindkey '^r' history-incremental-pattern-search-backward - bindkey '^s' history-incremental-pattern-search-forward -fi - # a generic accept-line wrapper # This widget can prevent unwanted autocorrections from command-name @@ -844,7 +1007,7 @@ abk=( '....' '../../..' 'BG' '& exit' 'C' '| wc -l' - 'G' '|& grep --color=auto ' + 'G' '|& grep '${grep_options:+"${grep_options[*]}"} 'H' '| head' 'Hl' ' --help |& less -r' #d (Display help in pager) 'L' '| less' @@ -870,98 +1033,27 @@ zleiab() { return 0 fi - matched_chars='[.-|_a-zA-Z0-9]#' - LBUFFER=${LBUFFER%%(#m)[.-|_a-zA-Z0-9]#} + LBUFFER=${LBUFFER%%(#m)[.\-+:|_a-zA-Z0-9]#} LBUFFER+=${abk[$MATCH]:-$MATCH} } zle -N zleiab -bindkey ",." zleiab -# autoloading -zrcautoload zmv # who needs mmv or rename? -zrcautoload history-search-end +help-show-abk() +{ + zle -M "$(print "Type ,. after these abbreviations to expand them:"; print -a -C 2 ${(kv)abk})" +} -# we don't want to quote/espace URLs on our own... -# if autoload -U url-quote-magic ; then -# zle -N self-insert url-quote-magic -# zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}=' -# else -# print 'Notice: no url-quote-magic available :(' -# fi -alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic' - -#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 - zrcautoload $rh -done; unset rh - -# completion system -if zrcautoload compinit ; then - compinit || print 'Notice: no compinit available :(' -else - print 'Notice: no compinit available :(' - function zstyle { } - function compdef { } -fi - -is4 && zrcautoload zed # use ZLE editor to edit a file or function - -is4 && \ -for mod in complist deltochar mathfunc ; do - zmodload -i zsh/${mod} 2>/dev/null || print "Notice: no ${mod} available :(" -done - -# autoload zsh modules when they are referenced -if is4 ; then - zmodload -a zsh/stat zstat - zmodload -a zsh/zpty zpty - zmodload -ap zsh/mapfile mapfile -fi - -if is4 && zrcautoload insert-files && zle -N insert-files ; then - #k# Insert files and test globbing - bindkey "^Xf" insert-files # C-x-f -fi - -bindkey ' ' magic-space # also do history expansion on space -#k# Trigger menu-complete -bindkey '\ei' menu-complete # menu completion via esc-i - -# press esc-e for editing command line in $EDITOR or $VISUAL -if is4 && zrcautoload edit-command-line && zle -N edit-command-line ; then - #k# Edit the current line in \kbd{\$EDITOR} - bindkey '\ee' edit-command-line -fi - -if is4 && [[ -n ${(k)modules[zsh/complist]} ]] ; then - #k# menu selection: pick item but stay in the menu - bindkey -M menuselect '\e^M' accept-and-menu-complete - # also use + and INSERT since it's easier to press repeatedly - bindkey -M menuselect "+" accept-and-menu-complete - bindkey -M menuselect "^[[2~" accept-and-menu-complete - - # accept a completion and try to complete again by using menu - # completion; very useful with completing directories - # by using 'undo' one's got a simple file browser - bindkey -M menuselect '^o' accept-and-infer-next-history -fi +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}'}; } zle -N insert-datestamp -#k# Insert a timestamp on the command line (yyyy-mm-dd) -bindkey '^Ed' insert-datestamp - # press esc-m for inserting last typed word again (thanks to caphuso!) insert-last-typed-word() { zle insert-last-word -- 0 -1 }; zle -N insert-last-typed-word; -#k# Insert last typed word -bindkey "\em" insert-last-typed-word - function grml-zsh-fg() { if (( ${#jobstates} )); then zle .push-input @@ -973,8 +1065,6 @@ function grml-zsh-fg() { fi } zle -N grml-zsh-fg -#k# A smart shortcut for \kbd{fg} -bindkey '^z' grml-zsh-fg # run command line as user root via sudo: sudo-command-line() { @@ -986,9 +1076,6 @@ sudo-command-line() { } zle -N sudo-command-line -#k# prepend the current command with "sudo" -bindkey "^Os" sudo-command-line - ### jump behind the first word on the cmdline. ### useful to add options. function jump_after_first_word() { @@ -1002,14 +1089,163 @@ function jump_after_first_word() { fi } zle -N jump_after_first_word -#k# jump to after first word (for adding options) -bindkey '^x1' jump_after_first_word -# complete word from history with menu (from Book: ZSH, OpenSource-Press) -zle -C hist-complete complete-word _generic -zstyle ':completion:hist-complete:*' completer _history -#k# complete word from history with menu -bindkey "^X^X" hist-complete +#f5# Create directory under cursor or the selected area +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 + # directory does not exist yet -> press ctrl-XM and problem solved + local PATHTOMKDIR + if ((REGION_ACTIVE==1)); then + local F=$MARK T=$CURSOR + if [[ $F -gt $T ]]; then + F=${CURSOR} + T=${MARK} + fi + # get marked area from buffer and eliminate whitespace + PATHTOMKDIR=${BUFFER[F+1,T]%%[[:space:]]##} + PATHTOMKDIR=${PATHTOMKDIR##[[:space:]]##} + else + local bufwords iword + bufwords=(${(z)LBUFFER}) + iword=${#bufwords} + bufwords=(${(z)BUFFER}) + PATHTOMKDIR="${(Q)bufwords[iword]}" + fi + [[ -z "${PATHTOMKDIR}" ]] && return 1 + PATHTOMKDIR=${~PATHTOMKDIR} + if [[ -e "${PATHTOMKDIR}" ]]; then + zle -M " path already exists, doing nothing" + else + zle -M "$(mkdir -p -v "${PATHTOMKDIR}")" + zle end-of-line + fi +} + +#k# mkdir -p from string under cursor or marked area +zle -N inplaceMkDirs + +#v1# set number of lines to display per page +HELP_LINES_PER_PAGE=20 +#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() +{ + emulate -L zsh + setopt extendedglob + unsetopt ksharrays #indexing starts at 1 + + #v1# choose files that help-zle will parse for keybindings + ((${+HELPZLE_KEYBINDING_FILES})) || HELPZLE_KEYBINDING_FILES=( /etc/zsh/zshrc ~/.zshrc.pre ~/.zshrc ~/.zshrc.local ) + + if [[ -r $HELP_ZLE_CACHE_FILE ]]; then + local load_cache=0 + 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 + #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['@']="set MARK" + help_zle_keybindings['xj']="vi-join lines" + help_zle_keybindings['xb']="jump to matching brace" + help_zle_keybindings['xu']="undo" + help_zle_keybindings['_']="undo" + help_zle_keybindings['xf']="find in cmdline" + help_zle_keybindings['a']="goto beginning of line" + help_zle_keybindings['e']="goto end of line" + help_zle_keybindings['t']="transpose charaters" + help_zle_keybindings['t']="transpose words" + help_zle_keybindings['s']="spellcheck word" + help_zle_keybindings['k']="backward kill buffer" + help_zle_keybindings['u']="forward kill buffer" + help_zle_keybindings['y']="insert previously killed word/string" + help_zle_keybindings["'"]="quote line" + help_zle_keybindings['"']="quote from mark to cursor" + help_zle_keybindings['']="repeat next cmd/char times (-10a -> -10 times 'a')" + help_zle_keybindings['u']="make next word Uppercase" + help_zle_keybindings['l']="make next word lowercase" + help_zle_keybindings['xd']="preview expansion under cursor" + help_zle_keybindings['q']="push current CL into background, freeing it. Restore on next CL" + help_zle_keybindings['.']="insert (and interate through) last word from prev CLs" + help_zle_keybindings[',']="complete word from newer history (consecutive hits)" + help_zle_keybindings['m']="repeat last typed word on current CL" + help_zle_keybindings['v']="insert next keypress symbol literally (e.g. for bindkey)" + help_zle_keybindings['!!:n*']="insert last n arguments of last command" + help_zle_keybindings['!!:n-']="insert arguments n..N-2 of last command (e.g. mv s s d)" + help_zle_keybindings['h']="show help/manpage for current command" + + #init global variables + unset help_zle_lines help_zle_sln + typeset -g -a help_zle_lines + typeset -g help_zle_sln=1 + + local k v + 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) + for f in $HELPZLE_KEYBINDING_FILES; do + [[ -r "$f" ]] || continue #not readable ? skip it + contents="$(<$f)" + for cline in "${(f)contents}"; do + #zsh pattern: matches lines like: #k# .............. + if [[ "$cline" == (#s)[[:space:]]#\#k\#[[:space:]]##(#b)(*)[[:space:]]#(#e) ]]; then + lastkeybind_desc="$match[*]" + num_lines_elapsed=0 + #zsh pattern: matches lines that set a keybinding using bindkey or compdef -k + # ignores lines that are commentend out + # grabs first in '' or "" enclosed string with length between 1 and 6 characters + elif [[ "$cline" == [^#]#(bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*) ]]; then + #description prevously 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/}/\\e\^\?/}/\\e\[5~/}/\\e\[6~/}//(\\e|\^\[)/}//\^/}/3~/} + #put keybinding in assoc array, possibly overwriting defaults or stuff found in earlier files + #Note that we are extracting the keybinding-string including the quotes (see Note at beginning) + help_zle_keybindings[${k}]=$lastkeybind_desc + fi + lastkeybind_desc="" + else + ((num_lines_elapsed++)) + fi + done + done + unset contents + #calculate length of keybinding column + local kstrlen=0 + for k (${(k)help_zle_keybindings[@]}) ((kstrlen < ${#k})) && kstrlen=${#k} + #convert the assoc array into preformated lines, which we are able to sort + for k v in ${(kv)help_zle_keybindings[@]}; do + #pad keybinding-string to kstrlen chars and remove outermost characters (i.e. the quotes) + help_zle_lines+=("${(r:kstrlen:)k[2,-2]}${v}") + done + #sort lines alphabetically + help_zle_lines=("${(i)help_zle_lines[@]}") + [[ -d ${HELP_ZLE_CACHE_FILE:h} ]] || mkdir -p "${HELP_ZLE_CACHE_FILE:h}" + echo "help_zle_lines=(${(q)help_zle_lines[@]})" >| $HELP_ZLE_CACHE_FILE + zcompile $HELP_ZLE_CACHE_FILE +} +typeset -g help_zle_sln +typeset -g -a help_zle_lines + +# Provides (partially autogenerated) help on keybindings and the zsh line editor +help-zle() +{ + emulate -L zsh + unsetopt ksharrays #indexing starts at 1 + #help lines already generated ? no ? then do it + [[ ${+functions[help_zle_parse_keybindings]} -eq 1 ]] && {help_zle_parse_keybindings && unfunction help_zle_parse_keybindings} + #already displayed all lines ? go back to the start + [[ $help_zle_sln -gt ${#help_zle_lines} ]] && help_zle_sln=1 + local sln=$help_zle_sln + #note that help_zle_sln is a global var, meaning we remember the last page we viewed + help_zle_sln=$((help_zle_sln + HELP_LINES_PER_PAGE)) + zle -M "${(F)help_zle_lines[sln,help_zle_sln-1]}" +} +zle -N help-zle ## complete word from currently visible Screen or Tmux buffer. if check_com -c screen || check_com -c tmux; then @@ -1028,7 +1264,8 @@ if check_com -c screen || check_com -c tmux; then tmux -q capture-pane \; save-buffer -b 0 $TMPFILE \; delete-buffer -b 0 else screen -X hardcopy $TMPFILE - #screen sucks, it dumps in latin1, apparently always. so recode it to system charset + # screen sucks, it dumps in latin1, apparently always. so recode it + # to system charset check_com recode && recode latin1 $TMPFILE fi _screen_display_wordlist=( ${(QQ)$(<$TMPFILE)} ) @@ -1036,24 +1273,252 @@ if check_com -c screen || check_com -c tmux; then _screen_display_wordlist[${_screen_display_wordlist[(i)$PREFIX]}]="" compadd -a _screen_display_wordlist } - #k# complete word from currently visible GNU screen buffer - bindkey -r "^XS" - compdef -k _complete_screen_display complete-word '^XS' + #m# k CTRL-x\,\,\,S Complete word from GNU screen buffer + bindkey -r "^xS" + compdef -k _complete_screen_display complete-word '^xS' +fi + +# Load a few more functions and tie them to widgets, so they can be bound: + +function zrcautozle() { + emulate -L zsh + local fnc=$1 + zrcautoload $fnc && zle -N $fnc +} + +function zrcgotwidget() { + (( ${+widgets[$1]} )) +} + +function zrcgotkeymap() { + [[ -n ${(M)keymaps:#$1} ]] +} + +zrcautozle insert-files +zrcautozle edit-command-line +zrcautozle insert-unicode-char +if zrcautoload history-search-end; then + zle -N history-beginning-search-backward-end history-search-end + zle -N history-beginning-search-forward-end history-search-end +fi +zle -C hist-complete complete-word _generic +zstyle ':completion:hist-complete:*' completer _history + +# The actual terminal setup hooks and bindkey-calls: + +# An array to note missing features to ease diagnosis in case of problems. +typeset -ga grml_missing_features + +function zrcbindkey() { + if (( ARGC )) && zrcgotwidget ${argv[-1]}; then + bindkey "$@" + fi +} + +function bind2maps () { + local i sequence widget + local -a maps + + while [[ "$1" != "--" ]]; do + maps+=( "$1" ) + shift + done + shift + + sequence="${key[$1]}" + widget="$2" + + [[ -z "$sequence" ]] && return 1 + + for i in "${maps[@]}"; do + zrcbindkey -M "$i" "$sequence" "$widget" + done +} + +if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then + function zle-smkx () { + printf '%s' ${terminfo[smkx]} + } + function zle-rmkx () { + printf '%s' ${terminfo[rmkx]} + } + function zle-line-init () { + zle-smkx + } + function zle-line-finish () { + zle-rmkx + } + zle -N zle-line-init + zle -N zle-line-finish +else + for i in {s,r}mkx; do + (( ${+terminfo[$i]} )) || grml_missing_features+=($i) + done + unset i +fi + +typeset -A key +key=( + Home "${terminfo[khome]}" + End "${terminfo[kend]}" + Insert "${terminfo[kich1]}" + Delete "${terminfo[kdch1]}" + Up "${terminfo[kcuu1]}" + Down "${terminfo[kcud1]}" + Left "${terminfo[kcub1]}" + Right "${terminfo[kcuf1]}" + PageUp "${terminfo[kpp]}" + PageDown "${terminfo[knp]}" + BackTab "${terminfo[kcbt]}" +) + +bind2maps emacs -- Home beginning-of-somewhere +bind2maps viins vicmd -- Home vi-beginning-of-line +bind2maps emacs -- End end-of-somewhere +bind2maps viins vicmd -- End vi-end-of-line +bind2maps emacs viins -- Insert overwrite-mode +bind2maps vicmd -- Insert vi-insert +bind2maps emacs -- Delete delete-char +bind2maps viins vicmd -- Delete vi-delete-char +bind2maps emacs viins vicmd -- Up up-line-or-search +bind2maps emacs viins vicmd -- Down down-line-or-search +bind2maps emacs -- Left backward-char +bind2maps viins vicmd -- Left vi-backward-char +bind2maps emacs -- Right forward-char +bind2maps viins vicmd -- Right vi-forward-char +bind2maps viins vicmd -- Right vi-forward-char + +if zrcgotkeymap menuselect; then + #m# k Shift-tab Perform backwards menu completion + bind2maps menuselect -- BackTab reverse-menu-complete + + #k# menu selection: pick item but stay in the menu + zrcbindkey -M menuselect '\e^M' accept-and-menu-complete + # also use + and INSERT since it's easier to press repeatedly + zrcbindkey -M menuselect "+" accept-and-menu-complete + zrcbindkey -M menuselect "^[[2~" accept-and-menu-complete + + # accept a completion and try to complete again by using menu + # completion; very useful with completing directories + # by using 'undo' one's got a simple file browser + zrcbindkey -M menuselect '^o' accept-and-infer-next-history fi +#k# Display list of abbreviations that expand when followed by ,. +zrcbindkey ",." zleiab +zrcbindkey '^xb' help-show-abk +zrcbindkey '^xM' inplaceMkDirs +#k# display help for keybindings and ZLE +zrcbindkey '^xz' help-zle + +#k# Insert files and test globbing +zrcbindkey "^xf" insert-files # C-x-f + +#k# Edit the current line in \kbd{\$EDITOR} +zrcbindkey '\ee' edit-command-line + +## use Ctrl-left-arrow and Ctrl-right-arrow for jumping to word-beginnings on the CL +zrcbindkey "\e[5C" forward-word +zrcbindkey "\e[5D" backward-word +zrcbindkey "\e[1;5C" forward-word +zrcbindkey "\e[1;5D" backward-word +## the same for alt-left-arrow and alt-right-arrow +zrcbindkey '^[[1;3C' forward-word +zrcbindkey '^[[1;3D' backward-word + +#k# search history backward for entry beginning with typed text +zrcbindkey '^xp' history-beginning-search-backward-end +#k# search history forward for entry beginning with typed text +zrcbindkey '^xP' history-beginning-search-forward-end +#k# search history backward for entry beginning with typed text +zrcbindkey "\e[5~" history-beginning-search-backward-end # PageUp +#k# search history forward for entry beginning with typed text +zrcbindkey "\e[6~" history-beginning-search-forward-end # PageDown + +# insert unicode character +# usage example: 'ctrl-x i' 00A7 'ctrl-x i' will give you an § +# See for example http://unicode.org/charts/ for unicode characters code +#k# Insert Unicode character +zrcbindkey '^xi' insert-unicode-char + +#k# Toggle abbreviation expansion on/off +zrcbindkey '^xA' grml_toggle_abbrev +zrcbindkey "^x^h" commit-to-history + +#k# Kill left-side word or everything up to next slash +zrcbindkey '\ev' slash-backward-kill-word +#k# Kill left-side word or everything up to next slash +zrcbindkey '\e^h' slash-backward-kill-word +#k# Kill left-side word or everything up to next slash +zrcbindkey '\e^?' slash-backward-kill-word + +# use the new *-pattern-* widgets for incremental history search +if zrcgotwidget history-incremental-pattern-search-backward; then + zrcbindkey '^r' history-incremental-pattern-search-backward + zrcbindkey '^s' history-incremental-pattern-search-forward +fi + +# Do history expansion on space: +zrcbindkey ' ' magic-space +#k# Trigger menu-complete +zrcbindkey '\ei' menu-complete # menu completion via esc-i +#k# Insert a timestamp on the command line (yyyy-mm-dd) +zrcbindkey '^ed' insert-datestamp +#k# Insert last typed word +zrcbindkey "\em" insert-last-typed-word +#k# A smart shortcut for \kbd{fg} +zrcbindkey '^z' grml-zsh-fg +#k# prepend the current command with "sudo" +zrcbindkey "^os" sudo-command-line +#k# jump to after first word (for adding options) +zrcbindkey '^x1' jump_after_first_word +#k# complete word from history with menu +zrcbindkey "^x^x" hist-complete + +# autoloading + +zrcautoload zmv +zrcautoload zed + +# we don't want to quote/espace URLs on our own... +# if autoload -U url-quote-magic ; then +# zle -N self-insert url-quote-magic +# zstyle ':url-quote-magic:*' url-metas '*?[]^()~#{}=' +# else +# print 'Notice: no url-quote-magic available :(' +# fi +alias url-quote='autoload -U url-quote-magic ; zle -N self-insert url-quote-magic' + +#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 + zrcautoload $rh +done; unset rh + +# command not found handling + +(( ${COMMAND_NOT_FOUND} == 1 )) && +function command_not_found_handler() { + emulate -L zsh + if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then + ${GRML_ZSH_CNF_HANDLER} $1 + fi + return 1 +} + # history -ZSHDIR=$HOME/.zsh +ZSHDIR=${ZDOTDIR:-${HOME}/.zsh} #v# -HISTFILE=$HOME/.zsh_history +HISTFILE=${ZDOTDIR:-${HOME}}/.zsh_history isgrmlcd && HISTSIZE=500 || HISTSIZE=5000 isgrmlcd && SAVEHIST=1000 || SAVEHIST=10000 # useful for setopt append_history # dirstack handling DIRSTACKSIZE=${DIRSTACKSIZE:-20} -DIRSTACKFILE=${DIRSTACKFILE:-${HOME}/.zdirs} +DIRSTACKFILE=${DIRSTACKFILE:-${ZDOTDIR:-${HOME}}/.zdirs} if [[ -f ${DIRSTACKFILE} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then dirstack=( ${(f)"$(< $DIRSTACKFILE)"} ) @@ -1075,89 +1540,84 @@ chpwd() { if is433 ; then -CHPWD_PROFILE='default' +# chpwd_profiles(): Directory Profiles, Quickstart: +# +# In .zshrc.local: +# +# zstyle ':chpwd:profiles:/usr/src/grml(|/|/*)' profile grml +# zstyle ':chpwd:profiles:/usr/src/debian(|/|/*)' profile debian +# chpwd_profiles +# +# For details see the `grmlzshrc.5' manual page. function chpwd_profiles() { - # Say you want certain settings to be active in certain directories. - # This is what you want. - # - # zstyle ':chpwd:profiles:/usr/src/grml(|/|/*)' profile grml - # zstyle ':chpwd:profiles:/usr/src/debian(|/|/*)' profile debian - # - # When that's done and you enter a directory that matches the pattern - # in the third part of the context, a function called chpwd_profile_grml, - # for example, is called (if it exists). - # - # If no pattern matches (read: no profile is detected) the profile is - # set to 'default', which means chpwd_profile_default is attempted to - # be called. - # - # A word about the context (the ':chpwd:profiles:*' stuff in the zstyle - # command) which is used: The third part in the context is matched against - # ${PWD}. That's why using a pattern such as /foo/bar(|/|/*) makes sense. - # Because that way the profile is detected for all these values of ${PWD}: - # /foo/bar - # /foo/bar/ - # /foo/bar/baz - # So, if you want to make double damn sure a profile works in /foo/bar - # and everywhere deeper in that tree, just use (|/|/*) and be happy. - # - # The name of the detected profile will be available in a variable called - # 'profile' in your functions. You don't need to do anything, it'll just - # be there. - # - # Then there is the parameter $CHPWD_PROFILE is set to the profile, that - # was is currently active. That way you can avoid running code for a - # profile that is already active, by running code such as the following - # at the start of your function: - # - # function chpwd_profile_grml() { - # [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1 - # ... - # } - # - # The initial value for $CHPWD_PROFILE is 'default'. - # - # Version requirement: - # This feature requires zsh 4.3.3 or newer. - # If you use this feature and need to know whether it is active in your - # current shell, there are several ways to do that. Here are two simple - # ways: - # - # a) If knowing if the profiles feature is active when zsh starts is - # good enough for you, you can put the following snippet into your - # .zshrc.local: - # - # (( ${+functions[chpwd_profiles]} )) && print "directory profiles active" - # - # b) If that is not good enough, and you would prefer to be notified - # whenever a profile changes, you can solve that by making sure you - # start *every* profile function you create like this: - # - # function chpwd_profile_myprofilename() { - # [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1 - # print "chpwd(): Switching to profile: $profile" - # ... - # } - # - # That makes sure you only get notified if a profile is *changed*, - # not everytime you change directory, which would probably piss - # you off fairly quickly. :-) - # - # There you go. Now have fun with that. - local -x profile - - zstyle -s ":chpwd:profiles:${PWD}" profile profile || profile='default' - if (( ${+functions[chpwd_profile_$profile]} )) ; then - chpwd_profile_${profile} + local profile context + local -i reexecute + + context=":chpwd:profiles:$PWD" + zstyle -s "$context" profile profile || profile='default' + zstyle -T "$context" re-execute && reexecute=1 || reexecute=0 + + if (( ${+parameters[CHPWD_PROFILE]} == 0 )); then + typeset -g CHPWD_PROFILE + local CHPWD_PROFILES_INIT=1 + (( ${+functions[chpwd_profiles_init]} )) && chpwd_profiles_init + elif [[ $profile != $CHPWD_PROFILE ]]; then + (( ${+functions[chpwd_leave_profile_$CHPWD_PROFILE]} )) \ + && chpwd_leave_profile_${CHPWD_PROFILE} + fi + if (( reexecute )) || [[ $profile != $CHPWD_PROFILE ]]; then + (( ${+functions[chpwd_profile_$profile]} )) && chpwd_profile_${profile} fi CHPWD_PROFILE="${profile}" return 0 } + chpwd_functions=( ${chpwd_functions} chpwd_profiles ) fi # is433 +# Prompt setup for grml: + +# set colors for use in prompts (modern zshs allow for the use of %F{red}foo%f +# in prompts to get a red "foo" embedded, but it's good to keep these for +# backwards compatibility). +if zrcautoload colors && colors 2>/dev/null ; then + BLUE="%{${fg[blue]}%}" + RED="%{${fg_bold[red]}%}" + GREEN="%{${fg[green]}%}" + CYAN="%{${fg[cyan]}%}" + MAGENTA="%{${fg[magenta]}%}" + YELLOW="%{${fg[yellow]}%}" + WHITE="%{${fg[white]}%}" + NO_COLOR="%{${reset_color}%}" +else + BLUE=$'%{\e[1;34m%}' + RED=$'%{\e[1;31m%}' + GREEN=$'%{\e[1;32m%}' + CYAN=$'%{\e[1;36m%}' + WHITE=$'%{\e[1;37m%}' + MAGENTA=$'%{\e[1;35m%}' + YELLOW=$'%{\e[1;33m%}' + NO_COLOR=$'%{\e[0m%}' +fi + +# First, the easy ones: PS2..4: + +# secondary prompt, printed when the shell needs more information to complete a +# command. +PS2='\`%_> ' +# selection prompt used within a select loop. +PS3='?# ' +# the execution trace prompt (setopt xtrace). default: '+%N:%i>' +PS4='+%N:%i:%_> ' + +# Some additional features to use with our prompt: +# +# - battery status +# - debian_chroot +# - vcs_info setup and version specific fixes + # display battery status on right side of prompt via running 'BATTERY=1 zsh' if [[ $BATTERY -gt 0 ]] ; then if ! check_com -c acpi ; then @@ -1179,87 +1639,398 @@ if [[ $BATTERY -gt 0 ]] ; then fi fi } -# set colors for use in prompts -if zrcautoload colors && colors 2>/dev/null ; then - BLUE="%{${fg[blue]}%}" - RED="%{${fg_bold[red]}%}" - GREEN="%{${fg[green]}%}" - CYAN="%{${fg[cyan]}%}" - MAGENTA="%{${fg[magenta]}%}" - YELLOW="%{${fg[yellow]}%}" - WHITE="%{${fg[white]}%}" - NO_COLOUR="%{${reset_color}%}" + +# set variable debian_chroot if running in a chroot with /etc/debian_chroot +if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then + debian_chroot=$( ]] ; then + function VCS_INFO_realpath () { + setopt localoptions NO_shwordsplit chaselinks + ( builtin cd -q $1 2> /dev/null && pwd; ) + } + fi + + zstyle ':vcs_info:*' max-exports 2 + + if [[ -o restricted ]]; then + zstyle ':vcs_info:*' enable NONE + fi +fi + +# Change vcs_info formats for the grml prompt. The 2nd format sets up +# $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title. +# TODO: The included vcs_info() version still uses $VCS_INFO_message_N_. +# That needs to be the use of $VCS_INFO_message_N_ needs to be changed +# to $vcs_info_msg_N_ as soon as we use the included version. +if [[ "$TERM" == dumb ]] ; then + zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] " "zsh: %r" + zstyle ':vcs_info:*' formats "(%s%)-[%b] " "zsh: %r" else - BLUE=$'%{\e[1;34m%}' - RED=$'%{\e[1;31m%}' - GREEN=$'%{\e[1;32m%}' - CYAN=$'%{\e[1;36m%}' - WHITE=$'%{\e[1;37m%}' - MAGENTA=$'%{\e[1;35m%}' - YELLOW=$'%{\e[1;33m%}' - NO_COLOUR=$'%{\e[0m%}' + # these are the same, just with a lot of colors: + zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOR} " \ + "zsh: %r" + zstyle ':vcs_info:*' formats "${MAGENTA}(${NO_COLOR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOR}%} " \ + "zsh: %r" + zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r" fi -# gather version control information for inclusion in a prompt +# Now for the fun part: The grml prompt themes in `promptsys' mode of operation + +# This actually defines three prompts: +# +# - grml +# - grml-large +# - grml-chroot +# +# They all share the same code and only differ with respect to which items they +# contain. The main source of documentation is the `prompt_grml_help' function +# below, which gets called when the user does this: prompt -h grml + +function prompt_grml_help () { + cat <<__EOF0__ + prompt grml + + This is the prompt as used by the grml-live system . It is + a rather simple one-line prompt, that by default looks something like this: + + @ [ ]% + + The prompt itself integrates with zsh's prompt themes system (as you are + witnessing right now) and is configurable to a certain degree. In + particular, these aspects are customisable: + + - The items used in the prompt (e.g. you can remove \`user' from + the list of activated items, which will cause the user name to + be omitted from the prompt string). + + - The attributes used with the items are customisable via strings + used before and after the actual item. + + The available items are: at, battery, change-root, date, grml-chroot, + history, host, jobs, newline, path, percent, rc, rc-always, sad-smiley, + shell-level, time, user, vcs + + The actual configuration is done via zsh's \`zstyle' mechanism. The + context, that is used while looking up styles is: + + ':prompt:grml::' + + Here is either \`left' or \`right', signifying whether the + style should affect the left or the right prompt. is either + \`setup' or 'items:', where \`' is one of the available items. + + The styles: + + - use-rprompt (boolean): If \`true' (the default), print a sad smiley + in $RPROMPT if the last command a returned non-successful error code. + (This in only valid if is "right"; ignored otherwise) + + - items (list): The list of items used in the prompt. If \`vcs' is + present in the list, the theme's code invokes \`vcs_info' + accordingly. Default (left): rc change-root user at host path vcs + percent; Default (right): sad-smiley + + Available styles in 'items:' 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 + default blue: + + zstyle ':prompt:grml:*:items:user' pre '%F{red}' + + Note, that the \`post' style may remain at its default value, because its + default value is '%f', which turns the foreground text attribute off (which + is exactly, what is still required with the new \`pre' value). +__EOF0__ +} + +function prompt_grml-chroot_help () { + cat <<__EOF0__ + prompt grml-chroot + + This is a variation of the grml prompt, see: prompt -h grml + + The main difference is the default value of the \`items' style. The rest + behaves exactly the same. Here are the defaults for \`grml-chroot': + + - left: grml-chroot user at host path percent + - right: (empty list) +__EOF0__ +} + +function prompt_grml-large_help () { + cat <<__EOF0__ + prompt grml-large + + This is a variation of the grml prompt, see: prompt -h grml + + The main difference is the default value of the \`items' style. In + particular, this theme uses _two_ lines instead of one with the plain + \`grml' theme. The rest behaves exactly the same. Here are the defaults + for \`grml-large': + + - left: rc jobs history shell-level change-root time date newline user + at host path vcs percent + - right: sad-smiley +__EOF0__ +} + +function grml_prompt_setup () { + emulate -L zsh + autoload -Uz vcs_info + autoload -Uz add-zsh-hook + add-zsh-hook precmd prompt_$1_precmd +} + +function prompt_grml_setup () { + grml_prompt_setup grml +} + +function prompt_grml-chroot_setup () { + grml_prompt_setup grml-chroot +} + +function prompt_grml-large_setup () { + grml_prompt_setup grml-large +} + +# These maps define default tokens and pre-/post-decoration for items to be +# used within the themes. All defaults may be customised in a context sensitive +# matter by using zsh's `zstyle' mechanism. +typeset -gA grml_prompt_pre_default \ + grml_prompt_post_default \ + grml_prompt_token_default + +grml_prompt_pre_default=( + at '' + battery ' ' + change-root '' + date '%F{blue}' + grml-chroot '%F{red}' + history '%F{green}' + host '' + jobs '%F{cyan}' + newline '' + path '%B' + percent '' + rc '%F{red}' + rc-always '' + sad-smiley '' + shell-level '%F{red}' + time '%F{blue}' + user '%B%F{blue}' + vcs '' +) + +grml_prompt_post_default=( + at '' + battery '' + change-root '' + date '%f' + grml-chroot '%f ' + history '%f' + host '' + jobs '%f' + newline '' + path '%b' + percent '' + rc '%f' + rc-always '' + sad-smiley '' + shell-level '%f' + time '%f' + user '%f%b' + vcs '' +) + +grml_prompt_token_default=( + at '@' + battery 'PERCENT' + change-root 'debian_chroot' + date '%D{%Y-%m-%d}' + grml-chroot 'GRML_CHROOT' + history '{history#%!} ' + host '%m ' + jobs '[%j running job(s)] ' + newline $'\n' + path '%40<..<%~%<< ' + percent '%# ' + rc '%(?..%? )' + rc-always '%?' + sad-smiley '%(?..:()' + shell-level '%(3L.+ .)' + time '%D{%H:%M:%S} ' + user '%n' + vcs '0' +) + +function grml_typeset_and_wrap () { + emulate -L zsh + local target="$1" + local new="$2" + local left="$3" + local right="$4" + + if (( ${+parameters[$new]} )); then + typeset -g "${target}=${(P)target}${left}${(P)new}${right}" + fi +} + +function grml_prompt_addto () { + emulate -L zsh + local target="$1" + local lr it apre apost new v + local -a items + shift + + [[ $target == PS1 ]] && lr=left || lr=right + zstyle -a ":prompt:${grmltheme}:${lr}:setup" items items || items=( "$@" ) + typeset -g "${target}=" + for it in "${items[@]}"; do + zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" pre apre \ + || apre=${grml_prompt_pre_default[$it]} + zstyle -s ":prompt:grml:${grmltheme}:${lr}:$it" post apost \ + || 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}" + case $it in + battery) + grml_typeset_and_wrap $target $new '' '' + ;; + change-root) + grml_typeset_and_wrap $target $new '(' ')' + ;; + grml-chroot) + if [[ -n ${(P)new} ]]; then + typeset -g "${target}=${(P)target}(CHROOT)" + fi + ;; + vcs) + v="vcs_info_msg_${new}_" + if (( ! vcscalled )); then + vcs_info + vcscalled=1 + fi + if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then + typeset -g "${target}=${(P)target}${(P)v}" + fi + ;; + *) typeset -g "${target}=${(P)target}${new}" ;; + esac + typeset -g "${target}=${(P)target}${apost}" + done +} + +function prompt_grml_precmd () { + emulate -L zsh + local grmltheme=grml + local -a left_items right_items + left_items=(rc change-root user at host path vcs percent) + right_items=(sad-smiley) + + prompt_grml_precmd_worker +} + +function prompt_grml-chroot_precmd () { + emulate -L zsh + local grmltheme=grml-chroot + local -a left_items right_items + left_items=(grml-chroot user at host path percent) + right_items=() + + prompt_grml_precmd_worker +} -if zrcautoload vcs_info; then - # `vcs_info' in zsh versions 4.3.10 and below have a broken `_realpath' - # function, which can cause a lot of trouble with our directory-based - # profiles. So: - if [[ ${ZSH_VERSION} == 4.3.<-10> ]] ; then - function VCS_INFO_realpath () { - setopt localoptions NO_shwordsplit chaselinks - ( builtin cd -q $1 2> /dev/null && pwd; ) - } - fi +function prompt_grml-large_precmd () { + emulate -L zsh + local grmltheme=grml-large + local -a left_items right_items + left_items=(rc jobs history shell-level change-root time date newline + user at host path vcs percent) + right_items=(sad-smiley) - zstyle ':vcs_info:*' max-exports 2 + prompt_grml_precmd_worker +} - if [[ -o restricted ]]; then - zstyle ':vcs_info:*' enable NONE - fi -fi +function prompt_grml_precmd_worker () { + emulate -L zsh + local -i vcscalled=0 -# Change vcs_info formats for the grml prompt. The 2nd format sets up -# $vcs_info_msg_1_ to contain "zsh: repo-name" used to set our screen title. -# TODO: The included vcs_info() version still uses $VCS_INFO_message_N_. -# That needs to be the use of $VCS_INFO_message_N_ needs to be changed -# to $vcs_info_msg_N_ as soon as we use the included version. -if [[ "$TERM" == dumb ]] ; then - zstyle ':vcs_info:*' actionformats "(%s%)-[%b|%a] " "zsh: %r" - zstyle ':vcs_info:*' formats "(%s%)-[%b] " "zsh: %r" -else - # these are the same, just with a lot of colours: - zstyle ':vcs_info:*' actionformats "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${YELLOW}|${RED}%a${MAGENTA}]${NO_COLOUR} " \ - "zsh: %r" - zstyle ':vcs_info:*' formats "${MAGENTA}(${NO_COLOUR}%s${MAGENTA})${YELLOW}-${MAGENTA}[${GREEN}%b${MAGENTA}]${NO_COLOUR}%} " \ - "zsh: %r" - zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YELLOW}%r" -fi + grml_prompt_addto PS1 "${left_items[@]}" + if zstyle -T ":prompt:${grmltheme}:right:setup" use-rprompt; then + grml_prompt_addto RPS1 "${right_items[@]}" + fi +} -# command not found handling +grml_prompt_fallback() { + setopt prompt_subst + precmd() { + (( ${+functions[vcs_info]} )) && vcs_info + } -(( ${COMMAND_NOT_FOUND} == 1 )) && -function command_not_found_handler() { - emulate -L zsh - if [[ -x ${GRML_ZSH_CNF_HANDLER} ]] ; then - ${GRML_ZSH_CNF_HANDLER} $1 + p0="${RED}%(?..%? )${WHITE}${debian_chroot:+($debian_chroot)}" + p1="${BLUE}%n${NO_COLOR}@%m %40<...<%B%~%b%<< "'${vcs_info_msg_0_}'"%# " + if (( EUID == 0 )); then + PROMPT="${BLUE}${p0}${RED}${p1}" + else + PROMPT="${RED}${p0}${BLUE}${p1}" fi - return 1 + unset p0 p1 } -# set prompt if zrcautoload promptinit && promptinit 2>/dev/null ; then - promptinit # people should be able to use their favourite prompt + # Since we define the required functions in here and not in files in + # $fpath, we need to stick the theme's name into `$prompt_themes' + # ourselves, since promptinit does not pick them up otherwise. + prompt_themes+=( grml grml-chroot grml-large ) + # Also, keep the array sorted... + prompt_themes=( "${(@on)prompt_themes}" ) else print 'Notice: no promptinit available :(' + grml_prompt_fallback fi -setopt prompt_subst +if is437; then + # The prompt themes use modern features of zsh, that require at least + # version 4.3.7 of the shell. Use the fallback otherwise. + if [[ $BATTERY -gt 0 ]]; then + zstyle ':prompt:grml:right:setup' items sad-smiley battery + add-zsh-hook precmd battery + fi + if [[ "$TERM" == dumb ]] ; then + zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" pre '' + zstyle ":prompt:grml(|-large|-chroot):*:items:grml-chroot" post ' ' + for i in rc user path jobs history date time shell-level; do + zstyle ":prompt:grml(|-large|-chroot):*:items:$i" pre '' + zstyle ":prompt:grml(|-large|-chroot):*:items:$i" post '' + done + unset i + zstyle ':prompt:grml(|-large|-chroot):right:setup' use-rprompt false + elif (( EUID == 0 )); then + zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%F{red}' + fi -# make sure to use right prompt only when not running a command -is41 && setopt transient_rprompt + # Finally enable one of the prompts. + if [[ -n $GRML_CHROOT ]]; then + prompt grml-chroot + elif [[ $GRMLPROMPT -gt 0 ]]; then + prompt grml-large + else + prompt grml + fi +else + grml_prompt_fallback +fi +# Terminal-title wizardry function ESC_print () { info_print $'\ek' $'\e\\' "$@" @@ -1278,30 +2049,7 @@ function info_print () { printf '%s' "${esc_end}" } -# TODO: revise all these NO* variables and especially their documentation -# in zsh-help() below. -is4 && [[ $NOPRECMD -eq 0 ]] && precmd () { - [[ $NOPRECMD -gt 0 ]] && return 0 - # update VCS information - (( ${+functions[vcs_info]} )) && vcs_info - - if [[ $TERM == screen* ]] ; then - if [[ -n ${vcs_info_msg_1_} ]] ; then - ESC_print ${vcs_info_msg_1_} - else - ESC_print "zsh" - fi - fi - # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT - if [[ ${DONTSETRPROMPT:-} -eq 0 ]] ; then - if [[ $BATTERY -gt 0 ]] ; then - # update battery (dropped into $PERCENT) information - battery - RPROMPT="%(?..:() ${PERCENT}" - else - RPROMPT="%(?..:() " - fi - fi +function grml_reset_screen_title () { # adjust title of xterm # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html [[ ${NOTITLE:-} -gt 0 ]] && return 0 @@ -1312,23 +2060,33 @@ is4 && [[ $NOPRECMD -eq 0 ]] && precmd () { esac } -# preexec() => a function running before every command -is4 && [[ $NOPRECMD -eq 0 ]] && \ -preexec () { - [[ $NOPRECMD -gt 0 ]] && return 0 -# set hostname if not running on host with name 'grml' +function grml_vcs_to_screen_title () { + if [[ $TERM == screen* ]] ; then + if [[ -n ${vcs_info_msg_1_} ]] ; then + ESC_print ${vcs_info_msg_1_} + else + ESC_print "zsh" + fi + fi +} + +function grml_maintain_name () { + # set hostname if not running on host with name 'grml' if [[ -n "$HOSTNAME" ]] && [[ "$HOSTNAME" != $(hostname) ]] ; then NAME="@$HOSTNAME" fi -# get the name of the program currently running and hostname of local machine -# set screen window title if running in a screen +} + +function grml_cmd_to_screen_title () { + # get the name of the program currently running and hostname of local + # machine set screen window title if running in a screen if [[ "$TERM" == screen* ]] ; then - # local CMD=${1[(wr)^(*=*|sudo|ssh|-*)]} # don't use hostname - local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" # use hostname + local CMD="${1[(wr)^(*=*|sudo|ssh|-*)]}$NAME" ESC_print ${CMD} fi -# adjust title of xterm - [[ ${NOTITLE} -gt 0 ]] && return 0 +} + +function grml_control_xterm_title () { case $TERM in (xterm*|rxvt*) set_title "${(%):-"%n@%m:"}" "$1" @@ -1336,42 +2094,17 @@ preexec () { esac } -EXITCODE="%(?..%?%1v )" -PS2='\`%_> ' # secondary prompt, printed when the shell needs more information to complete a command. -PS3='?# ' # selection prompt used within a select loop. -PS4='+%N:%i:%_> ' # the execution trace prompt (setopt xtrace). default: '+%N:%i>' - -# set variable debian_chroot if running in a chroot with /etc/debian_chroot -if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then - debian_chroot=$(cat /etc/debian_chroot) -fi - -# don't use colors on dumb terminals (like emacs): -if [[ "$TERM" == dumb ]] ; then - PROMPT="${EXITCODE}${debian_chroot:+($debian_chroot)}%n@%m %40<...<%B%~%b%<< " -else - # only if $GRMLPROMPT is set (e.g. via 'GRMLPROMPT=1 zsh') use the extended prompt - # set variable identifying the chroot you work in (used in the prompt below) - if [[ $GRMLPROMPT -gt 0 ]] ; then - PROMPT="${RED}${EXITCODE}${CYAN}[%j running job(s)] ${GREEN}{history#%!} ${RED}%(3L.+.) ${BLUE}%* %D -${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< " - else - # This assembles the primary prompt string - if (( EUID != 0 )); then - PROMPT="${RED}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${BLUE}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< " - else - PROMPT="${BLUE}${EXITCODE}${WHITE}${debian_chroot:+($debian_chroot)}${RED}%n${NO_COLOUR}@%m %40<...<%B%~%b%<< " - fi +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 + add-zsh-hook preexec grml_maintain_name + add-zsh-hook preexec grml_cmd_to_screen_title + if [[ $NOTITLE -eq 0 ]]; then + add-zsh-hook preexec grml_control_xterm_title fi fi -PROMPT="${PROMPT}"'${vcs_info_msg_0_}'"%# " - -# if we are inside a grml-chroot set a specific prompt theme -if [[ -n "$GRML_CHROOT" ]] ; then - PROMPT="%{$fg[red]%}(CHROOT) %{$fg_bold[red]%}%n%{$fg_no_bold[white]%}@%m %40<...<%B%~%b%<< %\# " -fi - # 'hash' some often used directories #d# start hash -d deb=/var/cache/apt/archives @@ -1388,30 +2121,34 @@ hash -d www=/var/www # some aliases if check_com -c screen ; then if [[ $UID -eq 0 ]] ; then - [[ -r /etc/grml/screenrc ]] && alias screen="${commands[screen]} -c /etc/grml/screenrc" + if [[ -r /etc/grml/screenrc ]]; then + alias screen="${commands[screen]} -c /etc/grml/screenrc" + fi elif [[ -r $HOME/.screenrc ]] ; then alias screen="${commands[screen]} -c $HOME/.screenrc" else if [[ -r /etc/grml/screenrc_grml ]]; then alias screen="${commands[screen]} -c /etc/grml/screenrc_grml" else - [[ -r /etc/grml/screenrc ]] && alias screen="${commands[screen]} -c /etc/grml/screenrc" + if [[ -r /etc/grml/screenrc ]]; then + alias screen="${commands[screen]} -c /etc/grml/screenrc" + fi fi fi fi # do we have GNU ls with color-support? -if ls --help 2>/dev/null | grep -- --color= >/dev/null && [[ "$TERM" != dumb ]] ; then - #a1# execute \kbd{@a@}:\quad ls with colors - alias ls='ls -b -CF --color=auto' - #a1# execute \kbd{@a@}:\quad list all files, with colors - alias la='ls -la --color=auto' - #a1# long colored list, without dotfiles (@a@) - alias ll='ls -l --color=auto' - #a1# long colored list, human readable sizes (@a@) - alias lh='ls -hAl --color=auto' - #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...) - alias l='ls -lF --color=auto' +if [[ "$TERM" != dumb ]]; then + #a1# List files with colors (\kbd{ls -b -CF \ldots}) + alias ls='ls -b -CF '${ls_options:+"${ls_options[*]}"} + #a1# List all files, with colors (\kbd{ls -la \ldots}) + alias la='ls -la '${ls_options:+"${ls_options[*]}"} + #a1# List files with long colored list, without dotfiles (\kbd{ls -l \ldots}) + alias ll='ls -l '${ls_options:+"${ls_options[*]}"} + #a1# List files with long colored list, human readable sizes (\kbd{ls -hAl \ldots}) + alias lh='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='ls -lF '${ls_options:+"${ls_options[*]}"} else alias ls='ls -b -CF' alias la='ls -la' @@ -1428,16 +2165,6 @@ if [[ -x /sbin/kexec ]] && [[ -r /proc/cmdline ]] ; then alias "$(uname -r)-reboot"="kexec -l --initrd=/boot/initrd.img-"$(uname -r)" --command-line=\"$(cat /proc/cmdline)\" /boot/vmlinuz-"$(uname -r)"" fi -alias cp='nocorrect cp' # no spelling correction on cp -alias mkdir='nocorrect mkdir' # no spelling correction on mkdir -alias mv='nocorrect mv' # no spelling correction on mv -alias rm='nocorrect rm' # no spelling correction on rm - -#a1# Execute \kbd{rmdir} -alias rd='rmdir' -#a1# Execute \kbd{mkdir} -alias md='mkdir' - # see http://www.cl.cam.ac.uk/~mgk25/unicode.html#term for details alias term2iso="echo 'Setting terminal to iso mode' ; print -n '\e%@'" alias term2utf="echo 'Setting terminal to utf-8 mode'; print -n '\e%G'" @@ -1462,31 +2189,12 @@ iso2utf() { fi } -# I like clean prompt, so provide simple way to get that -check_com 0 || alias 0='return 0' - -# for really lazy people like mika: -check_com S &>/dev/null || alias S='screen' -check_com s &>/dev/null || alias s='ssh' - # especially for roadwarriors using GNU screen and ssh: if ! check_com asc &>/dev/null ; then asc() { autossh -t "$@" 'screen -RdU' } compdef asc=ssh fi -# get top 10 shell commands: -alias top10='print -l ${(o)history%% *} | uniq -c | sort -nr | head -n 10' - -# truecrypt; use e.g. via 'truec /dev/ice /mnt/ice' or 'truec -i' -if check_com -c truecrypt ; then - if isutfenv ; then - alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077,utf8" ' - else - alias truec='truecrypt --mount-options "rw,sync,dirsync,users,uid=1000,gid=users,umask=077" ' - fi -fi - #f1# Hints for the use of zsh on grml zsh-help() { print "$bg[white]$fg[black] @@ -1514,10 +2222,6 @@ very lately. System wide configuration without touching configuration files of grml can take place in /etc/zsh/zshrc.local. -Normally, the root user (EUID == 0) does not get the whole grml setup. -If you want to force the whole setup for that user, too, set -GRML_ALWAYS_LOAD_ALL=1 in .zshrc.pre in root'\''s home directory. - For information regarding zsh start at http://grml.org/zsh/ Take a look at grml'\''s zsh refcard: @@ -1535,7 +2239,8 @@ Basically meant for bash users who are not used to the power of the zsh yet. :) "NOCOR=1 zsh" => deactivate automatic correction - "NOMENU=1 zsh" => do not use auto menu completion (note: use ctrl-d for completion instead!) + "NOMENU=1 zsh" => do not use auto menu completion + (note: use ctrl-d for completion instead!) "NOPRECMD=1 zsh" => disable the precmd + preexec commands (set GNU screen title) "NOTITLE=1 zsh" => disable setting the title of xterms without disabling preexec() and precmd() completely @@ -1587,197 +2292,38 @@ if [[ -r /etc/debian_version ]] ; then alias su="sudo su" 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 - -# sort installed Debian-packages by size -if check_com -c dpkg-query ; then - #a3# List installed Debian-packages sorted by size - 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" -fi - -# 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 <' and 'cd -' with menu - # zstyle ':completion:*:*:cd:*:directory-stack' menu yes select - - # insert all expansions for expand completer - zstyle ':completion:*:expand:*' tag-order all-expansions - zstyle ':completion:*:history-words' list false - - # activate menu - zstyle ':completion:*:history-words' menu yes - - # ignore duplicate entries - zstyle ':completion:*:history-words' remove-all-dups yes - zstyle ':completion:*:history-words' stop yes - - # match uppercase from lowercase - zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' - - # separate matches into groups - zstyle ':completion:*:matches' group 'yes' - zstyle ':completion:*' group-name '' - - if [[ "$NOMENU" -eq 0 ]] ; then - # if there are more than 5 options allow selecting from a menu - zstyle ':completion:*' menu select=5 - else - # don't use any menus at all - setopt no_auto_menu - fi - - zstyle ':completion:*:messages' format '%d' - zstyle ':completion:*:options' auto-description '%d' - - # describe options in full - zstyle ':completion:*:options' description 'yes' - - # on processes completion complete all user processes - zstyle ':completion:*:processes' command 'ps -au$USER' - - # offer indexes before parameters in subscripts - zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters - - # provide verbose completion information - zstyle ':completion:*' verbose true - - # recent (as of Dec 2007) zsh versions are able to provide descriptions - # for commands (read: 1st word in the line) that it will list for the user - # to choose from. The following disables that, because it's not exactly fast. - zstyle ':completion:*:-command-:*:' verbose false - - # set format for warnings - zstyle ':completion:*:warnings' format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d' - - # define files to ignore for zcompile - zstyle ':completion:*:*:zcompile:*' ignored-patterns '(*~|*.zwc)' - zstyle ':completion:correct:' prompt 'correct to: %e' - - # Ignore completion functions for commands you don't have: - zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*' - - # Provide more processes in completion of programs like killall: - zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq' - - # complete manual by their section - zstyle ':completion:*:manuals' separate-sections true - zstyle ':completion:*:manuals.*' insert-sections true - zstyle ':completion:*:man:*' menu yes select - - # provide .. as a completion - zstyle ':completion:*' special-dirs .. - - # run rehash on completion so new installed program are found automatically: - _force_rehash() { - (( CURRENT == 1 )) && rehash - return 1 - } - - ## correction - # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it - if [[ "$NOCOR" -gt 0 ]] ; then - zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored - setopt nocorrect - else - # try to be smart about when to use what completer... - setopt correct - zstyle -e ':completion:*' completer ' - if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then - _last_try="$HISTNO$BUFFER$CURSOR" - reply=(_complete _match _ignored _prefix _files) - else - if [[ $words[1] == (rm|mv) ]] ; then - reply=(_complete _files) - else - reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files) - fi - fi' - fi - - # command for process lists, the local web server details and host completion - zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html' + #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 - # caching - [[ -d $ZSHDIR/cache ]] && zstyle ':completion:*' use-cache yes && \ - zstyle ':completion::complete:*' cache-path $ZSHDIR/cache/ +# sort installed Debian-packages by size +if check_com -c dpkg-query ; then + #a3# List installed Debian-packages sorted by size + 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" +fi - # host completion - if is42 ; then - [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=() - [[ -r /etc/hosts ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(@']="set MARK" - help_zle_keybindings['XJ']="vi-join lines" - help_zle_keybindings['XB']="jump to matching brace" - help_zle_keybindings['XU']="undo" - help_zle_keybindings['_']="undo" - help_zle_keybindings['XF']="find in cmdline" - help_zle_keybindings['A']="goto beginning of line" - help_zle_keybindings['E']="goto end of line" - help_zle_keybindings['t']="transpose charaters" - help_zle_keybindings['T']="transpose words" - help_zle_keybindings['s']="spellcheck word" - help_zle_keybindings['K']="backward kill buffer" - help_zle_keybindings['U']="forward kill buffer" - help_zle_keybindings['y']="insert previously killed word/string" - help_zle_keybindings["'"]="quote line" - help_zle_keybindings['"']="quote from mark to cursor" - help_zle_keybindings['']="repeat next cmd/char times (-10a -> -10 times 'a')" - help_zle_keybindings['U']="make next word Uppercase" - help_zle_keybindings['l']="make next word lowercase" - help_zle_keybindings['Xd']="preview expansion under cursor" - help_zle_keybindings['q']="push current CL into background, freeing it. Restore on next CL" - help_zle_keybindings['.']="insert (and interate through) last word from prev CLs" - help_zle_keybindings[',']="complete word from newer history (consecutive hits)" - help_zle_keybindings['m']="repeat last typed word on current CL" - help_zle_keybindings['V']="insert next keypress symbol literally (e.g. for bindkey)" - help_zle_keybindings['!!:n*']="insert last n arguments of last command" - help_zle_keybindings['!!:n-']="insert arguments n..N-2 of last command (e.g. mv s s d)" - help_zle_keybindings['H']="run help on current command" - - #init global variables - unset help_zle_lines help_zle_sln - typeset -g -a help_zle_lines - typeset -g help_zle_sln=1 - - local k v - 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) - for f in $HELPZLE_KEYBINDING_FILES; do - [[ -r "$f" ]] || continue #not readable ? skip it - contents="$(<$f)" - for cline in "${(f)contents}"; do - #zsh pattern: matches lines like: #k# .............. - if [[ "$cline" == (#s)[[:space:]]#\#k\#[[:space:]]##(#b)(*)[[:space:]]#(#e) ]]; then - lastkeybind_desc="$match[*]" - num_lines_elapsed=0 - #zsh pattern: matches lines that set a keybinding using bindkey or compdef -k - # ignores lines that are commentend out - # grabs first in '' or "" enclosed string with length between 1 and 6 characters - elif [[ "$cline" == [^#]#(bindkey|compdef -k)[[:space:]](*)(#b)(\"((?)(#c1,6))\"|\'((?)(#c1,6))\')(#B)(*) ]]; then - #description prevously 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/}/\\e\^\?/}/\\e\[5~/}/\\e\[6~/}//(\\e|\^\[)/}//\^/}/3~/} - #put keybinding in assoc array, possibly overwriting defaults or stuff found in earlier files - #Note that we are extracting the keybinding-string including the quotes (see Note at beginning) - help_zle_keybindings[${k}]=$lastkeybind_desc - fi - lastkeybind_desc="" - else - ((num_lines_elapsed++)) - fi - done - done - unset contents - #calculate length of keybinding column - local kstrlen=0 - for k (${(k)help_zle_keybindings[@]}) ((kstrlen < ${#k})) && kstrlen=${#k} - #convert the assoc array into preformated lines, which we are able to sort - for k v in ${(kv)help_zle_keybindings[@]}; do - #pad keybinding-string to kstrlen chars and remove outermost characters (i.e. the quotes) - help_zle_lines+=("${(r:kstrlen:)k[2,-2]}${v}") - done - #sort lines alphabetically - help_zle_lines=("${(i)help_zle_lines[@]}") - [[ -d ${HELP_ZLE_CACHE_FILE:h} ]] || mkdir -p "${HELP_ZLE_CACHE_FILE:h}" - echo "help_zle_lines=(${(q)help_zle_lines[@]})" >| $HELP_ZLE_CACHE_FILE - zcompile $HELP_ZLE_CACHE_FILE -} -typeset -g help_zle_sln -typeset -g -a help_zle_lines - -#f1# Provides (partially autogenerated) help on keybindings and the zsh line editor -help-zle() -{ - emulate -L zsh - unsetopt ksharrays #indexing starts at 1 - #help lines already generated ? no ? then do it - [[ ${+functions[help_zle_parse_keybindings]} -eq 1 ]] && {help_zle_parse_keybindings && unfunction help_zle_parse_keybindings} - #already displayed all lines ? go back to the start - [[ $help_zle_sln -gt ${#help_zle_lines} ]] && help_zle_sln=1 - local sln=$help_zle_sln - #note that help_zle_sln is a global var, meaning we remember the last page we viewed - help_zle_sln=$((help_zle_sln + HELP_LINES_PER_PAGE)) - zle -M "${(F)help_zle_lines[sln,help_zle_sln-1]}" -} -#k# display help for keybindings and ZLE (cycle pages with consecutive use) -zle -N help-zle && bindkey '^Xz' help-zle - # grep for running process, like: 'any vim' any() { emulate -L zsh @@ -2135,7 +2568,7 @@ any() { echo "any - grep for process(es) by keyword" >&2 echo "Usage: any " >&2 ; return 1 else - ps xauwww | grep -i --color=auto "[${1[1]}]${1[2,-1]}" + ps xauwww | grep -i "${grep_options[@]}" "[${1[1]}]${1[2,-1]}" fi } @@ -2156,9 +2589,11 @@ deswap() { # VIM_OPTIONS=( -p ) # This will cause vim to send every file given on the # commandline to be send to it's own tab (needs vim7). -vim() { - VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@" -} +if check_com vim; then + vim() { + VIM_PLEASE_SET_TITLE='yes' command vim ${VIM_OPTIONS} "$@" + } +fi # make a backup of a file bk() { @@ -2212,107 +2647,60 @@ fi # load the lookup subsystem if it's available on the system zrcautoload lookupinit && lookupinit -### non-root (EUID != 0) code below -### - -if (( GRML_ALWAYS_LOAD_ALL == 0 )) && (( $EUID == 0 )) ; then - zrclocal - return 0 -fi - # variables # set terminal property (used e.g. by msgid-chooser) export COLORTERM="yes" -#m# v QTDIR \kbd{/usr/share/qt[34]}\quad [for non-root only] -[[ -d /usr/share/qt3 ]] && export QTDIR=/usr/share/qt3 -[[ -d /usr/share/qt4 ]] && export QTDIR=/usr/share/qt4 - -# support running 'jikes *.java && jamvm HelloWorld' OOTB: -#v# [for non-root only] -[[ -f /usr/share/classpath/glibj.zip ]] && export JIKESPATH=/usr/share/classpath/glibj.zip - # aliases -# Xterm resizing-fu. -# Based on http://svn.kitenet.net/trunk/home-full/.zshrc?rev=11710&view=log (by Joey Hess) -alias hide='echo -en "\033]50;nil2\007"' -alias tiny='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso8859-15\007"' -alias small='echo -en "\033]50;6x10\007"' -alias medium='echo -en "\033]50;-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-15\007"' -alias default='echo -e "\033]50;-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-15\007"' -alias large='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-150-*-*-c-*-iso8859-15\007"' -alias huge='echo -en "\033]50;-misc-fixed-medium-r-normal-*-*-210-*-*-c-*-iso8859-15\007"' -alias smartfont='echo -en "\033]50;-artwiz-smoothansi-*-*-*-*-*-*-*-*-*-*-*-*\007"' -alias semifont='echo -en "\033]50;-misc-fixed-medium-r-semicondensed-*-*-120-*-*-*-*-iso8859-15\007"' - # general #a2# Execute \kbd{du -sch} alias da='du -sch' #a2# Execute \kbd{jobs -l} alias j='jobs -l' -# compile stuff -#a2# Execute \kbd{./configure} -alias CO="./configure" -#a2# Execute \kbd{./configure --help} -alias CH="./configure --help" - # listing stuff #a2# Execute \kbd{ls -lSrah} alias dir="ls -lSrah" #a2# Only show dot-directories -alias lad='ls -d .*(/)' # only show dot-directories +alias lad='ls -d .*(/)' #a2# Only show dot-files -alias lsa='ls -a .*(.)' # only show dot-files +alias lsa='ls -a .*(.)' #a2# Only files with setgid/setuid/sticky flag -alias lss='ls -l *(s,S,t)' # only files with setgid/setuid/sticky flag -#a2# Only show 1st ten symlinks -alias lsl='ls -l *(@)' # only symlinks +alias lss='ls -l *(s,S,t)' +#a2# Only show symlinks +alias lsl='ls -l *(@)' #a2# Display only executables -alias lsx='ls -l *(*)' # only executables +alias lsx='ls -l *(*)' #a2# Display world-{readable,writable,executable} files -alias lsw='ls -ld *(R,W,X.^ND/)' # world-{readable,writable,executable} files +alias lsw='ls -ld *(R,W,X.^ND/)' #a2# Display the ten biggest files -alias lsbig="ls -flh *(.OL[1,10])" # display the biggest files +alias lsbig="ls -flh *(.OL[1,10])" #a2# Only show directories -alias lsd='ls -d *(/)' # only show directories +alias lsd='ls -d *(/)' #a2# Only show empty directories -alias lse='ls -d *(/^F)' # only show empty directories +alias lse='ls -d *(/^F)' #a2# Display the ten newest files -alias lsnew="ls -rtlh *(D.om[1,10])" # display the newest files +alias lsnew="ls -rtlh *(D.om[1,10])" #a2# Display the ten oldest files -alias lsold="ls -rtlh *(D.Om[1,10])" # display the oldest files +alias lsold="ls -rtlh *(D.Om[1,10])" #a2# Display the ten smallest files -alias lssmall="ls -Srl *(.oL[1,10])" # display the smallest files - -# chmod -#a2# Execute \kbd{chmod 600} -alias rw-='chmod 600' -#a2# Execute \kbd{chmod 700} -alias rwx='chmod 700' -#m# a2 r-{}- Execute \kbd{chmod 644} -alias r--='chmod 644' -#a2# Execute \kbd{chmod 755} -alias r-x='chmod 755' +alias lssmall="ls -Srl *(.oL[1,10])" +#a2# Display the ten newest directories and ten newest .directories +alias lsnewdir="ls -rthdl *(/om[1,10]) .*(D/om[1,10])" +#a2# Display the ten oldest directories and ten oldest .directories +alias lsolddir="ls -rthdl *(/Om[1,10]) .*(D/Om[1,10])" # some useful aliases -#a2# Execute \kbd{mkdir -p} -alias md='mkdir -p' -#a2# Remove current empty directory. Execute \kbd{cd ..; rmdir $OLDCWD} +#a2# Remove current empty directory. Execute \kbd{cd ..; rmdir \$OLDCWD} alias rmcdir='cd ..; rmdir $OLDPWD || cd $OLDPWD' #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"' +#a2# scp with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset alias insecscp='scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"' -# simple webserver -check_com -c python && alias http="python -m SimpleHTTPServer" - -# Use 'g' instead of 'git': -check_com g || alias g='git' - # work around non utf8 capable software in utf environment via $LANG and luit if check_com isutfenv && check_com luit ; then if check_com -c mrxvt ; then @@ -2358,7 +2746,16 @@ cd() { #f5# Create Directoy and \kbd{cd} to it mkcd() { - mkdir -p "$@" && cd "$@" + if (( ARGC != 1 )); then + printf 'usage: mkcd \n' + return 1; + fi + if [[ ! -d "$1" ]]; then + command mkdir -p "$1" + else + printf '`%s'\'' already exists: cd-ing.\n' "$1" + fi + builtin cd "$1" } #f5# Create temporary directory and \kbd{cd} to it @@ -2369,40 +2766,6 @@ cdt() { builtin cd "$t" } -#f5# Create directory under cursor or the selected area -# 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 -# directory does not exist yet -> press ctrl-XM and problem solved -inplaceMkDirs() { - local PATHTOMKDIR - if ((REGION_ACTIVE==1)); then - local F=$MARK T=$CURSOR - if [[ $F -gt $T ]]; then - F=${CURSOR} - T=${MARK} - fi - # get marked area from buffer and eliminate whitespace - PATHTOMKDIR=${BUFFER[F+1,T]%%[[:space:]]##} - PATHTOMKDIR=${PATHTOMKDIR##[[:space:]]##} - else - local bufwords iword - bufwords=(${(z)LBUFFER}) - iword=${#bufwords} - bufwords=(${(z)BUFFER}) - PATHTOMKDIR="${(Q)bufwords[iword]}" - fi - [[ -z "${PATHTOMKDIR}" ]] && return 1 - if [[ -e "${PATHTOMKDIR}" ]]; then - zle -M " path already exists, doing nothing" - else - zle -M "$(mkdir -p -v "${PATHTOMKDIR}")" - zle end-of-line - fi -} -#k# mkdir -p from string under cursor or marked area -zle -N inplaceMkDirs && bindkey '^XM' inplaceMkDirs - #f5# List files which have been accessed within the last {\it n} days, {\it n} defaults to 1 accessed() { emulate -L zsh @@ -2425,7 +2788,7 @@ check_com new || alias new=modified # use colors when GNU grep with color-support #a2# Execute \kbd{grep -{}-color=auto} -(grep --help 2>/dev/null |grep -- --color) >/dev/null && alias grep='grep --color=auto' +(( $#grep_options > 0 )) && alias grep='grep '${grep_options:+"${grep_options[*]}"} # Translate DE<=>EN # 'translate' looks up fot a word in a file with language-to-language @@ -2464,62 +2827,62 @@ simple-extract() { zparseopts -D -E "d=DELETE_ORIGINAL" for ARCHIVE in "${@}"; do case $ARCHIVE in - *.(tar.bz2|tbz2|tbz)) + *(tar.bz2|tbz2|tbz)) DECOMP_CMD="tar -xvjf -" USES_STDIN=true USES_STDOUT=false ;; - *.(tar.gz|tgz)) + *(tar.gz|tgz)) DECOMP_CMD="tar -xvzf -" USES_STDIN=true USES_STDOUT=false ;; - *.(tar.xz|txz|tar.lzma)) + *(tar.xz|txz|tar.lzma)) DECOMP_CMD="tar -xvJf -" USES_STDIN=true USES_STDOUT=false ;; - *.tar) + *tar) DECOMP_CMD="tar -xvf -" USES_STDIN=true USES_STDOUT=false ;; - *.rar) + *rar) DECOMP_CMD="unrar x" USES_STDIN=false USES_STDOUT=false ;; - *.lzh) + *lzh) DECOMP_CMD="lha x" USES_STDIN=false USES_STDOUT=false ;; - *.7z) + *7z) DECOMP_CMD="7z x" USES_STDIN=false USES_STDOUT=false ;; - *.(zip|jar)) + *(zip|jar)) DECOMP_CMD="unzip" USES_STDIN=false USES_STDOUT=false ;; - *.deb) + *deb) DECOMP_CMD="ar -x" USES_STDIN=false USES_STDOUT=false ;; - *.bz2) + *bz2) DECOMP_CMD="bzip2 -d -c -" USES_STDIN=true USES_STDOUT=true ;; - *.(gz|Z)) + *(gz|Z)) DECOMP_CMD="gzip -d -c -" USES_STDIN=true USES_STDOUT=true ;; - *.(xz|lzma)) + *(xz|lzma)) DECOMP_CMD="xz -d -c -" USES_STDIN=true USES_STDOUT=true @@ -2607,56 +2970,6 @@ _simple_extract() compdef _simple_extract simple-extract alias se=simple-extract -# Usage: smartcompress () -#f5# Smart archive creator -smartcompress() { - emulate -L zsh - if [[ -n $2 ]] ; then - case $2 in - tgz | tar.gz) tar -zcvf$1.$2 $1 ;; - tbz2 | tar.bz2) tar -jcvf$1.$2 $1 ;; - tar.Z) tar -Zcvf$1.$2 $1 ;; - tar) tar -cvf$1.$2 $1 ;; - gz | gzip) gzip $1 ;; - bz2 | bzip2) bzip2 $1 ;; - *) - echo "Error: $2 is not a valid compression type" - ;; - esac - else - smartcompress $1 tar.gz - fi -} - -# Usage: show-archive -#f5# List an archive's content -show-archive() { - emulate -L zsh - if [[ -f $1 ]] ; then - case $1 in - *.tar.gz) gunzip -c $1 | tar -tf - -- ;; - *.tar) tar -tf $1 ;; - *.tgz) tar -ztf $1 ;; - *.zip) unzip -l $1 ;; - *.bz2) bzless $1 ;; - *.deb) dpkg-deb --fsys-tarfile $1 | tar -tf - -- ;; - *) echo "'$1' Error. Please go away" ;; - esac - else - echo "'$1' is not a valid archive" - fi -} - -# TODO: So, this is the third incarnation of this function!? -#f5# Reload given functions -refunc() { - for func in $argv ; do - unfunction $func - autoload $func - done -} -compdef _functions refunc - #f5# Set all ulimit parameters to \kbd{unlimited} allulimit() { ulimit -c unlimited @@ -2690,46 +3003,50 @@ xtrename() { return 0 } -# TODO: -# Rewrite this by either using tinyurl.com's API -# or using another shortening service to comply with -# tinyurl.com's policy. -# -# Create small urls via http://tinyurl.com using wget(1). -#function zurl() { -# emulate -L zsh -# [[ -z $1 ]] && { print "USAGE: zurl " ; return 1 } -# -# local PN url tiny grabber search result preview -# PN=$0 -# url=$1 -## Check existence of given URL with the help of ping(1). -## N.B. ping(1) only works without an eventual given protocol. -# ping -c 1 ${${url#(ftp|http)://}%%/*} >& /dev/null || \ -# read -q "?Given host ${${url#http://*/}%/*} is not reachable by pinging. Proceed anyway? [y|n] " -# -# if (( $? == 0 )) ; then -## Prepend 'http://' to given URL where necessary for later output. -# [[ ${url} != http(s|)://* ]] && url='http://'${url} -# tiny='http://tinyurl.com/create.php?url=' -# if check_com -c wget ; then -# grabber='wget -O- -o/dev/null' -# else -# print "wget is not available, but mandatory for ${PN}. Aborting." -# fi -## Looking for i.e.`copy('http://tinyurl.com/7efkze')' in TinyURL's HTML code. -# search='copy\(?http://tinyurl.com/[[:alnum:]]##*' -# result=${(M)${${${(f)"$(${=grabber} ${tiny}${url})"}[(fr)${search}*]}//[()\';]/}%%http:*} -## TinyURL provides the rather new feature preview for more confidence. -# preview='http://preview.'${result#http://} -# -# printf '%s\n\n' "${PN} - Shrinking long URLs via webservice TinyURL ." -# printf '%s\t%s\n\n' 'Given URL:' ${url} -# printf '%s\t%s\n\t\t%s\n' 'TinyURL:' ${result} ${preview} -# else -# return 1 -# fi -#} +# Create small urls via http://goo.gl using curl(1). +# API reference: https://code.google.com/apis/urlshortener/ +function zurl() { + emulate -L zsh + setopt extended_glob + + if [[ -z $1 ]]; then + print "USAGE: zurl " + return 1 + fi + + local PN url prog api json contenttype item + local -a data + PN=$0 + url=$1 + + # Prepend 'http://' to given URL where necessary for later output. + if [[ ${url} != http(s|)://* ]]; then + url='http://'${url} + fi + + if check_com -c curl; then + prog=curl + else + print "curl is not available, but mandatory for ${PN}. Aborting." + return 1 + fi + api='https://www.googleapis.com/urlshortener/v1/url' + contenttype="Content-Type: application/json" + json="{\"longUrl\": \"${url}\"}" + data=(${(f)"$($prog --silent -H ${contenttype} -d ${json} $api)"}) + # Parse the response + for item in "${data[@]}"; do + case "$item" in + ' '#'"id":'*) + item=${item#*: \"} + item=${item%\",*} + printf '%s\n' "$item" + return 0 + ;; + esac + done + return 1 +} #f2# Find history events by search pattern and list them by date. whatwhen() {