Отключить звуковой сигнал терминала, кроме случаев вызова вручную.

Вопрос или проблема

Терминальный сигнал звучит в нескольких сценариях. Чтобы назвать несколько:

  1. когда вы пытаетесь удалить, находясь в начале строки запроса
  2. когда вы пытаетесь дополнить с помощью табуляции без доступных опций
  3. в vim, когда вы пытаетесь переместить курсор, когда это невозможно (например, переместиться вниз, находясь на последней строке)

И есть множество других. Что я хочу сделать, это чтобы сигнал звучал только тогда, когда я намеренно заставляю его звучать, например, с помощью echo -e "\a".

Я добавил set bell-style none в мой .inputrc, но он все еще звучит в vim, и если я запускаю tmux, я получаю первые 2 сигнала, упомянутых выше. Возможно ли указать bash никогда не издавать сигнал, если я специально не укажу это?

Анализ

echo -e "\a" выводит символ BEL, 0x07 в кодировке ASCII (и перевод строки, который нас не касается). Ваш терминал (эмулятор терминала), когда получает этот конкретный символ, вместо того чтобы показывать вам какой-то глиф (например, показывает a, получая 0x61), вызывает слышимую, видимую или какую-то иную нотификацию.

Путь может быть длиннее, например:

  1. Ваше echo -e "\a" запускается в оболочке внутри панели tmux. Эмулятор терминала – это ваш сервер tmux. Он может реагировать на символ BEL каким-то образом и/или передавать его дальше.

  2. Если сервер tmux передает символ дальше, то символ дойдет до вашего клиента tmux, который просто выведет его, как если бы команда была echo -ne "\a".

  3. Терминал, под которым запускается клиент tmux, может реагировать на символ BEL. Виртуальная консоль может вызвать звуковой сигнал. Эмулятор терминала может воспроизвести звук, мигнуть окном или попросить рабочий стол показать всплывающее уведомление.

Самое важное, ни сервер tmux, ни клиент tmux, ни эмулятор терминала, ни окружение рабочего стола не могут знать, откуда пришел этот символ BEL: от echo, Bash или Vim или еще чего-то.

Существует концепция группы процессов на переднем плане. В указанном выше сценарии эмулятор терминала знает, что процесс на переднем плане – это клиент tmux. Аналогично, сервер tmux информирован (интерактивным Bash в панели), какой процесс сейчас на переднем плане. Сервер tmux находится в относительно хорошем положении для того, что вы хотите сделать, он мог бы сделать обоснованное предположение, что BEL пришел от лидера группы процессов, но:

  • Может быть больше процессов в группе процессов на переднем плане, и каждый из них мог сгенерировать BEL.
  • Когда сервер tmux начинает анализировать ситуацию, процесс, который генерировал BEL, может уже завершиться, группа процессов на переднем плане может измениться. Другими словами, может быть слишком поздно для какого-либо обоснованного предположения.
  • BEL мог быть сгенерирован процессом в фоновом режиме.
  • BEL мог быть сгенерирован процессом, запущенным в другой панели или где-либо еще.
  • Если “процесс” – это echo -e "\a", запущенный в интерактивном Bash, то это на самом деле встроенная функция оболочки, и процесс, который генерирует BEL, – это Bash; тот же Bash, который генерирует BEL, когда вы пытаетесь удалить, находясь в начале строки запроса. Так что даже если сервер tmux мог бы однозначно определить, какой процесс сгенерировал BEL, этого было бы недостаточно, чтобы отличать то, что вы хотите отличать.

Прямой ответ на явный вопрос

Возможно ли указать bash никогда не издавать сигнал, если я специально не укажу это?

Да, это set bell-style none для Readline, используемого Bash, вы уже это обнаружили. Некоторые сигналы, которые вы хотите блокировать, не имеют отношения к Bash. Помните, оболочка не действует как реле между программами и терминалом. Если программа выводит символ BEL на tty, то это просто так: программа выводит на tty напрямую, настройка оболочки на это не влияет.


Возможные решения фактической проблемы

