8000 Fontify the names of struct fields by 1buran · Pull Request #454 · dominikh/go-mode.el · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions go-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,14 @@ statements."
;; Match name+type pairs, such as "foo bar" in "var foo bar".
(go--match-ident-type-pair 2 font-lock-type-face)

;; Match the name of a struct field, such as "foo" in "foo int".
;; `font-lock-property-name-face' was added in Emacs 29 and,
;; unlike the older font-lock faces, is not also a variable, so
;; it has to be quoted: `font-lock-apply-highlight' evaluates the
;; face expression.
,@(when (facep 'font-lock-property-name-face)
'((go--match-struct-field 1 'font-lock-property-name-face)))

;; An anchored matcher for type switch case clauses.
(go--match-type-switch-case
(go--fontify-type-switch-case
Expand Down Expand Up @@ -1577,6 +1585,47 @@ succeeds."

found-match))

(defconst go--struct-field-name-re
;; A name starts a field declaration: it is at the beginning of a
;; line, or follows a comma or a semicolon.
(concat "\\(?:^\\|[,{;]\\)[ \t]*\\(" go-identifier-regexp "\\)"))

(defun go--match-struct-field (end)
"Search for the name of a field in a struct definition.

A field consists of the names of the field followed by its type,
as in \"foo int\" or \"foo, bar int\", or of a type alone, in which
case the field is embedded and has no name. Return non-nil if
search succeeds, yielding match-data for a name -- subexp 1 -- so
that it can be fontified with `font-lock-property-name-face'."
(let (found-match)
(while (and
(not found-match)
(re-search-forward go--struct-field-name-re end t))

(let ((name (match-string 1)) (name-end (match-end 1)))
(when (and
;; A name is never a keyword.
(not (member name go-mode-keywords))

;; Only fields of a struct are properties. A type has
;; to follow the names, on the same line, which rules
;; out the embedded "foo", a qualified type such as
;; "io.Reader", and a composite literal key "foo:".
(save-match-data
(and
(go--in-struct-definition-p)
(save-excursion
(goto-char name-end)
(while (looking-at (concat "[ \t]*,[ \t]*"
go-identifier-regexp))
(goto-char (match-end 0)))
;; A type starts with a name, "[", "*" or "<".
(looking-at "[ \t]+[[:alpha:]_*<[]")))))
(setq found-match t))))

found-match))

(defconst go--single-func-result-re (concat ")[[:space:]]+" go-type-name-regexp "\\(?:$\\|[[:space:]),]\\)"))

(defun go--match-single-func-result (end)
Expand Down
24 changes: 17 additions & 7 deletions test/go-font-lock-test.el
8000
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,22 @@ QKfuncK (VfV TintT) {}
"))

(ert-deftest go--fontify-struct ()
(go--should-fontify "KstructK { i TintT }")
(go--should-fontify "KstructK { a, b TintT }")
(go--should-fontify "KstructK { PiP TintT }")
(go--should-fontify "KstructK { PaP, PbP TintT }")

(go--should-fontify "
KstructK {
a TboolT
c KstructK { f *Tfoo.ZebraT }
PaP TboolT
PcP KstructK { PfP *Tfoo.ZebraT }
}")

;; A field's type may start with a keyword, and a field may have no
;; name at all, in which case it is embedded.
(go--should-fontify "
KstructK {
PiP KchanK TstringT
io.Reader
PjP []TstringT
}"))

(ert-deftest go--fontify-interface ()
Expand Down Expand Up @@ -86,7 +95,7 @@ KdefaultK:

(go--should-fontify "
KswitchK foo.(KtypeK) {
KcaseK KinterfaceK { FfooF(TintT, TstringT) }, KstructK { i, j TintT }, TstringT:
KcaseK KinterfaceK { FfooF(TintT, TstringT) }, KstructK { PiP, PjP TintT }, TstringT:
}")

(go--should-fontify "
Expand Down Expand Up @@ -167,7 +176,7 @@ KtypeK (
(go--should-fontify "KvarK VfooV, VbarV = bar, baz")
(go--should-fontify "KvarK VfooV TbarT D// DQcoolQ")
(go--should-fontify "KvarK VfooV TbarT = baz")
(go--should-fontify "KvarK VfooV KstructK { i TintT } = baz")
(go--should-fontify "KvarK VfooV KstructK { PiP TintT } = baz")
(go--should-fontify "KvarK VfooV []*Tfoo.ZarT D// DQcoolQ")

(go--should-fontify "
Expand Down Expand Up @@ -254,7 +263,7 @@ expects \"make\" to be a (B)uiltin and \"int\" to be a (T)type."
;; First pass through buffer looks for the face tags. We delete
;; the tags and record the expected face ranges in `faces'.
(let ((case-fold-search nil) faces start start-pos)
(while (re-search-forward "[TBKCFSNVDQ]" nil t)
(while (re-search-forward "[TBKCFSNVDPQ]" nil t)
(let ((found-char (char-before)))
(backward-delete-char 1)
(if start
Expand All @@ -269,6 +278,7 @@ expects \"make\" to be a (B)uiltin and \"int\" to be a (T)type."
(?S (if (eq mode 'go-mode) 'font-lock-string-face 'go-dot-mod-module-semver))
(?N (if (eq mode 'go-mode) 'font-lock-negation-char-face 'go-dot-mod-module-name))
(?V (if (eq mode 'go-mode) 'font-lock-variable-name-face 'go-dot-mod-module-version))
(?P 'font-lock-property-name-face)
(?D 'font-lock-comment-delimiter-face)
(?Q 'font-lock-comment-face))))
(setq faces (append faces `((,face ,start-pos ,(point))))))
Expand Down
0