Вопрос или проблема
У меня есть цикл while, который использует vared
для запроса ввода от пользователя. Я ищу способ установить время ожидания, выполнить значение по умолчанию и вернуться к запросу, если пользователь не вводит данные после определенного времени. Я знаю о команде read и ее аргументе timeout, но возможно ли это каким-либо образом с vared
?
Кроме того, есть ли способ установить значение по умолчанию для vared
, которое не будет выводиться на запрос?
local command
while :
do
echo "Введите команду или наберите 'quit' для выхода:"
vared -p "[*]: " command
if [ "$command" = "quit" ]; then
break
else
run command
fi
clear
done
Вы могли бы сделать что-то подобное:
default=foobar
if
command=$(
saved_settings=$(stty -g)
trap 'stty $saved_settings; exit 1' ALRM
v=
TMOUT=10 vared -p "Введите команду [$default]: " v &&
printf %s $v
)
then
command=${command:-$default}
printf 'Получено: "%s"\n' $command
else
print таймаут
fi
Вместо того чтобы инициализировать переменную значением по умолчанию, мы инициализируем ее пустой строкой и только устанавливаем значение по умолчанию, если переменная все еще пуста после того, как vared
вернет результат.
Чтобы обработать таймаут, мы используем специальную переменную $TMOUT
в дочерней оболочке, что приводит к выходу zle
из этой дочерней оболочки после $TMOUT
секунд.
Это глобальный таймаут в 10 секунд. Другой подход может заключаться в использовании дисциплины терминала для таймаута между символами (stty time x
, где x
выражается в десятых долях секунды), чтобы дать пользователю достаточно времени для ввода большой команды, но с таймаутом, скажем, после 3 секунд неактивности:
default=foobar
if
command=$(
saved_settings=$(stty -g)
trap 'stty $saved_settings' EXIT INT TERM ALRM
zle-line-init() stty -icanon time 30 min 0 <&2
zle -N zle-line-init
v=
vared -p "Введите команду [$default]: " v &&
printf %s $v
)
then
command=${command:-$default}
printf 'Получено: "%s"\n' $command
else
print
print таймаут
fi
Обратите внимание, что хотя эти решения работают в скриптах, в интерактивных оболочках это в настоящее время не работает, так как vared
отказывается работать в дочерних оболочках. Если вам нужно запустить это из интерактивной оболочки, пока это не будет исправлено в zsh
, вы можете изменить:
command=$(
...
)
На
command=$(default=$default zsh -c '
...
')
Ответ или решение
В Zsh, чтобы реализовать таймаут для команды vared
, вы можете использовать специальную переменную TMOUT
, которая устанавливает глобальный тайм-аут на ввод. Однако, так как vared
не может быть использован в подсчетах, вызванных подшеллами в интерактивном режиме, задача немного усложняется. Вот метод, который вы можете использовать, а также способы установить значение по умолчанию без его отображения в приглашении.
Реализация таймаута для vared
-
Использование переменной
TMOUT
:Вы можете установить переменную
TMOUT
, которая будет отвечать за время ожидания. Если пользователь не введет значение в течение указанного времени,vared
завершится, и вы сможете обработать это событие.
default=foobar
if command=$(
saved_settings=$(stty -g)
trap 'stty $saved_settings; exit 1' ALRM
v=
TMOUT=10 vared -p "Введите команду [$default]: " v && printf %s $v
)
then
command=${command:-$default}
printf 'Получено: "%s"\n' $command
else
print "Таймаут"
fi
В этом коде, если пользователь ничего не введет в течение 10 секунд, будет выведено сообщение о таймауте, а переменная command
будет установлена в значение $default
.
-
Настройка таймаута через терминал:
Также можно установить таймаут для ввода символов через терминал, чтобы обрабатывать бездействие пользователя.
default=foobar
if command=$(
saved_settings=$(stty -g)
trap 'stty $saved_settings' EXIT INT TERM ALRM
zle-line-init() stty -icanon time 30 min 0 >&2
zle -N zle-line-init
v=
vared -p "Введите команду [$default]: " v && printf %s $v
)
then
command=${command:-$default}
printf 'Получено: "%s"\n' $command
else
print "Таймаут"
fi
В данном примере, если пользователь не введет ничего в течение 3 секунд (или 30 десятых долей секунды), будет вызван таймаут.
Установка значения по умолчанию без отображения
Чтобы установить значение по умолчанию, не выводя его в приглашение, вы можете просто использовать переменную v
в vared
и затем обработать её после ввода:
default=foobar
v=
vared -p "Введите команду: " v
command=${v:-$default}
printf 'Получено: "%s"\n' "$command"
В этом примере, значение переменной v
будет использовано, если пользователь введёт что-то. Если пользователь оставит пустую строку, команда command
будет установлена на значение переменной $default
.
Заключение
Таким образом, вы можете реализовать таймаут для vared
, а также устанавливать значение по умолчанию без его отображения в приглашении. Будьте внимательны, что указанные методы могут работать не во всех интерактивных оболочках из-за ограничений, связанных с запуском vared
в подсчетах, но они должны выполняться корректно в большинстве сценариев.