bat/tests/syntax-tests/highlighted/dash/shfm
2021-05-14 23:02:23 +02:00

425 lines
67 KiB
Text
Vendored
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env dash
esc() {
 case $1 in
 # vt100 (IL is vt102) (DECTCEM is vt520)
 CUD) printf '%s[%sB' "$esc_c" "$2" ;; # cursor down
 CUP) printf '%s[%s;%sH' "$esc_c" "$2" "$3" ;; # cursor home
 CUU) printf '%s[%sA' "$esc_c" "$2" ;; # cursor up
 DECAWM) printf '%s[?7%s' "$esc_c" "$2" ;; # line wrap
 DECRC) printf '%s8' "$esc_c" ;; # cursor restore
 DECSC) printf '%s7' "$esc_c" ;; # cursor save
 DECSTBM) printf '%s[%s;%sr' "$esc_c" "$2" "$3" ;; # scroll region
 DECTCEM) printf '%s[?25%s' "$esc_c" "$2" ;; # cursor visible
 ED[0-2]) printf '%s[%sJ' "$esc_c" "${1#ED}" ;; # clear screen
 EL[0-2]) printf '%s[%sK' "$esc_c" "${1#EL}" ;; # clear line
 IL) printf '%s[%sL' "$esc_c" "$2" ;; # insert line
 SGR) printf '%s[%s;%sm' "$esc_c" "$2" "$3" ;; # colors
 # xterm (since 1988, supported widely)
 screen_alt) printf '%s[?1049%s' "$esc_c" "$2" ;; # alternate buffer
 esac
}
term_setup() {
 stty=$(stty -g)
 stty -icanon -echo
 esc screen_alt h
 esc DECAWM l
 esc DECTCEM l
 esc ED2
 esc DECSTBM 1 "$((LINES - 2))"
}
term_reset() {
 esc DECAWM h >&2
 esc DECTCEM h >&2
 esc ED2 >&2
 esc DECSTBM >&2
 esc screen_alt l >&2
 stty "$stty"
 # needed for cd-on-exit
 printf '%s\n' "$PWD" >&1
}
term_resize() {
 # false-positive, behavior intentional, globbing is disabled.
 # shellcheck disable=2046
 {
 set -f
 set +f -- $(stty size)
 }
 LINES=$1 COLUMNS=$2
 # space for status_line
 bottom=$((LINES - 2))
}
term_scroll_down() {
 case $((y - $#)) in
 [0-9]*) return
 esac
 y=$((y + 1))
 y2=$((y2 + 1 < bottom ? y2 + 1 : bottom))
 line_print "$((y - 1))" "$@"
 printf '\n'
 line_print "$y" "$@"
 status_line "$#"
}
term_scroll_up() {
 case $y in
 -*|0|1) return
 esac
 y=$((y - 1))
 line_print "$((y + 1))" "$@"
 case $y2 in
 1) esc IL ;;
 *) esc CUU; y2=$((y2 > 1 ? y2 - 1 : 1))
 esac
 line_print "$y" "$@"
 status_line "$#"
}
cmd_run() {
 stty "$stty"
 esc DECTCEM h
 esc DECSTBM
 esc ED2
 "$@" ||:
 esc DECSTBM 1 "$((LINES - 2))"
 esc DECTCEM l
 stty -icanon -echo
 hist=2
}
file_escape() {
 tmp=$1 safe=
 # loop over string char by char
 while c=${tmp%"${tmp#?}"}; do
 case $c in
 '') return ;;
 [[:cntrl:]]) safe=$safe\? ;;
 *) safe=$safe$c ;;
 esac
 tmp=${tmp#?}
 done
}
hist_search() {
 hist=0 j=1
 for file do
 case ${PWD%%/}/$file in
 "$old_pwd") y=$j y2=$((j > bottom ? mid : j)) cur=$file
 esac
 j=$((j + 1))
 done
}
list_print() {
 esc ED2
 esc CUP
 i=1
 end=$((bottom + 1))
 mid=$((bottom / 4 < 5 ? 1 : bottom / 4))
 case $# in
 1) [ -e "$1" ] || set -- empty
 esac
 case $hist in
 2) # redraw after cmd run
 shift "$((y > y2 ? y - y2 : 0))"
 ;;
 1) # redraw after go-to-parent
 hist_search "$@"
 shift "$((y >= bottom ? y - mid : 0))"
 ;;
 *) # everything else
 shift "$((y >= bottom ? y - bottom : 0))"
 ;;
 esac
 for file do
 case $i in
 "$y2") esc SGR 0 7
 esac
 case $((i - end)) in
 -*)
 line_format "$file"
 esc CUD
 ;;
 esac
 i=$((i + 1))
 done
 esc CUP "$((y > y2 ? y2 : y))"
}
redraw() {
 list_print "$@"
 status_line "$#"
}
status_line() {
 esc DECSC
 esc CUP "$LINES"
 case $USER in
 root) esc SGR 31 7 ;;
 *) esc SGR 34 7 ;;
 esac
 printf '%*s\r%s ' "$COLUMNS" "" "($y/$1)"
 case $ltype in
 '') printf %s "$PWD" ;;
 *) printf %s "$ltype"
 esac
 esc SGR 0 0
 esc DECRC
}
prompt() {
 esc DECSC
 esc CUP "$LINES"
 printf %s "$1"
 esc DECTCEM h
 esc EL0
 case $2 in
 r)
 stty icanon echo
 read -r ans ||:
 stty -icanon -echo
 ;;
 esac
 esc DECRC
 esc DECTCEM l
 status_line "($y/$#) $PWD"
}
line_print() {
 offset=$1
 case $offset in
 "$y") esc SGR 0 7
 esac
 shift "$offset"
 case $offset in
 "$y") cur=$1
 esac
 line_format "$1"
}
line_format() {
 file_escape "$1"
 [ -d "$1" ] && esc SGR 1 31
 printf %s "$safe"
 [ -d "$1" ] && printf /
 esc SGR 0 0
 esc EL0
 printf '\r'
}
main() {
 set -e
 case $1 in
 -h|--help)
 printf 'shfm -[hv] <starting dir>\n'
 exit 0
 ;;
 -v|--version)
 printf 'shfm 0.4.2\n'
 exit 0
 ;;
 *)
 cd -- "${1:-"$PWD"}"
 ;;
 esac
 esc_c=$(printf '\033')
 bs_char=$(printf '\177')
 set -- *
 cur=$1
 term_resize
 term_setup
 trap 'term_reset' EXIT INT
 trap 'term_resize; term_setup; y=1 y2=1; redraw "$@"' WINCH
 y=1 y2=1
 redraw "$@"
 while key=$(dd ibs=1 count=1 2>/dev/null); do
 case $key${esc:=0} in
 k?|A2)
 term_scroll_up "$@"
 ;;
 j?|B2)
 term_scroll_down "$@"
 ;;
 l?|C2|"$esc") # ARROW RIGHT
 if [ -d "$cur" ] && cd -- "$cur" >/dev/null 2>&1; then
 set -- *
 y=1 y2=1 cur=$1 ltype=
 redraw "$@"
 elif [ -e "$cur" ]; then
 cmd_run "${SHFM_OPENER:="${EDITOR:=vi}"}" "$cur"
 redraw "$@"
 fi
 ;;
 h?|D2|"$bs_char"?) # ARROW LEFT
 old_pwd=$PWD
 case $ltype in
 '') cd .. || continue ;;
 *) ltype= ;;
 esac
 set -- *
 y=1 y2=1 cur=$1 hist=1
 redraw "$@"
 ;;
 g?)
 case $y in
 1) continue
 esac
 y=1 y2=1 cur=$1
 redraw "$@"
 ;;
 G?)
 y=$#
 y2=$(($# < bottom ? $# : bottom))
 redraw "$@"
 ;;
 .?)
 case ${hidden:=1} in
 1) hidden=0; set -- .* ;;
 0) hidden=1; set -- *
 esac
 y=1 y2=1 cur=$1
 redraw "$@"
 ;;
 :?)
 prompt "cd: " r
 # false positive, behavior intentional
 # shellcheck disable=2088
 case $ans in
 '~') ans=$HOME ;;
 '~/'*) ans=$HOME/${ans#"~/"}
 esac
 cd -- "${ans:="$0"}" >/dev/null 2>&1|| continue
 set -- *
 y=1 y2=1 cur=$1
 redraw "$@"
 ;;
 /?)
 prompt / r
 # word splitting and globbing intentional
 # shellcheck disable=2086
 set -- $ans*
 case $1$# in
 "$ans*1") set -- 'no results'
 esac
 y=1 y2=1 cur=$1 ltype="search $PWD/$ans*"
 redraw "$@"
 status_line "$#"
 ;;
 -?)
 cd -- "$OLDPWD" >/dev/null 2>&1|| continue
 set -- *
 y=1 y2=1 cur=$1
 redraw "$@"
 ;;
 \~?)
 cd || continue
 set -- *
 y=1 y2=1 cur=$1
 redraw "$@"
 ;;
 \!?)
 export SHFM_LEVEL
 SHFM_LEVEL=$((SHFM_LEVEL + 1))
 cmd_run "${SHELL:=/bin/sh}"
 redraw "$@"
 ;;
 \??)
 set -- 'j - down' \
 'k - up' \
 'l - open file or directory' \
 'h - go up level' \
 'g - go to top' \
 'G - go to bottom' \
 'q - quit' \
 ': - cd to <input>' \
 '/ - search current directory <input>*' \
 '- - go to last directory' \
 '~ - go home' \
 '! - spawn shell' \
 '. - toggle hidden files' \
 '? - show keybinds'
 y=1 y2=1 cur=$1 ltype=keybinds
 redraw "$@"
 status_line "$#"
 ;;
 q?) exit 0 ;;
 # handle keys which emit escape sequences
 "$esc_c"*) esc=1 ;;
 '[1') esc=2 ;;
 *) esc=0 ;;
 esac
 done
}
main "$@" >/dev/tty