Conao3 Notes

Nixで始めるemacsclient

Emacsを使っていると、シェルから現在のEmacsのインスタンスを使ってファイル編集したいことがあります。

そこで登場するのがemacsclientです。 Emacsをサーバーとして常駐させておき、クライアントから接続することで瞬時にファイルを開くことができます。

この記事ではNixOSのservices.emacsを利用して、簡単にemacsclient環境を構築する方法を紹介します。

ref: nixpkgs/nixos/modules/services/editors/emacs.md at master · NixOS/nixpkgs · GitHub

emacsclientとは

Emacsはサーバー/クライアントモデルをサポートしています。 通常Emacsを起動すると独立したプロセスとして動作しますが、サーバーモードで起動することでバックグラウンドで常駐させることができます。

その後、emacsclientコマンドを使うことで既に起動しているEmacsサーバーに接続し、新しいフレームやバッファでファイルを開くことができます。

検証環境

NixOSを使っていない人でも試せるよう、NixのFlakeを使ってQEMU上でNixOS VMを起動する環境を用意します。 もちろんNixOSを既に使っている場合は、自分の configuration.nix に直接設定を追加すれば良いです。

今回の検証環境は最小限のXfceデスクトップ環境を持つVMで、Emacsのサーバー/クライアント機能を試すのに十分な環境となっています。

flake.nix

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

  outputs = { self, nixpkgs }: {
    nixosConfigurations.minimal-vm = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [ ./configuration.nix ];
    };

    packages.x86_64-linux.default = self.nixosConfigurations.minimal-vm.config.system.build.vm;
  };
}

configuration.nix

{ modulesPath, pkgs, ... }: {
  imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ];

  system.stateVersion = "24.11";

  users.users.demo = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
    initialPassword = "demo";
  };

  services.xserver.enable = true;
  services.xserver.desktopManager.xfce.enable = true;
  services.xserver.desktopManager.xfce.enableScreensaver = false;

  environment.systemPackages = with pkgs; [ git ];
}

この2ファイルを置いて、以下のコマンドでVMを起動できます。

QEMU_OPTS="-m 8192 -smp 4" nix run

img

以降、基本的にconfiguration.nixを編集することになります。

設定

services.emacs を有効化することで、ユーザーログイン時に自動的にEmacsサーバーが起動するようになります。

configuration.nix

{
  services.emacs = {
    enable = true;
    defaultEditor = true;
  };
}

この設定でOS起動時に同時にemacsclientを起動することができます。

さらに defaultEditor を設定することで EDITOR をemacsclientを利用するように設定できるため、 EDITOR を利用するソフトウェアとも透過的にemacsclientを利用することができます。

環境変数に設定されるだけのため、 EDITOR を e として起動できるようにしておくと e something.txt でファイルを開くことができるようになります。

{
  environment.shellAliases = {
    e = "$EDITOR";
  };
}

services.emacsのオプション

services.emacs には他にも便利なオプションがあります。

package

使用するEmacsのパッケージを指定できます。 デフォルトは pkgs.emacs ですが、emacs-noxやemacs-pgtk、自分でカスタマイズしたEmacsパッケージなども指定できます。

{
  services.emacs = {
    enable = true;
    package = pkgs.emacs-pgtk;
  };
}

使い方

起動後

emacsclientはOS起動時に起動しているため、新規フレームを開くことができます。 先ほど e を $EDITOR のエイリアスとして設定したので、 e を実行するだけで新しいフレームが開きます。 & を付けてブロックしないようにすると良いです。

e &

もちろん、 emacsclient -c を直接実行することもできます。

emacsclient -c &

img

ファイルを開く

同様に、 e something.txt でファイルを開くことができます。 開いたシェルに制御を返すには C-x # で編集終了を伝えることができます。

e something.txt

emacsclientの主要オプション

-c (--create-frame)

新しいフレームを作成して開きます。

e -c file.txt

-t (--tty)

ターミナル内でEmacsを開きます。

e -t file.txt

-n (--no-wait)

ファイルを開いた後、すぐにシェルに制御を返します。 デフォルトではemacsclientは編集が終わるまで待機しますが、このオプションを付けることでバックグラウンドで開くことができます。

e -n file.txt

サーバーの状態確認

Emacsサーバーが正常に動作しているか確認するには systemctl を使います。

systemctl --user status emacs

サーバーを手動で再起動したい場合:

systemctl --user restart emacs

トラブルシューティング

サーバーが起動しない

まずログを確認します。

journalctl --user -u emacs

多くの場合、Emacsの設定ファイル(init.el)にエラーがあることが原因です。 Emacsを通常起動して設定を修正した後、サーバーを再起動します。

複数のサーバーが動いている

何らかの理由で複数のEmacsサーバーが起動してしまった場合、以下のコマンドで全て停止できます。

systemctl --user stop emacs
pkill -u $USER emacs

その後、サーバーを再起動します。

systemctl --user start emacs

クリップボードの共有

QEMU VM上でコピーした内容をホスト側でも使えるようにするには、QEMUのGTKバックエンドを使用します。

VM起動時のQEMU_OPTSに -display gtk を追加するだけです:

QEMU_OPTS="-m 8192 -smp 4 -display gtk" nix run

これでVM内でコピーした内容がホスト側のクリップボードにも反映されるようになります。

tips

どういう設定がされているのか見てみると楽しいです。

systemdのユニットファイルを確認:

systemctl --user cat emacs

環境変数EDITORの内容を確認:

$ echo $EDITOR
emacseditor

$ which $EDITOR
/run/current-system/sw/bin/emacseditor

$ cat $(which $EDITOR)
#!/nix/store/lw117lsr8d585xs63kx5k233impyrq7q-bash-5.3p3/bin/bash
if [ -z "$1" ]; then
  exec /nix/store/3gh804i02baai4yvn4vz99hs4ncvxjdd-emacs-30.2/bin/emacsclient --create-frame --alternate-editor /nix/store/3gh804i02baai4yvn4vz99hs4ncvxjdd-emacs-30.2/bin/emacs
else
  exec /nix/store/3gh804i02baai4yvn4vz99hs4ncvxjdd-emacs-30.2/bin/emacsclient --alternate-editor /nix/store/3gh804i02baai4yvn4vz99hs4ncvxjdd-emacs-30.2/bin/emacs "$@"
fi

emacsclient を簡単にラップした emacseditor というシェルスクリプトが動いていることが分かります。

まとめ

NixOSの services.emacs を利用することで、emacsclientの環境を簡単に構築できます。 emacsclientに興味がありながらも上手く設定できずに悩んでいた人におすすめです。