diff options
| author | Po Lu | 2023-04-16 08:16:07 +0800 |
|---|---|---|
| committer | Po Lu | 2023-04-16 08:16:07 +0800 |
| commit | fe9e48a16af1140dcc49125ad8ea35bbf9e59dfc (patch) | |
| tree | 68d676dfc0a96edb7ca315c07c7ce54f7c27db84 /src | |
| parent | 5919511881b17ddd3cd0fa3071c545927b9eba88 (diff) | |
| parent | bc61a1afdd6c3ba8a605ed46ae97b1e36b40f951 (diff) | |
| download | emacs-fe9e48a16af1140dcc49125ad8ea35bbf9e59dfc.tar.gz emacs-fe9e48a16af1140dcc49125ad8ea35bbf9e59dfc.zip | |
Merge remote-tracking branch 'origin/master' into feature/android
Diffstat (limited to 'src')
| -rw-r--r-- | src/macfont.m | 50 | ||||
| -rw-r--r-- | src/nsterm.m | 20 | ||||
| -rw-r--r-- | src/treesit.c | 256 | ||||
| -rw-r--r-- | src/w32.c | 9 |
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; | |||
| 421 | static Lisp_Object Vtreesit_str_pred; | 421 | static 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 | |
| 426 | const ptrdiff_t treesit_recursion_limit = 1000; | 426 | If we think of programs and AST, it is very rare for any program to |
| 427 | bool 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 | |||
| 434 | static bool treesit_initialized = false; | ||
| 428 | 435 | ||
| 429 | static bool | 436 | static bool |
| 430 | load_tree_sitter_if_necessary (bool required) | 437 | load_tree_sitter_if_necessary (bool required) |
| @@ -478,40 +485,47 @@ treesit_initialize (void) | |||
| 478 | static void | 485 | static void |
| 479 | treesit_symbol_to_c_name (char *symbol_name) | 486 | treesit_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. */ | ||
| 488 | static bool | 503 | static bool |
| 489 | treesit_find_override_name (Lisp_Object language_symbol, Lisp_Object *name, | 504 | treesit_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. */ | ||
| 3157 | static Lisp_Object | ||
| 3158 | safe_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. */ | ||
| 3172 | static Lisp_Object | ||
| 3173 | treesit_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. */ | ||
| 3145 | static bool | 3196 | static bool |
| 3146 | treesit_traverse_validate_predicate (Lisp_Object pred, | 3197 | treesit_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 | ||
| 3713 | DEFUN ("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 | |||
| 3718 | PREDICATE can be a regexp matching node type, a predicate function, | ||
| 3719 | and more, see `treesit-things-definition' for detail. Return non-nil | ||
| 3720 | if 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 | |||
| 3615 | DEFUN ("treesit-subtree-stat", | 3747 | DEFUN ("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 | |||
| 3792 | then in the system default locations for dynamic libraries, in that order. */); | 3928 | then 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 | |||
| 3936 | The value should be an alist of (LANGUAGE . DEFINITIONS), where | ||
| 3937 | LANGUAGE is a language symbol, and DEFINITIONS is a list of | ||
| 3938 | |||
| 3939 | (THING PRED) | ||
| 3940 | |||
| 3941 | THING is a symbol representing the thing, like `defun', `sexp', or | ||
| 3942 | `block'; PRED defines what kind of node can be qualified as THING. | ||
| 3943 | |||
| 3944 | PRED can be a regexp string that matches the type of the node; it can | ||
| 3945 | be a predicate function that takes the node as the sole argument and | ||
| 3946 | returns t if the node is the thing; it can be a cons (REGEXP . FN), | ||
| 3947 | which is a combination of a regexp and a predicate function, and the | ||
| 3948 | node has to match both to qualify as the thing. | ||
| 3949 | |||
| 3950 | PRED can also be recursively defined. It can be (or PRED...), meaning | ||
| 3951 | satisfying anyone of the inner PREDs qualifies the node; or (not | ||
| 3952 | PRED), meaning not satisfying the inner PRED qualifies the node. | ||
| 3953 | |||
| 3954 | Finally, PRED can refer to other THINGs defined in this list by using | ||
| 3955 | the 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); |
| @@ -543,7 +543,14 @@ typedef LANGID (WINAPI *GetUserDefaultUILanguage_Proc) (void); | |||
| 543 | 543 | ||
| 544 | typedef COORD (WINAPI *GetConsoleFontSize_Proc) (HANDLE, DWORD); | 544 | typedef 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)) | ||
| 547 | typedef struct | 554 | typedef struct |
| 548 | { | 555 | { |
| 549 | DWORD nFont; | 556 | DWORD nFont; |