mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2026-09-10 07:46:51 -04:00
Fix filling around lists in markdown-ts-mode (bug#81712)
* lisp/textmodes/markdown-ts-mode.el (markdown-ts--node-containing): New function. (markdown-ts--list-item-at-point, markdown-ts--adaptive-fill) (markdown-ts--fill-forward-paragraph): Use it, stop at the list item's last non-blank line, and clamp the query end to point-max.
This commit is contained in:
parent
debf9d86a9
commit
84e2bb9a5d
|
|
@ -2174,36 +2174,16 @@ a line's leading whitespace resolves to the item on that line,
|
|||
not to a preceding item whose node spans the whitespace.
|
||||
Inside block quotes, also try from the content position past
|
||||
the `>' markers."
|
||||
(when-let* ((pos (save-excursion (back-to-indentation) (point)))
|
||||
(node (treesit-node-at pos 'markdown))
|
||||
(bol (line-beginning-position))
|
||||
(eol (line-end-position)))
|
||||
(or (let ((item (treesit-parent-until
|
||||
node (lambda (n)
|
||||
(equal (treesit-node-type n) "list_item")))))
|
||||
;; Verify the current line is within the item's range.
|
||||
;; `treesit-node-at' can return a node inside a list_item
|
||||
;; even when point is on a preceding line.
|
||||
(when (and item
|
||||
(<= (treesit-node-start item) eol)
|
||||
(>= (treesit-node-end item) bol))
|
||||
item))
|
||||
(let ((pos (save-excursion (back-to-indentation) (point)))
|
||||
;; When back-to-indentation lands on block quote markers,
|
||||
;; skip past them and try from the content position.
|
||||
(let ((content-pos (save-excursion
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward "> \t")
|
||||
(point))))
|
||||
(when (> content-pos pos)
|
||||
(when-let* ((cnode (treesit-node-at content-pos 'markdown)))
|
||||
(let ((item (treesit-parent-until
|
||||
cnode
|
||||
(lambda (n)
|
||||
(equal (treesit-node-type n) "list_item")))))
|
||||
(when (and item
|
||||
(<= (treesit-node-start item) eol)
|
||||
(>= (treesit-node-end item) bol))
|
||||
item))))))))
|
||||
(content-pos (save-excursion
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward "> \t")
|
||||
(point))))
|
||||
(or (markdown-ts--node-containing pos "\\`list_item\\'")
|
||||
(and (> content-pos pos)
|
||||
(markdown-ts--node-containing content-pos "\\`list_item\\'")))))
|
||||
|
||||
(defun markdown-ts--list-marker-width (item)
|
||||
"Return the width of ITEM's list marker including trailing space."
|
||||
|
|
@ -2609,14 +2589,24 @@ of the item's text. JUSTIFY is as in `fill-paragraph'."
|
|||
;; as per the contract of `fill-paragraph-function'.
|
||||
t))
|
||||
|
||||
(defun markdown-ts--node-containing (pos type)
|
||||
"Return the innermost node matching TYPE that contains POS, or nil.
|
||||
TYPE is as in `treesit-parent-until'. When no leaf node covers POS,
|
||||
`treesit-node-at' falls back to one that merely ends at POS, which does
|
||||
not contain POS and must not be reported here."
|
||||
(and-let* ((node (treesit-node-at pos 'markdown))
|
||||
(parent (treesit-parent-until node type))
|
||||
((<= (treesit-node-start parent) pos))
|
||||
((< pos (treesit-node-end parent))))
|
||||
parent))
|
||||
|
||||
(defun markdown-ts--adaptive-fill ()
|
||||
"Return the fill prefix for the current line in Markdown.
|
||||
When inside a list item, return spaces matching the column where
|
||||
the item's text starts."
|
||||
(and-let* ((node (treesit-node-at
|
||||
(and-let* ((item (markdown-ts--node-containing
|
||||
(save-excursion (back-to-indentation) (point))
|
||||
'markdown))
|
||||
(item (treesit-parent-until node "\\`list_item\\'")))
|
||||
"\\`list_item\\'")))
|
||||
(make-string (markdown-ts--list-item-text-column item) ?\s)))
|
||||
|
||||
(defun markdown-ts--fill-forward-paragraph (arg)
|
||||
|
|
@ -2640,21 +2630,21 @@ unfilled."
|
|||
(block (car (treesit-query-capture
|
||||
(treesit-buffer-root-node 'markdown)
|
||||
markdown-ts--fill-unfillable-block-query
|
||||
pos (1+ pos))))
|
||||
pos (min (1+ pos) (point-max)))))
|
||||
(indented-pos (save-excursion
|
||||
(goto-char pos)
|
||||
(back-to-indentation)
|
||||
(point)))
|
||||
(node (treesit-node-at indented-pos 'markdown))
|
||||
(item (treesit-parent-until node "\\`list_item\\'")))
|
||||
(item (markdown-ts--node-containing
|
||||
indented-pos "\\`list_item\\'")))
|
||||
;; When moving forward from whitespace between list items,
|
||||
;; skip to the next non-blank position and check again.
|
||||
(when (and (not item) (not block) (> direction 0))
|
||||
(let ((next-pos (save-excursion
|
||||
(skip-chars-forward " \t\n")
|
||||
(point))))
|
||||
(setq node (treesit-node-at next-pos 'markdown))
|
||||
(setq item (treesit-parent-until node "\\`list_item\\'"))))
|
||||
(setq item (markdown-ts--node-containing
|
||||
next-pos "\\`list_item\\'"))))
|
||||
(cond
|
||||
;; Inside an unfillable block: skip over it entirely.
|
||||
(block
|
||||
|
|
@ -2662,9 +2652,24 @@ unfilled."
|
|||
(setq moved (1+ moved)))
|
||||
;; Inside a list item: treat as paragraph boundary.
|
||||
(item
|
||||
(if (> direction 0)
|
||||
(goto-char (treesit-node-end item))
|
||||
(goto-char (treesit-node-start item)))
|
||||
(let ((target (if (< direction 0)
|
||||
(treesit-node-start item)
|
||||
;; The item node extends over the blank line
|
||||
;; separating the list from the block that
|
||||
;; follows it; stop after the item's last
|
||||
;; non-blank line, or filling deletes that
|
||||
;; blank line (bug#81712).
|
||||
(save-excursion
|
||||
(goto-char (treesit-node-end item))
|
||||
(skip-chars-backward
|
||||
" \t\n" (treesit-node-start item))
|
||||
(line-beginning-position 2)))))
|
||||
;; Move to the item boundary only when that makes progress;
|
||||
;; reporting a move we did not make loops `fill-region'
|
||||
;; forever (bug#81712).
|
||||
(if (if (> direction 0) (> target (point)) (< target (point)))
|
||||
(goto-char target)
|
||||
(forward-paragraph direction)))
|
||||
(setq moved (1+ moved)))
|
||||
;; Default: use standard paragraph motion.
|
||||
(t
|
||||
|
|
|
|||
Loading…
Reference in a new issue