# vim:ft=zsh:foldmethod=marker

prompt_ft_help () {
    cat << __EOF0__
  prompt ft

    This is a fairly simple one-line prompt for zsh.
    It displays non-zero return codes from commands, as well as the
    number of background jobs (if any).

    This prompt controls PS1 as well as RPS1.

    The attributes (such as colors), the prompt uses can be changed on
    the fly via various styles, looked up by zstyle.

    Those styles are looked up in ':prompt:ft:<subcontext>'
    <subcontext> is either ':items:<item>' or 'setup'.
    <item> it one of the items in the prompt:
        + returnvalue
        + jobnum
        + histevent
        + dash
        + path
        + vcsinfo
        + percent
        + end
    'dash' is kind of special, because it is used everywhere a dash is used,
    not only in the standalone positon in the item list above. The 'end' item
    is what is used at the end of the prompt - a single space, by default.
    'vcsinfo' is the \${vcs_info_msg_0_} from the vcs_info subsystem of zsh.
    You should probably leave its attributes to empty strings and use
    its own configuration to colorize it (see below for an example).

    There are three pseudo-items:
        + histevent-delim: ()
        + jobnum-delim: ()
        + returnvalue-delim: []
    Those are delimiters around the respective items (the brackets mentioned).
    For each of those you can supply the same styles as for normal items.

    Available styles in 'setup':
        + use-attributes (type: boolean - default: true)
            Use attribute styles (see below); if set to false, the prompt
            will be without colors.
        + vcsinfo-in-rprompt (type: boolean - default: false)
            If true, use \${vcs_info_msg_0_} in RPS1 rather then
            before 'percent' in PS1.

    To conveniently switch between coloring for dark and light backgrounded
    terminals, you may use the 'prompt_ft_choose' utility. Call it without
    arguments to display usage information.

    Available styles in 'items:<item>':
        + attrib_pre
        + attrib_post
    These are actually strings, inserted before (pre) and after (post) the
    item reflected by the used context.
__EOF0__

    prompt_ft_precmd getdefaults
    cat << __EOF1__

This prompt uses the following vcs_info setup:
zstyle ':vcs_info:*'     actionformats " %F{ma}(%f%s%F{ma})%F{ye}-%F{ma}[%F{green}%b%F{ye}|%F{red}%a%F{[ma}]%f-"
zstyle ':vcs_info:*'     formats       " %F{ma}(%f%s%F{ma})%F{ye}-%F{ma}[%F{green}%b%F{ma}]%f-"
zstyle ':vcs_info:cvs:*' formats       " %F{ma}(%f%s%F{ma})%F{ye}-%F{ma}[%F{green}%r%F{ma}]%f-"
zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b%F{red}:%F{ye}%r"

If you wish to change that, you have to do it *after* you called 'prompt ft'.

__EOF1__
}

prompt_ft_setup () {
    # load vcs_info and register our prompt function
    autoload -Uz vcs_info && vcs_info
    autoload -Uz add-zsh-hook
    add-zsh-hook precmd prompt_ft_precmd
    if [[ ${ZSH_PROMPT_MY_TERMINAL_IS} == light ]]; then
        prompt_ft_choose light
    else
        prompt_ft_choose dark
    fi
    zstyle ':vcs_info:*'     actionformats " %F{ma}(%f%s%F{ma})%F{ye}-%F{ma}[%F{green}%b%F{ye}|%F{red}%a%F{[ma}]%f-"
    zstyle ':vcs_info:*'     formats       " %F{ma}(%f%s%F{ma})%F{ye}-%F{ma}[%F{green}%b%F{ma}]%f-"
    zstyle ':vcs_info:cvs:*' formats       " %F{ma}(%f%s%F{ma})%F{ye}-%F{ma}[%F{green}%r%F{ma}]%f-"
    zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b%F{red}:%F{ye}%r"
}

