Subject: bug#76791: 31.0.50; forward-list doesn't work in bash-ts-mode

From: Juri Linkov <[email-masked]>
Date: Fri, 07 Mar 2025 09:10:13 +0200

> I stumbled upon a situation where the 'forward-list' doesn't work, but
> using `backward-list` works on the same bracket pair.
>
> Steps to reproduce:
>
> 1. emacs -Q
> 2. Remove everything from the scratch buffer and paste:
>
> #!/bin/sh
>
> check_dirs_file() {
>     if [ "$(wc -l "$dirs_file")" -gt 10 ]; then
> tmp_dirs_file="$(mktemp)"
> sed '1d' "$dirs_file" > "$tmp_dirs_file"
> cp "$tmp_dirs_file" "$dirs_file"
>     fi
> }
>
> 3. M-x bash-ts-mode
> 4. Move the cursor to the opening bracket of '$(mktemp)' and execute
> 'forward-list'. It gives "No next group" message.
>
> At the same time moving the cursor to the closing bracket and using
> 'backward-list' will work. Also, if i enable bash-mode instead of the
> treesitter one, then it will work for the opening bracket too.

Thanks for the bug report.  This is the curse of the boundary condition.
For this particular case it can be fixed by the following patch.
But it will break some other cases.  And it's hard as hell to figure out
when to use '<' and when to use '<='.

diff --git a/lisp/treesit.el b/lisp/treesit.el
index c5c08f47dc3..3aa554985e4 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -2961,8 +2961,8 @@ treesit--forward-list-with-default
                              (>= default-pos (treesit-node-end sibling))))
                        (or (null parent)
                            (if (> arg 0)
-                               (< default-pos (treesit-node-end parent))
-                             (> default-pos (treesit-node-start parent)))))
+                               (<= default-pos (treesit-node-end parent))
+                             (>= default-pos (treesit-node-start parent)))))
               (goto-char default-pos))
             (when sibling
               (goto-char (if (> arg 0)