aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremmett1 <me@emmett1.my>2026-05-30 23:51:26 +0800
committeremmett1 <me@emmett1.my>2026-05-30 23:51:26 +0800
commit8db9a070b7e63da034a0925788c8550d58000950 (patch)
treee8febf6e26780763b7ea4679c97d10ff12e54520
parentbed888c3c3910aecaff19d63e0ea905316d23507 (diff)
downloadsfm-8db9a070b7e63da034a0925788c8550d58000950.tar.gz
sfm-8db9a070b7e63da034a0925788c8550d58000950.zip
yes no box for file deletion confirmation
-rwxr-xr-xsfm175
1 files changed, 119 insertions, 56 deletions
diff --git a/sfm b/sfm
index 9b181c9..061c68a 100755
--- a/sfm
+++ b/sfm
@@ -1214,75 +1214,138 @@ do_open() {
esac
}
+# --- confirm overlay (yes/no popup) ---
+confirm_overlay() {
+ _co_rows=$(term_rows); _co_cols=$(term_cols)
+ _co_yes=" Yes "
+ _co_no=" No "
+ _co_gap=" "
+ _co_content="${_co_yes}${_co_gap}${_co_no}"
+
+ # size box to fit prompt or buttons, whichever is wider
+ _co_w=$(( ${#_prompt} + 4 ))
+ [ "$_co_w" -lt $(( ${#_co_content} + 4 )) ] && _co_w=$(( ${#_co_content} + 4 ))
+ [ "$_co_w" -gt "$_co_cols" ] && _co_w=$((_co_cols - 2))
+ _co_iw=$((_co_w - 2))
+ _co_hl=$(printf '%*s' "$_co_iw" '' | tr ' ' '-')
+
+ _co_x=$(( (_co_cols - _co_w) / 2 )); [ "$_co_x" -lt 0 ] && _co_x=0
+ _co_y=$(( (_co_rows - 5) / 2 )); [ "$_co_y" -lt 1 ] && _co_y=1
+ _co_sel=2 # 1=Yes, 2=No (default No for safety)
+
+ while true; do
+ # draw box top
+ goto "$_co_y" "$_co_x"
+ printf '%s+%s+%s' "${BOLD}${CYAN}" "$_co_hl" "${RESET}"
+ # prompt line
+ goto "$((_co_y+1))" "$_co_x"
+ _co_pl=$((_co_iw - ${#_prompt}))
+ [ "$_co_pl" -lt 0 ] && _co_pl=0
+ _co_pad=$(printf '%*s' "$_co_pl" '')
+ printf '%s|%s%s%s%s|%s' "${BOLD}${CYAN}" "${RESET}" "$_prompt" "$_co_pad" "${BOLD}${CYAN}" "${RESET}"
+ # separator
+ goto "$((_co_y+2))" "$_co_x"
+ printf '%s|%s|%s' "${BOLD}${CYAN}" "$_co_hl" "${RESET}"
+ # yes/no buttons
+ goto "$((_co_y+3))" "$_co_x"
+ _co_cpad=$(( (_co_iw - ${#_co_content}) / 2 ))
+ [ "$_co_cpad" -lt 0 ] && _co_cpad=0
+ _co_left=$(printf '%*s' "$_co_cpad" '')
+ _co_cpad=$(( _co_iw - ${#_co_content} - _co_cpad ))
+ [ "$_co_cpad" -lt 0 ] && _co_cpad=0
+ _co_right=$(printf '%*s' "$_co_cpad" '')
+ printf '%s|%s%s' "${BOLD}${CYAN}" "${RESET}" "$_co_left"
+ if [ "$_co_sel" -eq 1 ]; then
+ printf '%s%s%s' "${REV}${GREEN}${BOLD}" "$_co_yes" "${RESET}"
+ else
+ printf '%s' "$_co_yes"
+ fi
+ printf '%s' "$_co_gap"
+ if [ "$_co_sel" -eq 2 ]; then
+ printf '%s%s%s' "${REV}${RED}${BOLD}" "$_co_no" "${RESET}"
+ else
+ printf '%s' "$_co_no"
+ fi
+ printf '%s%s|%s' "$_co_right" "${BOLD}${CYAN}" "${RESET}"
+ # box bottom
+ goto "$((_co_y+4))" "$_co_x"
+ printf '%s+%s+%s' "${BOLD}${CYAN}" "$_co_hl" "${RESET}"
+
+ # read key
+ IFS= read -r -n1 _co_ch 2>/dev/null || IFS= read -r _co_ch
+ case "$_co_ch" in
+ "$(printf '\033')")
+ IFS= read -r -n2 -t 0.1 _co_seq 2>/dev/null || _co_seq=""
+ case "$_co_seq" in
+ '[D'|'[C') # left/right arrow
+ if [ "$_co_sel" -eq 1 ]; then _co_sel=2; else _co_sel=1; fi ;;
+ *) return 1 ;; # bare esc or unrecognised sequence
+ esac ;;
+ h) _co_sel=1 ;;
+ l) _co_sel=2 ;;
+ j) _co_sel=2 ;;
+ k) _co_sel=1 ;;
+ y|Y) return 0 ;;
+ n|N) return 1 ;;
+ "$(printf '\n')"|"$(printf '\r')")
+ if [ "$_co_sel" -eq 1 ]; then return 0; else return 1; fi ;;
+ esac
+ done
+}
+
do_delete() {
INFO_MSG=""
_c=$(count_selected)
if [ "$_c" -gt 0 ]; then
# --- bulk delete selected ---
- restore_term; show_cursor
- goto "$(term_rows)" 1
- printf '%s%s Delete %d selected items? [y/N] %s' \
- "${ERASE_LINE}" "${RED}${BOLD}" "$_c" "${RESET}"
- IFS= read -r ans
- setup_term; hide_cursor
- case "$ans" in
- y|Y)
- _rest="$SELECTED"
- while [ -n "$_rest" ]; do
- _line="${_rest%%
+ _prompt="Delete ${_c} selected items?"
+ confirm_overlay; _yes=$?
+ if [ "$_yes" -eq 0 ]; then
+ _rest="$SELECTED"
+ while [ -n "$_rest" ]; do
+ _line="${_rest%%
*}"
- _next="${_rest#*
+ _next="${_rest#*
}"
- [ "$_next" = "$_rest" ] && _next=""
- _rest="$_next"
- [ -z "$_line" ] && continue
- _name="${_line%@}"; _name="${_name%/}"
- _t="${CWD}/${_name}"
- if [ -d "$_t" ]; then rm -rf "$_t"; else rm -f "$_t"; fi
- done
- SELECTED=""
- [ "$SEL" -ge "$((COUNT - 1))" ] && SEL=$((COUNT - 2))
- [ "$SEL" -lt 0 ] && SEL=0
- load_entries
- ;;
- *) NEED_FULL_REDRAW=1 ;;
- esac
+ [ "$_next" = "$_rest" ] && _next=""
+ _rest="$_next"
+ [ -z "$_line" ] && continue
+ _name="${_line%@}"; _name="${_name%/}"
+ _t="${CWD}/${_name}"
+ if [ -d "$_t" ]; then rm -rf "$_t"; else rm -f "$_t"; fi
+ done
+ SELECTED=""
+ [ "$SEL" -ge "$((COUNT - 1))" ] && SEL=$((COUNT - 2))
+ [ "$SEL" -lt 0 ] && SEL=0
+ load_entries
+ else
+ NEED_FULL_REDRAW=1
+ fi
else
# --- single delete ---
entry=$(get_entry "$SEL")
_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}"
- IFS= read -r ans
- setup_term; hide_cursor
- case "$ans" in
- y|Y)
- if [ -d "$target" ]; then
- if [ -n "$(ls -A "$target" 2>/dev/null)" ]; then
- restore_term; show_cursor
- goto "$(term_rows)" 1
- printf '%s%s "%s" not empty. Delete ALL? [y/N] %s' \
- "${ERASE_LINE}" "${RED}${BOLD}" "$entry" "${RESET}"
- IFS= read -r ans2
- setup_term; hide_cursor
- case "$ans2" in
- y|Y) rm -rf "$target" ;;
- *) NEED_FULL_REDRAW=1; return ;;
- esac
- else
- rm -rf "$target"
- fi
- else
- rm -f "$target"
+ _prompt="Delete \"${entry}\"?"
+ confirm_overlay; _yes=$?
+ if [ "$_yes" -ne 0 ]; then
+ NEED_FULL_REDRAW=1; return
+ fi
+ if [ -d "$target" ]; then
+ if [ -n "$(ls -A "$target" 2>/dev/null)" ]; then
+ _prompt="\"${entry}\" not empty. Delete ALL?"
+ confirm_overlay; _yes2=$?
+ if [ "$_yes2" -ne 0 ]; then
+ NEED_FULL_REDRAW=1; return
fi
- [ "$SEL" -ge "$((COUNT - 1))" ] && SEL=$((COUNT - 2))
- [ "$SEL" -lt 0 ] && SEL=0
- load_entries
- ;;
- *) NEED_FULL_REDRAW=1 ;;
- esac
+ fi
+ rm -rf "$target"
+ else
+ rm -f "$target"
+ fi
+ [ "$SEL" -ge "$((COUNT - 1))" ] && SEL=$((COUNT - 2))
+ [ "$SEL" -lt 0 ] && SEL=0
+ load_entries
fi
}