Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coloring of scaladoc comments #85

Open
jeberger opened this issue Dec 29, 2014 · 1 comment
Open

Coloring of scaladoc comments #85

jeberger opened this issue Dec 29, 2014 · 1 comment

Comments

@jeberger
Copy link
Contributor

It would be nice if scaladoc comments could be coloured depending on their contents (i.e. use a different face for @tags and for wiki markup at least). I've given it a try, and you can see where I got here.

Note that:

  • It's not perfect, in particular it tends to loose the fontification randomly (and revert to font-lock-doc-face).
  • The scala-font-lock-doc-comments function was taken from cc-mode with very minor changes, and therefore it depends on other cc-mode functions. It might also be overkill for us since it is able to support several doc tools (javadoc, doxygen, gtk-doc, ...) and we don't need that much flexibility.
@hvesalai
Copy link
Owner

I copy-pasted your code here so that if the link goes does, the code is not lost

(make-face 'font-lock-header-face)
(set-face-attribute 'font-lock-header-face nil :weight 'bold :underline t)

;; Known limitations:
;; - Cannot combine wiki  faces that start or  end together: '''''bold
;;   italic''' does  not work. However '''bold ''bold italic'' bold'''
;;   works as expected.
;; - Sometimes parts of the comment revert back to font-lock-doc-face.
;;   Changing the  text of the comment  may make them go  back to more
;;   specific faces.
(defconst scaladoc-font-lock-doc-comments
   `(
       ;; Parameters and exceptions
       ("\\(@\\(?:t?param\\|throws\\)\\)\\s +\\([a-zA-Z_][a-zA-Z_1-90]*\\)"
        (1 ,c-doc-markup-face-name prepend nil)
        (2 font-lock-variable-name-face prepend nil))
       ;; Use cases
       ("\\(@usecase\\)\\s-+\\(.*\\)"
        (1 ,c-doc-markup-face-name prepend nil)
        (2 font-lock-variable-name-face prepend nil))
       ;; Wiki formatting
       ("\\s-\\(''\\sw\\(?:\\(?:'?[^']\\|\\Sw''\\|''\\sw\\)*\\sw\\)?''\\)\\(?:\\s-\\|$\\)"
        1 (quote italic) prepend nil)
       ("\\s-\\('''\\sw\\(?:\\(?:'?'?[^']\\|\\Sw'''\\|'''\\sw\\)*\\sw\\)?'''\\)\\(?:\\s-\\|$\\)"
        1 (quote bold) prepend nil)
       ("\\s-\\(__\\sw\\(?:\\(?:_?[^_]\\|\\Sw__\\|__\\sw\\)*\\sw\\)?__\\)\\(?:\\s-\\|$\\)"
        1 (quote underline) prepend nil)
       ("\\s-\\(`\\sw\\(?:\\(?:[^`]\\|\\Sw`\\|`\\sw\\)*\\sw\\)?`\\)\\(?:\\s-\\|$\\)"
        1 (quote underline) prepend nil) ; Should be monospace, but since the whole file already is...
       ("\\s-\\(\\^\\sw\\(?:\\(?:[^^]\\|\\Sw\\^\\|\\^\\sw\\)*\\sw\\)?\\^\\)\\(?:\\s-\\|$\\)"
        1 (quote superscript) prepend nil)
       ("\\s-\\(,,\\sw\\(?:\\(?:,?[^,]\\|\\Sw,,\\|,,\\sw\\)*\\sw\\)?,,\\)\\(?:\\s-\\|$\\)"
        1 (quote subscript) prepend nil)
       ("\\[\\[\\(?:]?[^]]\\)*\\]\\]"
        0 (quote underline) prepend nil) ; Links
       ("^\\s-*\\*\\s-*\\(=[^=]\\(?:.*[^=]\\)?=\\)\\s-*$"
        1 'font-lock-header-face prepend nil) ; Header 1
       ("^\\s-*\\*\\s-*\\(==[^=]\\(?:.*[^=]\\)?==\\)\\s-*$"
        1 'font-lock-header-face prepend nil) ; Header 2
       ("^\\s-*\\*\\s-*\\(===[^=]\\(?:.*[^=]\\)?===\\)\\s-*$"
        1 'font-lock-header-face prepend nil) ; Header 3
       ("^\\s-*\\*\\s-*\\(====[^=]\\(?:.*[^=]\\)?====\\)\\s-*$"
        1 'font-lock-header-face prepend nil) ; Header 4
       ;; Macros
       ("\\(@define\\)\\s +\\([a-zA-Z_][a-zA-Z_1-90]*\\)"
        (1 ,c-doc-markup-face-name prepend nil)
        (2 font-lock-variable-name-face prepend nil))
       ("\\$\\sw+"
        0 (quote underline) prepend nil)
       ;; Code blocks (only change the opening and closing brackets)
       ("{{{\\|}}}"
        0 ,c-doc-markup-face-name prepend nil)
       ;; HTML entities.
       ("&\\(\\sw\\|[.:]\\)+;"
          0 ,c-doc-markup-face-name prepend nil)
       ;; Other keywords
       (,(concat "@"
            (regexp-opt (list
                         "author"
                         "constructor"
                         "deprecated"
                         "example"
                         "inheritdoc"
                         "migration"
                         "note"
                         "return"
                         "see" "since"
                         "version"))
            "\\>")
          0 ,c-doc-markup-face-name prepend nil)
       (,(concat "@"
            (regexp-opt (list "todo"))
            "\\>")
          0 font-lock-warning-face prepend nil)))

(defun scala-font-lock-doc-comments (prefix limit keywords)
  ;; Fontifies doc  comments according  to KEYWORDS.  Assumes comments
  ;; have  been fontified  with `font-lock-doc-face'  already. nil  is
  ;; always returned.
  ;;
  ;; KEYWORDS is a list like `font-lock-keywords' except that anchored
  ;; matches  and   eval  clauses  aren't  supported   and  that  some
  ;; abbreviated forms  can't be used.  The buffer is narrowed  to the
  ;; comment while  KEYWORDS is applied; leading  comment starters are
  ;; included but trailing comment enders for block comment are not.
  ;;
  ;; This function is adapted from cc-mode
  ;;
  ;; This function might do hidden buffer changes.

  (let (comment-beg region-beg)
    (if (eq (get-text-property (point) 'face)
            'font-lock-doc-face)
        ;; Handle the case when the fontified region starts inside a
        ;; comment.
        (let ((range (c-literal-limits)))
          (setq region-beg (point))
          (when range
            (goto-char (car range)))
          (when (looking-at prefix)
            (setq comment-beg (point)))))

    (while (or
            comment-beg

            ;; Search for the prefix until a match is found at the start
            ;; of a comment.
            (while (when (re-search-forward prefix limit t)
                     (setq comment-beg (match-beginning 0))
                     (or (not (c-got-face-at comment-beg
                                             c-literal-faces))
                         (and (/= comment-beg (point-min))
                              (c-got-face-at (1- comment-beg)
                                             c-literal-faces))))
              (setq comment-beg nil))
            (setq region-beg comment-beg))

      (if (elt (parse-partial-sexp comment-beg (+ comment-beg 2)) 7)
          ;; Collect a sequence of doc style line comments.
          (progn
            (goto-char comment-beg)
            (while (and (progn
                          (c-forward-single-comment)
                          (skip-syntax-forward " ")
                          (< (point) limit))
                        (looking-at prefix))))
        (goto-char comment-beg)
        (c-forward-single-comment))
      (if (> (point) limit) (goto-char limit))
      (setq comment-beg nil)

      (let ((region-end (point))
            (keylist keywords) keyword matcher highlights)
        (save-restriction
          ;; Narrow to the doc comment.  Among other things, this
          ;; helps by making "^" match at the start of the comment.
          ;; Do not include a trailing block comment ender, though.
          (and (> region-end (1+ region-beg))
               (progn (goto-char region-end)
                      (backward-char 2)
                      (looking-at "\\*/"))
               (setq region-end (point)))
          (narrow-to-region region-beg region-end)

          (while keylist
            (setq keyword (car keylist)
                  keylist (cdr keylist)
                  matcher (car keyword))
            (goto-char region-beg)
            (while (if (stringp matcher)
                       (re-search-forward matcher region-end t)
                     (funcall matcher region-end))
              (setq highlights (cdr keyword))
              (if (consp (car highlights))
                  (while highlights
                    (font-lock-apply-highlight (car highlights))
                    (setq highlights (cdr highlights)))
                (font-lock-apply-highlight highlights))))

          (goto-char region-end)))))
  nil)

(font-lock-add-keywords
 'scala-mode
 `((,(lambda (limit)
       (scala-font-lock-doc-comments "/\\*\\*[^*]" limit
         scaladoc-font-lock-doc-comments)))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants