2ch-modeでIDに色付け

Jane Styleでは何回も発言したIDに色が付くようなので、
2ch-modeで同様の機能を実装してみることにした。


ある程度まで書いたところで、すでに似たような機能
公開されていることに気づいたけど、
せっかく作ったのでこっちも公開。
まあ一応こっちは何種類か色をつけられるということで。


というわけで機能について。

  • 発言回数に応じてIDの色を変える(*id-color-alist*参照)
  • 携帯から(IDの末尾が"O")の場合はIDに下線を引く

ことができます。
あと、*2ch-extract-regexp*はxyzzy Part12 290-291、300のものを
微妙に改造してますが、向こうのコードもそのまま使えるはず。

;;; 以下を.2ch/config.lに追加

;;; 二回以上発言している ID の色を変える
(defvar *2ch-extract-regexp*
  ;; 英数字しかマッチしないので ??? はこの段階で除外される。
  (compile-regexp "\\(ID:\\||\\)\\([+/0-9a-zA-Z]+\\)●?\\( BE:.+([0-9]+)\\)?\\(]\\||\\|$\\)"))
(defmacro match-id-str ()
  `(match-string 2))
(defmacro match-id-beg ()
  `(match-beginning 2))
(defmacro match-id-end ()
  `(match-end 2))

;; 発言回数や色を変える(追加する)場合はここを変更
(defvar *id-color-alist*
  `((5 . 1)                        ; 5回以上発言した場合は色1
    (2 . 4)                        ; 2回以上発言した場合は色4
    (1 . ,*thread-fgcolor-date*))) ; それ以外はデフォルトの色

(defvar-local thread-id-table nil)

(defun mobile-p (id)
  (string-match "O$" id))

(defun map-thread-id (func)
  (save-excursion
    (goto-char (point-min))
    (let (from to id)
      (while (multiple-value-setq (from to)
               (find-text-attribute 'date :start (point)))
        (goto-char from)
        (scan-buffer *2ch-extract-regexp* :regexp t :limit to)
        (when (setf id (match-id-str))
          (goto-char (match-id-beg))
          (funcall func id))
        (goto-char to)))))

(defun collect-thread-id ()
  (setf thread-id-table (make-hash-table :test #'equal :size 997))
  (map-thread-id
   #'(lambda (id)
       (setf (gethash id thread-id-table)
             (1+ (or (gethash id thread-id-table) 0))))))

(defun change-id-color ()
  (map-thread-id
   #'(lambda (id)
       (let* ((cnt (gethash id thread-id-table))
              (pair (find-if #'(lambda (val) (>= cnt val))
                             *id-color-alist* :key #'first)))
         (set-text-attribute (point) (+ (point) (length id)) 'date
                             :foreground (rest pair)
                             :underline (mobile-p id))))))

(defun change-id-color-buffer ()
  (collect-thread-id)
  (change-id-color))

(add-hook '*thread-show-pre-hook* 'change-id-color-buffer)