fix and updates
This commit is contained in:
@@ -16,23 +16,6 @@ MAGENTA=$(tput_cmd setaf 5)
|
||||
BLUE=$(tput_cmd setaf 4)
|
||||
ERASE_LINE=$(tput_cmd el || printf '\033[K')
|
||||
|
||||
# map a filename to a display colour based on extension
|
||||
file_colour() {
|
||||
_fc_name="$1"
|
||||
_fc_ext="${_fc_name##*.}"
|
||||
_fc_ext=$(printf '%s' "$_fc_ext" | tr '[:upper:]' '[:lower:]')
|
||||
# executable?
|
||||
[ -x "${CWD}/${_fc_name}" ] && { printf '%s' "${GREEN}${BOLD}" ; return; }
|
||||
# node device?
|
||||
[ -c "${CWD}/${_fc_name}" ] && { printf '%s' "${MAGENTA}${BOLD}"; return; }
|
||||
# block device?
|
||||
[ -b "${CWD}/${_fc_name}" ] && { printf '%s' "${MAGENTA}${BOLD}"; return; }
|
||||
# readable?
|
||||
[ -r "${CWD}/${_fc_name}" ] || { printf '%s' "${RED}${BOLD}" ; return; }
|
||||
# writable?
|
||||
[ -w "${CWD}/${_fc_name}" ] || { printf '%s' "${RED}${BOLD}" ; return; }
|
||||
}
|
||||
|
||||
goto() { printf '\033[%d;%dH' "$1" "$2"; }
|
||||
hide_cursor() { printf '\033[?25l'; }
|
||||
show_cursor() { printf '\033[?25h'; }
|
||||
@@ -174,8 +157,8 @@ $_line"; fi ;;
|
||||
# sort files using ls into a tmp file
|
||||
if [ -n "$_files" ]; then
|
||||
case "$SORT_MODE" in
|
||||
size) ls -1Sp "$CWD" 2>/dev/null | grep -v '/' > /tmp/_fm_sorted ;;
|
||||
date) ls -1tp "$CWD" 2>/dev/null | grep -v '/' > /tmp/_fm_sorted ;;
|
||||
size) ls -1Sp "$CWD" 2>/dev/null | grep -v '/' > /tmp/_fm_sorted_$$ ;;
|
||||
date) ls -1tp "$CWD" 2>/dev/null | grep -v '/' > /tmp/_fm_sorted_$$ ;;
|
||||
esac
|
||||
# only keep files that were already in our list (respects hidden filter)
|
||||
_sorted=""
|
||||
@@ -190,7 +173,7 @@ ${_n}
|
||||
else _sorted="$_sorted
|
||||
$_n"; fi ;;
|
||||
esac
|
||||
done < /tmp/_fm_sorted
|
||||
done < /tmp/_fm_sorted_$$
|
||||
_files="$_sorted"
|
||||
fi
|
||||
|
||||
@@ -265,16 +248,16 @@ $_line"; fi
|
||||
done
|
||||
fi
|
||||
# write to tmp file for O(1) line access in get_entry
|
||||
printf '%s\n' "$ENTRIES" > /tmp/_sfm_list
|
||||
printf '%s\n' "$ENTRIES" > /tmp/_sfm_list_$$
|
||||
}
|
||||
|
||||
get_entry() {
|
||||
sed -n "$(($1 + 1))p" /tmp/_sfm_list
|
||||
sed -n "$(($1 + 1))p" /tmp/_sfm_list_$$
|
||||
}
|
||||
|
||||
# find index of entry by name (0-based), returns -1 if not found
|
||||
find_entry() {
|
||||
_fe_n=$(grep -n "^${1}$" /tmp/_sfm_list 2>/dev/null | head -1 | cut -d: -f1)
|
||||
_fe_n=$(grep -nFx "$1" /tmp/_sfm_list_$$ 2>/dev/null | head -1 | cut -d: -f1)
|
||||
if [ -n "$_fe_n" ]; then
|
||||
printf '%d' $((_fe_n - 1))
|
||||
else
|
||||
@@ -284,12 +267,7 @@ find_entry() {
|
||||
|
||||
# is entry name in SELECTED list?
|
||||
is_selected() {
|
||||
case "
|
||||
${SELECTED}
|
||||
" in *"
|
||||
$1
|
||||
"*) return 0 ;; esac
|
||||
return 1
|
||||
printf '%s\n' "$SELECTED" | grep -Fxq "$1"
|
||||
}
|
||||
|
||||
count_selected() {
|
||||
@@ -1033,7 +1011,7 @@ do_find() {
|
||||
_query="$READ_LINE"
|
||||
|
||||
# run find and collect results into a tmp file
|
||||
_tmp=/tmp/_sfm_find
|
||||
_tmp=/tmp/_sfm_find_$$
|
||||
find "$CWD" -name "*${_query}*" 2>/dev/null | sort > "$_tmp"
|
||||
_total=$(wc -l < "$_tmp" | tr -d '[:space:]')
|
||||
|
||||
@@ -1258,7 +1236,8 @@ do_delete() {
|
||||
[ "$_next" = "$_rest" ] && _next=""
|
||||
_rest="$_next"
|
||||
[ -z "$_line" ] && continue
|
||||
_t="${CWD}/${_line%/}"
|
||||
_name="${_line%@}"; _name="${_name%/}"
|
||||
_t="${CWD}/${_name}"
|
||||
if [ -d "$_t" ]; then rm -rf "$_t"; else rm -f "$_t"; fi
|
||||
done
|
||||
SELECTED=""
|
||||
@@ -1271,7 +1250,8 @@ do_delete() {
|
||||
else
|
||||
# --- single delete ---
|
||||
entry=$(get_entry "$SEL")
|
||||
target="${CWD}/${entry%/}"
|
||||
_name="${entry%@}"; _name="${_name%/}"
|
||||
target="${CWD}/${_name}"
|
||||
restore_term; show_cursor
|
||||
goto "$(term_rows)" 1
|
||||
printf '%s%s Delete "%s"? [y/N] %s' "${ERASE_LINE}" "${RED}${BOLD}" "$entry" "${RESET}"
|
||||
@@ -1311,7 +1291,8 @@ do_rename() {
|
||||
goto "$(term_rows)" 1
|
||||
printf '%s%s Rename "%s" to (esc=cancel): %s' "${ERASE_LINE}" "${YELLOW}${BOLD}" "$entry" "${RESET}"
|
||||
if read_line && [ -n "$READ_LINE" ] && [ "$READ_LINE" != "$entry" ]; then
|
||||
mv "${CWD}/${entry%/}" "${CWD}/${READ_LINE}"
|
||||
_name="${entry%@}"; _name="${_name%/}"
|
||||
mv "${CWD}/${_name}" "${CWD}/${READ_LINE}"
|
||||
load_entries
|
||||
else
|
||||
NEED_FULL_REDRAW=1; draw
|
||||
@@ -1358,7 +1339,8 @@ do_chmod_nox() {
|
||||
do_info() {
|
||||
entry=$(get_entry "$SEL")
|
||||
[ -z "$entry" ] && return
|
||||
target="${CWD}/${entry%/}"
|
||||
_name="${entry%@}"; _name="${_name%/}"
|
||||
target="${CWD}/${_name}"
|
||||
# permissions + type
|
||||
_perm=$(ls -ld "$target" 2>/dev/null | awk '{print $1}')
|
||||
# size (human readable via du, fallback to ls)
|
||||
@@ -1396,9 +1378,10 @@ do_sort() {
|
||||
do_trash() {
|
||||
entry=$(get_entry "$SEL")
|
||||
[ -z "$entry" ] && return
|
||||
target="${CWD}/${entry%/}"
|
||||
_name="${entry%@}"; _name="${_name%/}"
|
||||
target="${CWD}/${_name}"
|
||||
_ts=$(date '+%Y%m%d_%H%M%S' 2>/dev/null || date '+%s')
|
||||
_dest="${TRASH_DIR}/${_ts}_${entry%/}"
|
||||
_dest="${TRASH_DIR}/${_ts}_${_name}"
|
||||
if mv "$target" "$_dest"; then
|
||||
INFO_MSG="trashed: ${entry}"
|
||||
[ "$SEL" -ge "$((COUNT - 1))" ] && SEL=$((COUNT - 2))
|
||||
@@ -1421,7 +1404,8 @@ do_open_trash() {
|
||||
do_copy_path() {
|
||||
entry=$(get_entry "$SEL")
|
||||
[ -z "$entry" ] && return
|
||||
_path="${CWD}/${entry%/}"
|
||||
_name="${entry%@}"; _name="${_name%/}"
|
||||
_path="${CWD}/${_name}"
|
||||
if command -v wl-copy >/dev/null 2>&1; then
|
||||
printf '%s' "$_path" | wl-copy
|
||||
elif command -v xclip >/dev/null 2>&1; then
|
||||
@@ -1479,6 +1463,8 @@ do_bookmark_jump() {
|
||||
_hl=$(printf '%*s' "$_iw" '' | tr ' ' '-')
|
||||
|
||||
_bsel=1
|
||||
_bvis=$((_ph - 3))
|
||||
_boff=1
|
||||
while true; do
|
||||
# draw picker inline
|
||||
goto "$_py" "$_px"
|
||||
@@ -1488,11 +1474,23 @@ do_bookmark_jump() {
|
||||
printf '%s|%s%s%s%s|%s' "${BOLD}${CYAN}" "${RESET}" "$_t" "$_p" "${BOLD}${CYAN}" "${RESET}"
|
||||
goto "$((_py+2))" "$_px"
|
||||
printf '%s|%s|%s' "${BOLD}${CYAN}" "$_hl" "${RESET}"
|
||||
# clear visible rows first
|
||||
_bri=0
|
||||
while [ "$_bri" -lt "$_bvis" ]; do
|
||||
goto "$((_py + 3 + _bri))" "$_px"
|
||||
_bep=$(printf '%*s' "$_iw" '')
|
||||
printf '%s|%s|%s' "${BOLD}${CYAN}" "$_bep" "${RESET}"
|
||||
_bri=$((_bri + 1))
|
||||
done
|
||||
# draw visible bookmarks
|
||||
_bi=0
|
||||
while IFS= read -r _bm; do
|
||||
[ -z "$_bm" ] && continue
|
||||
_bi=$((_bi+1))
|
||||
goto "$((_py+2+_bi))" "$_px"
|
||||
[ "$_bi" -lt "$_boff" ] && continue
|
||||
[ "$_bi" -ge $((_boff + _bvis)) ] && continue
|
||||
_drow=$((_py + 2 + _bi - _boff + 1))
|
||||
goto "$_drow" "$_px"
|
||||
_bt="${_bi} ${_bm}"
|
||||
if [ "${#_bt}" -gt "$_iw" ]; then _bt=$(printf '%s' "$_bt" | cut -c1-$((_iw-1))); _bt="${_bt}~"; fi
|
||||
_bpl=$((_iw - ${#_bt})); _bp=$(printf '%*s' "$_bpl" '')
|
||||
@@ -1506,14 +1504,18 @@ do_bookmark_jump() {
|
||||
printf '%s+%s+%s' "${BOLD}${CYAN}" "$_hl" "${RESET}"
|
||||
IFS= read -r -n1 _bk 2>/dev/null || IFS= read -r _bk
|
||||
case "$_bk" in
|
||||
j) _bsel=$((_bsel+1)); [ "$_bsel" -gt "$_bc" ] && _bsel=$_bc ;;
|
||||
k) _bsel=$((_bsel-1)); [ "$_bsel" -lt 1 ] && _bsel=1 ;;
|
||||
j) _bsel=$((_bsel+1)); [ "$_bsel" -gt "$_bc" ] && _bsel=$_bc
|
||||
[ "$_bsel" -ge $((_boff + _bvis)) ] && _boff=$((_bsel - _bvis + 1)) ;;
|
||||
k) _bsel=$((_bsel-1)); [ "$_bsel" -lt 1 ] && _bsel=1
|
||||
[ "$_bsel" -lt "$_boff" ] && _boff=$_bsel ;;
|
||||
"$(printf '\033')")
|
||||
# use timeout to distinguish bare esc from arrow sequences
|
||||
IFS= read -r -n2 -t 0.1 _seq 2>/dev/null || _seq=""
|
||||
case "$_seq" in
|
||||
'[A') _bsel=$((_bsel-1)); [ "$_bsel" -lt 1 ] && _bsel=1 ;;
|
||||
'[B') _bsel=$((_bsel+1)); [ "$_bsel" -gt "$_bc" ] && _bsel=$_bc ;;
|
||||
'[A') _bsel=$((_bsel-1)); [ "$_bsel" -lt 1 ] && _bsel=1
|
||||
[ "$_bsel" -lt "$_boff" ] && _boff=$_bsel ;;
|
||||
'[B') _bsel=$((_bsel+1)); [ "$_bsel" -gt "$_bc" ] && _bsel=$_bc
|
||||
[ "$_bsel" -ge $((_boff + _bvis)) ] && _boff=$((_bsel - _bvis + 1)) ;;
|
||||
'[C') # right — open
|
||||
_chosen=$(awk -v n="$_bsel" 'NR==n&&NF{print;exit}' "$BOOKMARK_FILE")
|
||||
if [ -n "$_chosen" ] && [ -d "$_chosen" ]; then
|
||||
@@ -1589,7 +1591,8 @@ do_yank() {
|
||||
if [ "$_c" -gt 0 ]; then
|
||||
CLIPBOARD=$(printf '%s\n' "$SELECTED" | while IFS= read -r _e; do
|
||||
[ -z "$_e" ] && continue
|
||||
printf '%s\n' "${CWD}/${_e%/}"
|
||||
_yname="${_e%@}"; _yname="${_yname%/}"
|
||||
printf '%s\n' "${CWD}/${_yname}"
|
||||
done)
|
||||
CLIP_MODE="copy"
|
||||
INFO_MSG="yanked ${_c} items"
|
||||
@@ -1597,7 +1600,8 @@ do_yank() {
|
||||
else
|
||||
entry=$(get_entry "$SEL")
|
||||
[ -z "$entry" ] && return
|
||||
CLIPBOARD="${CWD}/${entry%/}"
|
||||
_yname="${entry%@}"; _yname="${_yname%/}"
|
||||
CLIPBOARD="${CWD}/${_yname}"
|
||||
CLIP_MODE="copy"
|
||||
INFO_MSG="yanked: ${entry}"
|
||||
fi
|
||||
@@ -1609,7 +1613,8 @@ do_cut() {
|
||||
if [ "$_c" -gt 0 ]; then
|
||||
CLIPBOARD=$(printf '%s\n' "$SELECTED" | while IFS= read -r _e; do
|
||||
[ -z "$_e" ] && continue
|
||||
printf '%s\n' "${CWD}/${_e%/}"
|
||||
_cname="${_e%@}"; _cname="${_cname%/}"
|
||||
printf '%s\n' "${CWD}/${_cname}"
|
||||
done)
|
||||
CLIP_MODE="cut"
|
||||
INFO_MSG="cut ${_c} items"
|
||||
@@ -1617,7 +1622,8 @@ do_cut() {
|
||||
else
|
||||
entry=$(get_entry "$SEL")
|
||||
[ -z "$entry" ] && return
|
||||
CLIPBOARD="${CWD}/${entry%/}"
|
||||
_cname="${entry%@}"; _cname="${_cname%/}"
|
||||
CLIPBOARD="${CWD}/${_cname}"
|
||||
CLIP_MODE="cut"
|
||||
INFO_MSG="cut: ${entry}"
|
||||
fi
|
||||
@@ -1630,7 +1636,6 @@ do_paste() {
|
||||
NEED_FULL_REDRAW=1
|
||||
return
|
||||
fi
|
||||
_ok=0; _fail=0
|
||||
printf '%s\n' "$CLIPBOARD" | while IFS= read -r _src; do
|
||||
[ -z "$_src" ] && continue
|
||||
_name="${_src##*/}"
|
||||
@@ -1641,8 +1646,8 @@ do_paste() {
|
||||
_dest="${CWD}/${_base}_copy${_ext}"
|
||||
fi
|
||||
case "$CLIP_MODE" in
|
||||
copy) cp -r "$_src" "$_dest" && _ok=$((_ok+1)) || _fail=$((_fail+1)) ;;
|
||||
cut) mv "$_src" "$_dest" && _ok=$((_ok+1)) || _fail=$((_fail+1)) ;;
|
||||
copy) cp -r "$_src" "$_dest" ;;
|
||||
cut) mv "$_src" "$_dest" ;;
|
||||
esac
|
||||
done
|
||||
CLIPBOARD=""; CLIP_MODE=""
|
||||
@@ -1651,7 +1656,7 @@ do_paste() {
|
||||
}
|
||||
|
||||
# --- main ---
|
||||
trap 'restore_term; show_cursor; printf "\033[2J\033[H"; rm -f /tmp/_sfm_list /tmp/_sfm_find; exit 0' INT TERM EXIT
|
||||
trap 'restore_term; show_cursor; printf "\033[2J\033[H"; rm -f /tmp/_sfm_list_$$ /tmp/_sfm_find_$$; exit 0' INT QUIT TERM EXIT
|
||||
|
||||
setup_term
|
||||
hide_cursor
|
||||
@@ -1709,6 +1714,7 @@ while true; do
|
||||
m) do_mkdir ;;
|
||||
n) do_newfile ;;
|
||||
q|Q) break ;;
|
||||
'!') do_shell ;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user