#!/bin/bash # Copyright (C) 2006 Andre Noll # Licensed under the LGPL, version 3. See COPYING and COPYING.LESSER. if [[ "$(type -t _gsu_setup)" != "function" ]]; then gsu_dir=${gsu_dir:-${BASH_SOURCE[0]%/*}} . $gsu_dir/common || exit 1 _gsu_setup fi _gsu_node_name_pattern='[a-zA-Z_]' _get_geometry() { local x y result="$(stty size)" if (($? != 0)); then gsu_msg "fatal: could not get terminal geometry" exit 1 fi x="${result#* }" y="${result%% *}" (($x > 190)) && x=190 result="$y $x" } _set_dialog_ret() { local ec="$1" case "$ec" in 0) ret=$GSU_SUCCESS;; 1) ret=1;; # cancelled *) result="dialog exit code $ec" ret=-$E_GSU_DIALOG esac } # Open a dialog box which asks the user to input a text # # Usage: gsu_input_box # # is displayed above of the input field, which is is preset to . # The entered text is returned in $result. On success (user pressed OK) # the function returns zero. If the user selected Cancel, the return value is # one. On dialog errors, a negative error code is returned. gsu_inputbox() { local g text="$1" init="$2" _get_geometry g="$result" result="$(dialog --inputbox "$text" $g "$init" 3>&1 1>&2 2>&3 3>&-)" _set_dialog_ret $? } # Show the given file in a text box # # Usage: gsu_textbox # # The box has an OK button which closes the box when activated. gsu_textbox() { local g file="$1" _get_geometry g="$result" ret=-$E_GSU_DIALOG result='textbox' dialog --textbox "$file" $g _set_dialog_ret $? } # Show a message in a text box # # Usage: gsu_msgbox # # This is like gsu_textbox() but the text is passed as a string. gsu_msgbox() { local tmp # Some versions of dialog segfault if the text is too long. Hence we # always use a temporary file. gsu_make_tempfile 'gsu_msgbox.XXXXXXXXXX' (($ret < 0)) && return tmp="$result" trap "rm -f $tmp" EXIT echo "$1" > "$tmp" gsu_textbox "$tmp" rm -f "$tmp" # ignore errors } _gsu_menu() { local header="${1:-root}" local items="$2" local i state opts num=0 _get_geometry opts="$result 16" for i in $items; do let num++ opts+=" $i $num" done result="$(dialog --menu "$gsu_banner_txt ($header)" $opts 3>&1 1>&2 2>&3 3>&-)" _set_dialog_ret $? } _get_level() { local tmp="${1%%$_gsu_node_name_pattern*}" result="${#tmp}" } _get_subtree() { local tree="$1" root="${2%/}" local first TAB=' ' ret=-$E_GSU_MENU_TREE result="subtree grep failed" first="$(grep -n "$TAB\{1,\}$root/" <<< "$tree")" || return [[ -z "$first" ]] && return line_num="${first%%:*}" _get_level "${first#*:}" level="$result" #echo "line: $line_num, root: $root, indent level: $level" result="$(sed -e "1,${line_num}d;" <<< "$tree" \ | sed -e "/^$TAB\{1,$level\}$_gsu_node_name_pattern/,\$d" \ | sed -e "/^$TAB\{$(($level + 2))\}/d")" if (($? != 0)); then ret=-$E_GSU_MENU_TREE result="sed command for subtree $root failed" return fi ret=$GSU_SUCCESS } _get_root_nodes() { local tree="$1" TAB=' ' result="$(grep "^${TAB}${_gsu_node_name_pattern}" <<< "$tree")" if (($? != 0)); then ret=-$E_GSU_MENU_TREE result="root node grep failed" return fi ret=$GSU_SUCCESS } _browse() { local header="$1" old_header local tree="$2" subtree="$3" while :; do _gsu_menu "$header" "$subtree" (($ret < 0)) && return [[ -z "$result" ]] && return # menu was cancelled if [[ "${result%/}" != "$result" ]]; then old_header="$header" header="$result" _get_subtree "$tree" "$header" (($ret < 0)) && return _browse "$header" "$tree" "$result" (($ret < 0)) && return header="$old_header" continue fi eval ${gsu_name}_$result done } gsu_gui() { local tree="$1" subtree type -t dialog &> /dev/null if (($? != 0)); then gsu_msg "dialog executable not found" exit 1 fi _get_root_nodes "$tree" subtree="$result" _browse "main menu" "$tree" "$subtree" }