Escape-последовательности в выводе скрипта, вызванного из приложения ncurses

Escape-последовательности в выводе скрипта, вызванного из приложения ncurses

В настоящее время я запускаю mcabber как свой Jabber-клиент (который использует ncurses) в сеансе tmux на моем домашнем сервере. Локально я запускаю iTerm2 как эмулятор терминала, который поддерживает запуск уведомлений рычания через escape-последовательности символов.

Примечание: Все echoв этом вопросе работает как printf %b, или echo -eв bash и GNU echo.

например, echo "\e]9;foobar\007"заставляет iTerm2 отправлять сообщение Growl с текстом «foobar».

Однако в сеансе tmux escape-последовательности съедаются. Поэтому использование фирменной escape-последовательности символов \Ptmuxможет быть использовано следующим образом:

echo "\ePtmux;\e\e]9;foobar\007\e\\"

Это вызывает рычащее сообщение из сеанса tmux.

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

Полагаю, это связано с тем, что mcabber, который запускает скрипт, является приложением ncurses, поэтому вывод моего обычного скрипта bash теряется, и iTerm 2 никогда его не видит.

Я также пытался вызвать smcup, но безуспешно, прежде чем повторить некоторые идеи, которые я обнаружил

tput smcup
echo "\ePtmux;\e\e]9;$FROM: $MSG\007\e\\"
tput rmcup

Полагаю, это не сработает, поскольку проблема не в переключении обратно в «реальное окно терминала», а в направлении вывода в окно ncurses.

Есть идеи по этому поводу?

решение1

Причина, по которой сценарий события не может отправить сообщение «Growler», заключается в следующем:mcabberзакрывает стандартный ввод,выходи потоки ошибок, когда он запускает команду события. Вы можете увидеть это вhooks.c:

  if ((pid=fork()) == -1) {
    scr_LogPrint(LPRINT_LOGNORM, "Fork error, cannot launch external command.");
    g_free(datafname);
    return;   
  }    
  if (pid == 0) { // child
    // Close standard file descriptors
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    if (execl(extcmd, extcmd, arg_type, arg_info, bjid, arg_data,
              (char *)NULL) == -1) {
      // scr_LogPrint(LPRINT_LOGNORM, "Cannot execute external command.");
      exit(1);
    }
  }
  g_free(datafname);

Это позволяет скрипту события работать, не мешая потокам, используемымmcabber.

Специального режима ncurses, перехватывающего сообщение, не существует (в конце концов tmux,ужезапущенный как приложение terminfo). Вероятно, вы можете обойти эту проблему, перенаправив свой echo(предпочтительно printf) на /dev/tty, например,

#!/bin/sh
printf '\033Ptmux;\033\033]9;foobar\007\033\\' >/dev/tty

решение2

Программы tmux и screen напрямую не проходят через escape-последовательности. Они представляют один тип терминала приложению (тип терминала screen) и сами являются приложением ncurses для другого терминала. По сути, это что-то вроде транслятора терминала. Так что да, он потребляет (или отбрасывает) последовательности для типа терминала «screen» и выставляет буфер, который вы видите. Затем он берет эти события изменения буфера и использует любой тип терминала, который вы используете в данный момент, для отображения текущего буфера. Таким образом, исходное приложение и терминал просмотра разделены.

решение3

Если бы вы написали что-то вроде...

export "PTTY=$(tty)"

...в вашем /etc/profileтогда для каждой новой -lоболочки ogin, которую вы вызовете(что обычно и происходит, когда вы открываете новое окно терминала)эта переменная среды будет доступна всем ее дочерним процессам, в том числе tmuxи всем ее дочерним процессам.

Это должно позволить вам сделать...

printf '\033]9;foobar\007' >"$PTTY"

...и тем самым пропустить все ptyслои, которые могут существовать между вашей текущей оболочкой и используемым вами эмулятором терминала.

решение4

Если проблема заключается в том, что выходные данные вашего bash-скрипта теряются, то вы можете выиграть битву с помощью перенаправления:

echo "\ePtmux;\e\e]9;foobar\007\e\" > /dev/tty

Однако я подозреваю, что настоящая проблема заключается в том, что вам следует использовать echo -eкоманду , чтобы bash обрабатывал escape-последовательности в вашей строке.

Связанный контент