LINUX.ORG.RU

Многоуровневое меню на Bash

 , ,


0

1

Программа для просмотра изображений sxiv использует скрипт для выполнения операций над изображениями.

Пытаюсь таким образом реализовать многоуровневое меню. Но получается, что работает только первый уровень — выполняются команды 1, 2, 3, а то, что в «submenu» уже не работает

Вопрос.

В оператор «case» обычно завёрнуто либо одно условие, либо список условий, из которых выбирается подходящее.

case $переменная in
	"$условие" или "$условие" или "$условие" )
		команда...
		;;
	"$условие" )
		команда...
		;;
esac

Возможно ли перечислять условия последовательно?

Т. е. в качестве условий могут быть горячие клавиши и нужно, чтобы команда была выполнена лишь при последовательном нажатии определённых клавиш, на манер Вим’а.

Был бы рад обнаружить возможность работать с этим оператором таким образом, но не нашёл ничего похожего, потому путь реализации вижу в использовании вложенных «кейсов».

Задумка такая:

#!/bin/sh

n_cmd() {
    notify-send "Message"
}

submenu() {
    case $1 in
	a ) n_cmd
	    ;;
	b ) n_cmd
	    ;;
	c ) n_cmd
	    ;;
    esac
}

case $1 in
	1 ) n_cmd
	    ;;
	2 ) submenu
	    ;;
	3 ) n_cmd
	    ;;
esac

Да только не работает. В чём проблема и как правильно реализовать?

Используй ключи командной строки, это ж баш)

А тебе надо чтоб пользователь сразу ввёл всю команду или последовательно по уровням попадая в подменю и видя подсказку по уровню нажимал следующую?

pihter ★★★★★
()

Это оно?

If the ‘;;’ operator is used, no subsequent matches are attempted after the first pattern match. Using ‘;&’ in place of ‘;;’ causes execution to continue with the command-list associated with the next clause, if any. Using ‘;;&’ in place of ‘;;’ causes the shell to test the patterns in the next clause, if any, and execute any associated command-list on a successful match, continuing the case statement execution as if the pattern list had not matched.
sudoapter ★
()

Что конкретно не работает?

Внутри submenu проверяешь позиционный параметр, но ты не передаешь этой функции параметров.

1 )

Пробела не должно быть.

andytux ★★★★★
()
Ответ на: комментарий от sudoapter

Выглядит как то, что нужно, но заставить это работать у меня не получается. Есть примеры удачных реализаций? Я даже примеров кода не смог найти, где бы эти конструкции применялись

Dreamdrawer ★
() автор топика
Ответ на: комментарий от pihter

Да, последовательно, по уровням, каждый из которых может ветвиться — перебрасывая на другой уровень или быть командой

Dreamdrawer ★
() автор топика

sxiv передаёт в скрипт только одно сочетание после Ctrl-X. Это надо сохранять состояние между запусками скрипта, чтобы такое работало.

xaizek ★★★★★
()
Ответ на: комментарий от andytux

Я не уверен, что приведённый мною синтаксис корректен.

Не работает любой следующий уровень, кроме первого.

Если убрать круглые скобки у переменных — submenu() — то начинает работать во всех уровнях, но уровни перестают быть уровнями, исчезает последовательность.

Dreamdrawer ★
() автор топика
Ответ на: комментарий от Dreamdrawer

Начать с терминологии.

убрать круглые скобки у переменных — submenu()

submenu - это не переменная, а функция. Без скобок - это нарушение синтаксиса.

andytux ★★★★★
()
Ответ на: комментарий от Dreamdrawer

Я не вижу в коммитах ничего подобного.

xaizek ★★★★★
()
Ответ на: комментарий от Dreamdrawer

KISS: не юзай ты эти кейсы, нам даны условия! держи:

max@max-book:~/tmp/lor_help$ ./lor.sh 
ты за линукс(l) или за винду(w)?
l
отлично! за rpm(r) или deb(d)?
r
мы многим обязаны редхату -- уважуха
max@max-book:~/tmp/lor_help$ ./lor.sh 
ты за линукс(l) или за винду(w)?
l
отлично! за rpm(r) или deb(d)?
d
debian -- крупнейший дистрибудив линукс, мы его любим -- уважуха
max@max-book:~/tmp/lor_help$ ./lor.sh                                                                                                                  
ты за линукс(l) или за винду(w)?                                                                                                                       
w                                                                                                                                                      
за икспуху(x) или других(a)?                                                                                                                           
x                                                                                                                                                      
икспуха еще ниче была...                                                                                                                               
max@max-book:~/tmp/lor_help$ ./lor.sh                                                                                                                  
ты за линукс(l) или за винду(w)?                                                                                                                       
w                                                                                                                                                      
за икспуху(x) или других(a)?
a
остальные я не смотрел толком -- промолчу
max@max-book:~/tmp/lor_help$ ./lor.sh 
ты за линукс(l) или за винду(w)?
q
max@max-book:~/tmp/lor_help$ cat lor.sh 
#!/bin/sh

