#!/bin/sh -e

term_setup() {
    stty -icanon -echo

    printf '\033[?1049h\033[?7l\033[?25l\033[2J\033[1;%sr' \
        "$((LINES - 2))"
}

term_reset() {
    stty icanon echo

    printf '\033[?7h\033[?25h\e[2J\033[;r\033[?1049l'
}

term_resize() {
    set -f
    set +f -- $(stty size)

    LINES=$1 COLUMNS=$2

    # leave gap above statusline
    line_max=$((LINES - 2))
}

list_print() {
    printf '\033[2J\033[H\033[31;7m'

    for file do
        printf '%s\033[m\n' "$file"
    done

    printf '\033[%sH' "$y"
}

redraw() {
    list_print "$@"
    status_line
}

status_line() {
    printf '\0337\033[%sH\033[31;7m%-*s\033[m\0338' \
        "$LINES" "$COLUMNS" "${1:-$PWD (${y:=0}/$max)}"
}

print_line() {
    [ "$1" != "${y:=0}" ] || {
        printf '\033[31;7m'
    }

    shift "$(($1 + 1))"
    printf '\033[K%s\033[m\r' "$1"
}

main() {
    # change directory to the first argument
    cd "${1:-"$PWD"}"

    esc_char=$(printf '\033')

    set -- *
    max=$#

    term_resize
    term_setup
    redraw "$@"

    trap 'term_reset'  EXIT INT
    trap 'term_resize' WINCH

    while key=$(dd ibs=1 count=1 2>/dev/null); do
        case $key$esc in
            k?|A2) # ARROW UP
                y=$((y - 1 < 0 ? 0 : y - 1))

                print_line "$((y + 1))" "$@"
                printf '\033[A'
                print_line "$y" "$@"

                status_line
            ;;

            j?|B2) # ARROW DOWN
                y=$((y + 1 > max - 1 ? max - 1 : y + 1))

                print_line "$((y - 1))" "$@"
                printf '\n'
                print_line "$y" "$@"

                status_line
            ;;

            l?|C2) # ARROW RIGHT
            ;;

            h?|D2) # ARROW LEFT
            ;;

            g?)
            ;;

            G?)
            ;;

            q?)
                exit 0
            ;;

            # handle keys which emit escape sequences
            "$esc_char"*) esc=1 ;;
                    '[1') esc=2 ;;
                       *) esc=0 ;;
        esac
    done
}

main "$@"
