Spacemacs/Doom Emacsを飲み込む
TL;DR
- シンプルなEmacsを保ちたいからバニラEmacsを使いたいけれど、イケてる設定であるスターターキットが使いたい時もある。
- そこでEmacsの初期化処理を工夫して、好きなタイミングでSpacemacs化、Doom Emacs化できるようにした。
- 一度Spacemacs化、Doom Emacs化してしまうと、Emacsを起動したままバニラの状態には戻せないが、Emacsを再起動すれば元に戻せる。
Emacsとは
Emacsはテキストエディタ、つまりテキストファイルを編集するためのソフトウェアであり、文章やプログラムを書くために使われる。同種のソフトウェアとしては、vi、vim、neovim、nano、VSCode、Sublime Text、Cursor、秀丸エディタ、メモ帳、サクラエディタなどだ。
Emacsにはいくつかの実装があるが、現在主流なものはGNU Emacsだろう。以降、単にEmacsという時はGNU Emacsを指すものとする。
Emacsは簡単に拡張できるけどデフォルトの挙動は使いにくい
Emacsの特徴の1つは拡張する事の簡単さだ。Emacs Lispを書き、それを評価する。すると即座にその変更はEmacsに反映される。
このような気軽な拡張を是とする哲学が根底にあるからなのか、初期状態のユーザビリティに対してはあまり改善されない傾向がある。実際にEmacsの初期状態は、お世辞にも使いやすい状態とは言えないだろう。
例えば「コントロールキーを押しながらhキーを押す」といった操作をした時、エディタにはどのように動作して欲しいだろうか。もちろん僕は、カーソルの1文字前の文字を消す(つまりバックスペースキーを入力した時と同様)という挙動をして欲しい。他の多くのツールも、この挙動をするからだ。しかしEmacsのデフォルトではヘルプが表示される。
使いやすいEmacsにするには育成が前提
Emacsでは「コントロールキーを押しながらhキーを押す」という操作は C-h のように表現される。そしてこのキー操作を行うと、どの機能が呼び出されるかの対応の事を「キーバインド」と言う。
Emacs支持者(Emacian)の多くは、まずこの C-h のキーバインドを変更する所から始めるだろう。
(global-set-key (kbd "C-h") #'backward-delete-char-untabify)自分なりの設定を加えていく事で、Emacsの使用感は大きく変わる。このように設定の変更を日々積み重ね、長い時間をかけ改善し続ける事で、自分好みのEmacsに育てる事ができる。
イケてる初期設定であるスターターキットを使えばEmacsの育成をショートカットできる
しかしEmacsを使い始めた人にとって、この作業はハードルが高いだろう。きっと"イイ感じ"に使える設定が今すぐ欲しいはずだ。
そのような"イケてる"設定を配布している人達やコミュニティもあり、それらの設定はスターターキット、ディストリビューション、コンフィギュレーションフレームワーク等とと呼ばれる。本稿では「スターターキット」と呼ぶ事にする。またスターターキットを使わないEmacsは「バニラEmacs」と呼ばれる。
どのようなスターターキットがあるかについては、「awesome-emacsのStarter Kitの項目」が参考になる(もちろんここに掲載されていないものもある)。人気の高いスターターキットとしては spacemacs と Doom Emacs だろうか。
なぜ便利なスターターキットを避ける人達がいるのか
スターターキットはすぐに使えて便利である一方、その設定方法についてはEmacsに加えてスターターキット自体の作法を学ぶ必要がある。バニラEmacsを好む人達は、そういった追加で必要な学習を避け、構成要素が増える事による複雑さが増す事を回避する傾向があるように思う。
僕もバニラEmacsを好む。自分の身の丈に合ったものを使う事で、「何がなんだかよくわからない」という状況を避けたいからだ。ただしそれらは程度の問題でもあるので、そういったものを全て使わないというわけでもない。
バニラEmacsとスターターキットの同居
普段はバニラEmacsを使い、必要に応じてspacemacs化したりDoom Emacs化できるという状態が、僕にとっては望ましい。
スターターキットはあくまでEmacsの設定であり、Emacsの初期化時に設定が読み込むようになっている。起動の設定を工夫し、任意のタイミングでスターターキットの設定を読み込めるようにすれば、バニラEmacsを好きな時にspacemacsやDoom Emacsに変身させられるようになるだろう。
僕にはこれが、バニラEmacsがスターターキットの機能を飲み込み、基本はバニラEmacsだが必要に応じてスターターキットの能力を引き出しているように思えた。
本稿では、スターターキットの設定を読み込むタイミングを任意のタイミングで指定できるようにし、バニラEmacsをいつでも好きな時に spacemacs 化、 Doom Emacs 化できるようにする。
Spacemacs
https://www.spacemacs.org
Spacemacsは非常に人気のあるEmacsのスターターキットのひとつだ。SpacemacsはEmacsとVimの両方の操作感を上手く扱えるエディタ環境を提供する事を主なコンセプトにしている。また洗練された設定により、ほぼ初期状態でもモダンなエディタとして使用できる。通常は ~/.emacs.d にSpacemacsのリポジトリをcloneして用いる。
Spacemacsを飲み込む
僕は自分のEmacsの設定をhttps://github.com/TakesxiSximada/emacs.dにホスティングしており、 ~/.emacs.d にcloneして使用している。このリポジジトリの中のdistributions/spacemacsはGit Submoduleとなっており、実体はhttps://github.com/syl20bnr/spacemacsだ。
distributions/spacemacs/init.elをloadするための関数を定義する。
(defun start-spacemacs ()
(interactive)
(setq package-user-dir (expand-file-name "~/.elpa.spacemacs")
spacemacs-start-directory (expand-file-name "~/.emacs.d/distributions/spacemacs/")
spacemacs-bootstrap-file (file-name-concat spacemacs-start-directory "init.el")
custom-file (locate-user-emacs-file "custom-spacemacs.el")
)
(setenv "SPACEMACSDIR" (expand-file-name "~/.emacs.d/spacemacs/"))
(package-initialize t)
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(load spacemacs-bootstrap-file nil nil))
M-x start-spacemacs を実行するとパッケージ関連のパスを書き換え、Spacemacsのbootstrap用のファイルをロードする。

Doom Emacs
https://docs.doomemacs.org
Doom EmacsはSpacemacsと並んで人気があるスターターキットだ。 evil-mode (vi のキーバインドをEmacsで使用する拡張)を前提とした構成となっている。Doom Emacsは再現性のあるパッケージ管理を提供する。モダン化した方がよい部分は最小限の設定をし、独自の仕組みが小さくなるように作られている。また公式ドキュメントが詩的で趣深い。
Doom Emacsを飲み込む
基本的なアプローチは「Spacemacsを飲み込む」で説明した内容と同様だ。 .emacs.d の中のdistributions/doom-emacsをGit Submoduleにする。実体はhttps://github.com/hlissner/doom-emacsだ。
distributions/doom-emacs/init.elをloadするための関数を定義する。
(defun start-doom-emacs ()
(interactive)
(setenv "EMACSDIR" (expand-file-name "~/.emacs.d/distributions/doom-emacs/"))
(setenv "DOOMLOCALDIR" (expand-file-name "~/.emacs.d/doom.d/"))
(setenv "DOOMDIR" (expand-file-name "~/.emacs.d/doom.d/"))
(setq package-user-dir (expand-file-name "~/.elpa.doom-emacs")
custom-file (locate-user-emacs-file "custom-doom-emacs.el")
)
(setq user-emacs-directory (expand-file-name "~/.emacs.d/distributions/doom-emacs/"))
(load (concat user-emacs-directory "core/core") nil 'nomessage)
(load (expand-file-name "~/.emacs.d/distributions/doom-emacs/init.el") nil 'nomessage)
(switch-to-buffer (get-buffer "*doom*")))

Spacemacsと違い、shellコマンドを用いてインストールや設定の反映を行う必要がある。Doom Emacsは、パッケージシステムにstraight.elを採用している。
Doom Emacs本体は .emacs.d/distributions/doom-emacs にサブモジュールとして登録した。Doom Emacsの設定はデフォルトでは ~/.doom.d だが今回は .emacs.d/doom.d に配置したい。そのため環境変数EMACSDIR / DOOMLOCALDIR / DOOMDIRの設定を行っている。
Doom Emacsでインストールされたパッケージは通常のものと分けたいので package-user-dir の設定を変更しているが、Doom Emacsはstraight.elを採用しているため意図した挙動になっていない。
現状では ~/.emacs.d/doom.d/straight にパッケージが展開されてしまう。これはどこかのタイミングで修正する。
関連する処理だけ切り出した
自分のためだけに実装したものだし、こんな使い方をする人はいないだろうと思い、今までは.emacs.d/init.elに直接関数を実装していた。ただやはり.emacs.d/init.elの整理をしにくくなったため、別のファイルとして切り出すことにした。
;;; make-possess-preset --- Make process preset of configuration. -*- lexical-binding: t -*-
;; ⢠⣤⡀
;; ⣛⠷⣴⣶⣶⢶⣤⣄ ⣀
;; ⠈⠙⠻⡏⠈⠛⠛⠾⣾⣽⣷⣠⡄
;; ⣀⣤⠤⠴⠖⠒⠒⠶⠦⢤⣀⡋⠐⠦⠟⠘⠶⠄
;; ⣠⠴⠛⠉ ⠈⠙⠲⢤⡀
;; ⢀⣴⠛⠁ ⠙⢦⡀
;; ⢠⠞⠁ ⠹⣄
;; ⢠⠏ ⢀⣇⢠ ⣀⣀⡀ ⠘⣆
;; ⡟ ⠈⠉⠉ ⢠⣾⣿⣿⣿⣷⡄ ⢀⣤⣤⡄⠠⣼⢽⡄
;; ⢸⠁ ⢀⣾⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣆ ⣇
;; ⡟ ⢀⣘⣿⣿⣿⣿⣿⣿⣿⠰⢲⣿⣿⣿⣿⣿ ⣿
;; ⣸⠁ ⠘⠟⠚⣿⣿⣿⣿⣿⠏ ⢸⣿⣿⣿⣿⣿ ⡟
;; ⢠⡏ ⢺⣿⣿⣿⠛⠁⣀⣀⠈⠿⣿⣿⣿⣕⠇⢰⡇
;; ⢀⡾ ⢳⡀ ⠻⡿⠁ ⠹⠿⠟⠋ ⢸⡇
;; ⣠⠟⢀⡀ ⢻⡄ ⢸⡁
;; ⢀⡴⠞⠁⣠⠏ ⠈⡇ ⡼⠉⠳⣄
;; ⣀⡴⠞⠉ ⢰⣇⣠⠤⠒ ⠰⢦⣦⡤⠾⠃ ⢠⠇ ⠸⡇
;; ⢠⠖⠋⢁ ⢠⡦ ⠈⠁ ⡤ ⢀⡞⠲⣶⡶⠶⠃
;; ⠸⡆ ⠑⠢⢤⣀⡀ ⢀⡾⠁ ⢀ ⣇⢠⠇ ⣾⠁
;; ⠹⣄ ⠉ ⣀⡴⢟⡼ ⣿ ⣠⠄ ⣤ ⠉⠉ ⡼⠁
;; ⠈⠉⠑⠒⠒⠒⠒⠒⣻⠋ ⡎ ⣀⠄ ⢠⡼⠃ ⠉⠉⠁ ⢀⡾⠁ ⢀⡞⠁
;; ⢰⠃ ⠉⠉⠉⠁ ⣠⠟ ⣠⡶⠋ ⢠⠞
;; ⡏⢀ ⡏ ⢀⣀⣠⡾⠋ ⡀ ⢀⡴⠃
;; ⣇⠈⠁⢀⣠⠤⠖⠒⠚⣇ ⣠⡴⠛⠁ ⢷⣀ ⣀⡾⠋
;; ⠸⣦⠴⠋ ⠉⠙⠋⠁ ⠈⠛⠛⠁
;; ⣀⣀ Image: https://emojicombos.com/ghost-ascii-art
;;
;; Copyright (C) 2022 TakesxiSximada
;; Author: TakesxiSximada <[email protected]>
;; Maintainer: TakesxiSximada <[email protected]>
;; Version: 1
;; Package-Version: 20220528.0000
;; Package-Requires: ((emacs "27.1"))
;; Date: 2022-05-28
;; This file is part of make-possess-preset.
;; make-possess-preset is free software: you can redistribute it and/or
;; modify it under the terms of the GNU Affero General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;; make-possess-preset is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; Affero General Public License for more details.
;; You should have received a copy of the GNU Affero General Public
;; License along with this program. If not, see
;; <https://www.gnu.org/licenses/>.
;;; Code:
;;;###autoload
(defun make-possess-preset-of-spacemacs ()
(interactive)
(setq package-user-dir (format "%s.spacemacs" package-user-dir)
spacemacs-start-directory (expand-file-name "~/.emacs.d/distributions/spacemacs/")
spacemacs-bootstrap-file (file-name-concat spacemacs-start-directory "init.el")
custom-file (locate-user-emacs-file "custom-spacemacs.el")
)
(setenv "SPACEMACSDIR" (expand-file-name "~/.emacs.d/spacemacs.d/"))
(package-initialize t)
(load spacemacs-bootstrap-file nil nil))
;;;###autoload
(defun make-possess-preset-of-doom-emacs ()
(interactive)
(setenv "EMACS" "/Applications/Emacs28.0.50.app/Contents/MacOS/Emacs")
(setenv "EMACSDIR" (expand-file-name "~/.emacs.d/distributions/doom-emacs/"))
(setenv "DOOMLOCALDIR" (expand-file-name "~/.emacs.d/doom.d/"))
(setenv "DOOMDIR" (expand-file-name "~/.emacs.d/doom.d/"))
(setq package-user-dir (format "%s.doom-emacs" package-user-dir)
custom-file (locate-user-emacs-file "custom-doom-emacs.el")
)
(setq user-emacs-directory (expand-file-name "~/.emacs.d/distributions/doom-emacs/"))
(load (concat user-emacs-directory "core/core") nil 'nomessage)
(load (expand-file-name "~/.emacs.d/distributions/doom-emacs/init.el") nil 'nomessage)
(switch-to-buffer (get-buffer "*doom*")))
(provide 'make-possess-preset)
;;; make-possess-preset.el ends here過ぎ去った時間を取り戻すことはできない
EmacsがSpacemacsやDoom Emacsに変身した後、元の環境に戻すにはEmacsを再起動するしかない。SpacemacsやDoom Emacsの初期化処理によって更新された変数や関数などの情報を、以前の状態に元に戻すのが困難だからだ。過ぎ去った時間を取り戻すことはできない。
まとめ
本稿ではバニラEmacsを基本にしながら、必要に応じて簡単にスターターキットに切り替える方法を考え実装した。バニラEmacsのシンプルさを大切にしながらも、必要に応じてSpacemacsやDoom Emacsの恩恵を受けられるようになった。
一度、スターターキットに変身してしまうと、Emacsを起動したまま元に戻す事は難しい。たぶん失われたものは二度と戻らないという儚さの中にこそ、価値があるのだろう1。だからこそ、その一瞬一瞬の選択を丁寧に重ねながら、自分だけの理想のEmacsを静かに育てていきたい。
Emacsを再起動すれば、元に戻ります。