mirror of
				https://github.com/sharkdp/bat.git
				synced 2025-11-04 00:51:56 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			426 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Bash
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			426 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Bash
		
	
	
	
		
			Vendored
		
	
	
	
#!/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
 |