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 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.