Function: neocaml-mode--font-lock-settings
neocaml-mode--font-lock-settings is a natively compiled function
defined in neocaml.el.
Signature
(neocaml-mode--font-lock-settings LANGUAGE)
Documentation
Return tree-sitter font-lock settings for LANGUAGE.
The return value is suitable for treesit-font-lock-settings.
Source Code
;; Defined in /nix/store/ahssdx4rwzyxhyhavpn0bkznk13xrggi-emacs-packages-deps/share/emacs/site-lisp/elpa/neocaml-20260907.2015/neocaml.el
;; The `ocaml-interface' grammar inherits all node types from the base
;; `ocaml' grammar (overriding only `compilation_unit'), so queries
;; referencing .ml-only constructs (e.g. `application_expression',
;; `let_binding') silently produce no matches in .mli files. This
;; lets us use a single set of font-lock rules for both languages.
(defun neocaml-mode--font-lock-settings (language)
"Return tree-sitter font-lock settings for LANGUAGE.
The return value is suitable for `treesit-font-lock-settings'."
(append
(treesit-font-lock-rules
:language language
:feature 'comment
`((((comment) @font-lock-doc-face)
(:match ,neocaml--doc-comment-regexp @font-lock-doc-face))
(comment) @font-lock-comment-face
;; Preprocessor directives
(line_number_directive) @font-lock-comment-face
(directive) @font-lock-comment-face)
;; Must come after `comment' so the markup faces stack on top of
;; `font-lock-doc-face' rather than being painted over by it. The
;; doc-comment check happens inside the function (a `:match' here
;; would cons the whole comment text just to test its first chars).
:language language
:feature 'doc-markup
:override 'prepend
'((comment) @neocaml--fontify-doc-markup)
:language language
:feature 'definition
'(;; let-bound functions: with parameters, or with fun/function body
(let_binding pattern: (value_name) @font-lock-function-name-face (parameter)+)
(let_binding pattern: (value_name) @font-lock-function-name-face body: (fun_expression))
(let_binding pattern: (value_name) @font-lock-function-name-face body: (function_expression))
;; let-bound variables (must come after function patterns above)
(let_binding pattern: (value_name) @font-lock-variable-name-face (":" (_)) :? (":>" (_)) :? :anchor body: (_))
(method_definition (method_name) @font-lock-function-name-face)
(method_specification (method_name) @font-lock-function-name-face)
;; patterns containing bound variables
(value_pattern) @font-lock-variable-name-face
(constructor_pattern pattern: (value_name) @font-lock-variable-name-face)
(tuple_pattern (value_name) @font-lock-variable-name-face)
;; punned record fields in patterns
(field_pattern (field_path (field_name) @font-lock-variable-name-face) :anchor)
(field_pattern (field_path (field_name) @font-lock-variable-name-face) (type_constructor_path) :anchor)
;; signatures and misc
(instance_variable_name) @font-lock-variable-name-face
(value_specification (value_name) @font-lock-variable-name-face)
(value_specification ":" @font-lock-keyword-face)
(external (value_name) @font-lock-variable-name-face)
;; assignment of bindings in various circumstances
(type_binding ["="] @font-lock-keyword-face)
(let_binding ["="] @font-lock-keyword-face)
(field_expression ["="] @font-lock-keyword-face)
(for_expression ["="] @font-lock-keyword-face))
;; Upgrade function-typed `val' specifications (in .mli files) to the
;; function face, mirroring how function `let' bindings are highlighted
;; in implementations. This overrides the generic `value_specification'
;; rule above, so it lives in its own `:override' block under the same
;; `definition' feature.
:language language
:feature 'definition
:override t
'((value_specification (value_name) @font-lock-function-name-face (function_type)))
:language language
:feature 'keyword
`([,@neocaml-mode--keywords] @font-lock-keyword-face
(fun_expression "->" @font-lock-keyword-face)
(match_case "->" @font-lock-keyword-face)
(value_definition [(let_operator) (let_and_operator)] @font-lock-keyword-face)
(match_expression (match_operator) @font-lock-keyword-face))
;; See https://ocaml.org/manual/5.3/attributes.html
;; and https://ocaml.org/manual/5.3/extensionnodes.html
:language language
:feature 'attribute
'((attribute) @font-lock-preprocessor-face
(item_attribute) @font-lock-preprocessor-face
(floating_attribute) @font-lock-preprocessor-face
;; PPX extension nodes: [%foo ...], [%%foo ...], {%foo| ... |},
;; {%%foo| ... |}
(extension) @font-lock-preprocessor-face
(item_extension) @font-lock-preprocessor-face
(quoted_extension) @font-lock-preprocessor-face
(quoted_item_extension) @font-lock-preprocessor-face)
:language language
:feature 'string
:override t
'([(string) (quoted_string) (character)] @font-lock-string-face)
:language language
:feature 'escape-sequence
:override t
'((escape_sequence) @font-lock-escape-face
(conversion_specification) @font-lock-regexp-face)
:language language
:feature 'number
:override t
'([(number) (signed_number)] @font-lock-number-face)
:language language
:feature 'builtin
;; NOTE: these predicates must not use `regexp-opt' with `symbols', which
;; wraps the alternation in \_< ... \_>. Evaluating a symbol-boundary
;; assertion inside a `:match' predicate pulls in lazy `syntax-propertize'
;; while `treesit-query-capture' is still walking the query cursor, which
;; segfaults Emacs 31.1 (bug#81729, neocaml#67). The captures are whole
;; nodes, so anchoring the match to the node text is both safe and exact.
`(((value_path :anchor (value_name) @font-lock-builtin-face)
(:match ,(concat "\\`" (regexp-opt neocaml-mode--builtin-ids) "\\'") @font-lock-builtin-face))
((constructor_path :anchor (constructor_name) @font-lock-builtin-face)
(:match ,(concat "\\`" (regexp-opt neocaml-mode--builtin-ids) "\\'") @font-lock-builtin-face))
;; Builtin types (int, string, bool, etc.)
((type_constructor) @font-lock-builtin-face
(:match ,(concat "\\`" (regexp-opt neocaml-mode--builtin-types) "\\'") @font-lock-builtin-face)))
;; See https://ocaml.org/manual/5.3/const.html
:language language
:feature 'constant
`(;; some literals TODO: any more?
[,@neocaml-mode--constants] @font-lock-constant-face)
;; Variant constructors and polymorphic variant tags
:language language
:feature 'type
'((constructor_name) @font-lock-constant-face
(tag) @font-lock-constant-face
[(type_constructor) (type_variable) (hash_type)
(class_name) (class_type_name)] @font-lock-type-face
(function_type "->" @font-lock-type-face)
(tuple_type "*" @font-lock-type-face)
(polymorphic_variant_type ["[>" "[<" ">" "|" "[" "]"] @font-lock-type-face)
(object_type ["<" ">" ";" ".."] @font-lock-type-face)
(constructor_declaration ["->" "*"] @font-lock-type-face)
(record_declaration ["{" "}" ";"] @font-lock-type-face)
(parenthesized_type ["(" ")"] @font-lock-type-face)
(polymorphic_type "." @font-lock-type-face)
(module_name) @font-lock-type-face
(module_type_name) @font-lock-type-face)
;; Level 4 font-locking features
:language language
:feature 'operator
'((method_invocation "#" @font-lock-operator-face)
(infix_expression operator: _ @font-lock-operator-face)
(prefix_expression operator: _ @font-lock-operator-face)
;; Standalone operator tokens not inside infix/prefix expressions
["::" "<-"] @font-lock-operator-face)
:language language
:feature 'bracket
'((["(" ")" "[" "]" "{" "}" "[|" "|]" "[<" "[>"]) @font-lock-bracket-face)
:language language
:feature 'delimiter
'((["," "." ";" ":" ";;"]) @font-lock-delimiter-face)
:language language
:feature 'variable
'((value_name) @font-lock-variable-use-face)
:language language
:feature 'property
'((field_name) @font-lock-property-use-face)
:language language
:feature 'label
'(;; Labeled arguments: ~label, ?label
(label_name) @font-lock-property-use-face)
:language language
:feature 'function
:override t
'((application_expression function: (value_path (value_name) @font-lock-function-call-face))
(application_expression function: (value_path (module_path (_) @font-lock-type-face) (value_name) @font-lock-function-call-face))
;; x |> f — highlight f as function call
((infix_expression
operator: (rel_operator) @_op
right: (value_path (value_name) @font-lock-function-call-face))
(:match "^|>$" @_op))
;; f @@ x — highlight f as function call
((infix_expression
left: (value_path (value_name) @font-lock-function-call-face)
operator: (concat_operator) @_op)
(:match "^@@$" @_op))))
;; shebang is only valid in the ocaml grammar, not ocaml-interface
(when (eq language 'ocaml)
(treesit-font-lock-rules
:language 'ocaml
:feature 'comment
'((shebang) @font-lock-comment-face)))))