(Следующий список не является исчерпывающим.)

  • Настроить каждую программу (например, Vim) или библиотеку (например, Readline) отдельно. Для некоторых программ это может быть невозможно.

  • Прервать путь, который проходит BEL. Затем, когда вы хотите намеренно заставить его звучать, используйте “обходной путь” и обойдите нарушение. Например, если вы настроите ваш эмулятор терминала игнорировать BEL полностью, обходным путем будет вручную выполнить то, что эмулятор терминала сделал бы: воспроизвести звук или вызвать уведомление. Другой пример приведен ниже.


Пример

Этот пример для tmux. Выполните команды в оболочке внутри панели tmux.

Чтобы прервать BEL на сервере tmux:

tmux set monitor-bell off

Чтобы взять обходной путь и напечатать символ BEL на tty клиента tmux:

printf '\a' > "$(tmux display-message -p '#{client_tty}')"

.

Ответ или решение

Отключение звукового сигнала терминала, за исключением случаев, когда вы намеренно вызываете его, является достаточно распространенной задачей среди пользователей, работающих в командной строке. Звуковой сигнал терминала, также известный как "bell", может вызываться в различных ситуациях, как было упомянуто в описании проблемы. Этот сигнал может быть раздражающим и ненужным в большинстве случаев, когда вы не хотите его слышать.

Теория

Терминальный "bell" представляет собой символ ASCII с кодом 0x07, известный как BEL. Когда этот символ отправляется в терминал, это приводит к звуковому, визуальному или иному уведомлению. Проблема заключается в том, что терминал, будь то эмулятор терминала или физическая консоль, не может различать, откуда пришел этот BEL — это может быть команда echo -e "\a" или операции Bash/Vim, или любое другое приложение.

Основные сценарии возникновения "bell":

  1. Попытка удалить символ в начале строки в Bash.
  2. Попытка выполнить автодополнение с помощью клавиши Tab при отсутствии доступных опций.
  3. В редакторе Vim при попытке переместить курсор за пределы доступного диапазона.

Чтобы минимизировать количество ненужных сигналов, мы можем настроить каждую программу или библиотеку, генерирующую сигнал, на подавление этого действия. Однако это может быть не всегда возможно, так как некоторые программы не поддерживают отключение "bell".

Пример

Рассмотрим более детально, как можно управлять звуковыми сигналами в tmux. Tmux — это мультиплексор терминала, который может сам по себе генерировать "bell", если этот сигнал не был отключен.

Отключение сигналов в tmux:

tmux set monitor-bell off

Генерация звукового сигнала вручную:

Чтобы вручную вызвать "bell", когда он отключен в tmux:

printf '\a' > "$(tmux display-message -p '#{client_tty}')"

В этом примере мы находим tty-клиента tmux и отправляем на него символ BEL.

Применение

Bash

Для Bash можно использовать настройку в .inputrc таким образом:

set bell-style none

Это правило отключает звуковой сигнал в readline, библиотеке, которая используется в Bash для обработки ввода пользователя. Однако этот способ работает не для всех программ, так как они могут генерировать \a независимо от Bash.

Vim

Для Vim уберите звуковые сигналы с помощью следующей настройки в файле ~/.vimrc:

set noerrorbells visualbell t_vb=

Эта настройка отключает как звуковые, так и визуальные сигналы в Vim, оставляя возможность имитировать их через визуальные эффекты.

Общий подход

Как универсальное решение, настройте ваш эмулятор терминала для игнорирования звуковых сигналов. Например, в таких эмуляторах, как GNOME Terminal, можно отключить звуки через настройки профиля. В некоторых случаях можно также использовать утилиту xset для отключения системных сигналов:

xset b off

Имейте в виду, что этот метод отключит все звуковые уведомления терминала на уровне X11.

Заключение

Полное подавление звукового сигнала может потребовать многослойного подхода, учитывающего настройки и возможностей каждой отдельной программы и среды. В том случае, когда требуется вызывать "bell" намеренно, всегда предусмотрите способ его ручного вызова, как было показано в примере с printf. Такой подход позволяет максимально контролировать звуковые уведомления в среде терминала, не затрагивая функциональность нужных вам процессов.

Оцените материал
Добавить комментарий

Капча загружается...