Ю. Шен обсуждает в комментариях совершенно другой случай.Упомянутый синтаксис не анализируется простым синтаксическим анализатором (см., Например, syntax-ppss
).Нужно определить свой собственный обработчик шрифтов (предпочтительно jit-lock
).
В данной задаче есть особая проблема.Необходимо определить, когда пользователь завершил ввод символа, иначе каждая часть символа будет зарегистрирована в словаре и получит свой собственный цвет.Код ниже проверяет, находится ли точка вне символа.Если после символа ввести пробел, символ будет выделен.
Приведенный ниже код является лишь приблизительной реализацией одного из возможных решений.Существуют и другие, возможно, лучшие решения.
(defvar tag-font-lock-dict (make-hash-table :test 'equal)
"Dictionary that assigns colors to tags.")
(make-variable-buffer-local 'tag-font-lock-dict)
(defvar tag-font-lock-re "#[[:alnum:]]+\\>"
"Regular expression defining tags.")
(defvar tag-font-lock-colors (apply 'vector (cdddr (defined-colors)))
"Vector of available colors. We should be more selective here.")
(defvar tag-font-lock-num-used-colors 0
"Number of used colors.")
(make-variable-buffer-local 'tag-font-lock-num-used-colors)
(require 'cl)
(defun tag-font-lock-next-color ()
"Get the next color for a new tag."
(prog1
(aref tag-font-lock-colors tag-font-lock-num-used-colors)
(setq tag-font-lock-num-used-colors
(mod (1+ tag-font-lock-num-used-colors)
(length tag-font-lock-colors)))))
(defun tag-font-lock-handler (b e)
"Colorize tags in region from b to e."
(let (col ol sym (pt (point)))
(save-excursion
(remove-overlays b e 'tag-font-lock t) ;; No danger of splitted overlays. We have always full lines.
(goto-char b)
(while (re-search-forward tag-font-lock-re e 'noErr)
(when (or (= pt (match-end 0)))
(setq sym (match-string-no-properties 0)
ol (make-overlay (match-beginning 0) (match-end 0))
col (or (gethash sym tag-font-lock-dict)
(puthash sym (tag-font-lock-next-color) tag-font-lock-dict)))
(overlay-put ol 'face (list (list :foreground col)))
(overlay-put ol 'tag-font-lock t)
)))))
(defun tag-font-lock-clear ()
"Remove color from tags in current buffer."
(interactive)
(remove-overlays 0 (buffer-size) 'tag-font-lock t)
(clrhash tag-font-lock-dict))
(define-minor-mode tag-font-lock-mode
"Highlight tags."
:lighter " TH" ;; stands for tag highlight
(if tag-font-lock-mode
(progn
(setq font-lock-extend-region-functions 'font-lock-extend-region-wholelines)
(font-lock-mode 1)
(jit-lock-register 'tag-font-lock-handler))
(jit-lock-unregister 'tag-font-lock-handler)
(tag-font-lock-clear)))