line-spacing を制御する
line-spacing
は、行間を制御する変数です。バッファローカルな変数なので、ミニバッファも含めて、各バッファの行間を個別に制御できます。
これまでは起動時に (set-default 'line-spacing 0.3)
としていましたが、 bs.el
に関連した改良を進めるうちに、 (message "1\n2")
で作られるミニバッファの改行において、行間を制御するのが困難なことがわかりました。
症状としては、 global
に設定された 0.3
を超えるような行間にはできるが、それを下回る値、具体的には行間を nil
に戻すことができないことがわかりました(いやできる、という場合は教えて下さい〜)。なお、 minibuffer-setup-hook
を使うことも考えられますが、やはり上手くいきません。
で、最終的にたどり着いた解決策は、行間を global
には指定せずに、バッファを開くたびに line-spacing
を自動で指定するアプローチです。次のようにします。
(defun my-linespacing ()
(unless (minibufferp)
(setq-local line-spacing 0.3)))
(add-hook 'buffer-list-update-hook #'my-linespacing)
(add-hook 'org-src-mode-hook #'my-linespacing)
ポイントは、 buffer-list-update-hook
です。個人的には初めて使う hook
ですが、基本的にはカーソルが別バッファに移動したら呼ばれる hook
として考えて良さそうです。例外的に org mode
のソースブロックでは発火しないので、別途 org-src-mode-hook
を設定しています。
my-linespacing
はシンプルに、 global
ではなく local
変数の line-spacing
を書き換えます。 (minibufferp)
で括っているのは、ミニバッファの行間を my-linespacing
に左右されずに制御するためです。
先に示した (message "1\n2")
の行間を制御するには propertize
を使います。これは Emacs JP の Slack で教えてもらいました。ありがとうございます。
(message (propertize "1\n2" 'line-spacing 0.9))
のように指定します。カジュアルに試すには、 run-with-timer
を使うと良く、
(run-with-timer
1 nil
(lambda () (message (propertize "1\n2" 'line-spacing 0.9))))
を評価(M-:
)すれば、効果を確認できます。