1 概要

emacs-2-after.png

Org-mode はsrcブロックを適宜挿入して、文書にコードを記述することができます。 しかし、デフォルトではコード部が薄暗くなってしまう他、本文とコード部をわかりやすく 理解するためにfaceを設定しました。

同時に色のRGB値を計算する関数を定義しました。

2 環境

  • Emacs 24.5.1
  • Org-mode 9.0.9

3 コード

とりあえずelispを掲載します。init.elなどに記述してください。

(defun modify-color (raw-color raw-shift)
  "COLOR<string> is RGB color like \"#999999\"
SHIFT<integer> or <list<integer>> is color shift num (r g b)"
  (let ((color '(0 0 0)) (shift '(0 0 0)))
    (if (listp raw-shift)
        (progn
          (setq shift (make-list 3 (first raw-shift)))
          (dotimes (i (if (<= (length raw-shift) 3) (length raw-shift) 3))
            (setf (nth i shift) (nth i raw-shift))))
      (setq shift (make-list 3 raw-shift)))
    (dotimes (i 3)
      (setf (nth i color) (string-to-number (substring raw-color
                                                       (+ 1 (* i 2))
                                                       (+ 1 (* (+ i 1) 2)))
                                            16))
      (setf (nth i color) (+ (nth i color) (nth i shift)))
      (setf (nth i color) (let ((x (nth i color)))
                            (cond ((< x 0) 0)
                                  ((> x 255) 255)
                                  (t x))))
      (setf (nth i color) (format "%02X" (nth i color))))
    (concat "#" (mapconcat #'identity color ""))))

;; foregroundをdefault(普通の色)と同じにする。
;; backgroundをdefault(普通の色)より少し暗くする。
(set-face-foreground 'org-block (face-foreground 'default))
(set-face-background 'org-block (modify-color (face-background 'default) -5))

;; 言語ごとに切り替えたい場合はこの変数で設定する。
;; org-src-block-facesが優先されるので、org-blockで設定した上で特に区別したい言語をこちらで設定するといい。
(setq org-src-block-faces `(("emacs-lisp" ((:background ,(modify-color (face-background 'default) -5))
                                           (:foreground ,(face-foreground 'default))))
                            ("python" (:background "#002030"))))

4 解説

とりあえずweb上の表示

emacs-2-sumple-2.png

にOrg-modeの表示を合わせたくて設定をはじめました。

私はsolarized-darkを現在使用していますが、color-themeの変更に強くするため色のハードコーディングを避けようとして 冗長なコードを書いてしまいました。リファクタリングして頂ける方大歓迎です。。。! elisp力を上げたい今日このごろですが、取りあえず動くものは作れました。

関数 modify-color はただ16進の数字を10進数に変換して与えられた数だけシフトしているだけです。 シフト量はRGB全てで指定されることを期待しますが、数が上下しても動くようになっています。 動作は次の通り。scratchでの評価結果を記載します。

;; 基本の形です。与えられた色を指定された量だけシフトします。(RGB) -> (RGB)
(modify-color "#505050" '(-5 5 10))
"#4B555A"

;; シフトが一つしか与えられない場合、RGB全てに適用します。(R) -> (RRR)
(modify-color "#505050" 10)
"#5A5A5A"

;; シフトが2つしか与えられない場合、RのシフトをBのシフトとして使用します。(RG) -> (RGR)
;; この記法を使うことはほとんどなく、推奨されません。
(modify-color "#505050" '(5 10))
"#555A55"

;; シフトが4個以上与えられた場合、4個目以上の数を無視します。(RGBXXXX) -> (RGB)
(modify-color "#505050" '(-5 5 10 3 5 6 8))
"#4B555A"

;; シフトした結果、色の範囲(00~FF)を超えた場合、それぞれ00とFFに丸められます。
(modify-color "#505050" '(-100 5 200))
"#0055FF"

後は describe-chardescribe-faceOrg-mode のソースコードを頑張って読んで設定すれば 冒頭のスクリーンショットのようになります。

ちなみに設定前と設定後はこちらになります。

  • 設定前 emacs-2-before.png
  • 設定後 emacs-2-after.png

ただ設定後もカーソル行が気に入らないので、改良の余地ありです。 また何か更新があったらこのブログで公開します。