ファイル毎にバッファの色を変更する

前からそのようなスクリプトを使っていたのだが、set-buffer-colorsはベクタで指定するため、変更したいところの前に変更したくない箇所があっても、配列を埋める必要があって面倒だった。


そこで、色を個別に指定できる形式で書いてみた。xyzzyはなぜかバッファの色が取得できないので、iniファイルから色設定を読み込んで、それを変更するようにしてみた。項目名はiniに書いてあるとおりである。


なお、このコードはOHKUBO Hiroshiのchini.lに依存している。

;;;hook-color.l

;;; ### depending ###
;;; chini.l

(provide "hook-color")

(defvar *hook-color* nil)

(defun ini-hexl (hex)
  (if (integerp hex) hex (parse-integer hex :radix 16 :start 1)))

(defun change-buffer-colors (&optional change-a-list)
  (let ((s (ed::chini-read-config-data-1 "Colors")))
    (set-buffer-colors
     (dolist (a change-a-list (apply 'vector (mapcar 'ini-hexl (mapcar 'cdr s))))
       (rewrite-ini-data s a)))))

(defun rewrite-ini-data (a-list pair)
  (let ((i (assoc (if (stringp (car pair)) (car pair) (symbol-name (car pair))) a-list :test 'string-equal)))
    (if i (rplacd i (if (atom (cdr pair)) (cdr pair) (cadr pair))))))

(defun hook-color ()
  (let ((ext (file-namestring (get-buffer-file-name (selected-buffer)))))
    (dolist (plist *hook-color*)
      (if (string-match (car plist) ext)
          (return (change-buffer-colors (cdr plist)))))))

(add-hook '*find-file-hooks* 'hook-color)

これをhook-color.lという名前でsite-lisp以下において(require "hook-color")する。


実際に色を変更するには、.xyzzyなどに

(setq *hook-color*
        ("\\.tex$"
         (textColor #x000000)
         (backColor #xefe0ff))
        ("\\.\\(l\\|lisp$\\|xyzzy$\\|skk\\)$"
         (backcolor #xe0f0f9)
         (kwdcolor1 #x3333cc)
         (kwdcolor3 #xaa22aa))
        ("\\.pl$\\|\\.rb$"
         (backcolor #xe0f0e0))
        ("\\.\\(i?html?\\|xml\\)$"
         (backcolor #xfff0f6))
        ("\\.\\(php3?\\|phtml\\|inc\\)$"
         (backcolor #xe0ffff))

みたいな感じで書く。色指定はなぜかBBGGRRの順なので注意しよう。また、バッファごとの指定で意味を持つのは"unselectedModeLineBg"までで、それ以降の設定は無視されるようだ。