spacemacsにコントリビュートをした話

実際のプルリクエスト

github.com

背景

2022年の年末頃から、日本語文章の執筆用途としてEmacsを使い始めた。

1から設定を積み上げていくのはそれなりに大変であることが予想されたので、Spacemacsを導入した上で、個別の設定を追加している。

Spacemacsでコード補完の候補を表示するレイヤー(パッケージやデフォルト設定集)はauto-completion layerを使用していて、表示フロントエンドにはcompany-boxを使用している。実際の設定は下記の通り。

     (auto-completion :variables
                      auto-completion-enable-sort-by-usage t
                      auto-completion-use-company-box t
                      auto-completion-enable-help-tooltip 'manual
                      auto-completion-complete-with-key-sequence-delay 0.0
                      auto-completion-enable-snippets-in-popup t
                      auto-completion-minimum-prefix-length 1)

この設定で補完候補を表示した場合に、アイコンと文字列が中央揃えにならない、意図しない画像が表示される、という事象が発生していることに気づいた。

この不具合の原因を簡易版、やや厳密な説明版の2つで説明してみようと思う。

不具合の原因(簡易版)

company-boxで defvar を使って定義されている変数 company-box-icons-all-the-icons をuse-packageの :custom で設定をしようとしていため。

:custom に記述した内容は、パッケージが読み込まれる前に実行されるのだが、company-box-icons-all-the-icons はパッケージ読み込み前には当然未定義であるため、設定が正しく行えない

なおuse-packageは下記の記事でも解説を試みた。

qiita.com

不具合の原因(やや厳密な説明版)

少々込み入っているので、箇条書きで説明をすると、

  1. use-packageには:custom で設定した値が custom file に保存されることを防ぐことができるオプション( use-package-use-theme )がある
  2. 上記のオプションが有効になっている場合 :custom の変数定義は custom-theme-set-variables で行われる
  3. この custom-theme-set-variables は「変数が定義済みの場合には上書き、未定義の場合には指定したテーマのシンボルに対するプロパティの追加のみを行う
  4. 他方、上記でプロパティに設定を追加したテーマ(シンボル名: 'use-package)は常に無効な状態になっている

という、事象の掛け合わせで :custom の設定が反映されない状態になっていた。

厳密な説明を試みたものの正しく説明できている自信はないので「defvar で定義された変数を use-packageの :custom セクションで定義をすると設定が反映されないことがある」くらいに捉えてもらうのがいいと思う。

不具合の解消

パッケージが読み込まれる後に実行される :config セクションに移動し、 setq で上書きするように変更したことで修正が完了した。

spacemacsのこのレイヤーでは、自動テストなどは用意されていなかったため、コード差分と動作確認用のスクリーンショットをつけてプルリクエストを送った。

まとめ

変数がdefvarで定義されていることに気づくのもそれなりに時間がかかったが、それ以上になぜdefvarをuse-packageの:custom で上書きできないのか、という調査に時間を取られた。

ただ、時間をかけて原因追及をしたことで、Spacemacsのレイヤーの仕組み、use-package、変数定義(setq, defvar, defcustom)、マクロ展開、テーマなどの多くの知識を手に入れられた。 また、本記事では触れなかったがedebugを使ったデバッグなど、Elispの不具合発見方法に馴染むことができた。

今後もEmacsの設定や各種パッケージへのコントリビュートをしていこうと思う。