emacsの--no-waitと同等


8

emacsclientプログラムは、フラグができます--no-wait(と略す-nemacsのサーバーが指定されたファイルを訪問し、すぐに返すために発生します)。

emacsclient -n ~/.bashrc

代替エディターを提供した場合、Emacsサーバーが実行されていない場合でも機能します

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc

ただし、サーバーが実行されている場合は、この呼び出しがすぐに返されるため、これにより一貫性のない動作が発生します。サーバーが実行されておらず、代替エディターが使用されている場合、呼び出しはブロッキング呼び出しになり、Emacsを終了するまで戻りません。

emacs(とは対照的にemacsclient)新しいフレームを作成してから戻るように指示する方法はありますか?


1
Emacsを代替エディターとして提供することに抵抗がないようです。-a ''「Emacsデーモンを起動してemacsclientを再試行する」オプションを使用しないことを選択する理由はありますか?
purple_arrows 2014年

@purple_arrows私の経験では、使用-a ''するとサーバーの代わりにデーモンが起動します。次に、ターミナル Emacs を開こうとし-nますが、オプションを指定したため、開いたままにはなりません。シェルに跳ね返るだけです。
nispio 2014年

回答:


6

説明文

emacsclientを呼び出すときのデフォルトの動作は少し保守的です。emacsclient.cからこのコメントをチェックしてください :

  /* Unless we are certain we don't want to occupy the tty, send our
     tty information to Emacs.  For example, in daemon mode Emacs may
     need to occupy this tty if no other frame is available.  */

説明とコメントから、-nフラグを使用しながらオンデマンドでEmacsサーバーを起動しようとしているようです。ここの「例」のコメントは、emacsclient -n -a '' FILEサーバーが実行されていないときに探しているものを満たさない理由です。

  1. -a ''ロジックは、デーモンを起動します。
  2. 次にemacsclient、新しいターミナルフレームを作成するように指示します。これは、elispを評価していない限り、これがデフォルトであるためです。
  3. -nロジックは、すぐにその新しいターミナルフレームを殺します。

ステップ2を変更して、デフォルトで新しいグラフィックフレームを作成できる場合 emacsclient -n -a '' FILEは、必要な処理を実行します。

Elispソリューション

Emacsにデフォルトで新しいグラフィックフレームを作成させるには、次のように関数に通知しますserver-process-filter

(defadvice server-process-filter (before prefer-graphical activate)
  ;; STRING is a sequence of commands sent from emacsclient to the server.
  (when (and
         ;; Check that we're editing a file, as opposed to evaluating elisp.
         (string-match "-file" string)
         ;; Check that there are no frames beyond the Emacs daemon's terminal.
         (daemonp)
         (null (cdr (frame-list)))
         (eq (selected-frame) terminal-frame)
         ;; Check that we have a graphical display.
         ;; `display-graphic-p' doesn't work here.
         (getenv "DISPLAY"))
    (setq string (concat
                  ;; STRING must be all one line, but comes to us
                  ;; newline-terminated.  Strip off the trailing newline.
                  (replace-regexp-in-string "\n$" "" string)
                  ;; Add the commands to create a graphical frame.
                  "-window-system "
                  "-display " (getenv "DISPLAY")
                  ;; Add back the newline.
                  "\n"))))

それをあなたのinitファイルに入れてください、そして、言われたように、emacsclient -n -a '' FILEそしてボブはあなたの叔父です。

シェルソリューションと比較

一方で、私はArchenothによって提案されスクリプトを使用する場合と比較して、このdefadviceアプローチを使用することのいくつかの利点を指摘でき ます。

#!/bin/bash
emacs --eval '(server-start)' $* &

代替エディタとして。defadviceで:

  1. save-buffers-kill-terminalC-x C-cデフォルト)すべてのフレームにわたって一貫して動作します。すべてのフレームは常にクライアントフレームであるため、Emacsプロセスが強制終了されることはありません。
  2. デーモンのターミナルフレームがハングします。find-grepそのような外部プロセスへのシェルアウトのようなコマンドは、ダムターミナルが存在する場合により適切に動作します。少なくとも、シェルエスケープに関連する頭痛が少なくなります。

一方で...ええ。

  1. そのシェルスクリプトは美しくシンプルです。
  2. Emacsの通信プロトコルに助言することはできません。

結論

たぶん妥協があるのでしょうか?これは私が思いつくことができる最高のものです。$ EDITORとして設定します。

#!/bin/sh

emacsclient -e "(frames-on-display-list \"${DISPLAY}\")" 1>/dev/null 2>/dev/null
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n "$@"
fi

では、emacsが実行されていないときに関数にアドバイスするにはどうすればよいですか?
nispio 2014年

あなたはそれをinitファイルにドロップすることができるはずです。デーモンは、起動時にそのファイルを読み取り、emacsclientがコマンドの送信を開始する前に読み取りを終了します。少なくとも私はそうしています。
purple_arrows 2014年

4

Emacs内で厳密にそれを行う方法はわかりませんが、幸運にもあなたが説明するものを取得する他の方法があります。

.emacsサーバーを起動するものがない場合は、常に、編集したいファイルでEmacsを起動し、サーバーをフォークして起動する小さなスクリプトを作成できます。

何かのようなもの:

#!/bin/bash
emacs --eval '(server-start)' $* &

そして、それをに渡し-aます。


ただし...で
サーバーを起動している.emacs場合は、実際にスクリプトを作成する必要はありません。少し簡潔なオプションがあります:

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc &

アンパサンドは、プロセスをバックグラウンドで実行し、Emacsが初めて起動したときでも即座にシェルを返します。

disown終了時にbashがジョブを強制終了する場合は、プロセスが必要になる場合があります。その場合はdisown、末尾にa を追加するだけです。

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc & disown

Windowsでは、最も近いものは " start"コマンドです...

したがって、上記のスクリプトの提案のように、次のようなものを含むバッチファイルを作成する必要があります。

start /b C:\path\to\emacs %*

そして、それに-a議論を向けます。
これにより、バッチファイルが実行され、適切なファイルでEmacsを起動した直後に戻ります。


私はLinux(RHEL 6.5)を使用して&いて、最初に試したものです。残念ながら、次のテキストがに送信されますstderr終了までのプロセスを待っている端子台、その後::emacsclient: can't find socket; have you started the server? To start the server in Emacs, type "M-x server-start". 私は推測していますそのemacsclient背景にフォークが、それ呼び出すemacsフォアグラウンドで開かれます。
nispio 2014年

その場合、おそらく小さなスクリプトが最適なルートかもしれません。emacs --eval '(server-start)' $* &多分何か?そのようにサーバーが起動すると、ターミナルが取得され、emacsclient接続できるサーバーができます。
Archenoth 2014年

私はそれをテストし、私の答えに追加しました...それについて申し訳ありません!emacs通常の方法でサーバーを起動するためのメカニズムがあると思っていました。ほとんどの人はおそらくその構成を持たないだろうから、それが答えの最初の部分です。それが役に立てば幸い..!
Archenoth 2014年

@nispioは、最後に&が付くように代替エディターパラメーターを設定します。
Malabarba 2014年

2
@Malabarbaコマンドライン引数またはシェルディレクティブを代替エディターに渡すことはできません。そのため、小さなスクリプトを提案しました。
Archenoth 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.