aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuan Fu2026-04-04 22:33:19 -0700
committerYuan Fu2026-04-04 22:35:35 -0700
commit45d7678ca3717ebcb422145e5705de49df881010 (patch)
tree6300b6aaa68787ef443b57d383c2f035d2b9e1b9 /src
parentae1ac739b799608cca0ec9f0e78f2b852078bd57 (diff)
downloademacs-45d7678ca3717ebcb422145e5705de49df881010.tar.gz
emacs-45d7678ca3717ebcb422145e5705de49df881010.zip
Fix treesit-query-capture's NODE-ONLY param
Before the fix, if user uses the NODE-ONLY option, we don't keep the capture names in the results, then predicates won't work because they can't reference capture names. * src/treesit.c (query_capture_remove_capture_name): New function. (Ftreesit_query_capture): Use the new function to remove capture names AFTER running the predicate. * test/src/treesit-tests.el: (treesit-query-node-only-and-grouped): New test.
Diffstat (limited to 'src')
-rw-r--r--src/treesit.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/src/treesit.c b/src/treesit.c
index bec37067b50..c08691af3d8 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -3977,6 +3977,22 @@ treesit_initialize_query (Lisp_Object query, const TSLanguage *lang,
3977 } 3977 }
3978} 3978}
3979 3979
3980/* Go over a list from START to END (until the element eq to END),
3981 replace (capture-name . node) with just node. */
3982static void query_capture_remove_capture_name (Lisp_Object start,
3983 Lisp_Object end)
3984{
3985 Lisp_Object tail = start;
3986 FOR_EACH_TAIL (tail)
3987 {
3988 Lisp_Object cell = CAR (tail);
3989 CHECK_CONS (cell);
3990 XSETCAR (tail, CDR (cell));
3991
3992 if (EQ (CDR (tail), end)) return;
3993 }
3994}
3995
3980DEFUN ("treesit-query-capture", 3996DEFUN ("treesit-query-capture",
3981 Ftreesit_query_capture, 3997 Ftreesit_query_capture,
3982 Streesit_query_capture, 2, 6, 0, 3998 Streesit_query_capture, 2, 6, 0,
@@ -4122,18 +4138,12 @@ the query. */)
4122 TSQueryCapture capture = captures[idx]; 4138 TSQueryCapture capture = captures[idx];
4123 Lisp_Object captured_node = make_treesit_node (lisp_parser, 4139 Lisp_Object captured_node = make_treesit_node (lisp_parser,
4124 capture.node); 4140 capture.node);
4125 4141 const char *capture_name
4126 Lisp_Object cap; 4142 = ts_query_capture_name_for_id (treesit_query, capture.index,
4127 if (NILP (node_only)) 4143 &capture_name_len);
4128 { 4144 Lisp_Object cap
4129 const char *capture_name 4145 = Fcons (intern_c_string_1 (capture_name, capture_name_len),
4130 = ts_query_capture_name_for_id (treesit_query, capture.index, 4146 captured_node);
4131 &capture_name_len);
4132 cap = Fcons (intern_c_string_1 (capture_name, capture_name_len),
4133 captured_node);
4134 }
4135 else
4136 cap = captured_node;
4137 4147
4138 if (NILP (grouped)) 4148 if (NILP (grouped))
4139 result = Fcons (cap, result); /* Mode 1. */ 4149 result = Fcons (cap, result); /* Mode 1. */
@@ -4166,12 +4176,24 @@ the query. */)
4166 if (!NILP (predicate_signal_data)) 4176 if (!NILP (predicate_signal_data))
4167 break; 4177 break;
4168 4178
4169 /* Mode 1: Predicates didn't pass, roll back. */ 4179 /* Mode 1: Roll back if predicate didn't pass, don't roll back if
4170 if (!match && NILP (grouped)) 4180 predicate passed. */
4171 result = prev_result; 4181 if (NILP (grouped))
4172 /* Mode 2: Predicates pass, add this match group. */ 4182 {
4183 if (!match)
4184 result = prev_result;
4185 else if (!NILP (node_only))
4186 query_capture_remove_capture_name (result, prev_result);
4187 }
4188 /* Mode 2: Add this match group if predicate pass, don't add this
4189 group if predicate didn't pass. */
4173 if (match && !NILP (grouped)) 4190 if (match && !NILP (grouped))
4174 result = Fcons (Fnreverse (match_group), result); 4191 {
4192 match_group = Fnreverse (match_group);
4193 if (!NILP (node_only))
4194 query_capture_remove_capture_name (match_group, Qnil);
4195 result = Fcons (match_group, result);
4196 }
4175 } 4197 }
4176 4198
4177 /* Final clean up. */ 4199 /* Final clean up. */