prompt_ft_zle_highlight_default () {
    emulate -L zsh
    local -i idx remove

    if [[ -t ${(t)zle_highlight} ]]; then
        typeset -ga zle_highlight
    fi
    if (( $# )); then
        remove=0
    else
        remove=1
    fi

    idx=${zle_highlight[(I)default:*]}
    if (( idx )); then
        if (( remove )); then
            zle_highlight[$idx]=()
        else
            zle_highlight[$idx]="default:$1"
        fi
    elif (( remove )); then
        return 0
    else
        zle_highlight+=( "default:$1" )
    fi
    return 0
}

prompt_ft_choose () {
    case $1 in
    (light|l)
        zstyle ':prompt:ft:items:path' attrib_pre '%F{magenta}'
        prompt_ft_zle_highlight_default
        ;;
    (dark|d)
        zstyle ':prompt:ft:items:path' attrib_pre '%F{yellow}'
        prompt_ft_zle_highlight_default fg=cyan
        ;;
    (*)
        printf 'usage: prompt_ft_choose <setting>\n'
        printf '  ...were <setting> is one of the following:\n'
        printf '    - dark (or d)       for dark terminal backgrounds\n'
        printf '    - light (or l)      for light terminal backgrounds\n'
        ;;
    esac
}

prompt_ft_precmd () {
    setopt localoptions noksharrays extendedglob
    local -A sitems attrib_pre_def attrib_post_def attr_pre attr_post rv jn delims
    local -a items
    local item tmp

    items=( returnvalue jobnum histevent dash path vcsinfo percent end )
    attrib_pre_def=(
        dash              ''
        end               ''
        histevent         '%F{red}'
        histevent-delim   ''
        jobnum            '%F{cyan}'
        jobnum-delim      ''
        path              '%F{yellow}'
        percent           ''
        returnvalue       '%K{red}%F{white}'
        returnvalue-delim '%K{red}%F{white}'
    )
    attrib_post_def=(
        dash              ''
        end               ''
        histevent         '%f'
        histevent-delim   ''
        jobnum            '%f'
        jobnum-delim      ''
        path              '%f'
        percent           ''
        returnvalue       '%f%k'
        returnvalue-delim '%f%k'
    )
    sitems=( dash '-' percent '%#' end ' ' histevent '%!' )
    delims=( histevent '()' jobnum '()' returnvalue '[]' )
    rv=( pre '%(?..' main    '%?' post '%dash%)'  )
    jn=( pre '%1(j.' main 'j: %j' post '%dash%.)' )

    if [[ $1 == 'getdefaults' ]] ; then
        printf '\n    Defaults for attrib_pre:\n'
        for tmp in ${(ok)attrib_pre_def} ; do
            printf '       %18s '\''%s'\''\n' ${tmp} ${(V)attrib_pre_def[$tmp]}
        done
        printf '\n    Defaults for attrib_post:\n'
        for tmp in ${(ok)attrib_pre_def} ; do
            printf '       %18s '\''%s'\''\n' ${tmp} ${(V)attrib_post_def[$tmp]}
        done
        return 0
    fi
    vcs_info

    zstyle -s ':prompt:ft:items:path' length tmp && sitems[path]="%${tmp}~" || sitems[path]='%3~'
    if zstyle -T ':prompt:ft:setup' use-attributes ; then
        for item in returnvalue{,-delim} dash path histevent{,-delim} percent jobnum{,-delim} end; do
            zstyle -s ":prompt:ft:items:${item}" attrib_pre  tmp && attr_pre[${item}]=${tmp}  || attr_pre[${item}]=${attrib_pre_def[$item]}
            zstyle -s ":prompt:ft:items:${item}" attrib_post tmp && attr_post[${item}]=${tmp} || attr_post[${item}]=${attrib_post_def[$item]}
        done
    fi

    PS1=''; RPS1=''
    for item in ${items} ; do
        case ${item} in
        (returnvalue)
            PS1+=${rv[pre]}
            PS1+=${attr_pre[${item}-delim]}${${delims[${item}]}[1]}${attr_post[${item}-delim]}
            PS1+=${attr_pre[${item}]}${rv[main]}${attr_post[${item}]}
            PS1+=${attr_pre[${item}-delim]}${${delims[${item}]}[2]}${attr_post[${item}-delim]}
            PS1+=${${rv[post]}//'%dash%'/${attr_pre[dash]}-${attr_post[dash]}}
            ;;
        (jobnum)
            PS1+=${jn[pre]}
            PS1+=${attr_pre[${item}-delim]}${${delims[${item}]}[1]}${attr_post[${item}-delim]}
            PS1+=${attr_pre[${item}]}${jn[main]}${attr_post[${item}]}
            PS1+=${attr_pre[${item}-delim]}${${delims[${item}]}[2]}${attr_post[${item}-delim]}
            PS1+=${${jn[post]}//'%dash%'/${attr_pre[dash]}-${attr_post[dash]}}
            ;;
        (histevent)
            PS1+=${attr_pre[${item}-delim]}${${delims[${item}]}[1]}${attr_post[${item}-delim]}
            PS1+=${attr_pre[${item}]}${sitems[${item}]}${attr_post[${item}]}
            PS1+=${attr_pre[${item}-delim]}${${delims[${item}]}[2]}${attr_post[${item}-delim]}
            ;;
        (dash|end|percent|path)
            PS1+=${attr_pre[${item}]}${sitems[${item}]}${attr_post[${item}]}
            ;;
        (vcsinfo)
            if zstyle -t ':prompt:ft:setup' vcsinfo-in-rprompt ; then
                RPS1+=${vcs_info_msg_0_}${attr_post[end]}
            else
                PS1+=${vcs_info_msg_0_}
            fi
            ;;
        (*)
            printf 'ft_prompt: Unknown item %s\n' ${item}
            ;;
        esac
    done
}

prompt_ft_setup "$@"