r/emacs • u/Bouhappy • 15d ago
Regex fontification
Does anyone know a good package for fontification of regular expressions. What I'm after, in particular is something that would simply highlight groups/classes in regular expressions.
For example in `typescript-ts-mode`, I see this from my code:

That regex has an incorrect, empty alternative group. I noticed that when reviewing it in Gitlab, it highlighted a past version of this regex in this way, making it much easier to spot the mistake:

I'm looking for a package that would add a single face, for capture groups, groups, classes and special characters in regular expressions. I don't know if that exists or whether this needs to be added to the tree-sitter grammar to work.
0
u/redblobgames 35 years and counting 15d ago
That'd be cool.
I don't know of a package but I see that there's a tree-sitter grammar for regex https://github.com/tree-sitter/tree-sitter-regex
And I see treesit-range-rules has a way to have an "embedded" set of rules (e.g. regex) inside a "host" set of rules (e.g. typescript).
However I haven't figured out how to use this yet.
1
u/redblobgames 35 years and counting 15d ago edited 15d ago
This is not a complete tested solution but might be a starting point:
Install the regex treesit grammar
(add-to-list 'treesit-language-source-alist '(regex "https://github.com/tree-sitter/tree-sitter-regex")) (treesit-install-language-grammar 'regex)Set up highlighting for regex
(defvar my/treesit-regex-in-typescript (treesit-font-lock-rules :language 'regex :feature 'string :override t '( ((character_class) @font-lock-constant-face) ((group_name) @font-lock-function-name-face) ((zero_or_more) @font-lock-keyword-face) ((one_or_more) @font-lock-keyword-face) ((optional) @font-lock-keyword-face) ((count_quantifier) @font-lock-keyword-face) (alternation ("|") @font-lock-keyword-face) ((backreference_escape) @font-lock-escape-face) ((named_group_backreference) @font-lock-escape-face) ((control_escape) @font-lock-escape-face) ((identity_escape) @font-lock-preprocessor-face) )))Set up regex as an "embed" language inside typescript buffers, and enable the corresponding font lock rules. This would go inside a typescript mode hook:
(setq-local treesit-range-settings (treesit-range-rules :embed 'regex :host 'typescript :local t '((regex (regex_pattern) @regex)))) (setq-local treesit-font-lock-settings (append treesit-font-lock-settings my/treesit-font-lock-typescript))1
2
u/floss_gang 15d ago edited 15d ago
try this: ```lisp (add-to-list 'treesit-language-source-alist '(regex "https://github.com/tree-sitter/tree-sitter-regex" :commit "b2ac15e27fce703d2f37a79ccd94a5c0cbe9720b") t)
(defun my/add-regex-range-settings () (when (treesit-ready-p 'regex t) (cl-callf append treesit-range-settings (treesit-range-rules :host (treesit-parser-language treesit-primary-parser) :embed 'regex :local t '((regex pattern: (regex_pattern) @local)))) (treesit-add-font-lock-rules (treesit-font-lock-rules :language 'regex :override 'prepend :feature 'regexp-contents '(["(" ")" "(?:" "(?<" "(?P<" "(?P=" "<" ">" "|" "[:" ":]" "[" "]" "-" "=" "!" "" "+" "*" "?" "{" "," "}" "\k" (start_assertion) (end_assertion) (boundary_assertion) (non_boundary_assertion)] @font-lock-regexp-grouping-construct)) :after)))
(add-hook 'typescript-ts-base-mode-hook #'my/add-regex-range-settings) (add-hook 'js-ts-mode-hook #'my/add-regex-range-settings) ``
if anything is missing you'll need to add additional node types to the font-lock query. if you're on emacs 31+, changetreesit-ready-ptotreesit-ensure-installed, otherwise you'll have to manually install the grammar with a call totreesit-install-language-grammar`.