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


14

В настоящее время я использую 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

0

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


0

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

export "PTTY=$(tty)"

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

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

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

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


0

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.