From 9f4262566c886cb3122471169ab733ccf0122ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=84min=20Baumeler?= Date: Fri, 20 Mar 2026 22:37:57 +0100 Subject: [PATCH] improved: user prompts --- src/main.sh | 8 ++++---- src/sh/send.sh | 14 +++++++++++--- src/sh/theme.sh | 6 ++++++ src/sh/userprompt.sh | 39 ++++++++++++++++++++++++++++++++++++++ src/sh/varia.sh | 45 -------------------------------------------- 5 files changed, 60 insertions(+), 52 deletions(-) create mode 100644 src/sh/userprompt.sh delete mode 100644 src/sh/varia.sh diff --git a/src/main.sh b/src/main.sh index 6a2f9fc..2ba0a7b 100755 --- a/src/main.sh +++ b/src/main.sh @@ -32,8 +32,8 @@ set -eu # preview functions . "sh/preview.sh" -# varia functions -. "sh/varia.sh" +# userprompt functions +. "sh/userprompt.sh" # tags . "sh/tags.sh" @@ -143,7 +143,7 @@ if [ "${1:-}" = "--open-part" ]; then [ "$res" ] || exit tmpfile=$(mktemp) nm_message_get_part "$messageid" "$res" > "$tmpfile" - if ynprompt "Are you sure you want to open this file?" "$($0 --preview-file-info "$tmpfile")"; then + if $0 --preview-file-info "$tmpfile" | ynprompt "Are you sure you want to open this file?"; then # TODO: should we clean up at some point? open "$tmpfile" >/dev/null 2>/dev/stdout fi @@ -203,7 +203,7 @@ if [ "${1:-}" = "--purge" ]; then shift query="tag:$TAG_DEL and ($(echo " $*" | sed "s/\s\(\S\)/ thread:\1/g"))" files=$(nm_files_all "$query") - if ynprompt "Are you sure you want to purge these files?" "$files"; then + if echo "$files" | ynprompt "Are you sure you want to purge these files?"; then printf '%s' "$files" | xargs -d "\n" rm nm_new fi diff --git a/src/sh/send.sh b/src/sh/send.sh index 4df907e..4918c45 100644 --- a/src/sh/send.sh +++ b/src/sh/send.sh @@ -2,8 +2,16 @@ # @argument $1: Path to email file # @argument $2: if set, don't prompt the user (optional) send() { - if [ ! "${2:-}" ] && ! ynprompt "Do you want to send this email?" "$($CATEMAIL "$tmpfile")"; then - return + if [ ! "${2:-}" ]; then + # Prompt user + undecided=1 + while [ "$undecided" ]; do + case "$($CATEMAIL "$1" | multiprompt "Do you want to send this email?" "$YESSTRING\n$EDITSTRING\n$ABORTSTRING")" in + 0) undecided= ;; + 1) $EDITOR "$1" ;; + 2) return ;; + esac + done fi $MSMTP -t --read-envelope-from -X "$SMTPLOGFILE" < "$1" >/dev/null 2>&1 || true log=$(tail -1 "$SMTPLOGFILE") @@ -11,7 +19,7 @@ send() { return fi # Handle errors - res=$(printf "0 Retry\n1 Edit email\n2 Abort\n" | multiprompt "Could not send the email. What's next?" "$(echo "$log" | $CATLOG)") + res=$(echo "$log" | $CATLOG | multiprompt "Could not send the email. What's next?" "Retry\n$EDITSTRING\n$ABORTSTRING") case "$res" in 0) send "$1" ;; 1) $EDITOR "$1"; send "$1" ;; diff --git a/src/sh/theme.sh b/src/sh/theme.sh index db1d992..29641ac 100644 --- a/src/sh/theme.sh +++ b/src/sh/theme.sh @@ -12,8 +12,14 @@ if [ ! "${THEME_LOADED:-}" ]; then COLTAGS="$(printf '\033[38;5;%sm' "$ANSICOLORTAGS")" COLRESET="$(printf '\033[0m')" + YESSTRING="${YESSTRING:-$(printf '\033[32mYes\033[0m')}" + NOSTRING="${NOSTRING:-$(printf '\033[31mNo\033[0m')}" + ABORTSTRING="${ABORTSTRING:-$(printf '\033[31mAbort\033[0m')}" + EDITSTRING="${EDITSTRING:-$(printf '\033[33mEdit email\033[0m')}" + export ANSICOLORDATE ANSICOLORCNTS ANSICOLORFROM ANSICOLORSUBJ ANSICOLORTAGS export COLDATE COLCNTS COLFROM COLSUBJ COLTAGS COLRESET + export YESSTRING NOSTRING ABORTSTRING EDITSTRING export THEME_LOADED=1 fi diff --git a/src/sh/userprompt.sh b/src/sh/userprompt.sh new file mode 100644 index 0000000..9690e4c --- /dev/null +++ b/src/sh/userprompt.sh @@ -0,0 +1,39 @@ +# Various functions + +# This prompts the user for a series of options. +# The content for the preview is read from stdin. +# The possible options are given as newlineline-delimited string. +# The function prints the line number (zero-based) of the selected option. +# +# @argument $1: Question +# @argument $2: Options +multiprompt() { + pf=$(mktemp) + cat > "$pf" + echo "$2" | awk '{ print FNR-1, $0 }' | $FZF \ + --reverse \ + --no-input \ + --header="$1" \ + --preview-window='60%,border-line,wrap-word' \ + --margin='5%,5%,5%,15%' \ + --preview="cat \"$pf\"" \ + --bind="$KEYS_PREVIEW_DOWN:preview-down" \ + --bind="$KEYS_PREVIEW_UP:preview-up" \ + --bind="$KEYS_PREVIEW_DOWN_HP:preview-half-page-down" \ + --bind="$KEYS_PREVIEW_UP_HP:preview-half-page-up" \ + --bind="$KEYS_PREVIEW_TOGGLE_WRAP:toggle-preview-wrap-word" \ + --with-nth=2.. \ + --accept-nth=1 \ + --header-border='line' \ + --bind="ctrl-c,esc,ctrl-q:" \ + --color='border:yellow,header:yellow' || true + rm -f "$pf" +} + +# This prompts the user for a "yes" or a "no", and shows the content from stdin +# in the preview window. +# @argument $1: Question +# @return: 0 if the user answered "yes" and 1 otherwise. +ynprompt() { + return "$(cat | multiprompt "$1" "$YESSTRING\n$NOSTRING")" +} diff --git a/src/sh/varia.sh b/src/sh/varia.sh deleted file mode 100644 index d4912ab..0000000 --- a/src/sh/varia.sh +++ /dev/null @@ -1,45 +0,0 @@ -# Various functions - -# This prompts the user for a "yes" or a "no" -# @argument $1: Question -# @argument $2: Content to show in preview window -# @return: 0 if the user answered "yes" and 1 otherwise. -ynprompt() { - return "$(printf '0 \033[32myes\033[0m\n1 \033[31mno\033[0m\n' | - $FZF \ - --sync \ - --bind='start:pos(2)' \ - --bind='ctrl-c,ctrl-g,ctrl-q,esc:pos(2)+accept' \ - --reverse \ - --no-input \ - --header="$1" \ - --preview-window='60%,border-line,wrap-word' \ - --margin='5%,5%,5%,15%' \ - --preview="echo \"$2\"" \ - --with-nth=2.. \ - --accept-nth=1 \ - --header-border='line' \ - --color='border:yellow,header:yellow')" -} - -# This prompts the user for a series of options. -# The options are read from stdin in the form "integer\toption\n". -# Prints number -# -# @argument $1: Question -# @argument $2: Content to show in preview window -multiprompt() { - cat | - $FZF \ - --reverse \ - --no-input \ - --header="$1" \ - --preview-window='60%,border-line,wrap-word' \ - --margin='5%,5%,5%,15%' \ - --preview="echo \"$2\"" \ - --with-nth=2.. \ - --accept-nth=1 \ - --header-border='line' \ - --bind="ctrl-c,esc,ctrl-q:" \ - --color='border:yellow,header:yellow' | head -1 || true -}