Function: python--treesit-fontify-string

python--treesit-fontify-string is a byte-compiled function defined in python.el.gz.

Signature

(python--treesit-fontify-string NODE OVERRIDE START END &rest _)

Documentation

Fontify string.

NODE is the string node. Do not fontify the initial f for f-strings. OVERRIDE is the override flag described in treesit-font-lock-rules. START and END mark the region to be fontified.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/python.el.gz
(defun python--treesit-fontify-string (node override start end &rest _)
  "Fontify string.
NODE is the string node.  Do not fontify the initial f for
f-strings.  OVERRIDE is the override flag described in
`treesit-font-lock-rules'.  START and END mark the region to be
fontified."
  ;; Criteria for docstring: go up the parse tree until top-level or a
  ;; node under function/class, at each level, the node is the first
  ;; child (excluding comments).  This condition also rules out negative
  ;; cases like
  ;;
  ;;     def function():
  ;;         return "some string"
  ;;
  ;; And it recognizes for BOF docstrings, and allows comments before
  ;; the docstring.
  ;;
  ;; Older grammar has function_definition -> block -> expression_statement -> string
  ;; Newer grammar has function_definition -> block -> string
  ;; This algorithm works for both.
  (let* ((cursor node)
         (face (catch 'break
                 (while t
                   (let ((parent (treesit-node-parent cursor))
                         (cursor-idx (treesit-node-index cursor)))
                     (when (null parent)
                       (throw 'break 'font-lock-doc-face))

                     (when (and (member (treesit-node-type parent)
                                        '("function_definition"
                                          "class_definition"))
                                (equal (treesit-node-field-name-for-child
                                        parent cursor-idx)
                                       "body"))
                       (throw 'break 'font-lock-doc-face))

                     ;; If there's any non-comment sibling before
                     ;; cursor, the string isn't a docstring.
                     (dotimes (idx cursor-idx)
                       (unless (equal (treesit-node-type
                                       (treesit-node-child parent idx))
                                      "comment")
                         (throw 'break 'font-lock-string-face)))
                     (setq cursor parent)))))
         (ignore-interpolation
          (not (seq-some
                (lambda (feats) (memq 'string-interpolation feats))
                (seq-take treesit-font-lock-feature-list
                          (if (fboundp 'treesit--compute-font-lock-level)
                              (treesit--compute-font-lock-level
                               treesit-font-lock-level)
                            treesit-font-lock-level)))))
         ;; If interpolation is enabled, highlight only
         ;; string_start/string_content/string_end children.  Do not
         ;; touch interpolation node that can occur inside of the
         ;; string.
         (string-nodes (if ignore-interpolation
                           (list node)
                         (treesit-filter-child
                          node
                          (lambda (ch) (member (treesit-node-type ch)
                                               '("string_start"
                                                 "string_content"
                                                 "string_end")))
                          t))))

    (dolist (string-node string-nodes)
      (let ((string-beg (treesit-node-start string-node))
            (string-end (treesit-node-end string-node)))
        (when (or ignore-interpolation
                  (equal (treesit-node-type string-node) "string_start"))
          ;; Don't highlight string prefixes like f/r/b.
          (save-excursion
            (goto-char string-beg)
            (when (re-search-forward "[\"']" string-end t)
              (setq string-beg (match-beginning 0)))))

        (treesit-fontify-with-override
         string-beg string-end face override start end)))))