Function: markdown-ts--fontify-non-ts-collect-faces

markdown-ts--fontify-non-ts-collect-faces is a byte-compiled function defined in markdown-ts-mode.el.gz.

Signature

(markdown-ts--fontify-non-ts-collect-faces MODE BEG END)

Documentation

Run MODE on the BEG..END region's text and harvest face properties.

Return a list of (BUF-BEG BUF-END FACE) triples in base-buffer coordinates.

For non-tree-sitter modes use an indirect buffer narrowed to BEG..END: regex/syntactic font-lock honors narrowing and the indirect buffer shares text with the base, so this is less expensive and copy-free.

For ts modes in markdown-ts-code-block-force-conventional-modes, fall back to a temp buffer. A parser created in the source buffer does not react to narrowing in an indirect buffer derived from it (only parsers created in that indirect buffer would honor its narrowing), so reusing the host parser via an indirect buffer is not an option here. And in the host buffer itself, the inner content of a fenced code block is just opaque text inside a code_fence_content node, never re-parsed as a fresh document. A temp buffer with a fresh parser sees the inner content as a standalone markdown document, which is what we want.

Source Code

;; Defined in /usr/src/emacs/lisp/textmodes/markdown-ts-mode.el.gz
(defun markdown-ts--fontify-non-ts-collect-faces (mode beg end)
  "Run MODE on the BEG..END region's text and harvest face properties.
Return a list of (BUF-BEG BUF-END FACE) triples in base-buffer
coordinates.

For non-tree-sitter modes use an indirect buffer narrowed to BEG..END:
regex/syntactic font-lock honors narrowing and the indirect buffer
shares text with the base, so this is less expensive and copy-free.

For ts modes in `markdown-ts-code-block-force-conventional-modes', fall
back to a temp buffer.  A parser created in the source buffer does not
react to narrowing in an indirect buffer derived from it (only parsers
created in that indirect buffer would honor its narrowing), so reusing
the host parser via an indirect buffer is not an option here.  And in
the host buffer itself, the inner content of a fenced code block is
just opaque text inside a `code_fence_content' node, never re-parsed
as a fresh document.  A temp buffer with a fresh parser sees the inner
content as a standalone markdown document, which is what we want."
  (cond ((memq mode markdown-ts-code-block-force-conventional-modes)
         (let ((content (buffer-substring-no-properties beg end))
               res)
           (with-work-buffer
             (insert content)
             (markdown-ts--inhibit-messages-and-warnings
               'markdown-ts-inhibit-code-block-mode-warnings
               (delay-mode-hooks
                 (let ((markdown-ts--set-up-inline t))
                   (markdown-ts-mode))))
             (font-lock-ensure)
             (let ((pos (point-min)))
               (while (< pos (point-max))
                 (let ((next (next-single-property-change
                              pos 'face nil (point-max)))
                       (face (get-text-property pos 'face)))
                   (when face
                     ;; Translate temp-buffer offsets back to base-buffer
                     ;; positions: temp `point-min' corresponds to BEG.
                     (push (list (+ beg (1- pos)) (+ beg (1- next)) face)
                           res))
                   (setq pos next)))))
           (nreverse res)))
        (t
         (let ((indirect-buffer (make-indirect-buffer
                                 (current-buffer)
                                 (generate-new-buffer-name (buffer-name))
                                 nil 'inhibit-buffer-hooks))
               res)
           (unwind-protect
               (with-current-buffer indirect-buffer
                 (markdown-ts--inhibit-messages-and-warnings
                   'markdown-ts-inhibit-code-block-mode-warnings
                   (delay-mode-hooks (funcall mode)))
                 (narrow-to-region beg end)
                 (let ((font-lock-dont-widen t)) (font-lock-ensure))
                 (let ((pos (point-min)))
                   (while (< pos (point-max))
                     (let ((next (next-single-property-change
                                  pos 'face nil (point-max)))
                           (face (get-text-property pos 'face)))
                       (when face
                         (push (list pos next face) res))
                       (setq pos next)))))
             (kill-buffer indirect-buffer))
           (nreverse res)))))