Dialoge passen sich an Terminal, Text und Anzahl der Eintraege an

Die Fenstergroesse war fest (22x78, Liste 13 Zeilen). Bei einem langen
Erklaertext blieb davon nur eine sichtbare Listenzeile uebrig - die
Auswahl liess sich nur noch scrollend bedienen.

ui_calc berechnet die Groesse jetzt aus Terminalgroesse, Zeilenzahl des
Textes und Anzahl sowie Breite der Eintraege; ui_calc_text macht
dasselbe fuer Meldung, Abfrage und Eingabe, ui_text nutzt fast das
ganze Terminal. Damit sind beim beanstandeten Dialog alle drei
Eintraege sichtbar statt einem, und in einem 45-Zeilen-Terminal passen
alle 13 Hauptmenue-Punkte gleichzeitig hin.

Beim Bauen gleich wieder in die bekannte Falle getappt und behoben:
"[ bedingung ] && VAR=wert" liefert 1, wenn die Bedingung nicht
zutrifft, und beendet unter "set -e" die Funktion. Die Berechnung
verwendet deshalb durchgehend if-Bloecke; das ist im Quelltext
vermerkt, damit es nicht wieder passiert.

Geprueft: Geometrie fuer den beanstandeten Dialog und fuer lange
Listen, Rendern aller Menues unter whiptail in einem echten
Pseudo-Terminal ohne Fehlermeldung, und alle Menues kehren weiterhin
sauber zurueck.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-20 17:41:19 +02:00
co-authored by Claude Opus 5
parent 9c99429c15
commit 9417f0c102
3 changed files with 95 additions and 7 deletions
+3
View File
@@ -1619,6 +1619,9 @@ sudo ./scripts/cmk-manage.sh gui
Bedienung: Pfeiltasten, **Leertaste** markiert in Auswahllisten (z. B. mehrere
Sites für ein Backup), **Enter** bestätigt, **ESC/Cancel** geht zurück.
Die Fenstergröße richtet sich nach Terminalgröße, Textlänge und Anzahl der
Einträge – in einem größeren Terminal sind entsprechend mehr Einträge auf
einmal sichtbar.
Es wird `dialog` bevorzugt; ist nur `whiptail` vorhanden, wird dieses genutzt.
Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut.
+2
View File
@@ -1623,6 +1623,8 @@ The menu labels are German; the command table in
Operation: arrow keys, **space** toggles entries in selection lists (e.g.
several sites for a backup), **Enter** confirms, **ESC/Cancel** goes back.
The window size adapts to the terminal size, the length of the text and the
number of entries – in a larger terminal more entries are visible at once.
`dialog` is preferred; if only `whiptail` is present, that is used instead.
A file chooser with directory navigation is built in.
+90 -7
View File
@@ -224,6 +224,79 @@ primary_ip() {
# =====================================================================
UI_BACKTITLE="Checkmk Stack Manager - Container-Runtime: ${RUNTIME:-?}"
# Groesse des Terminals ermitteln (mit Rueckfallwerten)
ui_term_size() {
UI_ROWS="$(tput lines 2>/dev/null || true)"
UI_COLS="$(tput cols 2>/dev/null || true)"
case "$UI_ROWS" in ''|*[!0-9]*) UI_ROWS=24 ;; esac
case "$UI_COLS" in ''|*[!0-9]*) UI_COLS=80 ;; esac
if [ "$UI_ROWS" -lt 10 ]; then UI_ROWS=24; fi
if [ "$UI_COLS" -lt 40 ]; then UI_COLS=80; fi
return 0
}
# Fenstergroesse aus Textlaenge, Anzahl der Eintraege und Terminalgroesse
# berechnen. Vorher waren die Werte fest - bei langem Text blieb dann nur
# eine Zeile fuer die Liste uebrig.
#
# ACHTUNG: hier bewusst mit if-Bloecken statt "[ ... ] && VAR=...".
# Letzteres liefert 1, wenn die Bedingung nicht zutrifft, und beendet
# unter "set -e" die Funktion bzw. das ganze Skript.
#
# ui_calc TEXT FELDER_JE_EINTRAG EINTRAEGE...
ui_calc() {
local text="$1" per="$2"; shift 2
ui_term_size
local tl maxw
tl="$(printf '%s\n' "$text" | wc -l)"
maxw="$(printf '%s\n' "$text" | awk '{ if (length($0) > m) m = length($0) } END { print m+0 }')"
# breiteste Zeile der Liste (Kennung und Beschriftung stehen nebeneinander)
local -a args=("$@")
local i=0 w itemw=0 n=0
while [ "$i" -lt "${#args[@]}" ]; do
w=$(( ${#args[$i]} + 4 ))
if [ $((i+1)) -lt "${#args[@]}" ]; then
w=$(( w + ${#args[$((i+1))]} ))
fi
if [ "$w" -gt "$itemw" ]; then itemw="$w"; fi
i=$(( i + per )); n=$(( n + 1 ))
done
# Breite: der breitere von Text und Liste, plus Rahmen
if [ "$maxw" -gt "$itemw" ]; then UI_W=$(( maxw + 10 )); else UI_W=$(( itemw + 10 )); fi
if [ "$UI_W" -lt 60 ]; then UI_W=60; fi
if [ "$UI_W" -gt $(( UI_COLS - 4 )) ]; then UI_W=$(( UI_COLS - 4 )); fi
# Listenhoehe: moeglichst alle Eintraege zeigen, ohne aus dem Bild zu laufen
local avail=$(( UI_ROWS - tl - 9 ))
if [ "$avail" -lt 3 ]; then avail=3; fi
if [ "$n" -lt "$avail" ]; then UI_MH="$n"; else UI_MH="$avail"; fi
if [ "$UI_MH" -lt 1 ]; then UI_MH=1; fi
UI_H=$(( tl + UI_MH + 8 ))
if [ "$UI_H" -gt $(( UI_ROWS - 2 )) ]; then UI_H=$(( UI_ROWS - 2 )); fi
if [ "$UI_H" -lt 10 ]; then UI_H=10; fi
return 0
}
# Hoehe fuer Fenster ohne Liste (Meldung, Abfrage, Eingabe)
ui_calc_text() { # text zusatzzeilen
local text="$1" extra="${2:-7}"
ui_term_size
local tl maxw
tl="$(printf '%s\n' "$text" | wc -l)"
maxw="$(printf '%s\n' "$text" | awk '{ if (length($0) > m) m = length($0) } END { print m+0 }')"
UI_W=$(( maxw + 10 ))
if [ "$UI_W" -lt 60 ]; then UI_W=60; fi
if [ "$UI_W" -gt $(( UI_COLS - 4 )) ]; then UI_W=$(( UI_COLS - 4 )); fi
UI_H=$(( tl + extra ))
if [ "$UI_H" -gt $(( UI_ROWS - 2 )) ]; then UI_H=$(( UI_ROWS - 2 )); fi
if [ "$UI_H" -lt 8 ]; then UI_H=8; fi
return 0
}
ui_init() {
# Geometrie IMMER setzen - sonst laeuft das Skript unter "set -u" auf
# eine unbound variable, wenn UI_BIN von aussen vorgegeben wurde.
@@ -247,6 +320,7 @@ ui_require() {
ui_menu() { # title text tag item [tag item ...] -> gewaehlter tag auf stdout
ui_init
local title="$1" text="$2"; shift 2
ui_calc "$text" 2 "$@"
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$title" \
--menu "$text" "$UI_H" "$UI_W" "$UI_MH" "$@" 3>&1 1>&2 2>&3
}
@@ -254,6 +328,7 @@ ui_menu() { # title text tag item [tag item ...] -> gewaehlter tag auf stdout
ui_checklist() { # title text tag item status ...
ui_init
local title="$1" text="$2"; shift 2
ui_calc "$text" 3 "$@"
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$title" \
--checklist "$text" "$UI_H" "$UI_W" "$UI_MH" "$@" 3>&1 1>&2 2>&3
}
@@ -261,40 +336,48 @@ ui_checklist() { # title text tag item status ...
ui_radiolist() {
ui_init
local title="$1" text="$2"; shift 2
ui_calc "$text" 3 "$@"
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$title" \
--radiolist "$text" "$UI_H" "$UI_W" "$UI_MH" "$@" 3>&1 1>&2 2>&3
}
ui_input() { # title text default
ui_init
ui_calc_text "$2" 10
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" \
--inputbox "$2" 10 "$UI_W" "${3:-}" 3>&1 1>&2 2>&3
--inputbox "$2" "$UI_H" "$UI_W" "${3:-}" 3>&1 1>&2 2>&3
}
ui_password() {
ui_init
ui_calc_text "$2" 10
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" \
--passwordbox "$2" 10 "$UI_W" 3>&1 1>&2 2>&3
--passwordbox "$2" "$UI_H" "$UI_W" 3>&1 1>&2 2>&3
}
ui_msg() { # title text
ui_init
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --msgbox "$2" 16 "$UI_W"
ui_calc_text "$2" 7
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --msgbox "$2" "$UI_H" "$UI_W"
}
ui_yesno() { # title text -> exit 0 = ja
ui_init
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --yesno "$2" 14 "$UI_W"
ui_calc_text "$2" 8
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --yesno "$2" "$UI_H" "$UI_W"
}
ui_text() { # title file
ui_text() { # title file - so gross wie das Terminal es zulaesst
ui_init
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --textbox "$2" "$UI_H" "$UI_W"
ui_term_size
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --textbox "$2" \
$(( UI_ROWS - 2 )) $(( UI_COLS - 4 ))
}
ui_info() { # title text (ohne OK-Button)
ui_init
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --infobox "$2" 8 "$UI_W"
ui_calc_text "$2" 5
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --infobox "$2" "$UI_H" "$UI_W"
}
# Kommando ausfuehren, Ausgabe live in Datei, danach in Textbox anzeigen