Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fa830284e |
No files matched your search
@@ -8,7 +8,7 @@
|
|||||||
# Overridable so a packager can pass the version it is actually building
|
# Overridable so a packager can pass the version it is actually building
|
||||||
# (`make VERSION=$pkgver`). The literal below is the fallback for builds
|
# (`make VERSION=$pkgver`). The literal below is the fallback for builds
|
||||||
# straight from a checkout, and is what a release tag has to carry.
|
# straight from a checkout, and is what a release tag has to carry.
|
||||||
VERSION ?= 1.1.0
|
VERSION ?= 1.1.1
|
||||||
|
|
||||||
PREFIX ?= /usr
|
PREFIX ?= /usr
|
||||||
DESTDIR ?=
|
DESTDIR ?=
|
||||||
|
|||||||
@@ -75,6 +75,27 @@ cau_msg() {
|
|||||||
cau_msg_in "$(cau_ui_locale)" "$@"
|
cau_msg_in "$(cau_ui_locale)" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# cau_msg_into <locale> <msgid>
|
||||||
|
# Plain lookup with the result in CAU_MSG_RESULT and no printf formatting.
|
||||||
|
# For callers that redraw many labels per keypress, where wrapping cau_msg in a
|
||||||
|
# command substitution would cost a fork per label.
|
||||||
|
CAU_MSG_RESULT=''
|
||||||
|
|
||||||
|
cau_msg_into() {
|
||||||
|
local locale="$1" msgid="$2" cachekey
|
||||||
|
cachekey="${locale}"$'\x1f'"${msgid}"
|
||||||
|
|
||||||
|
if [[ -n ${CAU_MSG_CACHE[$cachekey]+set} ]]; then
|
||||||
|
CAU_MSG_RESULT="${CAU_MSG_CACHE[$cachekey]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
CAU_MSG_RESULT="$(LC_ALL="$locale" LANGUAGE="${locale%%.*}" gettext -- "$msgid" 2>/dev/null)"
|
||||||
|
[[ -n $CAU_MSG_RESULT ]] || CAU_MSG_RESULT="$msgid"
|
||||||
|
CAU_MSG_CACHE[$cachekey]="$CAU_MSG_RESULT"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Translations are memoized. Every gettext lookup is a fork, and the settings
|
# Translations are memoized. Every gettext lookup is a fork, and the settings
|
||||||
# screen redraws forty-odd labels per keypress; without this the redraw takes
|
# screen redraws forty-odd labels per keypress; without this the redraw takes
|
||||||
# long enough that a keystroke arriving during it is lost when the terminal
|
# long enough that a keystroke arriving during it is lost when the terminal
|
||||||
|
|||||||
+17
-8
@@ -20,11 +20,17 @@ _cau_config_slurp() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# cau_config_get <Key> [default]
|
# _cau_config_lookup <Key> [default]
|
||||||
cau_config_get() {
|
# Result in CAU_CONFIG_VALUE. Assigning rather than printing matters on the
|
||||||
|
# settings screen, which reads every key on every frame: a command substitution
|
||||||
|
# there is a fork, and forks were the entire cost of a redraw.
|
||||||
|
CAU_CONFIG_VALUE=''
|
||||||
|
|
||||||
|
_cau_config_lookup() {
|
||||||
local key="$1" default="${2:-}" val='' line
|
local key="$1" default="${2:-}" val='' line
|
||||||
|
|
||||||
[[ -r $CAU_CONFIG ]] || { printf '%s\n' "$default"; return; }
|
CAU_CONFIG_VALUE="$default"
|
||||||
|
[[ -r $CAU_CONFIG ]] || return 0
|
||||||
_cau_config_slurp
|
_cau_config_slurp
|
||||||
|
|
||||||
# last assignment wins, matching the previous sed|tail behaviour
|
# last assignment wins, matching the previous sed|tail behaviour
|
||||||
@@ -41,11 +47,14 @@ cau_config_get() {
|
|||||||
val="${val%\"}"
|
val="${val%\"}"
|
||||||
val="${val#\"}"
|
val="${val#\"}"
|
||||||
|
|
||||||
if [[ -n $val ]]; then
|
[[ -n $val ]] && CAU_CONFIG_VALUE="$val"
|
||||||
printf '%s\n' "$val"
|
return 0
|
||||||
else
|
}
|
||||||
printf '%s\n' "$default"
|
|
||||||
fi
|
# cau_config_get <Key> [default]
|
||||||
|
cau_config_get() {
|
||||||
|
_cau_config_lookup "$@"
|
||||||
|
printf '%s\n' "$CAU_CONFIG_VALUE"
|
||||||
}
|
}
|
||||||
|
|
||||||
# cau_config_bool <Key> <default: yes|no>
|
# cau_config_bool <Key> <default: yes|no>
|
||||||
|
|||||||
+72
-34
@@ -156,25 +156,33 @@ _cau_is_true() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# _cau_setting_display <type> <value>
|
# _cau_setting_display <type> <value>
|
||||||
|
# Result in CAU_SETTING_SHOWN. The three constant strings are resolved once by
|
||||||
|
# the caller into CAU_LBL_*; looking them up here would put a translation call
|
||||||
|
# on the per-line path.
|
||||||
|
CAU_SETTING_SHOWN=''
|
||||||
|
CAU_LBL_ON=''
|
||||||
|
CAU_LBL_OFF=''
|
||||||
|
CAU_LBL_NONE=''
|
||||||
|
|
||||||
_cau_setting_display() {
|
_cau_setting_display() {
|
||||||
local type="$1" value="$2"
|
local type="$1" value="$2"
|
||||||
|
|
||||||
case "$type" in
|
case "$type" in
|
||||||
bool)
|
bool)
|
||||||
if _cau_is_true "$value"; then
|
if _cau_is_true "$value"; then
|
||||||
printf '%s%s%s' "$CAU_C_GREEN" "$(cau_msg "ON")" "$CAU_C_RESET"
|
CAU_SETTING_SHOWN="${CAU_C_GREEN}${CAU_LBL_ON}${CAU_C_RESET}"
|
||||||
else
|
else
|
||||||
printf '%s%s%s' "$CAU_C_DIM" "$(cau_msg "OFF")" "$CAU_C_RESET"
|
CAU_SETTING_SHOWN="${CAU_C_DIM}${CAU_LBL_OFF}${CAU_C_RESET}"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
text)
|
text)
|
||||||
if [[ -n $value ]]; then
|
if [[ -n $value ]]; then
|
||||||
printf '%s' "$value"
|
CAU_SETTING_SHOWN="$value"
|
||||||
else
|
else
|
||||||
printf '%s%s%s' "$CAU_C_DIM" "$(cau_msg "(none)")" "$CAU_C_RESET"
|
CAU_SETTING_SHOWN="${CAU_C_DIM}${CAU_LBL_NONE}${CAU_C_RESET}"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*) printf '%s' "$value" ;;
|
*) CAU_SETTING_SHOWN="$value" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,58 +213,88 @@ _cau_setting_cycle() {
|
|||||||
# cau_ui_settings
|
# cau_ui_settings
|
||||||
# A cursor list rather than a numbered menu: there are eighteen settings, and
|
# A cursor list rather than a numbered menu: there are eighteen settings, and
|
||||||
# numbering them would run out of digits and force paging.
|
# numbering them would run out of digits and force paging.
|
||||||
|
#
|
||||||
|
# The frame is assembled in memory and written once. Everything constant - the
|
||||||
|
# specs, the translated labels, the clear sequence - is resolved before the
|
||||||
|
# loop, and the values are re-read only after something actually changes.
|
||||||
|
# Drawing the naive way cost a command substitution per label per frame, which
|
||||||
|
# measured 435 ms per keypress: arrow keys felt like the console was reloading,
|
||||||
|
# because in effect it was.
|
||||||
cau_ui_settings() {
|
cau_ui_settings() {
|
||||||
local cursor=0 key spec name type default label value line pad
|
|
||||||
local count=${#CAU_SETTINGS[@]}
|
local count=${#CAU_SETTINGS[@]}
|
||||||
|
local -a names=() types=() defaults=() labels=()
|
||||||
|
local -a values=()
|
||||||
|
local spec name type default label locale i key frame row pad dirty=1 cursor=0
|
||||||
|
|
||||||
while true; do
|
locale="$(cau_ui_locale)"
|
||||||
clear 2>/dev/null || true
|
cau_msg_into "$locale" "ON"; CAU_LBL_ON="$CAU_MSG_RESULT"
|
||||||
cau_head " $(cau_msg "Settings")"
|
cau_msg_into "$locale" "OFF"; CAU_LBL_OFF="$CAU_MSG_RESULT"
|
||||||
|
cau_msg_into "$locale" "(none)"; CAU_LBL_NONE="$CAU_MSG_RESULT"
|
||||||
|
|
||||||
local i=0
|
|
||||||
for spec in "${CAU_SETTINGS[@]}"; do
|
for spec in "${CAU_SETTINGS[@]}"; do
|
||||||
IFS='|' read -r name type default label <<< "$spec"
|
IFS='|' read -r name type default label <<< "$spec"
|
||||||
value="$(cau_config_get "$name" "$default")"
|
names+=("$name"); types+=("$type"); defaults+=("$default")
|
||||||
|
cau_msg_into "$locale" "$label"
|
||||||
if (( i == cursor )); then
|
labels+=("$CAU_MSG_RESULT")
|
||||||
line="${CAU_C_BLUE}▸${CAU_C_RESET} "
|
|
||||||
else
|
|
||||||
line=" "
|
|
||||||
fi
|
|
||||||
|
|
||||||
local text
|
|
||||||
text="$(cau_msg "$label")"
|
|
||||||
pad=$(( 42 - ${#text} ))
|
|
||||||
(( pad < 0 )) && pad=0
|
|
||||||
|
|
||||||
printf ' %s%s%*s %s\n' "$line" "$text" "$pad" '' \
|
|
||||||
"$(_cau_setting_display "$type" "$value")"
|
|
||||||
i=$(( i + 1 ))
|
|
||||||
done
|
done
|
||||||
|
|
||||||
printf '\n %s%s%s\n' "$CAU_C_DIM" \
|
local title hint
|
||||||
"$(cau_msg "Up/Down select - Space or Right changes - q goes back")" "$CAU_C_RESET"
|
cau_msg_into "$locale" "Settings"; title="$CAU_MSG_RESULT"
|
||||||
|
cau_msg_into "$locale" "Up/Down select - Space or Right changes - q goes back"
|
||||||
|
hint="$CAU_MSG_RESULT"
|
||||||
|
|
||||||
|
# the terminfo clear string, fetched once instead of forking per frame
|
||||||
|
local clearseq
|
||||||
|
clearseq="$(clear 2>/dev/null)" || clearseq=$'\033[H\033[2J'
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if (( dirty )); then
|
||||||
|
for i in "${!names[@]}"; do
|
||||||
|
_cau_config_lookup "${names[i]}" "${defaults[i]}"
|
||||||
|
values[i]="$CAU_CONFIG_VALUE"
|
||||||
|
done
|
||||||
|
dirty=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
frame="$clearseq"$'\n'"${CAU_C_BOLD}${CAU_C_BLUE} ${title}${CAU_C_RESET}"$'\n\n'
|
||||||
|
|
||||||
|
local marker selected="${CAU_C_BLUE}▸${CAU_C_RESET} "
|
||||||
|
for i in "${!names[@]}"; do
|
||||||
|
_cau_setting_display "${types[i]}" "${values[i]}"
|
||||||
|
pad=$(( 42 - ${#labels[i]} ))
|
||||||
|
(( pad < 0 )) && pad=0
|
||||||
|
if (( i == cursor )); then marker="$selected"; else marker=' '; fi
|
||||||
|
printf -v row ' %s%s%*s %s' \
|
||||||
|
"$marker" "${labels[i]}" "$pad" '' "$CAU_SETTING_SHOWN"
|
||||||
|
frame+="$row"$'\n'
|
||||||
|
done
|
||||||
|
|
||||||
|
frame+=$'\n'" ${CAU_C_DIM}${hint}${CAU_C_RESET}"$'\n'
|
||||||
|
printf '%s' "$frame"
|
||||||
|
|
||||||
key="$(cau_read_key)" || return 0
|
key="$(cau_read_key)" || return 0
|
||||||
|
|
||||||
IFS='|' read -r name type default label <<< "${CAU_SETTINGS[cursor]}"
|
type="${types[cursor]}"
|
||||||
value="$(cau_config_get "$name" "$default")"
|
name="${names[cursor]}"
|
||||||
|
|
||||||
case "$key" in
|
case "$key" in
|
||||||
up|k) cursor=$(( (cursor - 1 + count) % count )) ;;
|
up|k) cursor=$(( (cursor - 1 + count) % count )) ;;
|
||||||
down|j) cursor=$(( (cursor + 1) % count )) ;;
|
down|j) cursor=$(( (cursor + 1) % count )) ;;
|
||||||
space|enter|right|l)
|
space|enter|right|l)
|
||||||
if [[ $type == text ]]; then
|
if [[ $type == text ]]; then
|
||||||
cau_ui_edit_text "$name" "$value"
|
cau_ui_edit_text "$name" "${values[cursor]}"
|
||||||
else
|
else
|
||||||
cau_config_set "$name" "$(_cau_setting_cycle "$type" "$value" 1)" \
|
cau_config_set "$name" "$(_cau_setting_cycle "$type" "${values[cursor]}" 1)" \
|
||||||
|| { cau_bad "$(cau_msg "Could not write the configuration file.")"; cau_pause; }
|
|| { cau_bad "$(cau_msg "Could not write the configuration file.")"; cau_pause; }
|
||||||
fi
|
fi
|
||||||
|
dirty=1
|
||||||
;;
|
;;
|
||||||
left|h)
|
left|h)
|
||||||
[[ $type == text ]] || cau_config_set "$name" \
|
if [[ $type != text ]]; then
|
||||||
"$(_cau_setting_cycle "$type" "$value" -1)" \
|
cau_config_set "$name" "$(_cau_setting_cycle "$type" "${values[cursor]}" -1)" \
|
||||||
|| { cau_bad "$(cau_msg "Could not write the configuration file.")"; cau_pause; }
|
|| { cau_bad "$(cau_msg "Could not write the configuration file.")"; cau_pause; }
|
||||||
|
dirty=1
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
q|Q|escape) return 0 ;;
|
q|Q|escape) return 0 ;;
|
||||||
*) ;;
|
*) ;;
|
||||||
|
|||||||
Reference in new issue
Block a user