#zdep options,vars
### vim:ft=zsh:foldmethod=marker
###
### zfunct - really short functions.
###
### Frank Terbeck <ft@bewatermyfriend.org>
### Last-Modified: Sun Aug 10 22:04:30 2008
###
### URI: <http://ft.bewatermyfriend.org/comp/zsh.html>
###

### precmd/exec
### {{{
### put the current program into screen's hardstatus
precmd () {
    if [[ "$TERM" == screen* ]]; then
        if [[ -n ${SSH_CLIENT} ]] ; then
            print -nP "\ek%m: zsh\e\\"
        else
            print -nP "\ekzsh\e\\"
        fi
    fi
}

preexec () {
    setopt localoptions extendedglob

    if [[ "$TERM" == screen* ]]; then
        local CMD=${1[(wr)^(*=*|sudo|-*)]}
        if [[ -n ${SSH_CLIENT} ]] ; then
            print -nP "\ek%m: $CMD\e\\"
        else
            print -nP "\ek$CMD\e\\"
        fi
    fi

    # currently unused...
    #case ${1} in
    #    (*) ;;
    #esac
}
### }}}

### prompt manipulation functions
### Using $(function ...) things in $PROMPT requires 'promptsubst'
### to be set. Use $(prompt_git) to get a prompt entry with colors
### and $(prompt_git nc) to get the same without colors.
###   Example: PROMPT="%3~"'$(prompt_git nc)'"%# "
function Prompt_git_getaction () { #{{{
    local gitaction='' gitdir=${1}
    local tmp

    for tmp in "${gitdir}/rebase-apply" \
               "${gitdir}/rebase"       \
               "${gitdir}/../.dotest" ; do
        if [[ -d ${tmp} ]] ; then
            if   [[ -f "${tmp}/rebasing" ]] ; then
                gitaction="rebase"
            elif [[ -f "${tmp}/applying" ]] ; then
                gitaction="am"
            else
                gitaction="am/rebase"
            fi
            print '%s' ${gitaction}
            return 0
        fi
    done

    for tmp in "${gitdir}/rebase-merge/interactive" \
               "${gitdir}/.dotest-merge/interactive" ; do
        if [[ -f "${tmp}" ]] ; then
            printf '%s' "rebase-i"
            return 0
        fi
    done

    for tmp in "${gitdir}/rebase-merge" \
               "${gitdir}/.dotest-merge" ; do
        if [[ -d "${tmp}" ]] ; then
            printf '%s' "rebase-m"
            return 0
        fi
    done

    if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
        printf '%s' "merge"
    else
        if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
            printf '%s' "bisect"
        fi
    fi

    return 1
}
# }}}
function Prompt_git_getbranch () { #{{{
    local gitbranch gitdir=${1}
    local gitsymref='git symbolic-ref HEAD'

    if    [[ -d "${gitdir}/rebase-apply" ]] \
       || [[ -d "${gitdir}/rebase" ]]       \
       || [[ -d "${gitdir}/../.dotest" ]]   \
       || [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
        gitbranch="$(${(z)gitsymref} 2> /dev/null)"

    elif   [[ -f "${gitdir}/rebase-merge/interactive" ]] \
        || [[ -d "${gitdir}/rebase-merge" ]] ; then
        gitbranch="$(< ${gitdir}/rebase-merge/head-name)"

    elif   [[ -f "${gitdir}/.dotest-merge/interactive" ]] \
        || [[ -d "${gitdir}/.dotest-merge" ]] ; then
        gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"

    else
        gitbranch="$(${(z)gitsymref} 2> /dev/null)"

        if [[ $? -ne 0 ]] ; then
            gitbranch="$(git describe --exact-match HEAD 2>/dev/null)"

            if [[ $? -ne 0 ]] ; then
                gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
            fi
        fi
    fi

    printf '%s' "${gitbranch##refs/heads/}"
}
# }}}
function prompt_git () { # {{{
    local gitdir gitbranch gitaction gitprompt

    gitdir="$(git rev-parse --git-dir 2> /dev/null)"

    if [[ $? -eq 0 ]] ; then
        gitbranch="$(Prompt_git_getbranch ${gitdir})"
    fi

    if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
        return
    fi

    gitaction="$(Prompt_git_getaction ${gitdir})"

    if [[ ${1} == 'nc' ]] ; then
        [[ -n ${gitaction} ]] && \
            printf '%s' " [${gitbranch}|${gitaction}]-" || \
            printf '%s' " [${gitbranch}]-"
    else
        [[ -n ${gitaction} ]] && \
            printf '%s' \
                " %{${fg[magenta]}%}[%{${fg[green]}%}${gitbranch}%{${fg[yellow]}%}|%{${fg[red]}%}${gitaction}%{${fg[magenta]}%}]%{${reset_color}%}-" || \
            printf '%s' " %{${fg[magenta]}%}[%{${fg[green]}%}${gitbranch}%{${fg[magenta]}%}]%{${reset_color}%}-"
    fi
}
# }}}

### wrappers
### dquilt()      call quilt with changed $QUILT_PATCHES {{{
if [[ -x $(which quilt) ]] ; then
    function dquilt() {
        local QUILT_PATCHES
        QUILT_PATCHES="debian/patches" quilt "$@"
    }

    compdef dquilt=quilt
fi
### }}}
### gitsm()       git send-email + template generation {{{
function gitsm() {
    # This works for a patch series that is at the top of a branch;
    # E.g. created by: git format-patch -5
    # ...for a series of the last 5 commits on the current branch.
    # Or for sending out a series that corresponds to a topic-branch:
    #   % rm -f 0*.patch
    #   % git format-patch master..topicbranch
    #   % gitsm 0*.patch
    # Creates a List of commit-lines and a diffstat for all commits.
    local tempfile GIT_EDITOR

    if [[ -z $1 ]] ; then
        printf 'gitsm <patches-from-format-patches>...\n'
        return 1
    fi

    tempfile=$(mktemp ${TMPDIR:-/tmp}/gitsm.XXXXXXXXXX)
    if [[ $? -gt 0 ]] ; then
        printf 'tempfile creation failed.\n'
        return 1
    fi

    [[ -e ${tempfile} ]] && rm ${tempfile}
    git shortlog -${#@} | sed -e '/^[^ ]/d' -e '/^$/d' -e 's,^ *,,' >> ${tempfile}
    printf '\n' >> ${tempfile}
    git diff --stat 'HEAD~'${#@} >> ${tempfile}
    GIT_EDITOR='vim +":normal Go" \
                    +":r'${tempfile}'" \
                    +":normal 2G$"' \
        git send-email --compose --subject "[PATCH 0/${#@}] " "${@}"
    rm ${tempfile}
}
### }}}
### grmldch()     call dch with changed $DEBEMAIL {{{
[[ -x $(which dch) ]] && \
function grmldch() {
    DEBEMAIL=${GRMLEMAIL} dch --no-auto-nmu "$@"
}
### }}}
### kmake()       this is just a simple wrapper around 'make' {{{
[[ ${OSTYPE} == linux* ]] && \
[[ -x $(which make) ]]    && \
function kmake() {
    ### uses special compiler (and destination) to build the kernel.
    ### vars used: ${KERNEL_COMPILER}, ${KERNEL_BUILD_DIR}
    setopt localoptions
    setopt rmstarsilent
    setopt normstarwait
    local opwd

    case $1 in
        (-buildclean)
            if [[ -z ${KERNEL_BUILD_DIR} ]] ; then
                printf '\${KERNEL_BUILD_DIR} not set. ignoring.\n'
            else
                builtin cd ${KERNEL_BUILD_DIR}
                command rm -Rf *
                command rm -f .*(.)
                builtin cd ${OLDPWD}
            fi
            return
            ;;
        (-catconfig)
            if [[ -n ${KERNEL_BUILD_DIR} ]] && [[ -f /proc/config.gz ]] ; then
                command zcat /proc/config.gz > "${KERNEL_BUILD_DIR}/.config"
            else
                printf '\${KERNEL_BUILD_DIR} not set or /proc/config.gz not found. ignoring.\n'
            fi
            return
            ;;
    esac

    if [[ -z ${KERNEL_BUILD_DIR} ]] ; then
        command make "$@" V=1 CC=${KERNEL_COMPILER:-gcc} HOSTCC=${KERNEL_COMPILER:-gcc}
    else
        command make "$@" V=1 CC=${KERNEL_COMPILER:-gcc} HOSTCC=${KERNEL_COMPILER:-gcc} O=${KERNEL_BUILD_DIR}
    fi
}
### }}}
### vim() wrapper for the best edi... oh well, for vim. {{{
function vim() {
    command vim -p "$@"
}
### }}}

### normal functions
### check_com()   check if a command exists {{{
### eg: check_com "vim -p"
function check_com() {
    local val=${1} ; local com

    if zis_317 "atleast" ; then
        com=(${(z)val})
    else
        ### <3.1.7 does not know (z); this makes things less flexible. Oh well...
        com=(${(s: :)val})
    fi

    [[ -x $(whence -p ${com[1]}) ]] && return 0
    return 1
}
### }}}
### ccron()       change the state file of cron wrapper {{{
if [[ -d ${HOME}/var/run ]] ; then
function ccron () {
    # i use this switch my cronjobs on/off
    setopt localoptions extendedglob
    local sf="${HOME}/var/run/nocron"

    case $1 in
    ((#i)on)
        if [[ -e ${sf} ]] ; then
            printf 'enabling cronjobs\n'
            rm -f ${sf}
        else
            printf 'cronjobs enabled already.\n'
        fi
        ;;
    ((#i)off)
        if [[ ! -e ${sf} ]] ; then
            printf 'disabling cronjobs\n'
            touch ${sf}
        else
            printf 'cronjobs disabled already.\n'
        fi
        ;;
    (*)
        if [[ -e ${HOME}/var/run/nocron ]] ; then
            printf 'cronjobs disabled\n'
        else
            printf 'cronjobs enabled\n'
        fi
        ;;
    esac
}
fi
### }}}
### get_ic()      queries imap servers for capabilities; real simple. no imaps {{{
[[ -x $(which nc) ]] && \
function ic_get() {
    local port

    if [[ ! -z $1 ]]; then
        port=${2:-143}
        print "querying imap server on $1:${port}...\n";
        print "a1 capability\na2 logout\n" | nc $1 ${port}
    else
        print "usage:\n  $0 <imap-server> [port]"
    fi
}
### }}}
### hgexport()    shortcut for creating exports with hg {{{
[[ -x $(which hg) ]] && \
function hgexport() {
    local ddir
    ddir=${1} ; shift

    if [[ ${ddir} == '-h' ]] ; then
        printf 'Usage: hgexport <destination-dir> COMMIT(s)...\n'
        return 0
    fi
    if [[ ! -d ${ddir} ]] ; then
        printf 'Destination directory (%s) does not exist. Abort.\n' ${ddir}
        return 1
    fi

    command hg export -o ${ddir}'/%b-%nof%N-%h.diff' "$@"
}
### }}}
### hl()          highlighted less {{{
### ...because sometimes an editor is just too much.
if [[ -x $(which highlight) ]] ; then

function hl() {
    local theme lang
    theme=${HL_THEME:-""}

    case ${1} in
        (-l|--list)
            ( printf 'available languages (syntax parameter):\n\n' ;
              highlight --list-langs ; ) | less -SMr
            ;;
        (-t|--themes)
            ( printf 'available themes (style parameter):\n\n' ;
              highlight --list-themes ; ) | less -SMr
            ;;
        (-h|--help)
            printf 'usage: hl <syntax[:theme]> <file>\n'
            printf '    available options: --list (-l), --themes (-t), --help (-h)\n\n'
            printf '  Example: hl c main.c\n'
            ;;
        (*)
            if [[ -z ${2} ]] || (( ${#argv} > 2 )) ; then
                printf 'usage: hl <syntax[:theme]> <file>\n'
                printf '    available options: --list (-l), --themes (-t), --help (-h)\n'
                (( ${#argv} > 2 )) && printf '  Too many arguments.\n'
                return 1
            fi
            lang=${1%:*}
            [[ ${1} == *:* ]] && [[ -n ${1#*:} ]] && theme=${1#*:}
            if [[ -n ${theme} ]] ; then
                highlight --xterm256 --syntax ${lang} --style ${theme} ${2} | less -SMr
            else
                highlight --ansi --syntax ${lang} ${2} | less -SMr
            fi
            ;;
    esac
    return 0
}

fi
### }}}
### mkmaildir()   creates a Maildir/ with its {new,cur,tmp} subdirs {{{
function mkmaildir() {
    ### Uses $MAILDIR_ROOT
    local root subdir

    root=${MAILDIR_ROOT:-${HOME}/Mail}
    if [[ -z ${1} ]] ; then
        print "Usage\n $0 <dirname>"
        return 1
    fi

    subdir=${1}
    mkdir -p ${root}/${subdir}/{cur,new,tmp}
}
### }}}
### prompt_sw()   switch prompts on the fly {{{
function prompt_sw() {
    if [[ ! -z ${1} ]] ; then
        case ${1} in
            (c*) PROMPT=${COLORED_PROMPT}   ;;
            (u*) PROMPT=${UNCOLORED_PROMPT} ;;
            (s*) PROMPT=${SIMPLE_PROMPT}    ;;
            (o*) PROMPT=${OLD_PROMPT}       ;;
            (*)  echo "unknown prompt"      ;;
        esac
        return 0
    fi

    print "usage:\n  ${0} { (c)olored, (u)ncolored, (s)imple, (o)ld }"
}
### }}}
### salias()      smart creation of sudo aliases {{{
### This is based on the salias() function I did for the grml zshrc.
### However, I changed it again to work with older versions of zsh as well.
### Added -c option. Added -C option.
### Note, that this has _nothing_ to do with suffix aliases.

function salias() {
    local only=0 multi=0 check=0 chkcom=1 sudo_host=0
    local sudo_u sudo_us sudo_h i j key val mval
    if (( ${#argv} == 0 )) ; then
        printf 'salias(): Missing argument. Try salias -h for help.\n'
        return 1
    fi
    while [[ ${1} == -* ]] ; do
        case ${1} in
            (-o) only=1  ;;
            (-C) chkcom=0 ;;
            (-c) check=1 ;;
            (-a) multi=1 ;;
            (--) shift ; break ;;
            (-h)
                printf 'usage: salias [-h|-o|-a|-c|-C] <alias-expression>\n'
                printf '  -h      shows this help text.\n'
                printf '  -a      replace '\'' ; '\'' sequences with '\'' ; sudo '\''.\n'
                printf '          be careful using this option.\n'
                printf '  -o      only sets an alias if a preceding sudo would be needed.\n'
                printf '  -c      check $sudo_hosts[] array.\n'
                printf '  -C      don'\''t check if the command in the alias exists.\n'
                printf '          Use this if the command requires a special check, that.\n'
                printf '          check_com() cannot deal with.\n'
                return 0
                ;;
            (*) printf "unkown option: '%s'\n" "${1}" ; return 1 ;;
        esac
        shift
    done
    if (( check > 0 )) ; then #{{{
        for i in ${sudo_hosts} ; do
            sudo_u=${${(s:@:)i}[1]}
            sudo_us=(${(s:,:)sudo_u})
            sudo_h=${${(s:@:)i}[2]}
            if [[ ${sudo_h} == ${HOST} ]] ; then
                for j in ${sudo_us} ; do
                    if [[ ${USER:-${LOGNAME}} == ${j} ]] ; then
                        ### user and host matches, okay.
                        sudo_host=1
                        break;
                    fi
                done
                break;
            fi
        done
        (( sudo_host == 0 )) && return 0
    fi #}}}
    if (( ${#argv} > 1 )) ; then
        printf 'Too many arguments %s\n' "${#argv}"
        return 1
    fi
    ### create the alias {{{
    key="${1%%\=*}" ;  val="${1#*\=}"
    if (( EUID == 0 )) && (( only == 0 )); then
        if (( chkcom > 0 )) ; then
            check_com ${val} || return 0
        fi
        alias -- "${key}=${val}"
    elif (( EUID > 0 )) ; then
        if (( multi > 0 )) ; then
            mval=(${(s, ; ,)val})
            if (( chkcom > 0 )) ; then
                check_com ${mval[1]} || return 0
            fi
            val="sudo ${mval[1]}"
            shift mval
            for i in ${mval} ; do
                if (( chkcom > 0 )) ; then
                    check_com ${i} || return 0
                fi
                val="${val} ; sudo ${i}"
            done
            alias -- "${key}=${val}"
        else
            if (( chkcom > 0 )) ; then
                check_com ${val} || return 0
            fi
            alias -- "${key}=sudo ${val}"
        fi
    fi
    ### }}}
    return 0
}
### }}}
### xalias()      check for executable, then create alias {{{
### only supposed to be used with simple aliases.
function xalias() {
    local key val com
    if (( ${#argv} == 0 )) ; then
        printf 'xalias(): Missing argument.\n'
        return 1
    fi
    if (( ${#argv} > 1 )) ; then
        printf 'xalias(): Too many arguments %s\n' "${#argv}"
        return 1
    fi

    key="${1%%\=*}" ;  val="${1#*\=}"
    check_com ${val} && alias -- "${key}=${val}"
    return 0
}
### }}}
### xhashd()      check for directory, then create hash -d {{{
function xhashd() {
    local key val com
    if (( ${#argv} == 0 )) ; then
        printf 'xhashd(): Missing argument.\n'
        return 1
    fi
    if (( ${#argv} > 1 )) ; then
        printf 'xhashd(): Too many arguments %s\n' "${#argv}"
        return 1
    fi

    key="${1%%\=*}" ;  val="${1#*\=}"
    [[ -d ${val} ]] && hash -d -- "${key}=${val}"
    return 0
}
### }}}
### xtrename()    rename xterm from within GNU-screen {{{
function xtrename() {
    if [[ -z ${DISPLAY} ]] ; then
        printf 'xtrename only makes sense in X11.\n'
        return 1
    fi
    if [[ -z ${1} ]] ; then
        printf 'usage: xtrename() "title for xterm"\n'
        printf '  renames the title of xterm from _within_ screen.\n'
        printf '  Also works without screen.\n'
        return 0
    fi

    print -n "\eP\e]0;${1}\C-G\e\\"
    return 0
}
### }}}
### zcm()         count mail (new mail that is) {{{
function zcm() {
    local md=${MAILDIR:-${HOME}/Mail}
    local c  ; integer c
    local bc ; integer bc
    local i
    local b

    (( c=0 ))
    for i in ${md}/*(/N) ; do
        (( bc=0 ))
        for b in ${i}/new/*(.N) ; do
            (( c++  ))
            (( bc++ ))
        done
        if (( bc > 0 )) ; then
            (( bc == 1 )) && printf "%7d new Mail  in %s\n" $((bc)) ${i:t}
            (( bc >  1 )) && printf "%7d new Mails in %s\n" $((bc)) ${i:t}
        fi
    done
    (( c >= 1 )) && printf "--------------------------------------------------\n"
    (( c >  1 )) && printf "%7d new Mails in total.\n" $((c))
    (( c == 1 )) && printf "%7d new Mail in total.\n" $((c))
    (( c == 0 )) && printf "%7s new Mail.\n" "No"
    return 0
}
### }}}
### zremovecomp() remove *.zwc files {{{
function zremovecomp() {
    local i
    for i in ${ZRC_SOURCE_DIR}/*.zwc(N) ; do
        printf "Removing $i\n"
        rm -f $i
    done
}
### }}}
### zurl()        create small urls via tinyurl.com {{{
###   needs wget, grep and sed. yes, it's a hack ;)
function zurl() {
    [[ -z ${1} ]] && print "please give an url to shrink." && return 1
    local url=${1}
    local tiny="http://tinyurl.com/create.php?url="

    #print "${tiny}${url}" ; return
    wget  -O-             \
          -o/dev/null     \
          "${tiny}${url}" \
          | grep -Eio 'value="(http://tinyurl.com/.*)"' \
          | sed 's/value=//;s/"//g'
}
### }}}