emacs内からemacsを再起動します


44

emacsを何度も再起動します。私がやりたいのは、代わりに新しいものを生成するためだけに、現在のemacsを殺す関数を作成することです。理想的には、これはTTYでも機能します。


8
好奇心から、なぜ頻繁に殺してすぐに再起動するのですか?
ダン

2
私は非常に積極的に開発.emacs.dしています。つまり、emacsを再起動して、自分の環境に吹き飛ばしたゴミをすべて削除します。これを行うユースケースは他にもいくつかありますが、それが最大です。
PythonNut 14

1
@PythonNut、質問を少し再構成する必要があると思います。bash終了後に再起動するように指示できますか?またはvi?または、他のプロセス、原則として?いいえ、それは懸念の範囲外であり、外部で適切に処理されるためです。いずれにせよ、本当に必要なのは、VMをクリアして初期化コードを(プロセス強制終了することなく)再実行することにより、emacs を再初期化する方法です。これはemacsにとって有用で適切です。存在するかどうかはわかりませんが、:)
harpo 14

4
@harpoはい、bash再起動できますexec bash。私はvimについて全く知りません。
PythonNut 14

11
FWIW、終了して再起動するのではなく、設定変更をテストするために、Emacsの新しいインスタンスを開始する傾向があります。どうして?コードにエラーがある場合、Emacsは再起動時に設定をロードできない可能性があり、その時点では通常の設定で実行中のインスタンスを実際に取得できないため、あまり馴染みのない編集を使用する必要がありますバグを修正する環境。頻繁に起こることはありませんが、そうなると迷惑です。emacs -qもちろん、問題を実行して修正することはできますが、安全のために、構成をハッキングするときは常に「良い」インスタンスを実行し続けることを好みます。
-phils

回答:


25

注:ここでrestart-emacs入手可能なパッケージに以下をラップしました。


以下は、純粋なelispを使用して目的を達成する別の方法です(実際にはシェルに依存しているためではありません)。秘Theは、現在のemacsが殺される直前に別のemacsプロセスを生成することです。

(defun launch-separate-emacs-in-terminal ()
  (suspend-emacs "fg ; emacs -nw"))

(defun launch-separate-emacs-under-x ()
  (call-process "sh" nil nil nil "-c" "emacs &"))

(defun restart-emacs ()
  (interactive)
  ;; We need the new emacs to be spawned after all kill-emacs-hooks
  ;; have been processed and there is nothing interesting left
  (let ((kill-emacs-hook (append kill-emacs-hook (list (if (display-graphic-p)
                                                           #'launch-separate-emacs-under-x
                                                         #'launch-separate-emacs-in-terminal)))))
    (save-buffers-kill-emacs)))

emacsのGUIバージョンを開始するコードは簡単です。端末でemacsを起動するコードは少し注意が必要です。suspend-emacs親プロセス(シェル)への端末入力として渡される文字列を渡すことができるという事実を使用します。ドキュメントから

(suspend-emacsおよびオプションのSTUFFSTRING)

Emacsを停止し、上位プロセスに戻ります。後で再開できます。「cannot-suspend」が非nilの場合、またはシステムがジョブ制御をサポートしていない場合は、代わりにサブシェルを実行します。

オプションの引数STUFFSTRINGが非nilの場合、その文字は一時停止後にEmacsの親によって端末入力として読み込まれるように詰められます。

そのため、基本的には、Emacsが強制終了される直前に一時停止し、現在一時停止中のemacs(すぐに終了する)を親シェルに伝えてから、別のemacsプロセスを起動します。これは、ターミナルemacsが実際にサスペンドできないがサブシェルを開始できるプラットフォーム(Windowsなど)では機能しないことに注意してください。


これは私には機能しません。sh -c "emacs &"シェルから実行すると、「emacs: standard input is not a tty」で停止します。(このM-x restart-emacsエラーメッセージが表示されない場合、Emacsは終了します。)
コンスタンティン14

Xの下で私のために動作します。stdinとstdoutを/ dev / nullにリダイレクトするため、ターミナルでは動作しません。親ttyをサブプロセスに渡すことはおそらく実行可能ですが、より複雑です。
ベニチェルニアフスキーパスキン14

1
これは完全に機能し、実際には少し怖いです。いったいなぜEmacsはコマンドを含むシェルにコマンドを渡すことができますか?
ラドンロズバラ16

そのためにどのキーバインディングを使用しますか?
slk500

32

私の知る限り、終了後にEmacsに再起動するように指示することはできませんが、最初にEmacsを起動したプロセスが再起動することを検出できるように終了コードを設定できます。

たとえば、このシェルスクリプトは、コード123で終了した場合、Emacsを再起動します。

#!/bin/sh
while emacs -nw "$@"; [ $? = 123 ]; do :; done

次に、kill-emacs-and-restartスクリプトによって認識されるマジックナンバーに等しい終了コードでEmacsを終了させることを定義します。

(defun kill-emacs-and-restart ()
  (interactive)
  (kill-emacs 123))

このスクリプトを使用してEmacsを実行すると、再起動M-x kill-emacs-and-restart(またはキーシーケンスにバインド)できます。


問題を回避する素敵な方法!理由を教えていただければこれを受け入れますyou cannot tell Emacs to re-start after terminating。これは技術的な制限ですか?
PythonNut 14

3
@PythonNut:私の知る限り、プロセスを再起動する唯一の方法は、exec...ファミリの関数の1つを使用することです(とにかくPOSIXシステムで)。Emacs Lispのプロセス制御関数は、そのような低レベルの呼び出しを公開しません。私はにかかわらず、専門家ではないので、うまくいけば誰より知識豊富な意志のチャイム。
コンスタンティン

2

https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-programmaticallyから突然盗まれた

「」を文字列に埋め込むための構文が正しいと仮定すると、これでうまくいきます。

(defun restart-emacs ()
  (call-process "sh" nil nil nil "-c" "gdb -p $(ps h -o ppid -p $$) -ex 'call execl(\"/bin/sh\", \"/bin/sh\", \"-c\", \"exec emacs\")'"))

11
しないでください。これはEmacsのすべての内部クリーンアップをバイパス確認なしですべての現在の状態(変更されたバッファーなど)破棄します
lunaryorn

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