ncursesアプリケーションから呼び出されるスクリプトの出力のエスケープシーケンス


14

現在、ホームサーバーの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

イベントスクリプトが「グローラー」メッセージの送信に失敗する理由は、イベントコマンドを実行するときに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プログラムは、エスケープシーケンスを直接通過しません。これらは、アプリケーションに1種類の端末(画面端末タイプ)を提示し、それ自体が別の端末に対するncursesアプリです。実際には、それは端末翻訳者のようなものです。そのため、「スクリーン」端末タイプのシーケンスを消費(または破棄)し、表示されるバッファーを設定します。次に、これらのバッファー変更イベントを取得し、現在使用しているあらゆる種類の端末を使用して現在のバッファーを表示します。したがって、元のアプリと表示端末は分離されています。


0

次のようなものを配置する場合...

export "PTTY=$(tty)"

...そのとき、呼び出す/etc/profileすべての新しい-loginシェル(新しいターミナルウィンドウを開いたときに一般的に発生することです)に対して、その環境変数はそのすべての子プロセスで使用可能になります。tmuxとそのすべての子。

これにより、次のことが可能になります...

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

...それによりpty、現在のシェルと使用しているターミナルエミュレータの間に存在する可能性のあるレイヤーをすべてスキップします。


0

bashスクリプトからの出力が失われているという問題がある場合は、リダイレクトで戦いに勝つことができます。

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

ただし、実際の問題はecho -e、bashが文字列内のエスケープシーケンスを処理するように使用する必要があるということです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.