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-:)すれば,効果を確認できます.

amazon_banner_large
amazon_banner_small