私はSpacemacsを使っています。いつからか定かではないのですが、Spacemacsをサーバとしたemacsclientが、内容のある新しいファイルを一度目では開けないという問題に困っていました。これを先程解消することができました。

原因はspell-checkingレイヤーのspell-checking-enable-auto-dictionaryでした。

(spell-checking :variables spell-checking-enable-auto-dictionary t)

spell-checking-enable-auto-dictionaryを有効にしないことで解消しました。

問題の症状の詳細

私は普段emacsclientを自分で使うことはなく、gitのコミットメッセージを入力することにのみ使っていました。普段はEmacsから直接ファイルを開くため、emacsclientを使う必要がなかったのです。gitの操作は例外でmagitも使いますが多くの操作をシェル上で行っています。

git commitをすると、emacsclientによりEmacsにコミットメッセージの入力バッファが開くのが期待する動作なのです。しかし何回かに一度の間隔でEmacsが反応しませんでした。この反応しない時、Emacsは何かを待機しているようで、C-gを押すと入力を受け付ける状態になります。ただしコミットメッセージを入力するバッファは表示されません。このあともう一度git commitするとEmacsにコミットメッセージを入力するバッファが表示されます。二度連続で反応しなくなることはなかったので、不便でしたが困ってはいませんでした。

最初はgitレイヤーとversion-controlレイヤーを疑った

私にとってはgit commitのときにみ起こる問題でしたので、最も関連のありそうなgitレイヤーとversion-controlレイヤーを疑い、これらを無効化しましたが解消しませんでした。素のEmacsで試すとこの問題が起きないのは確認していたので、Spacemacsの何かが悪いのは分かっていたのですが、原因が分からず放置していました。

転機は先日作ったinvoke newコマンド

Pelicanの記事のテンプレートを作るコマンドを先日作りました。新しい記事のテンプレートを作ったのなら、その後はEmacsで編集するに決まっているのだから、emacsclientで作った記事を開くよう改良しました。

@task
def new(c, filename):
    now = datetime.datetime.now(
        datetime.timezone(datetime.timedelta(hours=+9), 'JST'))
    dest = f'content/{now.year}/{filename}.rst'
    created_at = now.isoformat(timespec='seconds')
    underline = '#' * len(filename)
    with open(dest, 'w') as f:
        f.write(f"""{filename}
{underline}

:slug: {filename}
:date: {created_at}
:modified: {created_at}
:tags: Python, Pelican
:category: N/A

.. SUMMARY_END

.. contents::

""")

    c.run(f'emacsclient --no-wait {dest}')

※ テンプレートの内容も変わっていますが、それはここでは関係ありません。

そしてこの改良したコマンドを実行したところ、git commitと同じ現象が起きたのです。ここで私はようやく、これがgit関連の問題ではないことに気が付きました。新たなヒントを得たことで、問題を調べる気が起きました。

問題箇所を二分探索で探す

まずはSpacemacsの本体に問題があるのか、私の設定に問題があるのかを確認しました。.spacemacsのdotspacemacs-configuration-layersをすべてコメントアウトすると、この状態では問題が起きないことが確認できました。これで原因がレイヤーにあることが分かりました。もしもレイヤーに問題なければuser-initもコメントアウトするつもりでしたが、その必要はなくなりました。

後は簡単です。layerの設定を半分戻し確認、問題が起きれば今コメントアウトしていないレイヤーに問題があるので、更に半分をコメントアウト、と続けるだけです。そして冒頭に書いた(spell-checking :variables spell-checking-enable-auto-dictionary t)に当たりました。ここでspell-checking-enable-auto-dictionary tを取り除くき確認すると問題が起きなくなりましたので、(spell-checking :variables spell-checking-enable-auto-dictionary t)spell-checkingにして解決です。

spell-checking-enable-auto-dictionaryは言語をバッファから自動的に検出する機能を有効にする機能です。私の場合は日本語と英語しか書かないのでそもそも使う必要がない機能でした。