Specify a command search path for sudo completion [Closes: issue1207]
[grml-etc-core.git] / etc / zsh / zshrc
index f8cfd74..b7cb2e5 100644 (file)
@@ -139,12 +139,14 @@ 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
 }
 
 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 +165,10 @@ isgrmlcd(){
 if isgrml ; then
 #f1# Checks whether or not you're running grml-small
     isgrmlsmall() {
-        [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]] && return 0 ; return 1
+        if [[ ${${${(f)"$(</etc/grml_version)"}%% *}##*-} == 'small' ]]; then
+            return 0
+        fi
+        return 1
     }
 else
     isgrmlsmall() { return 1 }
@@ -174,6 +179,11 @@ isdarwin(){
     return 1
 }
 
+isfreebsd(){
+    [[ $OSTYPE == freebsd* ]] && return 0
+    return 1
+}
+
 #f1# are we running within an utf environment?
 isutfenv() {
     case "$LANG $CHARSET $LANGUAGE" in
@@ -246,41 +256,78 @@ function zrcautoload() {
     return 0
 }
 
-# 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.
+# 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 }
 
 # set some important options (as early as possible)
-setopt append_history       # append history list to the history file (important for multiple parallel zsh sessions!)
-is4 && setopt SHARE_HISTORY # import new commands from the history file also in other zsh-session
-setopt extended_history     # save each command's beginning timestamp and the duration to the history file
-is4 && setopt histignorealldups # If  a  new  command  line being added to the history
-                            # list duplicates an older one, the older command is removed from the list
-setopt histignorespace      # remove command lines from the history list when
-                            # the first character on the line is a space
-setopt auto_cd              # 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 extended_glob        # 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 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 +335,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
@@ -480,8 +538,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
@@ -513,9 +572,15 @@ 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
@@ -591,12 +656,6 @@ bindkey '\e[8~' end-of-somewhere        # end
 bindkey '\e[A'  up-line-or-search       # cursor up
 bindkey '\e[B'  down-line-or-search     # <ESC>-
 
-## 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
@@ -619,8 +678,8 @@ 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
+# 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 ยง
@@ -628,7 +687,7 @@ bindkey "\e[6~" history-beginning-search-forward-end  # PageDown
 zrcautoload insert-unicode-char
 zle -N insert-unicode-char
 #k# Insert Unicode character
-bindkey '^Xi' insert-unicode-char
+bindkey '^xi' insert-unicode-char
 
 #m# k Shift-tab Perform backwards menu completion
 if [[ -n "$terminfo[kcbt]" ]]; then
@@ -651,6 +710,7 @@ grml_toggle_abbrev() {
     fi
 }
 
+#k# Toggle abbreviation expansion on/off
 zle -N grml_toggle_abbrev
 bindkey '^xA' grml_toggle_abbrev
 
@@ -844,7 +904,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'
@@ -875,8 +935,15 @@ zleiab() {
     LBUFFER+=${abk[$MATCH]:-$MATCH}
 }
 
-zle -N zleiab
-bindkey ",." zleiab
+zle -N zleiab && bindkey ",." zleiab
+
+#f# display contents of assoc array $abk
+help-show-abk()
+{
+  zle -M "$(print "Type ,. after these abbreviations to expand them:"; print -a -C 2 ${(kv)abk})"
+}
+#k# Display list of abbreviations that expand when followed by ,.
+zle -N help-show-abk && bindkey '^xb' help-show-abk
 
 # autoloading
 zrcautoload zmv    # who needs mmv or rename?
@@ -902,7 +969,6 @@ if zrcautoload compinit ; then
     compinit || print 'Notice: no compinit available :('
 else
     print 'Notice: no compinit available :('
-    function zstyle { }
     function compdef { }
 fi
 
@@ -922,7 +988,7 @@ fi
 
 if is4 && zrcautoload insert-files && zle -N insert-files ; then
     #k# Insert files and test globbing
-    bindkey "^Xf" insert-files # C-x-f
+    bindkey "^xf" insert-files # C-x-f
 fi
 
 bindkey ' '   magic-space    # also do history expansion on space
@@ -953,7 +1019,7 @@ 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
+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 };
@@ -987,7 +1053,7 @@ sudo-command-line() {
 zle -N sudo-command-line
 
 #k# prepend the current command with "sudo"
-bindkey "^Os" sudo-command-line
+bindkey "^os" sudo-command-line
 
 ### jump behind the first word on the cmdline.
 ### useful to add options.
@@ -1009,7 +1075,7 @@ bindkey '^x1' jump_after_first_word
 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
+bindkey "^x^x" hist-complete
 
 ## complete word from currently visible Screen or Tmux buffer.
 if check_com -c screen || check_com -c tmux; then
@@ -1028,7 +1094,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)} )
@@ -1037,8 +1104,8 @@ if check_com -c screen || check_com -c tmux; then
         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'
+    bindkey -r "^xS"
+    compdef -k _complete_screen_display complete-word '^xS'
 fi
 
 # history
@@ -1075,85 +1142,39 @@ 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
@@ -1337,9 +1358,13 @@ preexec () {
 }
 
 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>'
+# 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:%_> '
 
 # set variable debian_chroot if running in a chroot with /etc/debian_chroot
 if [[ -z "$debian_chroot" ]] && [[ -r /etc/debian_chroot ]] ; then
@@ -1350,8 +1375,9 @@ fi
 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)
