#
# Set vi mode status bar.
#
# WYGIWYG status bar. If it works it works. There are too many termials in
# the world to have it work with all of them. So it works on one of them ;)
#
# Written by Jonas Juselius <jonas@iki.fi>
#

#
# Enter VI mode
#
setopt vi

#
# Set some good keybindings
#
bindkey -M vicmd "^R" redo
bindkey -M vicmd "u" undo
bindkey -M vicmd "ga" what-cursor-position

#
# Reads until the given character has been entered.
#
readuntil () {
    typeset a
    while [ "$a" != "$1" ]
    do
        read -E -k 1 a
    done
}

#
# If the $SHOWMODE variable is set, displays the vi mode, specified by
# the $VIMODE variable, under the current command line.
# 
# Arguments:
#
#   1 (optional): Beyond normal calculations, the number of additional
#   lines to move down before printing the mode.  Defaults to zero.
#
showmode() {
    typeset movedown
    typeset row

    # Get number of lines down to print mode
    movedown=$(($(echo "$RBUFFER" | wc -l) + ${1:-0}))
    
    # Get current row position
    echo -n "\e[6n"
    row="${${$(readuntil R)#*\[}%;*}"
    
    # Are we at the bottom of the terminal?
	if [ $((row+movedown)) -gt "$LINES" ]
	then
		# Scroll terminal up one line
		#echo -n "\e[1S"
		echo -n "\eD"
		
		# Move cursor up one line
		echo -n "\e[1A"
	fi
    
    # Save cursor position
    echo -n "\e7"
    
    # Move cursor to start of line $movedown lines down 
    echo -n "\e[$((row+movedown));1H"
    #echo -n "\e[$LINES;1H"
    
	# Clear mode line
	echo -n "\e[0K"

    # Change font attributes
    echo -n "\e[1m"
    
    # Has a mode been set?
    if [ -n "$VIMODE" ]
    then
        # Print mode line
        echo -n "-- $VIMODE -- "
    else
        # Clear mode line
        echo -n "\e[0K"
    fi

    # Restore font
    echo -n "\e[0m"
    
    # Restore cursor position
    echo -n "\e8"
}

clearmode() {
    VIMODE= showmode
}

#
# Temporary function to extend built-in widgets to display mode.
#
#   1: The name of the widget.
#
#   2: The mode string.
#
#   3 (optional): Beyond normal calculations, the number of additional
#   lines to move down before printing the mode.  Defaults to zero.
#
makemodal () {
	# Create new function
	if [[ -n "$2" ]] {
		eval "$1() { zle .'$1'; VIMODE='$2'; showmode $3 }"
	} else {
		eval "$1() { zle .'$1'; VIMODE=''; showmode $3 }"
	}

	# Create new widget
	zle -N "$1"
}


#makemodal () { # orig. makemodal
#    # Create new function
#    eval "$1() { zle .'$1'; ${2:+VIMODE='$2'}; showmode $3 }"
#
#    # Create new widget
#    zle -N "$1"
#}

# Extend widgets

init_statusbar () {
makemodal vi-add-eol           #INSERT
makemodal vi-add-next          #INSERT
makemodal vi-change            #INSERT
makemodal vi-change-eol        #INSERT
makemodal vi-change-whole-line #INSERT
makemodal vi-insert            #INSERT 
makemodal vi-insert-bol        #INSERT
makemodal vi-open-line-above   #INSERT
makemodal vi-substitute        #INSERT
makemodal vi-open-line-below   INSERT 1
makemodal vi-replace           REPLACE
makemodal vi-cmd-mode          COMMAND

unfunction makemodal
unfunction init_statusbar
}

init_statusbar

# vim: set syntax=zsh:
