From a83b67bb4174cbb125bee3a920ac98344f36facb Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Thu, 1 May 2025 21:23:33 +0300 Subject: [PATCH] Embed html, yaml and toml in markdown-ts-mode. * lisp/textmodes/markdown-ts-mode.el (markdown-ts--treesit-settings): Use @italic on the whole 'block_quote'. (markdown-ts-outline-predicate): New function. (markdown-ts--range-settings): Embed 'yaml' in host 'markdown', embed 'toml' in host 'markdown', embed 'html' in host 'markdown-inline', and use local 'html_block'. (markdown-ts-setup): Append html/yaml/toml to treesit-font-lock-settings and treesit-font-lock-feature-list when their grammars are ready. (markdown-ts-mode): Set comment-start/comment-end. Set treesit-outline-predicate to 'markdown-ts-outline-predicate'. * lisp/textmodes/toml-ts-mode.el (toml-ts-mode--font-lock-feature-list): New variable. (toml-ts-mode): Use it. * lisp/textmodes/yaml-ts-mode.el (yaml-ts-mode--font-lock-feature-list): New variable. (yaml-ts-mode): Use it. (yaml-ts-mode--outline-nodes): New variable. (yaml-ts-mode--outline-predicate): Use it. * lisp/treesit-x.el (liquid-generic-ts-mode): Use 'treesit-ready-p' on optional 'yaml' grammar. Merge 'yaml-ts-mode--font-lock-feature-list'. (cherry picked from commit 1b0fe9b387ee4021b86f6fb120f5f7ed05367a9d) --- lisp/textmodes/markdown-ts-mode.el | 71 ++++++++++++++++++++++++++++-- lisp/textmodes/toml-ts-mode.el | 13 +++--- lisp/textmodes/yaml-ts-mode.el | 22 +++++---- lisp/treesit-x.el | 11 +++-- 4 files changed, 98 insertions(+), 19 deletions(-) diff --git a/lisp/textmodes/markdown-ts-mode.el b/lisp/textmodes/markdown-ts-mode.el index e09a18fde5e..572a61cb6f4 100644 --- a/lisp/textmodes/markdown-ts-mode.el +++ b/lisp/textmodes/markdown-ts-mode.el @@ -178,7 +178,8 @@ maps to tree-sitter language `cpp'.") :language 'markdown :feature 'paragraph :override 'prepend - '((block_quote_marker) @markdown-ts-delimiter + '((block_quote) @italic + (block_quote_marker) @markdown-ts-delimiter (fenced_code_block_delimiter) @markdown-ts-delimiter (fenced_code_block (info_string (language) @markdown-ts-language-keyword)) @@ -217,6 +218,12 @@ maps to tree-sitter language `cpp'.") (treesit-node-text (treesit-node-parent node)) name))) +(defun markdown-ts-outline-predicate (node) + "Match a hierarchical section that has a heading." + (and (equal (treesit-node-type node) "section") + (when-let* ((child (treesit-node-child node 0))) + (equal (treesit-node-type child) "atx_heading")))) + ;;; Code blocks (defvar-local markdown-ts--configured-languages nil @@ -287,10 +294,26 @@ the same features enabled in MODE." :range-fn #'treesit-range-fn-exclude-children '((inline) @markdown-inline) + :embed 'yaml + :host 'markdown + :local t + '((minus_metadata) @yaml) + + :embed 'toml + :host 'markdown + :local t + '((plus_metadata) @toml) + :embed 'html :host 'markdown + :local t '((html_block) @html) + :embed 'html + :host 'markdown-inline + :local t + '((html_tag) @html) + :embed #'markdown-ts--convert-code-block-language :host 'markdown :local t @@ -303,19 +326,61 @@ the same features enabled in MODE." "Setup tree-sitter for `markdown-ts-mode'." (setq-local treesit-font-lock-settings markdown-ts--treesit-settings) (setq-local treesit-range-settings (markdown-ts--range-settings)) + + (when (treesit-ready-p 'html t) + (require 'html-ts-mode) + (defvar html-ts-mode--font-lock-settings) + (defvar html-ts-mode--treesit-font-lock-feature-list) + (setq-local treesit-font-lock-settings + (append treesit-font-lock-settings + html-ts-mode--font-lock-settings)) + (setq-local treesit-font-lock-feature-list + (treesit-merge-font-lock-feature-list + treesit-font-lock-feature-list + html-ts-mode--treesit-font-lock-feature-list))) + + (when (treesit-ready-p 'yaml t) + (require 'yaml-ts-mode) + (defvar yaml-ts-mode--font-lock-settings) + (defvar yaml-ts-mode--font-lock-feature-list) + (setq-local treesit-font-lock-settings + (append treesit-font-lock-settings + yaml-ts-mode--font-lock-settings)) + (setq-local treesit-font-lock-feature-list + (treesit-merge-font-lock-feature-list + treesit-font-lock-feature-list + yaml-ts-mode--font-lock-feature-list))) + + (when (treesit-ready-p 'toml t) + (require 'toml-ts-mode) + (defvar toml-ts-mode--font-lock-settings) + (defvar toml-ts-mode--font-lock-feature-list) + (setq treesit-font-lock-settings + (append treesit-font-lock-settings + toml-ts-mode--font-lock-settings)) + (setq-local treesit-font-lock-feature-list + (treesit-merge-font-lock-feature-list + treesit-font-lock-feature-list + toml-ts-mode--font-lock-feature-list))) + (treesit-major-mode-setup)) ;;;###autoload (define-derived-mode markdown-ts-mode text-mode "Markdown" "Major mode for editing Markdown using tree-sitter grammar." + + (setq-local comment-start "") + (setq-local font-lock-defaults nil treesit-font-lock-feature-list '((delimiter heading) (paragraph) (paragraph-inline))) (setq-local treesit-simple-imenu-settings - `(("Headings" markdown-ts-imenu-node-p nil markdown-ts-imenu-name-function))) - (setq-local treesit-outline-predicate "section") + `(("Headings" ,#'markdown-ts-imenu-node-p + nil ,#'markdown-ts-imenu-name-function))) + (setq-local treesit-outline-predicate #'markdown-ts-outline-predicate) (when (and (treesit-ensure-installed 'markdown) (treesit-ensure-installed 'markdown-inline)) diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el index b1414852dbb..854ff93fd6b 100644 --- a/lisp/textmodes/toml-ts-mode.el +++ b/lisp/textmodes/toml-ts-mode.el @@ -114,6 +114,13 @@ '((ERROR) @font-lock-warning-face)) "Font-lock settings for TOML.") +(defvar toml-ts-mode--font-lock-feature-list + '((comment) + (constant number pair string) + (escape-sequence) + (delimiter error)) + "Font-lock feature list for TOML.") + (defun toml-ts-mode--defun-name (node) "Return the defun name of NODE. Return nil if there is no name or if NODE is not a defun node." @@ -153,11 +160,7 @@ Return nil if there is no name or if NODE is not a defun node." ;; Font-lock. (setq-local treesit-font-lock-settings toml-ts-mode--font-lock-settings) - (setq-local treesit-font-lock-feature-list - '((comment) - (constant number pair string) - (escape-sequence) - (delimiter error))) + (setq-local treesit-font-lock-feature-list toml-ts-mode--font-lock-feature-list) ;; Imenu. (setq-local treesit-simple-imenu-settings diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el index 3338044652b..6bd1bd946ae 100644 --- a/lisp/textmodes/yaml-ts-mode.el +++ b/lisp/textmodes/yaml-ts-mode.el @@ -126,6 +126,13 @@ '((ERROR) @font-lock-warning-face)) "Tree-sitter font-lock settings for `yaml-ts-mode'.") +(defvar yaml-ts-mode--font-lock-feature-list + '((comment) + (string type) + (constant escape-sequence number property) + (bracket delimiter error misc-punctuation)) + "Tree-sitter font-lock feature list for `yaml-ts-mode'.") + (defun yaml-ts-mode--fill-paragraph (&optional justify) "Fill paragraph. Behaves like `fill-paragraph', but respects block node @@ -158,11 +165,14 @@ Return nil if there is no name or if NODE is not a defun node." node "key") t))) +(defvar yaml-ts-mode--outline-nodes + (rx (or "block_mapping_pair" "block_sequence_item")) + "Node names for outline headings.") + (defun yaml-ts-mode--outline-predicate (node) "Limit outlines to top-level mappings." - (let ((regexp (rx (or "block_mapping_pair" "block_sequence_item")))) - (when (string-match-p regexp (treesit-node-type node)) - (not (treesit-node-top-level node regexp))))) + (when (string-match-p yaml-ts-mode--outline-nodes (treesit-node-type node)) + (not (treesit-node-top-level node yaml-ts-mode--outline-nodes)))) ;;;###autoload (define-derived-mode yaml-ts-mode text-mode "YAML" @@ -183,11 +193,7 @@ Return nil if there is no name or if NODE is not a defun node." ;; Font-lock. (setq-local treesit-font-lock-settings yaml-ts-mode--font-lock-settings) - (setq-local treesit-font-lock-feature-list - '((comment) - (string type) - (constant escape-sequence number property) - (bracket delimiter error misc-punctuation))) + (setq-local treesit-font-lock-feature-list yaml-ts-mode--font-lock-feature-list) (setq-local fill-paragraph-function #'yaml-ts-mode--fill-paragraph) diff --git a/lisp/treesit-x.el b/lisp/treesit-x.el index b0e3863c034..d13d6b1a35a 100644 --- a/lisp/treesit-x.el +++ b/lisp/treesit-x.el @@ -244,9 +244,10 @@ of `define-treesit-generic-mode'. "for_loop_statement") eos))))) - (when (treesit-ensure-installed 'yaml) - (defvar yaml-ts-mode--font-lock-settings) + (when (treesit-ready-p 'yaml t) (require 'yaml-ts-mode) + (defvar yaml-ts-mode--font-lock-settings) + (defvar yaml-ts-mode--font-lock-feature-list) (setq-local treesit-range-settings (append treesit-range-settings (treesit-range-rules @@ -256,7 +257,11 @@ of `define-treesit-generic-mode'. '(((front_matter) @cap))))) (setq-local treesit-font-lock-settings (append treesit-font-lock-settings - yaml-ts-mode--font-lock-settings)))) + yaml-ts-mode--font-lock-settings)) + (setq-local treesit-font-lock-feature-list + (treesit-merge-font-lock-feature-list + treesit-font-lock-feature-list + yaml-ts-mode--font-lock-feature-list)))) (defvar alpinejs-generic-ts-attr-regexp (rx bos (or "x-" ":" "@")) -- 2.39.5