+    # 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%<< "
@@ -1388,30 +1414,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
+if [[ "$TERM" != dumb ]]; then
     #a1# execute \kbd{@a@}:\quad ls with colors
-    alias ls='ls -b -CF --color=auto'
+    alias ls='ls -b -CF '${ls_options:+"${ls_options[*]}"}
     #a1# execute \kbd{@a@}:\quad list all files, with colors
-    alias la='ls -la --color=auto'
+    alias la='ls -la '${ls_options:+"${ls_options[*]}"}
     #a1# long colored list, without dotfiles (@a@)
-    alias ll='ls -l --color=auto'
+    alias ll='ls -l '${ls_options:+"${ls_options[*]}"}
     #a1# long colored list, human readable sizes (@a@)
-    alias lh='ls -hAl --color=auto'
+    alias lh='ls -hAl '${ls_options:+"${ls_options[*]}"}
     #a1# List files, append qualifier to filenames \\&\quad(\kbd{/} for directories, \kbd{@} for symlinks ...)
-    alias l='ls -lF --color=auto'
+    alias l='ls -lF '${ls_options:+"${ls_options[*]}"}
 else
     alias ls='ls -b -CF'
     alias la='ls -la'
@@ -1428,16 +1458,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 +1482,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 +1515,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 +1532,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
@@ -1624,7 +1622,7 @@ limit -s
 
 # 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
+#         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
 
