aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/macfont.m50
-rw-r--r--src/nsterm.m20
-rw-r--r--src/treesit.c256
-rw-r--r--src/w32.c9
4 files changed, 265 insertions, 70 deletions
diff --git a/src/macfont.m b/src/macfont.m
index d0cdbcd08c7..9f9f6f4efaf 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -632,21 +632,35 @@ get_cgcolor_from_nscolor (NSColor *nsColor, struct frame *f)
632 632
633#define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face) \ 633#define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face) \
634 do { \ 634 do { \
635 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face)); \ 635 CGColorRef refcol = get_cgcolor (NS_FACE_FOREGROUND (face)); \
636 CGContextSetFillColorWithColor (context, refcol_) ; \ 636 CGContextSetFillColorWithColor (context, refcol); \
637 CGColorRelease (refcol_); \ 637 CGColorRelease (refcol); \
638 } while (0) 638 } while (0)
639#define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face) \ 639#define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face) \
640 do { \ 640 do { \
641 CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face)); \ 641 CGColorRef refcol = get_cgcolor (NS_FACE_BACKGROUND (face)); \
642 CGContextSetFillColorWithColor (context, refcol_); \ 642 CGContextSetFillColorWithColor (context, refcol); \
643 CGColorRelease (refcol_); \ 643 CGColorRelease (refcol); \
644 } while (0)
645#define CG_SET_FILL_COLOR_WITH_FRAME_CURSOR(context, frame) \
646 do { \
647 CGColorRef refcol \
648 = get_cgcolor_from_nscolor (FRAME_CURSOR_COLOR (frame), frame); \
649 CGContextSetFillColorWithColor (context, refcol); \
650 CGColorRelease (refcol); \
651 } while (0)
652#define CG_SET_FILL_COLOR_WITH_FRAME_BACKGROUND(context, frame) \
653 do { \
654 CGColorRef refcol \
655 = get_cgcolor_from_nscolor (FRAME_BACKGROUND_COLOR (frame), frame); \
656 CGContextSetFillColorWithColor (context, refcol); \
657 CGColorRelease (refcol); \
644 } while (0) 658 } while (0)
645#define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face) \ 659#define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face) \
646 do { \ 660 do { \
647 CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face)); \ 661 CGColorRef refcol = get_cgcolor (NS_FACE_FOREGROUND (face)); \
648 CGContextSetStrokeColorWithColor (context, refcol_); \ 662 CGContextSetStrokeColorWithColor (context, refcol); \
649 CGColorRelease (refcol_); \ 663 CGColorRelease (refcol); \
650 } while (0) 664 } while (0)
651 665
652 666
@@ -2933,9 +2947,12 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2933 { 2947 {
2934 if (s->hl == DRAW_CURSOR) 2948 if (s->hl == DRAW_CURSOR)
2935 { 2949 {
2936 CGColorRef colorref = get_cgcolor_from_nscolor (FRAME_CURSOR_COLOR (f), f); 2950 if (face && (NS_FACE_BACKGROUND (face)
2937 CGContextSetFillColorWithColor (context, colorref); 2951 == [(NSColor *) FRAME_CURSOR_COLOR (f)
2938 CGColorRelease (colorref); 2952 unsignedLong]))
2953 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face);
2954 else
2955 CG_SET_FILL_COLOR_WITH_FRAME_CURSOR (context, f);
2939 } 2956 }
2940 else 2957 else
2941 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face); 2958 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face);
@@ -2949,9 +2966,12 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y,
2949 CGContextScaleCTM (context, 1, -1); 2966 CGContextScaleCTM (context, 1, -1);
2950 if (s->hl == DRAW_CURSOR) 2967 if (s->hl == DRAW_CURSOR)
2951 { 2968 {
2952 CGColorRef colorref = get_cgcolor_from_nscolor (FRAME_BACKGROUND_COLOR (f), f); 2969 if (face && (NS_FACE_BACKGROUND (face)
2953 CGContextSetFillColorWithColor (context, colorref); 2970 == [(NSColor *) FRAME_CURSOR_COLOR (f)
2954 CGColorRelease (colorref); 2971 unsignedLong]))
2972 CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face);
2973 else
2974 CG_SET_FILL_COLOR_WITH_FRAME_BACKGROUND (context, f);
2955 } 2975 }
2956 else 2976 else
2957 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face); 2977 CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face);
diff --git a/src/nsterm.m b/src/nsterm.m
index 87bdb44eadc..ecbf80ff72d 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3750,14 +3750,18 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
3750 { 3750 {
3751 struct face *face = s->face; 3751 struct face *face = s->face;
3752 if (!face->stipple) 3752 if (!face->stipple)
3753 { 3753 {
3754 if (s->hl != DRAW_CURSOR) 3754 if (s->hl != DRAW_CURSOR)
3755 [(NS_FACE_BACKGROUND (face) != 0 3755 [(NS_FACE_BACKGROUND (face) != 0
3756 ? [NSColor colorWithUnsignedLong:NS_FACE_BACKGROUND (face)] 3756 ? [NSColor colorWithUnsignedLong:NS_FACE_BACKGROUND (face)]
3757 : FRAME_BACKGROUND_COLOR (s->f)) set]; 3757 : FRAME_BACKGROUND_COLOR (s->f)) set];
3758 else 3758 else if (face && (NS_FACE_BACKGROUND (face)
3759 [FRAME_CURSOR_COLOR (s->f) set]; 3759 == [(NSColor *) FRAME_CURSOR_COLOR (s->f)
3760 } 3760 unsignedLong]))
3761 [[NSColor colorWithUnsignedLong:NS_FACE_FOREGROUND (face)] set];
3762 else
3763 [FRAME_CURSOR_COLOR (s->f) set];
3764 }
3761 else 3765 else
3762 { 3766 {
3763 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f); 3767 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
diff --git a/src/treesit.c b/src/treesit.c
index dbbfa29c19d..d2dd83b29fe 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -421,10 +421,17 @@ static Lisp_Object Vtreesit_str_match;
421static Lisp_Object Vtreesit_str_pred; 421static Lisp_Object Vtreesit_str_pred;
422 422
423/* This is the limit on recursion levels for some tree-sitter 423/* This is the limit on recursion levels for some tree-sitter
424 functions. Remember to update docstrings when changing this 424 functions. Remember to update docstrings when changing this value.
425 value. */ 425
426const ptrdiff_t treesit_recursion_limit = 1000; 426 If we think of programs and AST, it is very rare for any program to
427bool treesit_initialized = false; 427 have a very deep AST. For example, you would need 1000+ levels of
428 nested if-statements, or a struct somehow nested for 1000+ levels.
429 It’s hard for me to imagine any hand-written or machine generated
430 program to be like that. So I think 1000 is already generous. If
431 we look at xdisp.c, its AST only have 30 levels. */
432#define TREESIT_RECURSION_LIMIT 1000
433
434static bool treesit_initialized = false;
428 435
429static bool 436static bool
430load_tree_sitter_if_necessary (bool required) 437load_tree_sitter_if_necessary (bool required)
@@ -478,40 +485,47 @@ treesit_initialize (void)
478static void 485static void
479treesit_symbol_to_c_name (char *symbol_name) 486treesit_symbol_to_c_name (char *symbol_name)
480{ 487{
481 for (int idx = 0; idx < strlen (symbol_name); idx++) 488 size_t len = strlen (symbol_name);
489 for (int idx = 0; idx < len; idx++)
482 { 490 {
483 if (symbol_name[idx] == '-') 491 if (symbol_name[idx] == '-')
484 symbol_name[idx] = '_'; 492 symbol_name[idx] = '_';
485 } 493 }
486} 494}
487 495
496/* Find the override name for LANGUAGE_SYMBOL in
497 treesit-load-name-override-list. Set NAME and C_SYMBOL to the
498 override name, and return true if there exists one, otherwise
499 return false.
500
501 This function may signal if treesit-load-name-override-list is
502 malformed. */
488static bool 503static bool
489treesit_find_override_name (Lisp_Object language_symbol, Lisp_Object *name, 504treesit_find_override_name (Lisp_Object language_symbol, Lisp_Object *name,
490 Lisp_Object *c_symbol) 505 Lisp_Object *c_symbol)
491{ 506{
492 Lisp_Object tem;
493
494 CHECK_LIST (Vtreesit_load_name_override_list); 507 CHECK_LIST (Vtreesit_load_name_override_list);
508 Lisp_Object tail = Vtreesit_load_name_override_list;
495 509
496 tem = Vtreesit_load_name_override_list; 510 FOR_EACH_TAIL (tail)
497
498 FOR_EACH_TAIL (tem)
499 { 511 {
500 Lisp_Object lang = XCAR (XCAR (tem)); 512 Lisp_Object entry = XCAR (tail);
513 CHECK_LIST (entry);
514 Lisp_Object lang = XCAR (entry);
501 CHECK_SYMBOL (lang); 515 CHECK_SYMBOL (lang);
502 516
503 if (EQ (lang, language_symbol)) 517 if (EQ (lang, language_symbol))
504 { 518 {
505 *name = Fnth (make_fixnum (1), XCAR (tem)); 519 *name = Fnth (make_fixnum (1), entry);
506 CHECK_STRING (*name); 520 CHECK_STRING (*name);
507 *c_symbol = Fnth (make_fixnum (2), XCAR (tem)); 521 *c_symbol = Fnth (make_fixnum (2), entry);
508 CHECK_STRING (*c_symbol); 522 CHECK_STRING (*c_symbol);
509 523
510 return true; 524 return true;
511 } 525 }
512 } 526 }
513 527
514 CHECK_LIST_END (tem, Vtreesit_load_name_override_list); 528 CHECK_LIST_END (tail, Vtreesit_load_name_override_list);
515 529
516 return false; 530 return false;
517} 531}
@@ -1619,6 +1633,9 @@ buffer. */)
1619 TSRange *treesit_ranges = xmalloc (sizeof (TSRange) * len); 1633 TSRange *treesit_ranges = xmalloc (sizeof (TSRange) * len);
1620 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer); 1634 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
1621 1635
1636 /* We can use XFUXNUM, XCAR, XCDR freely because we have checked
1637 the input by treesit_check_range_argument. */
1638
1622 for (int idx = 0; !NILP (ranges); idx++, ranges = XCDR (ranges)) 1639 for (int idx = 0; !NILP (ranges); idx++, ranges = XCDR (ranges))
1623 { 1640 {
1624 Lisp_Object range = XCAR (ranges); 1641 Lisp_Object range = XCAR (ranges);
@@ -1639,9 +1656,6 @@ buffer. */)
1639 } 1656 }
1640 success = ts_parser_set_included_ranges (XTS_PARSER (parser)->parser, 1657 success = ts_parser_set_included_ranges (XTS_PARSER (parser)->parser,
1641 treesit_ranges, len); 1658 treesit_ranges, len);
1642 /* Although XFIXNUM could signal, it should be impossible
1643 because we have checked the input by treesit_check_range_argument.
1644 So there is no need for unwind-protect. */
1645 xfree (treesit_ranges); 1659 xfree (treesit_ranges);
1646 } 1660 }
1647 1661
@@ -2295,11 +2309,11 @@ See Info node `(elisp)Pattern Matching' for detailed explanation. */)
2295{ 2309{
2296 if (BASE_EQ (pattern, QCanchor)) 2310 if (BASE_EQ (pattern, QCanchor))
2297 return Vtreesit_str_dot; 2311 return Vtreesit_str_dot;
2298 if (BASE_EQ (pattern, intern_c_string (":?"))) 2312 if (BASE_EQ (pattern, QCquestion))
2299 return Vtreesit_str_question_mark; 2313 return Vtreesit_str_question_mark;
2300 if (BASE_EQ (pattern, intern_c_string (":*"))) 2314 if (BASE_EQ (pattern, QCstar))
2301 return Vtreesit_str_star; 2315 return Vtreesit_str_star;
2302 if (BASE_EQ (pattern, intern_c_string (":+"))) 2316 if (BASE_EQ (pattern, QCplus))
2303 return Vtreesit_str_plus; 2317 return Vtreesit_str_plus;
2304 if (BASE_EQ (pattern, QCequal)) 2318 if (BASE_EQ (pattern, QCequal))
2305 return Vtreesit_str_pound_equal; 2319 return Vtreesit_str_pound_equal;
@@ -3008,7 +3022,7 @@ treesit_cursor_helper (TSTreeCursor *cursor, TSNode node, Lisp_Object parser)
3008 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree); 3022 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree);
3009 *cursor = ts_tree_cursor_new (root); 3023 *cursor = ts_tree_cursor_new (root);
3010 bool success = treesit_cursor_helper_1 (cursor, &node, end_pos, 3024 bool success = treesit_cursor_helper_1 (cursor, &node, end_pos,
3011 treesit_recursion_limit); 3025 TREESIT_RECURSION_LIMIT);
3012 if (!success) 3026 if (!success)
3013 ts_tree_cursor_delete (cursor); 3027 ts_tree_cursor_delete (cursor);
3014 return success; 3028 return success;
@@ -3139,17 +3153,80 @@ treesit_traverse_child_helper (TSTreeCursor *cursor,
3139 } 3153 }
3140} 3154}
3141 3155
3156/* Assq but doesn't signal. */
3157static Lisp_Object
3158safe_assq (Lisp_Object key, Lisp_Object alist)
3159{
3160 Lisp_Object tail = alist;
3161 FOR_EACH_TAIL_SAFE (tail)
3162 if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
3163 return XCAR (tail);
3164 return Qnil;
3165}
3166
3167/* Given a symbol THING, and a language symbol LANGUAGE, find the
3168 corresponding predicate definition in treesit-things-settings.
3169 Don't check for the type of THING and LANGUAGE.
3170
3171 If there isn't one, return Qnil. */
3172static Lisp_Object
3173treesit_traverse_get_predicate (Lisp_Object thing, Lisp_Object language)
3174{
3175 Lisp_Object cons = safe_assq (language, Vtreesit_thing_settings);
3176 if (NILP (cons))
3177 return Qnil;
3178 Lisp_Object definitions = XCDR (cons);
3179 Lisp_Object entry = safe_assq (thing, definitions);
3180 if (NILP (entry))
3181 return Qnil;
3182 /* ENTRY looks like (THING PRED). */
3183 Lisp_Object cdr = XCDR (entry);
3184 if (!CONSP (cdr))
3185 return Qnil;
3186 return XCAR (cdr);
3187}
3188
3142/* Validate the PRED passed to treesit_traverse_match_predicate. If 3189/* Validate the PRED passed to treesit_traverse_match_predicate. If
3143 there's an error, set SIGNAL_DATA to something signal accepts, and 3190 there's an error, set SIGNAL_DATA to something signal accepts, and
3144 return false, otherwise return true. */ 3191 return false, otherwise return true. This function also check for
3192 recusion levels: we place a arbitrary 100 level limit on recursive
3193 predicates. RECURSION_LEVEL is the current recursion level (that
3194 starts at 0), if it goes over 99, return false and set
3195 SIGNAL_DATA. LANGUAGE is a LANGUAGE symbol. */
3145static bool 3196static bool
3146treesit_traverse_validate_predicate (Lisp_Object pred, 3197treesit_traverse_validate_predicate (Lisp_Object pred,
3147 Lisp_Object *signal_data) 3198 Lisp_Object language,
3199 Lisp_Object *signal_data,
3200 ptrdiff_t recursion_level)
3148{ 3201{
3202 if (recursion_level > 99)
3203 {
3204 *signal_data = list1 (build_string ("Predicate recursion level "
3205 "exceeded: it must not exceed "
3206 "100 levels"));
3207 return false;
3208 }
3149 if (STRINGP (pred)) 3209 if (STRINGP (pred))
3150 return true; 3210 return true;
3151 else if (FUNCTIONP (pred)) 3211 else if (FUNCTIONP (pred))
3152 return true; 3212 return true;
3213 else if (SYMBOLP (pred))
3214 {
3215 Lisp_Object definition = treesit_traverse_get_predicate (pred,
3216 language);
3217 if (NILP (definition))
3218 {
3219 *signal_data = list2 (build_string ("Cannot find the definition "
3220 "of the predicate in "
3221 "`treesit-things-settings'"),
3222 pred);
3223 return false;
3224 }
3225 return treesit_traverse_validate_predicate (definition,
3226 language,
3227 signal_data,
3228 recursion_level + 1);
3229 }
3153 else if (CONSP (pred)) 3230 else if (CONSP (pred))
3154 { 3231 {
3155 Lisp_Object car = XCAR (pred); 3232 Lisp_Object car = XCAR (pred);
@@ -3172,7 +3249,9 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
3172 return false; 3249 return false;
3173 } 3250 }
3174 return treesit_traverse_validate_predicate (XCAR (cdr), 3251 return treesit_traverse_validate_predicate (XCAR (cdr),
3175 signal_data); 3252 language,
3253 signal_data,
3254 recursion_level + 1);
3176 } 3255 }
3177 else if (BASE_EQ (car, Qor)) 3256 else if (BASE_EQ (car, Qor))
3178 { 3257 {
@@ -3187,7 +3266,9 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
3187 FOR_EACH_TAIL (cdr) 3266 FOR_EACH_TAIL (cdr)
3188 { 3267 {
3189 if (!treesit_traverse_validate_predicate (XCAR (cdr), 3268 if (!treesit_traverse_validate_predicate (XCAR (cdr),
3190 signal_data)) 3269 language,
3270 signal_data,
3271 recursion_level + 1))
3191 return false; 3272 return false;
3192 } 3273 }
3193 return true; 3274 return true;
@@ -3195,8 +3276,7 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
3195 else if (STRINGP (car) && FUNCTIONP (cdr)) 3276 else if (STRINGP (car) && FUNCTIONP (cdr))
3196 return true; 3277 return true;
3197 } 3278 }
3198 *signal_data = list2 (build_string ("Invalid predicate, see TODO for " 3279 *signal_data = list2 (build_string ("Invalid predicate, see `treesit-thing-settings' for valid forms of predicate"),
3199 "valid forms of predicate"),
3200 pred); 3280 pred);
3201 return false; 3281 return false;
3202} 3282}
@@ -3232,6 +3312,14 @@ treesit_traverse_match_predicate (TSTreeCursor *cursor, Lisp_Object pred,
3232 Lisp_Object lisp_node = make_treesit_node (parser, node); 3312 Lisp_Object lisp_node = make_treesit_node (parser, node);
3233 return !NILP (CALLN (Ffuncall, pred, lisp_node)); 3313 return !NILP (CALLN (Ffuncall, pred, lisp_node));
3234 } 3314 }
3315 else if (SYMBOLP (pred))
3316 {
3317 Lisp_Object language = XTS_PARSER (parser)->language_symbol;
3318 Lisp_Object definition = treesit_traverse_get_predicate (pred,
3319 language);
3320 return treesit_traverse_match_predicate (cursor, definition,
3321 parser, named);
3322 }
3235 else if (CONSP (pred)) 3323 else if (CONSP (pred))
3236 { 3324 {
3237 Lisp_Object car = XCAR (pred); 3325 Lisp_Object car = XCAR (pred);
@@ -3268,10 +3356,11 @@ treesit_traverse_match_predicate (TSTreeCursor *cursor, Lisp_Object pred,
3268 return false; 3356 return false;
3269} 3357}
3270 3358
3271/* Traverse the parse tree starting from CURSOR. See TODO for the 3359/* Traverse the parse tree starting from CURSOR. See
3272 shapes PRED can have. If the node satisfies PRED, leave CURSOR on 3360 `treesit-thing-settings' for the shapes PRED can have. If the
3273 that node and return true. If no node satisfies PRED, move CURSOR 3361 node satisfies PRED, leave CURSOR on that node and return true. If
3274 back to starting position and return false. 3362 no node satisfies PRED, move CURSOR back to starting position and
3363 return false.
3275 3364
3276 LIMIT is the number of levels we descend in the tree. FORWARD 3365 LIMIT is the number of levels we descend in the tree. FORWARD
3277 controls the direction in which we traverse the tree, true means 3366 controls the direction in which we traverse the tree, true means
@@ -3384,13 +3473,9 @@ Return the first matched node, or nil if none matches. */)
3384 CHECK_SYMBOL (all); 3473 CHECK_SYMBOL (all);
3385 CHECK_SYMBOL (backward); 3474 CHECK_SYMBOL (backward);
3386 3475
3387 Lisp_Object signal_data = Qnil;
3388 if (!treesit_traverse_validate_predicate (predicate, &signal_data))
3389 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3390
3391 /* We use a default limit of 1000. See bug#59426 for the 3476 /* We use a default limit of 1000. See bug#59426 for the
3392 discussion. */ 3477 discussion. */
3393 ptrdiff_t the_limit = treesit_recursion_limit; 3478 ptrdiff_t the_limit = TREESIT_RECURSION_LIMIT;
3394 if (!NILP (depth)) 3479 if (!NILP (depth))
3395 { 3480 {
3396 CHECK_FIXNUM (depth); 3481 CHECK_FIXNUM (depth);
@@ -3400,6 +3485,13 @@ Return the first matched node, or nil if none matches. */)
3400 treesit_initialize (); 3485 treesit_initialize ();
3401 3486
3402 Lisp_Object parser = XTS_NODE (node)->parser; 3487 Lisp_Object parser = XTS_NODE (node)->parser;
3488 Lisp_Object language = XTS_PARSER (parser)->language_symbol;
3489
3490 Lisp_Object signal_data = Qnil;
3491 if (!treesit_traverse_validate_predicate (predicate, language,
3492 &signal_data, 0))
3493 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3494
3403 Lisp_Object return_value = Qnil; 3495 Lisp_Object return_value = Qnil;
3404 TSTreeCursor cursor; 3496 TSTreeCursor cursor;
3405 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser)) 3497 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser))
@@ -3455,13 +3547,16 @@ always traverse leaf nodes first, then upwards. */)
3455 CHECK_SYMBOL (all); 3547 CHECK_SYMBOL (all);
3456 CHECK_SYMBOL (backward); 3548 CHECK_SYMBOL (backward);
3457 3549
3458 Lisp_Object signal_data = Qnil;
3459 if (!treesit_traverse_validate_predicate (predicate, &signal_data))
3460 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3461
3462 treesit_initialize (); 3550 treesit_initialize ();
3463 3551
3464 Lisp_Object parser = XTS_NODE (start)->parser; 3552 Lisp_Object parser = XTS_NODE (start)->parser;
3553 Lisp_Object language = XTS_PARSER (parser)->language_symbol;
3554
3555 Lisp_Object signal_data = Qnil;
3556 if (!treesit_traverse_validate_predicate (predicate, language,
3557 &signal_data, 0))
3558 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3559
3465 Lisp_Object return_value = Qnil; 3560 Lisp_Object return_value = Qnil;
3466 TSTreeCursor cursor; 3561 TSTreeCursor cursor;
3467 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser)) 3562 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser))
@@ -3572,16 +3667,12 @@ a regexp. */)
3572{ 3667{
3573 CHECK_TS_NODE (root); 3668 CHECK_TS_NODE (root);
3574 3669
3575 Lisp_Object signal_data = Qnil;
3576 if (!treesit_traverse_validate_predicate (predicate, &signal_data))
3577 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3578
3579 if (!NILP (process_fn)) 3670 if (!NILP (process_fn))
3580 CHECK_TYPE (FUNCTIONP (process_fn), Qfunctionp, process_fn); 3671 CHECK_TYPE (FUNCTIONP (process_fn), Qfunctionp, process_fn);
3581 3672
3582 /* We use a default limit of 1000. See bug#59426 for the 3673 /* We use a default limit of 1000. See bug#59426 for the
3583 discussion. */ 3674 discussion. */
3584 ptrdiff_t the_limit = treesit_recursion_limit; 3675 ptrdiff_t the_limit = TREESIT_RECURSION_LIMIT;
3585 if (!NILP (depth)) 3676 if (!NILP (depth))
3586 { 3677 {
3587 CHECK_FIXNUM (depth); 3678 CHECK_FIXNUM (depth);
@@ -3591,6 +3682,13 @@ a regexp. */)
3591 treesit_initialize (); 3682 treesit_initialize ();
3592 3683
3593 Lisp_Object parser = XTS_NODE (root)->parser; 3684 Lisp_Object parser = XTS_NODE (root)->parser;
3685 Lisp_Object language = XTS_PARSER (parser)->language_symbol;
3686
3687 Lisp_Object signal_data = Qnil;
3688 if (!treesit_traverse_validate_predicate (predicate, language,
3689 &signal_data, 0))
3690 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3691
3594 Lisp_Object parent = Fcons (Qnil, Qnil); 3692 Lisp_Object parent = Fcons (Qnil, Qnil);
3595 /* In this function we never traverse above NODE, so we don't need 3693 /* In this function we never traverse above NODE, so we don't need
3596 to use treesit_cursor_helper. */ 3694 to use treesit_cursor_helper. */
@@ -3612,6 +3710,40 @@ a regexp. */)
3612 return parent; 3710 return parent;
3613} 3711}
3614 3712
3713DEFUN ("treesit-node-match-p",
3714 Ftreesit_node_match_p,
3715 Streesit_node_match_p, 2, 2, 0,
3716 doc: /* Check whether NODE matches PREDICATE.
3717
3718PREDICATE can be a regexp matching node type, a predicate function,
3719and more, see `treesit-things-definition' for detail. Return non-nil
3720if NODE matches PRED, nil otherwise. */)
3721 (Lisp_Object node, Lisp_Object predicate)
3722{
3723 CHECK_TS_NODE (node);
3724
3725 Lisp_Object parser = XTS_NODE (node)->parser;
3726 Lisp_Object language = XTS_PARSER (parser)->language_symbol;
3727
3728 Lisp_Object signal_data = Qnil;
3729 if (!treesit_traverse_validate_predicate (predicate, language,
3730 &signal_data, 0))
3731 xsignal1 (Qtreesit_invalid_predicate, signal_data);
3732
3733 TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (node)->node);
3734
3735 specpdl_ref count = SPECPDL_INDEX ();
3736 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3737
3738 bool match = false;
3739 match = treesit_traverse_match_predicate (&cursor, predicate,
3740 parser, false);
3741
3742 unbind_to (count, Qnil);
3743
3744 return match ? Qt : Qnil;
3745}
3746
3615DEFUN ("treesit-subtree-stat", 3747DEFUN ("treesit-subtree-stat",
3616 Ftreesit_subtree_stat, 3748 Ftreesit_subtree_stat,
3617 Streesit_subtree_stat, 1, 1, 0, 3749 Streesit_subtree_stat, 1, 1, 0,
@@ -3709,6 +3841,9 @@ syms_of_treesit (void)
3709 DEFSYM (Qnot, "not"); 3841 DEFSYM (Qnot, "not");
3710 3842
3711 DEFSYM (QCanchor, ":anchor"); 3843 DEFSYM (QCanchor, ":anchor");
3844 DEFSYM (QCquestion, ":?");
3845 DEFSYM (QCstar, ":*");
3846 DEFSYM (QCplus, ":+");
3712 DEFSYM (QCequal, ":equal"); 3847 DEFSYM (QCequal, ":equal");
3713 DEFSYM (QCmatch, ":match"); 3848 DEFSYM (QCmatch, ":match");
3714 DEFSYM (QCpred, ":pred"); 3849 DEFSYM (QCpred, ":pred");
@@ -3760,7 +3895,8 @@ syms_of_treesit (void)
3760 "This parser is deleted and cannot be used", 3895 "This parser is deleted and cannot be used",
3761 Qtreesit_error); 3896 Qtreesit_error);
3762 define_error (Qtreesit_invalid_predicate, 3897 define_error (Qtreesit_invalid_predicate,
3763 "Invalid predicate, see TODO for valid forms for a predicate", 3898 "Invalid predicate, see `treesit-thing-settings' "
3899 "for valid forms for a predicate",
3764 Qtreesit_error); 3900 Qtreesit_error);
3765 3901
3766 DEFVAR_LISP ("treesit-load-name-override-list", 3902 DEFVAR_LISP ("treesit-load-name-override-list",
@@ -3792,6 +3928,33 @@ then in the `tree-sitter' subdirectory of `user-emacs-directory', and
3792then in the system default locations for dynamic libraries, in that order. */); 3928then in the system default locations for dynamic libraries, in that order. */);
3793 Vtreesit_extra_load_path = Qnil; 3929 Vtreesit_extra_load_path = Qnil;
3794 3930
3931 DEFVAR_LISP ("treesit-thing-settings",
3932 Vtreesit_thing_settings,
3933 doc:
3934 /* A list defining things.
3935
3936The value should be an alist of (LANGUAGE . DEFINITIONS), where
3937LANGUAGE is a language symbol, and DEFINITIONS is a list of
3938
3939 (THING PRED)
3940
3941THING is a symbol representing the thing, like `defun', `sexp', or
3942`block'; PRED defines what kind of node can be qualified as THING.
3943
3944PRED can be a regexp string that matches the type of the node; it can
3945be a predicate function that takes the node as the sole argument and
3946returns t if the node is the thing; it can be a cons (REGEXP . FN),
3947which is a combination of a regexp and a predicate function, and the
3948node has to match both to qualify as the thing.
3949
3950PRED can also be recursively defined. It can be (or PRED...), meaning
3951satisfying anyone of the inner PREDs qualifies the node; or (not
3952PRED), meaning not satisfying the inner PRED qualifies the node.
3953
3954Finally, PRED can refer to other THINGs defined in this list by using
3955the symbol of that THING. For example, (or block sexp). */);
3956 Vtreesit_thing_settings = Qnil;
3957
3795 staticpro (&Vtreesit_str_libtree_sitter); 3958 staticpro (&Vtreesit_str_libtree_sitter);
3796 Vtreesit_str_libtree_sitter = build_pure_c_string ("libtree-sitter-"); 3959 Vtreesit_str_libtree_sitter = build_pure_c_string ("libtree-sitter-");
3797 staticpro (&Vtreesit_str_tree_sitter); 3960 staticpro (&Vtreesit_str_tree_sitter);
@@ -3879,6 +4042,7 @@ then in the system default locations for dynamic libraries, in that order. */);
3879 defsubr (&Streesit_search_subtree); 4042 defsubr (&Streesit_search_subtree);
3880 defsubr (&Streesit_search_forward); 4043 defsubr (&Streesit_search_forward);
3881 defsubr (&Streesit_induce_sparse_tree); 4044 defsubr (&Streesit_induce_sparse_tree);
4045 defsubr (&Streesit_node_match_p);
3882 defsubr (&Streesit_subtree_stat); 4046 defsubr (&Streesit_subtree_stat);
3883#endif /* HAVE_TREE_SITTER */ 4047#endif /* HAVE_TREE_SITTER */
3884 defsubr (&Streesit_available_p); 4048 defsubr (&Streesit_available_p);
diff --git a/src/w32.c b/src/w32.c
index f45750ea5c1..c75beb630e5 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -543,7 +543,14 @@ typedef LANGID (WINAPI *GetUserDefaultUILanguage_Proc) (void);
543 543
544typedef COORD (WINAPI *GetConsoleFontSize_Proc) (HANDLE, DWORD); 544typedef COORD (WINAPI *GetConsoleFontSize_Proc) (HANDLE, DWORD);
545 545
546#if _WIN32_WINNT < 0x0501 546/* Old versions of mingw.org's MinGW, before v5.2.0, don't have a
547 _WIN32_WINNT guard for CONSOLE_FONT_INFO in wincon.h, and so don't
548 need the conditional definition below, which causes compilation
549 errors. Note: MinGW64 sets _WIN32_WINNT to a higher version, and
550 its w32api.h version stays fixed at 3.14. */
551#if _WIN32_WINNT < 0x0501 \
552 && (__W32API_MAJOR_VERSION > 5 \
553 || (__W32API_MAJOR_VERSION == 5 && __W32API_MINOR_VERSION >= 2))
547typedef struct 554typedef struct
548{ 555{
549 DWORD nFont; 556 DWORD nFont;