Emacsのモードラインで右寄せする方法メモ
ググっても日本語の記事がなかったので。
mode-line-format変数
Emacsのモードラインを自分の手で組み立てたいと思う人はなかなかいないと思いますが、そういう人はmode-line-format
変数をいじることになります。
mode-line-format
には文字列や、文字列のリスト、または:eval
とともに文字列を返す関数などを与えられます1が、これらは左詰めで表示されます。
よって、右寄せして表示することはできないように思えますが、実は頑張ればできます。
右寄せで表示する方法
(let* ((leftstr (propertize "left" 'face '(:background "#ffa0a0"))) (rightstr (propertize "right" 'face '(:background "#a0a0ff"))) (margin (propertize " " 'display `(space :align-to (- right ,(length rightstr)))))) (setq mode-line-format (concat leftstr margin rightstr)))
(表示した時のわかりやすさのために、leftstr
とrightstr
の背景に色をつけています。)
上のようにして、rightstr
がちょうど右寄せになるような幅を持つmargin
を挟めば右寄せすることができます2。
margin
はdisplayプロパティを持った文字列です。displayプロパティは画像を表示するのに使われるプロパティですが、スペース(空白)を表示するのにも使えます3。:align-to
プロパティを使えば指定した横幅まで空白で表示することができます。:align-to
に与える値としてPixel Specification4という特別な表現を使い、右にrightstr
文字列の幅だけ確保するようにスペースを表示するようにします。そしてその後ろでrightstr
文字列を表示すれば、実質右寄せで表示できているというわけです。
Pixel Specificationのright
はウィンドウの幅の変化に応じて変わるため、上のコードはC-x 3
などでウィンドウの幅を変えてもしっかり右寄せは保たれます。
powerlineのようなライブラリも同様のことをして右寄せを実現しています。
ちなみにmode-line-format
はバッファローカルな変数なので、上の式を評価してモードラインが変わったとしても同じバッファで以下を評価すれば元に戻ります。
(kill-local-variable 'mode-line-format) ;; もしくは M-x kill-local-variable mode-line-format
もっとカンペキに右寄せで表示する方法
上の方法は端末上でのEmacsならいい感じに右寄せになりますが、GUIのEmacsでは完全には右寄せになりません。
GUIのEmacsでのfringeやスクロールバーを考慮するなら以下のようになります。
(let* ((leftstr (propertize "left" 'face '(:background "#ffa0a0"))) (rightstr (propertize "right" 'face '(:background "#a0a0ff"))) (margin (propertize " " 'display `(space :align-to (- (+ scroll-bar scroll-bar) ,(length rightstr)))))) (setq mode-line-format (concat leftstr margin rightstr)))
scroll-bar
が2回登場していますが、一つ目のscroll-bar
はscroll-barの相対位置、二つ目のscroll-bar
はscroll-barの幅を表します。
これなら、M-x scroll-bar-mode
でスクロールバーの表示を切り替えたときもそれに対応して右寄せされます。
ただ、前の例もこの例も、右寄せさせたい文字列が日本語や絵文字などのマルチバイト文字だと右寄せはうまくいかないことがあります(そのときはlength
をstring-width
にするといい感じになるかも?)。
実践的な例
上では"left"や"right"など固定された文字列をmode lineに表示しましたが、普通は変動する文字列を表示したくなると思います。
そんなときは文字列を返す関数を定義して、それを:eval
を使ったリストにしてmode-line-format
に与えましょう。
(defun my/mode-line--form () (let* ((leftstr (propertize (format-mode-line "%b") 'face '(:background "#ffa0a0"))) (rightstr (propertize (format-mode-line "%l") 'face '(:background "#a0a0ff"))) (margin (propertize " " 'display `(space :align-to (- (+ scroll-bar scroll-bar) ,(length rightstr)))))) (concat leftstr margin rightstr))) (setq mode-line-format '(:eval (my/mode-line--form)))
おわり
右寄せを使って、イケてるモードラインを作りましょう!
参考
- zk-phiさんのinitファイル
- 標準の
list-colors-print
関数(list-colors-display
の中で使われる)
-
詳しくは Mode Line Data - GNU Emacs Lisp Reference Manual を見てください。↩
-
ここでは
" "
という文字列をプロパタイズしてスペースを表示していますが、長さが1以上の文字列ならなんでもokです。(例えばput-image
関数は"x"
という文字列にdisplayプロパティを追加して画像を表示している)↩ -
詳しくは Specified Space - GNU Emacs Lisp Reference Manual を見てください。↩
-
詳しくは Pixel Specification - GNU Emacs Lisp Reference Manual を見てください。↩