@@ -1712,6 +1710,15 @@ grmlcomp() {
     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 ..
 
@@ -1927,6 +1934,7 @@ compdef _functions edfunc
 #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}
 if [[ -d /etc/init.d || -d /etc/service ]] ; then
     __start_stop() {
         local action_="${1:l}"  # e.g Start/Stop/Restart
@@ -1958,7 +1966,7 @@ if [[ -d /etc/init.d || -d /etc/service ]] ; then
         _describe "service startup script" scripts
     }
 
-    for i in Start Restart Stop Force-Reload Reload ; do
+    for i in Start Restart Stop Force-Reload Reload Status ; do
         eval "$i() { __start_stop $i \"\$1\" \"\$2\" ; }"
         compdef _grmlinitd $i
     done
@@ -2021,7 +2029,7 @@ help_zle_parse_keybindings()
 
     if [[ -r $HELP_ZLE_CACHE_FILE ]]; then
         local load_cache=0
-        for f ($KEYBINDING_FILES) [[ $f -nt $HELP_ZLE_CACHE_FILE ]] && load_cache=1
+        for f ($HELPZLE_KEYBINDING_FILES) [[ $f -nt $HELP_ZLE_CACHE_FILE ]] && load_cache=1
         [[ $load_cache -eq 0 ]] && . $HELP_ZLE_CACHE_FILE && return
     fi
 
@@ -2029,33 +2037,33 @@ help_zle_parse_keybindings()
     #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['<Ctrl>X<Ctrl>J']="vi-join lines"
-    help_zle_keybindings['<Ctrl>X<Ctrl>B']="jump to matching brace"
-    help_zle_keybindings['<Ctrl>X<Ctrl>U']="undo"
+    help_zle_keybindings['<Ctrl>x<Ctrl>j']="vi-join lines"
+    help_zle_keybindings['<Ctrl>x<Ctrl>b']="jump to matching brace"
+    help_zle_keybindings['<Ctrl>x<Ctrl>u']="undo"
     help_zle_keybindings['<Ctrl>_']="undo"
-    help_zle_keybindings['<Ctrl>X<Ctrl>F<c>']="find <c> in cmdline"
-    help_zle_keybindings['<Ctrl>A']="goto beginning of line"
-    help_zle_keybindings['<Ctrl>E']="goto end of line"
+    help_zle_keybindings['<Ctrl>x<Ctrl>f<c>']="find <c> in cmdline"
+    help_zle_keybindings['<Ctrl>a']="goto beginning of line"
+    help_zle_keybindings['<Ctrl>e']="goto end of line"
     help_zle_keybindings['<Ctrl>t']="transpose charaters"
-    help_zle_keybindings['<Alt>T']="transpose words"
+    help_zle_keybindings['<Alt>t']="transpose words"
     help_zle_keybindings['<Alt>s']="spellcheck word"
-    help_zle_keybindings['<Ctrl>K']="backward kill buffer"
-    help_zle_keybindings['<Ctrl>U']="forward kill buffer"
+    help_zle_keybindings['<Ctrl>k']="backward kill buffer"
+    help_zle_keybindings['<Ctrl>u']="forward kill buffer"
     help_zle_keybindings['<Ctrl>y']="insert previously killed word/string"
     help_zle_keybindings["<Alt>'"]="quote line"
     help_zle_keybindings['<Alt>"']="quote from mark to cursor"
     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>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>xd']="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)"
     help_zle_keybindings['<Alt>m']="repeat last typed word on current CL"
-    help_zle_keybindings['<Ctrl>V']="insert next keypress symbol literally (e.g. for bindkey)"
+    help_zle_keybindings['<Ctrl>v']="insert next keypress symbol literally (e.g. for bindkey)"
     help_zle_keybindings['!!:n*<Tab>']="insert last n arguments of last command"
     help_zle_keybindings['!!:n-<Tab>']="insert arguments n..N-2 of last command (e.g. mv s s d)"
-    help_zle_keybindings['<Alt>H']="run help on current command"
+    help_zle_keybindings['<Alt>h']="show help/manpage for current command"
 
     #init global variables
     unset help_zle_lines help_zle_sln
@@ -2125,7 +2133,7 @@ help-zle()
     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
+zle -N help-zle && bindkey '^xz' help-zle
 
 # grep for running process, like: 'any vim'
 any() {
@@ -2135,7 +2143,7 @@ any() {
         echo "any - grep for process(es) by keyword" >&2
         echo "Usage: any <keyword>" >&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 +2164,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() {
 # 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}
 alias rmcdir='cd ..; rmdir $OLDPWD || cd $OLDPWD'
 
-# console stuff
-#a2# Execute \kbd{mplayer -vo fbdev}
-alias cmplayer='mplayer -vo fbdev'
-#a2# Execute \kbd{mplayer -vo fbdev -fs -zoom}
-alias fbmplayer='mplayer -vo fbdev -fs -zoom'
-#a2# Execute \kbd{links2 -driver fb}
-alias fblinks='links2 -driver fb'
-
 #a2# ssh with StrictHostKeyChecking=no \\&\quad and UserKnownHostsFile unset
 alias insecssh='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null"'
 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
@@ -2366,7 +2320,16 @@ cd() {
 
 #f5# Create Directoy and \kbd{cd} to it
 mkcd() {
-    mkdir -p "$@" && cd "$@"
+    if (( ARGC != 1 )); then
+        printf 'usage: mkcd <new-directory>\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
@@ -2401,6 +2364,7 @@ inplaceMkDirs() {
         PATHTOMKDIR="${(Q)bufwords[iword]}"
     fi
     [[ -z "${PATHTOMKDIR}" ]] && return 1
+    PATHTOMKDIR=${~PATHTOMKDIR}
     if [[ -e "${PATHTOMKDIR}" ]]; then
         zle -M " path already exists, doing nothing"
     else
@@ -2409,7 +2373,7 @@ inplaceMkDirs() {
     fi
 }
 #k# mkdir -p <dir> from string under cursor or marked area
-zle -N inplaceMkDirs && bindkey '^XM' inplaceMkDirs
+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() {
@@ -2433,9 +2397,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'
-#a2# Execute \kbd{grep -i -{}-color=auto}
-alias GREP='grep -i --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
@@ -2474,62 +2436,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
@@ -2617,56 +2579,6 @@ _simple_extract()
 compdef _simple_extract simple-extract
 alias se=simple-extract
 
-# Usage: smartcompress <file> (<type>)
-#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 <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
@@ -2678,11 +2590,6 @@ allulimit() {
     ulimit -t unlimited
 }
 
-# highlight important stuff in diff output, usage example: hg diff | hidiff
-#m# a2 hidiff \kbd{histring} oneliner for diffs
-check_com -c histring && \
-    alias hidiff="histring -fE '^Comparing files .*|^diff .*' | histring -c yellow -fE '^\-.*' | histring -c green -fE '^\+.*'"
-
 #f5# Change the xterm title from within GNU-screen
 xtrename() {
     emulate -L zsh
@@ -2705,46 +2612,39 @@ 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 <URL>" ; 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. <http://tinyurl.com/preview.php>
-#            preview='http://preview.'${result#http://}
-#
-#            printf '%s\n\n' "${PN} - Shrinking long URLs via webservice TinyURL <http://tinyurl.com>."
-#            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
+    if [[ -z $1 ]]; then
+        print "USAGE: zurl <URL>"
+        return 1
+    fi
+
+    local PN url prog api json 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=$($prog --silent -H ${contenttype} -d ${json} $api)
+    # Match against a regex and print it
+    if [[ $data =~ '"id": "(http://goo.gl/[[:alnum:]]+)"' ]]; then
+        print $match;
+    fi
+}
 
 #f2# Find history events by search pattern and list them by date.
 whatwhen()  {