* When set to `true`, `hideDuplicateTextMateGrammars` will hide all grammars except whichever one the user has indicated a preference for — via `useTreeSitterParsers` and `useLegacyTreeSitter` settings, whether global or scope-specific.
* When set to `false`, `hideDuplicateTextMateGrammars` will show all grammars, even Legacy Tree-sitter.
…but only while we can afford to spend time on re-parsing.
Synchronous indentation hinting is clearly the best choice, but it can theoretically be very costly. So we'll set a time budget per transaction — currently 10ms, but could be adjusted up or down. We'll start out doing synchronous indentation, but flip to async indentation if we run out of time in a given transaction. At the end of a transaction, the time budget resets.
This allows us to balance indentation accuracy with editor responsiveness, and would even allow us to expose this tradeoff as a setting in the future. The current threshold, 10ms, would probably result in one dropped frame if exceeded, but not two.
Right now, any one parse can exceed the budget — because we don't set a timeout on the parse the way we do with an async parse. But this could be changed in the future. The main goal here is to prevent a catastrophic scenario where a complex transaction locks up the editor.
* A new predicate called `fold.invalidateOnChange` that can be used when a change should automatically invalidate the fold cache for each row in a node's range.
* The ability to use custom predicates in `folds.scm` files. (Previously, captures from `folds.scm` did not consult an instance of `ScopeResolver` in the processing phase.)
…such as in multi-line self-closing tags and multi-line opening tags.
Also fix an issue in fold handling that made it impossible to use `@_IGNORE_` captures in `folds.scm`.
Changes:
* `#define FOO 1` and `#define FOO` will _always_ scope `FOO` as `constant.other.c`, even when `FOO` is mixed-case or lower-case.
* `#define FOO()` will _always_ scope `FOO` as `entity.name.function.preprocessor.c`, even when `FOO` is mixed-case or lower-case.
* Usages of bare identifiers in other contexts in preprocessor directives should always scope them as `constant.other.c` — unless I’m made aware of any counterexamples where that shouldn’t happen. For example: in `#if TABLE_SIZE > 200`, `TABLE_SIZE` should always be `constant.other.c`, no matter its casing.
* All-caps variable declarations and assignments (`int FOO = 0`, etc.) should scope `FOO` as `variable` rather than `constant`. We should only scope an arbitrary identifier as `constant` if we think it’s been used in the context of a macro definition.
However:
* When deciding whether something outside of a directive refers to a macro constant, we have no choice but to use the `ALL_CAPS` heuristic. Ideally we’d be able to determine that from some sort of analysis of the source code files — but even if we could keep track of that sort of thing in a single buffer, it’d fall down when macro constants _defined in other files_ are used. All we can do here is make a best guess.