Emacsで状態に応じてモードラインの色を変える

モードラインの色を自動的に切り替えるためのマイナーモードをだいぶ前に作ってあったので, 使用例とともに紹介.

マイナーモードのソースコードと基本的な使い方

使い方

マイナーモードを有効にする

(require 'mode-line-color)
(mode-line-color-mode)

色切り替えの定義を追加する

(defun my-set-mode-line-color (setter)
  (unless mode-line-color-color
    ;; この定義よりも優先して色設定している定義があったら何もしない
    (cond (条件1 (funcall setter 色1))
          (条件2 (funcall setter 色2))
          ...)
(add-hook 'mode-line-color-hook 'my-set-mode-line-color)

色を変えるタイミングを設定する

(defadvice 色切り替えのトリガにする関数の名前
  (after 適当な名前)
  (mode-line-color-update))
特徴
  • 色切り替え定義(hookに指定した関数)が複数あっても大丈夫
    • hookを先に設定した方が優先
    • 優先順位の高い設定があった場合はmode-line-color-colorに色が設定されてくるだけなので優先順位を無視することも可能
  • mode-line-color-updateを呼べばいつでも強制的に色を反映できる

例1: SKKで日本語モードのときだけ色を変える

(defvar skk-j-mode-line-color "maroon")
(defun skk-set-mode-line-color (setter)
  (when (and (featurep 'skk) skk-j-mode
             ;; Viperを使ってるときはinsert-stateのときだけ
             (or (not (featurep 'viper))
                 (eq viper-current-state 'insert-state)))
    (funcall setter skk-j-mode-line-color)))
(add-hook 'mode-line-color-hook 'skk-set-mode-line-color)
(defadvice skk-update-modeline (after ad-skk-mode-line-color activate)
  (mode-line-color-update))

例2: Viper/Vimpulseでviper-current-stateに応じて色を変える

実はこれをやりたいがために作ったもの. もともとはid:mechairoivimpulse で stateごとにモードラインの色を変える - *iroi*を参考にした.

(setq viper-mode-line-color ;
      '((vi-state       . "white")
        (insert-state   . "khaki4")
        (replace-state  . "khaki4")
        (operator-state . "darkseagreen2")
        (visual-state   . "steelblue")
        (emacs-state    . "red")))
(when (featurep 'mode-line-color)
  (add-hook 'mode-line-color-hook
            '(lambda (setter)
               (unless mode-line-color-color
                 (funcall setter
                          (cdr (assq viper-current-state
                                     viper-mode-line-color)))))))
(defadvice viper-change-state (after ad-my-viper-update-mode-line activate)
  (when (featurep 'mode-line-color) (mode-line-color-update)))

https://github.com/tarao/dotfiles/blob/master/.emacs.d/dot/tarao/51_vimpulse.elではviper-current-stateに応じてモードラインに「--INSERT--」等を表示する設定もいっしょにやっている.