つうさにメモブログ

つうさにがメモをブログとして書いていくところ

Emacsのzenburn-theme.el

Emacsのテーマについて

Emacsにおけるfaceとtheme(テーマ)

face

Emacsではfaceという文字のグラフィックattribute(属性)を示すものを用いて、文字の色や背景、ボールド体などを設定します。

Emacsには多くのfaceが存在し、デフォルトの文字のためのdefault faceや、選択範囲のためのregion faceなどがあります。シンタックスハイライトもfaceが用いられています。

M-x describe-faceすると、faceを選択してそのfaceの属性の値を確認することができます。例えば、M-x describe-face<return>default<return>とすれば、ForegroundやBackground属性の値にデフォルトの文字の色や背景色が設定されていることがわかります。

faceのカスタマイズ

faceをカスタマイズすることで見た目を変えることができます。

以下にEmacs lispを用いたカスタマイズの例を示します。

;; mode-lineとmode-line-inactiveをカスタマイズ
(custom-set-faces
 '(mode-line ((t (:foreground "#606060" :background "#F0A0A0" :box (:line-width -1 :style released-button)))))
 '(mode-line-inactive ((t (:foreground "#404040" :background "#B0A0A0")))))

上を評価すると、mode lineの文字の色や背景の色を変更されます。また、:boxを指定することで、色だけでなくmode lineが線で囲まれるようにもできました。

theme

Emacsにおけるtheme(テーマ)とは、faceのカスタマイズのcollection(あつまり)1です。 1つのテーマは多くのfaceに対するカスタマイズ設定を含んでいます。1テーマを単位として、有効化、無効化ができ、テーマを変えることで見た目を大きく変えられます。 Emacsには標準で多くテーマ(Emacs25.3.1で14個)が入っています。

zenburn-theme.el

zenburn-themeEmacsのテーマの一つです。これをEmacsにインストールし、M-x load-theme<return>zenburn<return>とすると、zenburnテーマを適用できます。

f:id:tsuu_mmj:20180802213815p:plain
zenburnテーマ適用前
f:id:tsuu_mmj:20180802214109p:plain
zenburnテーマ適用後

zenburnはEmacsに含まれているパッケージのためのfaceだけでなく、多くの外部パッケージのfaceにも対応しています。もしMELPAから多くのパッケージをダウンロードしてEmacsを使っているのなら、zenburnのような多くの外部パッケージに対応したテーマを使うことをオススメします。

もし対応していない外部パッケージがあったら、テーマの雰囲気に合うように自分でfaceを設定する必要があります。

zenburnテーマではzenburn-with-color-variablesマクロを用いることで、"#f0f0f0"のようなカラーコードを指定するのではなく、独自のカラーパレットの色の名前(zenburn-bg-05など)を指定して色を設定できます。このため、自分でfaceを設定するのも楽です。

zenburnテーマのカスタマイズ

テーマのカスタマイズにはcustom-set-facesではなく、custom-theme-set-facesを使います。第2引数に指定したテーマに対して、faceのカスタマイズ設定を保存します。

また、zenburnでは、上でも言ったようにzenburn-with-color-variablesマクロを使って、zenburn-default-colors-alistにある色の名前を用いて、カスタマイズ設定をすることができます。

以下にカスタマイズ設定の例を示します。

(zenburn-with-color-variables
  (custom-theme-set-faces
   'zenburn
   `(mode-line-inactive
     ((t (:foreground ,zenburn-green-2
                      :background ,zenburn-bg-05
                      :box (:line-width -1 :color ,zenburn-bg+2)))))
   '(ivy-subdir ((t (:inherit dired-directory))))
   `(ivy-remote ((t (:foreground ,zenburn-blue+3 :background ,zenburn-bg))))
   `(ivy-virtual ((t (:foreground ,zenburn-orange))))
   `(whitespace-tab ((t (:foreground ,zenburn-yellow-1 :backgorund ,zenburn-cyan))))
   `(whitespace-space ((t (:foreground ,zenburn-blue-1 :background ,zenburn-bg+3))))
   `(whitespace-newline ((t (:foreground ,zenburn-orange))))
   `(whitespace-trailing ((t (:foreground ,zenburn-magenta :background ,zenburn-orange))))))

カラーコードは一切書かずに、用意された色名だけで設定することができました。

カラーコードを書かないことの利点として、テーマの雰囲気にあった色をわざわざ考え出さなくてもいい、ということが挙げられます。

rainbow-mode対応

rainbow-modeはバッファ上にあるカラーコードを示す文字列に対して、背景色をそのカラーコードの示す色にしてくれるパッケージです。カラーコードを見ただけでどんな色か思い浮かべるのは難しいので、色をつけてくれるのは非常に便利です。

zenburnテーマではこのrainbow-modeによる色表示に対応していて、zenburn-default-colors-alistで定義された色の文字列に対しても表示できるようになっています。

以下のように設定すると、rainbow-modeがインストールされている場合、zenburnの色に対応してくれます。

(setq zenburn-add-font-lock-keywords t)

この状態でzenburn--theme.elを見てみると、以下のようになり、rainbow-modeに対応していることがわかります。

f:id:tsuu_mmj:20180803002331p:plain
こんな感じ

org-mode関連

最近のzenburnではzenburn-scale-org-headlinesという変数が追加され、これをtにするとorg-modeの階層を文字の大きさでわかりやすく表示してくれます。

注意点として、これらのカスタマイズ可能な変数はテーマをロードする前に設定しておかなければなりません。

他のテーマ

MELPAにはzenburn以外の多くのテーマが公開されています。その中にはEmacsに同梱されているテーマのようにdefthemecustom-theme-set-facescustom-theme-set-facesのみを使って書かれているものもあれば、複雑なマクロを用いてテーマを定義しているものもあります。

spacemacs-themesolarized-emacsはdarkやlightテーマを作るのに共通の関数やマクロを通してテーマを作成しています。

まとめ

  • テーマを使えば一度に多くのfaceを変更できる(見た目をガラリと変えられる)。
  • MELPAにあるような多くの外部パッケージに対応したテーマを使えば、自分での設定が減る。
  • zenburn-themeは多くの外部パッケージに対応していて、拡張しやすくていい感じ。

initファイルへの記述例

最後にuse-packageを用いた、initファイルへの記述例を示しておきます。

;;; zenburn
(use-package zenburn-theme :ensure t
  :defer t
  :custom
  (zenburn-scale-org-headlines t)
  (zenburn-scale-outline-headlines t)
  :init
  (load-theme 'zenburn t)
  :config
  (zenburn-with-color-variables
    (custom-theme-set-faces
     'zenburn
     `(mode-line-inactive
       ((t (:foreground ,zenburn-green-2
                        :background ,zenburn-bg-05
                        :box (:line-width -1 :color ,zenburn-bg+2)))))
     '(ivy-subdir ((t (:inherit dired-directory))))
     `(ivy-remote ((t (:foreground ,zenburn-blue+3 :background ,zenburn-bg))))
     `(ivy-virtual ((t (:foreground ,zenburn-orange))))
     `(whitespace-tab ((t (:foreground ,zenburn-yellow-1 :backgorund ,zenburn-cyan))))
     `(whitespace-space ((t (:foreground ,zenburn-blue-1 :background ,zenburn-bg+3))))
     `(whitespace-newline ((t (:foreground ,zenburn-orange))))
     `(whitespace-trailing ((t (:foreground ,zenburn-magenta :background ,zenburn-orange))))
     `(tuareg-font-double-colon-face ((t (:foreground ,zenburn-orange-red))))))
  (setq zenburn-add-font-lock-keywords t))

参考

2019-09-06【追記】

rainbow-mode対応についてなど、古くなっていた内容を書き変えました。


  1. 正確にはfaceとcustomizable variableのcollectionです。テーマはcustom-theme-set-variablesでdefcustomな変数にもテーマごとの値を設定できます。