Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs

This commit is contained in:
Eli Zaretskii 2025-11-03 09:29:35 -05:00
commit 08c1775264
11 changed files with 99 additions and 68 deletions

View file

@ -1473,7 +1473,7 @@ example, with the following pattern:
@group
(
(array :anchor (_) @@first (_) @@last :anchor)
(:equal @@first @@last)
(:eq? @@first @@last)
)
@end group
@end example
@ -1482,24 +1482,32 @@ example, with the following pattern:
tree-sitter only matches arrays where the first element is equal to
the last element. To attach a predicate to a pattern, we need to
group them together. Currently there are three predicates:
@code{:equal}, @code{:match}, and @code{:pred}.
@code{:eq?}, @code{:match?}, and @code{:pred?}.
@deffn Predicate :equal arg1 arg2
@deffn Predicate :eq? arg1 arg2
Matches if @var{arg1} is equal to @var{arg2}. Arguments can be either
strings or capture names. Capture names represent the text that the
captured node spans in the buffer.
captured node spans in the buffer. Note that this is more like
@code{equal} in Elisp, but @code{eq?} is the convention used by
tree-sitter. Previously we supported the @code{:equal} predicate but
it's now considered deprecated.
@end deffn
@deffn Predicate :match regexp capture-name
@deffn Predicate :match? capture-name regexp
Matches if the text that @var{capture-name}'s node spans in the buffer
matches regular expression @var{regexp}, given as a string literal.
Matching is case-sensitive.
Matching is case-sensitive. The ordering of the arguments doesn't
matter. Previously we supported the @code{:match} predicate but it's
now considered deprecated.
@end deffn
@deffn Predicate :pred fn &rest nodes
@deffn Predicate :pred? fn &rest nodes
Matches if function @var{fn} returns non-@code{nil} when passed each
node in @var{nodes} as arguments. The function runs with the current
buffer set to the buffer of node being queried.
buffer set to the buffer of node being queried. Be very careful when
using this predicate, since it can be expensive when used in a tight
loop. Previously we supported the @code{:pred} predicate but it's now
considered deprecated.
@end deffn
Note that a predicate can only refer to capture names that appear in
@ -1554,9 +1562,9 @@ Anchor @code{:anchor} is written as @samp{.}.
@item
@samp{:+} is written as @samp{+}.
@item
@code{:equal}, @code{:match} and @code{:pred} are written as
@code{#equal}, @code{#match} and @code{#pred}, respectively.
In general, predicates change their @samp{:} to @samp{#}.
@code{:eq?}, @code{:match?} and @code{:pred?} are written as
@code{#eq?}, @code{#match?} and @code{#pred?}, respectively. In
general, predicates change the @samp{:} to @samp{#}.
@end itemize
For example,
@ -1565,7 +1573,7 @@ For example,
@group
'((
(compound_expression :anchor (_) @@first (_) :* @@rest)
(:match "love" @@first)
(:match? "love" @@first)
))
@end group
@end example
@ -1577,7 +1585,7 @@ is written in string form as
@group
"(
(compound_expression . (_) @@first (_)* @@rest)
(#match \"love\" @@first)
(#match? \"love\" @@first)
)"
@end group
@end example

View file

@ -1049,6 +1049,18 @@ Now 'treesit-explore-mode' (or 'treesit-explore') prompts for a parser
rather than a language, and it is now possible to select a local parser
at point to explore.
+++
*** Tree-sitter query predicate :equal, :match, and :pred are deprecated
Use :eq?, :match?, :pred? instead. The change is because newer
tree-sitter library mandates query predicates to end with question mark.
Emacs will transparently converts :equal, :match and :pred to :eq?,
:match? and :pred?, respectively, so existing queries still work fine
with latest tree-sitter library. Predicate :equal is changed to :eq? to
better follow tree-sitters convention. Also, the :match? predicates
can now take the regexp as either the first or second argument, so it
works with both tree-sitter convention (regexp arg second) and Emacs
convention (regexp arg first).
** Hideshow
+++

View file

@ -57,7 +57,7 @@ A `cond*' construct is a series of clauses, and a clause
normally has the form (CONDITION BODY...).
CONDITION can be a Lisp expression, as in `cond'.
Or it can be one of`(bind* BINDINGS...)', `(match* PATTERN DATUM)',
Or it can be one of `(bind* BINDINGS...)', `(match* PATTERN DATUM)',
or `(pcase* PATTERN DATUM)',
`(bind* BINDINGS...)' means to bind BINDINGS (as if they were in `let*')

View file

@ -4324,7 +4324,7 @@ one wildcard."
(when (cdr segment)
(concat
(when group "\\(")
(if (cl-every (lambda (x) (eq x 'any-delim)) (cdr segment))
(if (all (lambda (x) (eq x 'any-delim)) (cdr segment))
(concat completion-pcm--delim-wild-regex "*?")
"[^z-a]*?")
(when group "\\)")))))

View file

@ -315,6 +315,12 @@ function is called. Subsequent calls return the first evaluated value."
(:match "\\`[A-Z]" @font-lock-type-face))
(type_identifier) @font-lock-type-face
;; In Java, var is not a keyword but rather a auto-determined type.
;; But we want to fontify it as a keyword. (The override query is
;; below the general query because :override flag is set for this
;; rule.)
((type_identifier) @font-lock-keyword-face
(:match "\\`var\\'" @font-lock-keyword-face))
[(boolean_type)
(integral_type)

View file

@ -490,17 +490,17 @@ static Lisp_Object Vtreesit_str_dot;
static Lisp_Object Vtreesit_str_question_mark;
static Lisp_Object Vtreesit_str_star;
static Lisp_Object Vtreesit_str_plus;
static Lisp_Object Vtreesit_str_pound_equal;
static Lisp_Object Vtreesit_str_pound_match;
static Lisp_Object Vtreesit_str_pound_pred;
static Lisp_Object Vtreesit_str_pound_eq_question_mark;
static Lisp_Object Vtreesit_str_pound_match_question_mark;
static Lisp_Object Vtreesit_str_pound_pred_question_mark;
static Lisp_Object Vtreesit_str_open_bracket;
static Lisp_Object Vtreesit_str_close_bracket;
static Lisp_Object Vtreesit_str_open_paren;
static Lisp_Object Vtreesit_str_close_paren;
static Lisp_Object Vtreesit_str_space;
static Lisp_Object Vtreesit_str_equal;
static Lisp_Object Vtreesit_str_match;
static Lisp_Object Vtreesit_str_pred;
static Lisp_Object Vtreesit_str_eq_question_mark;
static Lisp_Object Vtreesit_str_match_question_mark;
static Lisp_Object Vtreesit_str_pred_question_mark;
static Lisp_Object Vtreesit_str_empty;
/* This is the limit on recursion levels for some tree-sitter
@ -3471,12 +3471,12 @@ See Info node `(elisp)Pattern Matching' for detailed explanation. */)
return Vtreesit_str_star;
if (BASE_EQ (pattern, QCplus))
return Vtreesit_str_plus;
if (BASE_EQ (pattern, QCequal))
return Vtreesit_str_pound_equal;
if (BASE_EQ (pattern, QCmatch))
return Vtreesit_str_pound_match;
if (BASE_EQ (pattern, QCpred))
return Vtreesit_str_pound_pred;
if (BASE_EQ (pattern, QCequal) || BASE_EQ (pattern, QCeq_q))
return Vtreesit_str_pound_eq_question_mark;
if (BASE_EQ (pattern, QCmatch) || BASE_EQ (pattern, QCmatch_q))
return Vtreesit_str_pound_match_question_mark;
if (BASE_EQ (pattern, QCpred) || BASE_EQ (pattern, QCpred_q))
return Vtreesit_str_pound_pred_question_mark;
Lisp_Object opening_delimeter
= VECTORP (pattern)
? Vtreesit_str_open_bracket : Vtreesit_str_open_paren;
@ -3507,7 +3507,9 @@ A PATTERN in QUERY can be
:*
:+
:equal
:eq?
:match
:match?
(TYPE PATTERN...)
[PATTERN...]
FIELD-NAME:
@ -3670,7 +3672,7 @@ treesit_predicate_equal (Lisp_Object args, struct capture_range captures,
return !NILP (Fstring_equal (text1, text2));
}
/* Handles predicate (#match "regexp" @node). Return true if "regexp"
/* Handles predicate (#match? "regexp" @node). Return true if "regexp"
matches the text spanned by @node; return false otherwise.
Matching is case-sensitive. If everything goes fine, don't touch
SIGNAL_DATA; if error occurs, set it to a suitable signal data. */
@ -3680,26 +3682,25 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures,
{
if (list_length (args) != 2)
{
*signal_data = list2 (build_string ("Predicate `match' requires two "
*signal_data = list2 (build_string ("Predicate `match?' requires two "
"arguments but got"),
Flength (args));
return false;
}
Lisp_Object regexp = XCAR (args);
Lisp_Object capture_name = XCAR (XCDR (args));
Lisp_Object arg1 = XCAR (args);
Lisp_Object arg2 = XCAR (XCDR (args));
Lisp_Object regexp = SYMBOLP (arg2) ? arg1 : arg2;
Lisp_Object capture_name = SYMBOLP (arg2) ? arg2 : arg1;
if (!STRINGP (regexp) || !SYMBOLP (capture_name))
{
*signal_data = list2 (build_string ("Predicate `match?' takes a regexp "
"and a node capture (order doesn't "
"matter), but got"),
Flength (args));
return false;
}
/* It's probably common to get the argument order backwards. Catch
this mistake early and show helpful explanation, because Emacs
loves you. (We put the regexp first because that's what
string-match does.) */
if (!STRINGP (regexp))
xsignal1 (Qtreesit_query_error,
build_string ("The first argument to `match' should "
"be a regexp string, not a capture name"));
if (!SYMBOLP (capture_name))
xsignal1 (Qtreesit_query_error,
build_string ("The second argument to `match' should "
"be a capture name, not a string"));
Lisp_Object node = Qnil;
if (!treesit_predicate_capture_name_to_node (capture_name, captures, &node,
@ -3783,11 +3784,11 @@ treesit_eval_predicates (struct capture_range captures, Lisp_Object predicates,
Lisp_Object predicate = XCAR (tail);
Lisp_Object fn = XCAR (predicate);
Lisp_Object args = XCDR (predicate);
if (!NILP (Fstring_equal (fn, Vtreesit_str_equal)))
if (!NILP (Fstring_equal (fn, Vtreesit_str_eq_question_mark)))
pass &= treesit_predicate_equal (args, captures, signal_data);
else if (!NILP (Fstring_equal (fn, Vtreesit_str_match)))
else if (!NILP (Fstring_equal (fn, Vtreesit_str_match_question_mark)))
pass &= treesit_predicate_match (args, captures, signal_data);
else if (!NILP (Fstring_equal (fn, Vtreesit_str_pred)))
else if (!NILP (Fstring_equal (fn, Vtreesit_str_pred_question_mark)))
pass &= treesit_predicate_pred (args, captures, signal_data);
else
{
@ -5175,8 +5176,11 @@ syms_of_treesit (void)
DEFSYM (QCstar, ":*");
DEFSYM (QCplus, ":+");
DEFSYM (QCequal, ":equal");
DEFSYM (QCeq_q, ":eq?");
DEFSYM (QCmatch, ":match");
DEFSYM (QCmatch_q, ":match?");
DEFSYM (QCpred, ":pred");
DEFSYM (QCpred_q, ":pred?");
DEFSYM (QCline, ":line");
DEFSYM (QCcol, ":col");
DEFSYM (QCpos, ":pos");
@ -5357,12 +5361,12 @@ depending on customization of `treesit-enabled-modes'. */);
Vtreesit_str_star = build_string ("*");
staticpro (&Vtreesit_str_plus);
Vtreesit_str_plus = build_string ("+");
staticpro (&Vtreesit_str_pound_equal);
Vtreesit_str_pound_equal = build_string ("#equal");
staticpro (&Vtreesit_str_pound_match);
Vtreesit_str_pound_match = build_string ("#match");
staticpro (&Vtreesit_str_pound_pred);
Vtreesit_str_pound_pred = build_string ("#pred");
staticpro (&Vtreesit_str_pound_eq_question_mark);
Vtreesit_str_pound_eq_question_mark = build_string ("#eq?");
staticpro (&Vtreesit_str_pound_match_question_mark);
Vtreesit_str_pound_match_question_mark = build_string ("#match?");
staticpro (&Vtreesit_str_pound_pred_question_mark);
Vtreesit_str_pound_pred_question_mark = build_string ("#pred?");
staticpro (&Vtreesit_str_open_bracket);
Vtreesit_str_open_bracket = build_string ("[");
staticpro (&Vtreesit_str_close_bracket);
@ -5373,12 +5377,12 @@ depending on customization of `treesit-enabled-modes'. */);
Vtreesit_str_close_paren = build_string (")");
staticpro (&Vtreesit_str_space);
Vtreesit_str_space = build_string (" ");
staticpro (&Vtreesit_str_equal);
Vtreesit_str_equal = build_string ("equal");
staticpro (&Vtreesit_str_match);
Vtreesit_str_match = build_string ("match");
staticpro (&Vtreesit_str_pred);
Vtreesit_str_pred = build_string ("pred");
staticpro (&Vtreesit_str_eq_question_mark);
Vtreesit_str_eq_question_mark = build_string ("eq?");
staticpro (&Vtreesit_str_match_question_mark);
Vtreesit_str_match_question_mark = build_string ("match?");
staticpro (&Vtreesit_str_pred_question_mark);
Vtreesit_str_pred_question_mark = build_string ("pred?");
staticpro (&Vtreesit_str_empty);
Vtreesit_str_empty = build_string ("");

View file

@ -208,7 +208,7 @@
(should (null (cl-ldiff l l)))
(should (equal l (cl-ldiff l '())))
;; must be part of the list
(should (equal l (cl-ldiff l '(2 3))))
(should (equal l (cl-ldiff l (list 2 3))))
(should (equal '(1) (cl-ldiff l (nthcdr 1 l))))
;; should return a copy
(should-not (eq (cl-ldiff l '()) l))))

View file

@ -386,8 +386,8 @@ Evaluate BODY for each created sequence.
(should (same-contents-p (seq-union v1 v2)
'("a" "b" "c" "f" "e"))))
(let ((v1 '("a"))
(v2 '("a"))
(let ((v1 (list (make-string 1 ?a)))
(v2 (list (make-string 1 ?a)))
(testfn #'eq))
(should (same-contents-p (seq-union v1 v2 testfn)
'("a" "a")))))

View file

@ -107,21 +107,21 @@ Adapted from scenario clash-of-chans/uniquify described in Bug#48598:
(ert-info ("#chan@foonet is exclusive and not contaminated")
(with-current-buffer "#chan/127.0.0.1"
(funcall expect 1 "<bob>")
(funcall expect 10 "<bob>")
(erc-d-t-absent-for 0.1 "<joe>")
(funcall expect 1 "strength to climb")
(should (eq erc-server-process server-process-foo))))
(ert-info ("#chan@barnet is exclusive and not contaminated")
(with-current-buffer "#chan/127.0.0.1<2>"
(funcall expect 1 "<joe>")
(funcall expect 10 "<joe>")
(erc-d-t-absent-for 0.1 "<bob>")
(funcall expect 1 "the loudest noise")
(should (eq erc-server-process server-process-bar))))
(ert-info ("Part #chan@foonet")
(with-current-buffer "#chan/127.0.0.1"
(erc-d-t-search-for 1 "shake my sword")
(erc-d-t-search-for 10 "shake my sword")
(erc-cmd-PART "#chan")
(funcall expect 3 "You have left channel #chan")
(should-not (erc-get-channel-user (erc-current-nick)))

View file

@ -35,7 +35,8 @@
,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
;; ERC's tests also run in external CI that exports this variable.
(when (getenv "CI")
;; Skip on 27 because `erc-scrolltobottom-all' currently requires 28+.
(when (or (getenv "CI") (< emacs-major-version 28))
(ert-skip "Times out intermittently"))
(should-not erc-scrolltobottom-all)

View file

@ -547,10 +547,10 @@ BODY is the test body."
;; String query.
'("(string) @string
(pair key: (_) @keyword)
((_) @bob (#match \"\\\\`B.b\\\\'\" @bob))
((_) @bob (#match? \"\\\\`B.b\\\\'\" @bob))
(number) @number
((number) @n3 (#equal \"3\" @n3))
((number) @n3p (#pred treesit--ert-pred-last-sibling @n3p))"
((number) @n3 (#eq? \"3\" @n3))
((number) @n3p (#pred? treesit--ert-pred-last-sibling @n3p))"
;; Sexp query.
((string) @string
(pair key: (_) @keyword)