ncurses 애플리케이션에서 호출되는 스크립트 출력의 이스케이프 시퀀스

ncurses 애플리케이션에서 호출되는 스크립트 출력의 이스케이프 시퀀스

저는 현재 홈 서버의 tmux 세션에서 Jabber 클라이언트(ncurses 사용)로 mcabber를 실행하고 있습니다. 로컬에서는 문자 이스케이프 시퀀스를 통해 으르렁거리는 알림 트리거를 지원하는 터미널 에뮬레이터로 iTerm2를 실행하고 있습니다.

참고: 이 질문의 모든 내용은 bash 및 GNU와 echo유사합니다 .printf %becho -eecho

예를 들어, echo "\e]9;foobar\007"iTerm2가 "foobar"라는 텍스트가 포함된 Growl 메시지를 보내도록 합니다.

그러나 tmux 세션 내에서는 이스케이프 시퀀스가 ​​소진됩니다. 따라서 \Ptmux독점 문자 이스케이프 시퀀스는 다음과 같이 사용할 수 있습니다.

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

그러면 tmux 세션에서 하울링 메시지가 트리거됩니다.

그러나 새 메시지가 수신될 때 실행되는 mcabber 이벤트 스크립트에서 이것을 사용하면 마치 에코가 잘못된 터미널로 전송되는 것처럼 알림이 실행되지 않습니다.

나는 이것이 ncurses 응용 프로그램인 스크립트를 트리거하는 mcabber와 관련이 있다고 생각하므로 일반 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 프로그램은 이스케이프 시퀀스를 직접 전달하지 않습니다. 그들은 애플리케이션에 터미널(스크린 터미널 유형)을 제공하며 그 자체가 다른 터미널에 대한 ncurses 애플리케이션입니다. 실제로는 터미널 번역기와 약간 비슷합니다. 그렇습니다. 일련의 "스크린" 터미널 유형을 소비(또는 폐기)하고 보시다시피 버퍼를 구축합니다. 그런 다음 이러한 버퍼 변경 이벤트를 가져오고 현재 사용 중인 터미널 유형을 사용하여 현재 버퍼를 표시합니다. 따라서 원래 앱과 시청 측이 분리됩니다.

답변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를 사용해야 한다는 것입니다.

관련 정보