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

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

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

참고: echo이 질문의 모든 내용은 printf %b, 또는 echo -ebash 및 GNU 에서 작동합니다 echo.

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

그러나 tmux 세션에서는 이스케이프 시퀀스가 ​​소모됩니다. 따라서 독점 문자 이스케이프 시퀀스를 사용하면 \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 프로그램은 이스케이프 시퀀스를 직접 통과하지 않습니다. 그들은 애플리케이션에 한 종류의 터미널을 제공하고(스크린 터미널 유형) 그 자체가 다른 터미널에 대한 ncurses 앱입니다. 실제로 그것은 터미널 번역기와 비슷합니다. 그렇습니다. "스크린" 터미널 유형에 대한 시퀀스를 소비(또는 삭제)하고 사용자가 볼 수 있는 버퍼를 설정합니다. 그런 다음 해당 버퍼 변경 이벤트를 사용하고 현재 버퍼를 표시하기 위해 현재 사용 중인 터미널의 종류를 사용합니다. 따라서 원본 앱과 보기 터미널이 분리됩니다.

답변3

다음과 같은 것을 넣었다면...

export "PTTY=$(tty)"

... 당신이 호출할 /etc/profile모든 새로운 -l로그인 셸 에 대해 then에서(일반적으로 새 터미널 창을 열 때 발생하는 현상입니다)tmux해당 환경 변수는 모든 하위 프로세스( 및 모든 하위 프로세스를 포함해야 함)에서 사용할 수 있게 됩니다 .

이렇게 하면 다음 작업을 수행할 수 있습니다.

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

...따라서 pty현재 셸과 사용 중인 터미널 에뮬레이터 사이에 존재할 수 있는 모든 레이어를 바로 건너뛸 수 있습니다.

답변4

bash 스크립트의 출력이 손실되는 것이 문제인 경우 리디렉션을 사용하여 전투에서 승리할 수 있습니다.

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

echo -e그러나 실제 문제는 bash가 문자열의 이스케이프 시퀀스를 처리하도록 사용해야 한다는 것입니다 .

관련 정보