やりたいこと
ターミナルにてファイルをtouchしてEmacsですぐ編集したい。例えば、README.mdを:
touch README.md
em README.md # em: Emacsのエイリアス
として編集したい。EmacsはGUI版が望ましい。
Emacsが既に立ち上がっている場合には多重起動せず、既存のフレーム(ウィンドウ)で開いてほしいし、
そうでない場合は新規に立ち上げてほしい。
やり方
Mac
openコマンドを利用し、-a
オプションでEmacsで開くよう指定する。
open -a Emacs.app README.md
.bashrcや.zshrcにてエイリアスを登録しておくと良い。
alias em='open -a Emacs.app'
環境
以下の環境で動作することを確認している。
- zsh 5.8 (x86_64-apple-darwin20.0)
- Emacs 27.1
Linux
Emacsを編集サーバーとして立ち上げておき、emacsclientで呼び出す。
サーバーを開始するには、以下の関数を実行する。
(server-start)
use-packageを使っている場合は、以下の通り書ける。
(use-package server
:ensure nil
:hook (after-init . server-mode))
また、.bashrcや.zshrcで以下の関数を定義しておく。
function emacsclient_or_emacs() {
if emacsclient -n -e "(select-frame-set-input-focus (selected-frame))" > /dev/null 2>&1; then
emacsclient -n "$@" > /dev/null &
else
emacs "$@" &
fi
}
emacsclientは、既に立ち上がっているEmacsサーバに任意のファイルを開くよう指示する。ただし、サーバが存在しない場合はエラーを返す。
-n
(--no-wait
) オプションはサーバからの応答を待たないことを示す。
このオプションを指定しない場合、開いたファイルの編集が完了するまでターミナルに処理が返らない。
また、-e
(--eval
) オプションは、Elispを引数としてサーバにそれを評価させることができる。すなわち、引数として与えた任意のElispを実行できる。
上記の関数emacsclient_or_emacs
では、(暗に存在していると仮定した)サーバにフォーカスを当てようとする。フォーカスを当てることに成功した場合は、サーバが存在しているということなので、続いてemacsclientでファイルを開ける。一方で、フォーカスを当てるのに失敗した場合は、サーバが起動していないということなので、通常のEmacsを立ち上げてファイルを開く。なお、Emacsは前述の設定により自動的にサーバを起動するようになっているため、以降はemacsclientでファイルを開かせることが可能になっている。
こちらもエイリアスとして登録しておく。
alias em='emacsclient_or_emacs'
MacOSとLinuxとで同居させるなら、以下のような書き方になる:
case `uname` in
Darwin)
alias em='open -a Emacs.app'
;;
Linux)
alias em='emacsclient_or_emacs'
esac
環境
- Ubuntu 18.04.5
- zsh 5.8 (x86_64-pc-linux-gnu)
- Emacs 27.1
- linuxbrewで入れたもの
備考(やった方が良いと思っているけど、できていないこと)
- Linuxでの実現方法(emacsclientを使う方法)は、MacOSでも利用可能と思われるが、確認していない
- Linuxでの実現方法では、起動元のシェルを終了すると、釣られてEmacsも終了してしまう
- emacsclientには、オプション
-a
(--alternate-editor
) があり、
サーバへの接続に失敗した場合に開くエディタを指定できる。-a ""
のようにエディタに空文字列を
指定すると、Emacsをサーバで立ち上げることができる、とヘルプに記載されている。
しかしながら、設定ファイルの書き方からか、自分の環境では立ち上がったEmacsで一部の
設定が反映されていない(原因は深追いしていない)
参考文献
-
[Emacs] emacsclient を快適に使うための設定 - Qiita
- 基本的なアイデア、およびEmacsが起動しているかどうかの判定について参考にさせていただいた
-
Start Emacs Client in GUI (and launch Emacs server if not already running)
- スクリプトにした例。本記事で紹介した方法よりリッチかもしれない