echo "ты за линукс(l) или за винду(w)?"

read OS

if [ "$OS" = "l" ]; then
  echo "отлично! за rpm(r) или deb(d)?"
  read TYPE
  
  if [ "$TYPE" = "r" ]; then
    echo "мы многим обязаны редхату -- уважуха"
    exit 0
  fi
  if [ "$TYPE" = "d" ]; then
    echo "debian -- крупнейший дистрибудив линукс, мы его любим -- уважуха"
    exit 0
  fi

  # пользователь дурак -- все пропало!
  exit 1
fi

if [ "$OS" = "w" ]; then
  echo "за икспуху(x) или других(a)?"
  read TYPE
  
  if [ "$TYPE" = "x" ]; then
    echo "икспуха еще ниче была..."
    exit 0
  fi
  if [ "$TYPE" = "a" ]; then
    echo "остальные я не смотрел толком -- промолчу"
    exit 0
  fi

  # пользователь дурак -- все пропало!
  exit 1
fi

# пользователь дурак -- все пропало!
exit 1

pihter ★★★★★
()
#!/bin/bash
#set -x

pause_func () {

while :; do
   read -n 1
   [[ $? = 0 ]] && break
done

}


clear

task1-5 () {

clear
while :; do

cat << 'MENUITEM'

    1. alb
       
    2. bla
    
       
    b.  Back to Main Menu

MENUITEM
echo -n "Enter: "
read -n 1 NUMBER

  case $NUMBER in

    1) echo; cut -d: -f1,3 /etc/group | tee file | more
    ;;
    2) echo; find . -type f -name "*.sh"
    pause_func
    ;;
   b) main_menu
  ;;
  esac

done

}

task6-10 () {

clear
while :; do

cat << 'MENUITEM'

    6. blabla
       
    7. blabla
    
    b.  Back to Main Menu

MENUITEM
echo -n "Enter: "
read -n 1 NUMBER

  case $NUMBER in

    6) echo; comm -12 <(ls -1 dir1) <(ls -1 dir2) | sort
    pause_func
    ;;
    7) echo; find -L . -samefile fileee
    pause_func
    ;;
    q) echo; exit 0
    pause_func
  ;;
   b) main_menu
  ;;
  esac

done

}

main_menu () {
clear
while :; do
    cat << MENUITEM
  1) task1-5
  2) task6-10
  q) Quit
MENUITEM
echo -n "Enter: "
read -n 1 NUMBER
  case $NUMBER in
    1) task1-5
    ;;
    2) task6-10
    ;;
    q) echo; exit 0
    ;;
    *) echo; echo "Please select 1, 2 ... or q for quit"
    ;;
  esac
done
}

main_menu 

nerve ★★
()
Ответ на: комментарий от nerve

Выглядит просто шикарно! Обязательно заиспользую в скриптах.

К сожалению, по всей видимости, товарищ @xaizek был прав, и sxiv передаёт в скрипт только одно сочетание, поскольку не работает, вообще никак не реагирует. Просто в консоли отлично работает

Dreamdrawer ★
() автор топика
Ответ на: комментарий от Dreamdrawer

Следующая мысль логически ведёт к реализации на уровне хардкода. Порывшись на гитхабе в конфигах пользователей sxiv, встретилась инструкция «it_shell_cmd», которую вешают на клавишу (в sxiv/config.h):

{ 0,    XK_e,    it_shell_cmd,    (arg_t) "exec путь-к-скрипту-со-списком-команд" },

Но при компиляции, говорит, что такая функция незадекларирована.

Может есть возможность в рамках хардкода сделать вызов внешнего скрипта со списком команд?

Dreamdrawer ★
() автор топика
Ответ на: комментарий от Dreamdrawer

Или… может, сделать вызов dmenu, которое выведет список команд, но можно ли привязать команды из этого списка к горячим клавишам?

Dreamdrawer ★
() автор топика
Ответ на: комментарий от Dreamdrawer

встретилась инструкция «it_shell_cmd»

Это из старых версий. g_prefix_external её и заменила, вроде. Можно найти и скопировать её код.

xaizek ★★★★★
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.