9

In clojure, the comment character is ;. clojure-mode syntax highlighting + color scheme greys comment text out.

I want emacs to color lines that begin with ;-; with a different color.

For example:

;; This is a normal greyed out comment, we use ;; by convention for blocks.
;  This is a typical grey inline comment, we use ; by convention.

;-; This is recognized as a comment and is normally greyed out.
;-; I want emacs to recognize this as something a little different and give
;-; it a different color.

How can I achieve this?

4 Answers 4

8

This is what I ended up going with:

(defface special-comment '((t (:foreground "#2aa198"))) "Cyan")

(font-lock-add-keywords
 'clojure-mode '((";-;.*" 0 'special-comment t)))

";-;.*" is regex. 0 matches the entire expression. t overrides existing highlights.

More info on font-lock-add-keywords can be found here: https://www.gnu.org/software/emacs/manual/html_node/elisp/Search_002dbased-Fontification.html. Of note is the (matcher . subexp-highlighter) section.

1
  • 3
    The basic approach is sound, however, one problem with this is that it matches ;-; in any context, including inside a string. If you replace the regexp with a function that perform a search for ;-; and ignore matches in the wrong context you should have a working solution. Commented Oct 31, 2016 at 20:16
2

You want to customize font-lock-syntactic-face-function.

The function stored in that variable is called for every string and comment to decide which face to use for it. Of course, you'll want to set it buffer-locally. It receives as argument a ppss, i.e. the return value of syntax-ppss at the current position, so you can figure out whether you're inside a string by checking (nth 3 ppss) or inside a comment with (nth 4 ppss) and you get to know where that string or comment started with (nth 8 ppss), so you can go check whether it started with ;-; or something else.

1
  • 1
    if you add code, that'd benefit us all! Thanks.
    – Xah Lee
    Commented Nov 1, 2016 at 2:49
1

You can use overlay for this. You'll need to search for the ;-; to end of line, then put overlay to it.

Here's full code.

(defun my-make-overlay-bold-region (*begin *end)
  "make the region bold, using overlay.
Calls `make-overlay' and `overlay-put'. This:
 (overlay-put (make-overlay *begin *end) 'face 'bold)"
  (interactive "r")
  (progn
    (overlay-put (make-overlay *begin *end) 'face 'bold)
    (setq mark-active nil )))

(defun my-remove-overlays-region (*begin *end)
  "Call `remove-overlays' interactively.
Call (remove-overlays *begin *end)"
  (interactive "r")
  (remove-overlays *begin *end))

(defun my-color-special-comment ()
  "highlight text beging with ;-; to end of line."
  (interactive)
  (let (p1 p2)
    (save-excursion
      (goto-char (point-min))
      (while (search-forward ";-;" )
        (left-char 3)
        (setq p1 (point) p2 (line-end-position))
        (goto-char p2)
        (my-make-overlay-bold-region p1 p2)))))

(add-hook 'clojure-mode-hook 'my-color-special-comment)

2
  • 2
    This isn't the best way: it won't catch new comments of this kind automatically (unless you add it to post-command/after-change hook, but traversing the whole buffer every time could be quite slow for larger files, and being more efficient would require more complexity than the other solutions). Also, it matches ;-; inside strings too (I think Stefan's suggestion of syntax-ppss is the only way around this).
    – npostavs
    Commented Oct 31, 2016 at 16:26
  • 1
    you are right. It's a poor man's method. @Stefan's answer is proper. I'd hope if he adds code.
    – Xah Lee
    Commented Nov 1, 2016 at 2:48
1

To add to @deadghost answer with @Lindydancer advice, here is a working solution in emacs 29.

(defface warning-hash-comment
  '((t :foreground "#FF5733" :slant italic :weight bold))  ;; Color for warning comments (orange-red)
  "Face for warning comments.")

(defun my/r-setup-comment-highlighting-python ()
  "Add custom comment highlighting in ESS R mode."
  (font-lock-add-keywords
   nil
   '(("^#-#\\s-.*" 0 'warning-hash-comment t)     ; warning comments
     ("^#\\s-.*" 0 'font-lock-doc-face t))))      ; usual comments

(defun my/r-setup-comment-highlighting-lisp ()
  "Add custom comment highlighting in ESS R mode."
  (font-lock-add-keywords
   nil
   '(("^;-;\\s-.*" 0 'warning-hash-comment t)     ; warning comments
     ("^;\\s-.*" 0 'font-lock-doc-face t))))      ; usual comments

(add-hook 'ess-r-mode-hook #'my/r-setup-comment-highlighting-python)
(add-hook 'python-ts-mode-hook #'my/r-setup-comment-highlighting-python)
(add-hook 'emacs-lisp-mode-hook #'my/r-setup-comment-highlighting-lisp)

You can create more faces and add many keywords to your liking. The ^ in the regexp is to make sure to look only at start of line, \\s- for a space after the comment symbol

3
  • But it's possible for comments not to start at the beginning of a line (e.g. in Emacs Lisp), so this method is not going to work for them - correct? Also, even if there is a comment character at the beginning of a line, it could be inside a string, so @Lindydancer's objection is still applicable - correct?
    – NickD
    Commented Nov 18 at 14:42
  • Assuming I'm correct, this illustrates the problems with using regexps to do syntactic analysis properly, I believe. Assuming that syntax-ppss does a better job, it still seems that @Stefan's answer is the way to go.
    – NickD
    Commented Nov 18 at 14:45
  • Indeed it has trouble with comments not starting at the start of the line. Ignoring tabs/space can be added to the regexp, and for after code comments maybe there is a regexp that can be found too. I tried @Stefan's answer but it seemed to also remove all other syntax highlighting if you use font-lock-syntactic-face-function. If you know how to incorporate Stefan's idea properly I would love it.
    – Clement B
    Commented Nov 20 at 10:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.