Add more granular features in font-locking

There is now support for three font-locking levels, 'minimal',
'moderate' and 'full'.  The richest experience is to be expected from
the 'full', and all levels are enabled by default.

* lisp/progmodes/js.el (js--treesit-font-lock-settings): New defvar
renamed from 'js--treesit-settings'.

(js--treesit-font-lock-settings): New defvar renamed from
'js--json-treesit-settings'.

* lisp/progmodes/ts-mode.el (ts-mode--font-lock-settings): New defvar
renamed from 'ts-mode--settings'.
This commit is contained in:
Theodor Thornhill 2022-10-17 12:49:19 +02:00 committed by Yuan Fu
parent 85073998cb
commit c4ad36cd2d
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
2 changed files with 122 additions and 137 deletions

View file

@ -3454,19 +3454,34 @@ indentation, which-function and movement functions."
"debugger" "default" "delete" "do" "else" "export" "extends" "finally"
"for" "from" "function" "get" "if" "import" "in" "instanceof" "let" "new"
"of" "return" "set" "static" "switch" "switch" "target" "throw" "try"
"typeof" "var" "void" "while" "with" "yield"))
"typeof" "var" "void" "while" "with" "yield")
"JavaScript keywords for tree-sitter font-locking.")
(defvar js--treesit-settings
(defvar js--treesit-font-lock-settings
(treesit-font-lock-rules
:language 'javascript
:feature 'basic
:override t
`(((identifier) @font-lock-constant-face
:feature 'minimal
`(
((identifier) @font-lock-constant-face
(:match "^[A-Z_][A-Z_\\d]*$" @font-lock-constant-face))
(new_expression
constructor: (identifier) @font-lock-type-face)
[(this) (super)] @font-lock-keyword-face
[(true) (false) (null)] @font-lock-constant-face
(regex pattern: (regex_pattern)) @font-lock-string-face
(number) @font-lock-constant-face
(string) @font-lock-string-face
(comment) @font-lock-comment-face
[,@js--treesit-keywords] @font-lock-keyword-face
(template_string) @js--fontify-template-string
(template_substitution ["${" "}"] @font-lock-constant-face))
:language 'javascript
:override t
:feature 'moderate
`(
(function
name: (identifier) @font-lock-function-name-face)
@ -3479,6 +3494,21 @@ indentation, which-function and movement functions."
(method_definition
name: (property_identifier) @font-lock-function-name-face)
(variable_declarator
name: (identifier) @font-lock-variable-name-face)
(new_expression
constructor: (identifier) @font-lock-type-face)
(for_in_statement
left: (identifier) @font-lock-variable-name-face)
(arrow_function
parameter: (identifier) @font-lock-variable-name-face))
:language 'javascript
:override t
:feature 'full
`(
(variable_declarator
name: (identifier) @font-lock-function-name-face
value: [(function) (arrow_function)])
@ -3502,20 +3532,11 @@ indentation, which-function and movement functions."
property:
(property_identifier) @font-lock-function-name-face)])
(variable_declarator
name: (identifier) @font-lock-variable-name-face)
(assignment_expression
left: [(identifier) @font-lock-variable-name-face
(member_expression
property: (property_identifier) @font-lock-variable-name-face)])
(for_in_statement
left: (identifier) @font-lock-variable-name-face)
(arrow_function
parameter: (identifier) @font-lock-variable-name-face)
(pair key: (property_identifier) @font-lock-variable-name-face)
(pair value: (identifier) @font-lock-variable-name-face)
@ -3546,20 +3567,8 @@ indentation, which-function and movement functions."
(jsx_attribute
(property_identifier)
@font-lock-constant-face)
[(this) (super)] @font-lock-keyword-face
[(true) (false) (null)] @font-lock-constant-face
(regex pattern: (regex_pattern)) @font-lock-string-face
(number) @font-lock-constant-face
(string) @font-lock-string-face
(comment) @font-lock-comment-face
[,@js--treesit-keywords] @font-lock-keyword-face
(template_string) @js--fontify-template-string
(template_substitution ["${" "}"] @font-lock-constant-face))))
@font-lock-constant-face)))
"Tree-sitter font-lock settings.")
(defun js--fontify-template-string (beg end node)
"Fontify template string but not substitution inside it.
@ -3651,12 +3660,11 @@ For BACKEND and WARN see `treesit-mode-function'."
(setq-local beginning-of-defun-function #'js--treesit-beginning-of-defun)
(setq-local end-of-defun-function #'js--treesit-end-of-defun)
(setq-local font-lock-keywords-only t)
(setq-local treesit-font-lock-settings js--treesit-settings)
(setq-local treesit-font-lock-feature-list '((basic)))
(add-hook 'which-func-functions #'js-treesit-current-defun nil t)
(setq-local font-lock-keywords-only t)
(setq-local treesit-font-lock-settings js--treesit-font-lock-settings)
(setq-local treesit-font-lock-feature-list '((minimal) (moderate) (full)))
(treesit-font-lock-enable))
;; Elisp.
((eq backend 'elisp)
@ -3753,10 +3761,10 @@ For BACKEND and WARN see `treesit-mode-function'."
(js--backend-toggle 'elisp nil)
(setq-local major-mode-backend-function #'js--backend-toggle))
(defvar js--json-treesit-settings
(defvar js-json--treesit-font-lock-settings
(treesit-font-lock-rules
:language 'json
:feature 'basic
:feature 'minimal
:override t
`(
(pair
@ -3770,8 +3778,8 @@ For BACKEND and WARN see `treesit-mode-function'."
(escape_sequence) @font-lock-constant-face
(comment) @font-lock-comment-face
)))
(comment) @font-lock-comment-face))
"Font-lock settings for JSON.")
(defvar js--json-treesit-indent-rules
@ -3793,7 +3801,7 @@ For BACKEND and WARN see `treesit-mode-function'."
(setq-local indent-line-function #'treesit-indent)
(setq-local font-lock-keywords-only t)
(setq-local treesit-font-lock-settings js--json-treesit-settings)
(setq-local treesit-font-lock-settings js-json--treesit-font-lock-settings)
(treesit-font-lock-enable))
;; Elisp.
((eq backend 'elisp)

View file

@ -104,17 +104,49 @@
(no-node parent-bol 0)))
"Tree-sitter indent rules.")
(defvar ts-mode--settings
(defvar ts-mode--keywords
'("!" "abstract" "as" "async" "await" "break"
"case" "catch" "class" "const" "continue" "debugger"
"declare" "default" "delete" "do" "else" "enum"
"export" "extends" "finally" "for" "from" "function"
"get" "if" "implements" "import" "in" "instanceof" "interface"
"keyof" "let" "namespace" "new" "of" "private" "protected"
"public" "readonly" "return" "set" "static" "switch"
"target" "throw" "try" "type" "typeof" "var" "void"
"while" "with" "yield")
"TypeScript keywords for tree-sitter font-locking.")
(defvar ts-mode--font-lock-settings
(treesit-font-lock-rules
:language 'tsx
:override t
:feature 'basic
'(((identifier) @font-lock-constant-face
:feature 'minimal
`(
((identifier) @font-lock-constant-face
(:match "^[A-Z_][A-Z_\\d]*$" @font-lock-constant-face))
[,@ts-mode--keywords] @font-lock-keyword-face
[(this) (super)] @font-lock-keyword-face
[(true) (false) (null)] @font-lock-constant-face
(regex pattern: (regex_pattern)) @font-lock-string-face
(number) @font-lock-constant-face
(string) @font-lock-string-face
(template_string) @ts-mode--fontify-template-string
(template_substitution ["${" "}"] @font-lock-builtin-face)
(comment) @font-lock-comment-face)
:language 'tsx
:override t
:feature 'moderate
'(
(nested_type_identifier
module: (identifier) @font-lock-type-face)
(type_identifier) @font-lock-type-face
(predefined_type) @font-lock-type-face
(new_expression
@ -129,6 +161,29 @@
(method_definition
name: (property_identifier) @font-lock-function-name-face)
(variable_declarator
name: (identifier) @font-lock-variable-name-face)
(enum_declaration (identifier) @font-lock-type-face)
(enum_body (property_identifier) @font-lock-type-face)
(enum_assignment name: (property_identifier) @font-lock-type-face)
(assignment_expression
left: [(identifier) @font-lock-variable-name-face
(member_expression
property: (property_identifier) @font-lock-variable-name-face)])
(for_in_statement
left: (identifier) @font-lock-variable-name-face)
(arrow_function
parameter: (identifier) @font-lock-variable-name-face))
:language 'tsx
:override t
:feature 'full
'(
(variable_declarator
name: (identifier) @font-lock-function-name-face
value: [(function) (arrow_function)])
@ -151,33 +206,12 @@
(member_expression
property: (property_identifier) @font-lock-function-name-face)])
(variable_declarator
name: (identifier) @font-lock-variable-name-face)
(enum_declaration (identifier) @font-lock-type-face)
(enum_body (property_identifier) @font-lock-type-face)
(enum_assignment name: (property_identifier) @font-lock-type-face)
(assignment_expression
left: [(identifier) @font-lock-variable-name-face
(member_expression
property: (property_identifier) @font-lock-variable-name-face)])
(for_in_statement
left: (identifier) @font-lock-variable-name-face)
(arrow_function
parameter: (identifier) @font-lock-variable-name-face)
(arrow_function
parameters:
[(_ (identifier) @font-lock-variable-name-face)
(_ (_ (identifier) @font-lock-variable-name-face))
(_ (_ (_ (identifier) @font-lock-variable-name-face)))])
(pair key: (property_identifier) @font-lock-variable-name-face)
(pair value: (identifier) @font-lock-variable-name-face)
@ -211,80 +245,24 @@
[(nested_identifier (identifier)) (identifier)]
@font-lock-function-name-face)
(jsx_attribute (property_identifier) @font-lock-constant-face)
[(this) (super)] @font-lock-keyword-face
[(true) (false) (null)] @font-lock-constant-face
(regex pattern: (regex_pattern)) @font-lock-string-face
(number) @font-lock-constant-face
(string) @font-lock-string-face
(template_string) @js--fontify-template-string
(template_substitution
["${" "}"] @font-lock-constant-face)
["!"
"abstract"
"as"
"async"
"await"
"break"
"case"
"catch"
"class"
"const"
"continue"
"debugger"
"declare"
"default"
"delete"
"do"
"else"
"enum"
"export"
"extends"
"finally"
"for"
"from"
"function"
"get"
"if"
"implements"
"import"
"in"
"instanceof"
"interface"
"keyof"
"let"
"namespace"
"new"
"of"
"private"
"protected"
"public"
"readonly"
"return"
"set"
"static"
"switch"
"target"
"throw"
"try"
"type"
"typeof"
"var"
"void"
"while"
"with"
"yield"
] @font-lock-keyword-face
(comment) @font-lock-comment-face
))
(jsx_attribute (property_identifier) @font-lock-constant-face)))
"Tree-sitter font-lock settings.")
(defun ts-mode--fontify-template-string (beg end node)
"Fontify template string but not substitution inside it.
BEG, END, NODE refers to the template_string node."
(ignore end)
;; Stolen from `js--fontify-template-string'
(let ((child (treesit-node-child node 0)))
(while child
(if (equal (treesit-node-type child) "template_substitution")
(put-text-property beg (treesit-node-start child)
'face 'font-lock-string-face)
(put-text-property beg (treesit-node-end child)
'face 'font-lock-string-face))
(setq beg (treesit-node-end child)
child (treesit-node-next-sibling child)))))
(defvar ts-mode--defun-type-regexp
(rx (or "class_declaration"
"method_definition"
@ -351,9 +329,8 @@ ARG is the same as in `end-of-defun."
(setq-local end-of-defun-function #'ts-mode--end-of-defun)
(setq font-lock-keywords-only t)
(setq-local treesit-font-lock-settings ts-mode--settings)
(setq treesit-font-lock-feature-list '((basic)))
(setq-local treesit-font-lock-settings ts-mode--font-lock-settings)
(setq treesit-font-lock-feature-list '((minimal) (moderate) (full)))
(treesit-font-lock-enable))
(t
(message "Tree-sitter for TypeScript isn't available, falling back to `js-mode'")