ncurses 애플리케이션에서 호출 된 스크립트 출력의 이스케이프 시퀀스 printf %b, 또는 echo

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

참고 : 모든 echo이 질문은 같은 작품에서 printf %b, 또는 echo -e배쉬와 GNU에 echo.

예를 들어 echo "\e]9;foobar\007"iTerm2가 텍스트 “foobar”와 함께 Growl 메시지를 보내도록합니다.

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

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

이는 tmux 세션 내에서 으르렁 메시지를 트리거합니다.

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

나는 이것이 스크립트를 트리거하는 mcabber와 관련이 있다고 가정하여 정상적인 bash 스크립트의 출력이 손실되고 iTerm 2는 그것을 보지 못합니다.

나는 또한 내가 발견 한 아이디어에 반향하기 전에 성공하지 않고 smcup를 호출하려고 시도했다.

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

문제가 “실제 터미널 창”으로 다시 전환되지 않고 ncurses 창에서 출력을 더 지시하기 때문에 이것이 작동하지 않는다고 생각합니다.

이것에 대한 아이디어가 있습니까?



답변

이벤트 스크립트가 “grower”메시지를 보내지 못하는 이유 는 이벤트 명령을 실행할 때 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


답변

tmux 및 스크린 프로그램은 이스케이프 시퀀스를 직접 통과하지 않습니다. 그들은 한 종류의 터미널을 응용 프로그램에 제공하고 (스크린 터미널 유형), 그 자체가 다른 터미널에 대한 ncurses 앱입니다. 실제로 그것은 터미널 번역기와 같은 것입니다. 따라서 “스크린”터미널 유형에 대한 시퀀스를 소비 (또는 버림)하고 표시되는 버퍼를 배치합니다. 그런 다음 버퍼 변경 이벤트를 가져와 현재 사용중인 모든 종류의 터미널을 사용하여 현재 버퍼를 표시합니다. 따라서 원래 앱과보기 터미널이 분리되었습니다.


답변

당신이 뭔가를 넣어야한다면 …

export "PTTY=$(tty)"

…에 /etc/profile다음 모든 새에 대한 -login의 당신이 호출 할 쉘 (새 터미널 창을 열 때 일반적으로 발생하는 인) 환경 변수가 자식 프로세스 모두에 사용할 것이라고 – 포함해야하는 tmux및 모든 하위 .

이것은 당신이 할 수 있어야합니다 …

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

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


답변

문제가 bash 스크립트의 출력이 손실되는 경우 리디렉션을 통해 전투에서 이길 수 있습니다.

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

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


답변