0

Is it possible to define a second comment face and comment-start indicator in Emacs such that the second comment highlight appears even if called from within the first comment-face?

I currently have a custom Emacs mode with the following:

.emacs file:: (set-face-attribute 'font-lock-comment-face nil :foreground "gray70")

custom_mode.el:: (set (make-local-variable 'comment-start) "//")

Is it possible to add:

.emacs file:: (set-face-attribute 'font-lock-comment-face nil :foreground "gray70") (set-face-attribute 'font-lock-comment2-face nil :foreground "forestgreen")

custom_mode.el:: (set (make-local-variable 'comment-start) "//") (set (make-local-variable 'comment2-start) "||")

such that the line

//Test comment: ||Second test comment

is rendered in two colors?

Would I need to define 'comment2' elsewhere?

Thanks!

1 Answers1

0

Coloring comments is generally handled by font-lock referring to the mode's syntax table, this only supports one face for comments.

You can however, specify a regexp for font-lock to force highlight in any color you want, this way we can specify a regexp that matches "//" followed by text, followed by "||" followed by more text, and have font-lock highlight the "||" and the following text only.

Here is a basic implementation of this in a major mode.

;; your custom face to color secondary comments blue
(defface my-second-comment-face '((t (:foreground "blue"))) "its a face")

(define-derived-mode testy-mode fundamental-mode
  "test"
  (modify-syntax-entry ?/ "<1")
  (modify-syntax-entry ?/ "<2")
  (modify-syntax-entry 10 ">")
  (font-lock-add-keywords
   'testy-mode
   ;; this highlights || followed by anything to the end of the line as long as there is
   ;; a // before it on the same line.
   ;; the 2 means only highlight the second regexp group, and the t means highlight it
   ;; even if it has been highlighted already, which is should have been.
   '(("\\(//.*\\)\\(||.*$\\)" 2 'my-second-comment-face t))))

You should note that this is a basic solution that doesn't handle all cases. A normal case like

foobar // comment || more comments

will be handled correctly, but something like

foobar "string//string" || text 

will not work correctly, the || text will be highlighted even though // occurs in a string

enter image description here

If you want fontification of these secondary comments to be "smarter" you will need to look into more advanced techniques for fontification. You use a hook in jit-lock-functions to do this. In your jit lock function, you would need to scan for the ||text pattern and highlight it based on whether or not it is already in a comment which you can find out with syntax-ppss assuming your syntax table is set up correctly.

Jordon Biondo
  • 3,974
  • 1
  • 27
  • 37
  • This is very helpful! I am assuming this code in implemented from the .emacs file? Or is it parsed out so that the modify-syntax-entry lines are in the custom_mode.el file with the other syntax table calls? I've not been able to get it to function, but I think I am placing it in the wrong sections. – user2597644 Dec 09 '14 at 18:58
  • you can eval that code anywhere you want, then open up a new buffer, do M-x testy-mode and type the text like in the picture and it should highlight. If it doesn't highlight immediately, type M-o M-o – Jordon Biondo Dec 09 '14 at 19:01
  • You need to evaluate the code first, try pasting it in your scratch buffer and running M-x eval-buffer – Jordon Biondo Dec 09 '14 at 21:33
  • My mistake - sorry; I realized I was modding a .emacs file when the .emacs.el file was controlling things. I added the code to that, and M-x testy-mode changes the entire file contents to the target my-second-comment-face color. The test line "//comment1 || comment2" still doesn't call the second color, however. Placing the code in a scratch buffer, followed by the test line and doing M-x eval-buffer returns "Symbol's value as variable is void: //comment". Does it matter that the major-mode file contains the line (set (make-local-variable 'comment-start) "//") ? – user2597644 Dec 09 '14 at 22:09