Skip to content

Commit 51807ed

Browse files
committed
further improve text object movement performance
1 parent dac3df4 commit 51807ed

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

helix-core/src/movement.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,13 @@ pub fn goto_treesitter_object(
405405

406406
let cap_name = |t: TextObject| format!("{}.{}", object_name, t);
407407
let mut cursor = QueryCursor::new();
408-
let nodes = lang_config.textobject_query()?.capture_nodes_any(
408+
let range = match dir {
409+
Direction::Forward => (byte_pos + 1)..slice.len_bytes(),
410+
Direction::Backward => 0..byte_pos,
411+
};
412+
// only search within the relevant range
413+
cursor.set_byte_range(range);
414+
let mut nodes = lang_config.textobject_query()?.capture_nodes_any(
409415
&[
410416
&cap_name(TextObject::Movement),
411417
&cap_name(TextObject::Around),
@@ -417,12 +423,12 @@ pub fn goto_treesitter_object(
417423
)?;
418424

419425
let node = match dir {
420-
Direction::Forward => nodes
421-
.filter(|n| n.start_byte() > byte_pos)
422-
.min_by_key(|n| n.start_byte())?,
423-
Direction::Backward => nodes
424-
.filter(|n| n.end_byte() < byte_pos)
425-
.max_by_key(|n| n.end_byte())?,
426+
// catpure_nodes_any always returns nodes in the correct order
427+
// so we don't need to iterate trough all of them which helps performance
428+
// tramendously
429+
Direction::Forward => nodes.next()?,
430+
// captures can not be iterated in reverse so we are stuck with this
431+
Direction::Backward => nodes.last()?,
426432
};
427433

428434
let len = slice.len_bytes();

helix-core/src/syntax.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,19 +356,22 @@ impl<'a> CapturedNode<'a> {
356356

357357
/// The number of matches a TS cursor can at once to avoid performance problems for medium to large files.
358358
/// Set with `set_match_limit`.
359-
/// Using such a limit means that we loose valid captures in so there is fundementally a tradeoff here.
359+
/// Using such a limit means that we loose valid captures in, so there is fundamentally a tradeoff here.
360+
///
360361
///
361362
/// Old tree sitter versions used a limit of 32 by default until this limit was removed in version `0.19.5` (must now best set manually).
362-
/// However this causes performance issues for medium to large files.
363-
/// In helix this problem caused textobjt motions to take multiple seconds to complete in medium sized rust files (3k loc).
363+
/// However, this causes performance issues for medium to large files.
364+
/// In helix, this problem caused treesitter motions to take multiple seconds to complete in medium-sized rust files (3k loc).
364365
/// Neovim also encountered this problem and reintroduced this limit after it was removed upstream
365366
/// (see https://github.com/neovim/neovim/issues/14897 and https://github.com/neovim/neovim/pull/14915).
366-
/// The number used here is fundementally a tradeoff between breaking some obscure edgecases and performance.
367+
/// The number used here is fundamentally a tradeoff between breaking some obscure edge cases and performance.
368+
///
367369
///
368-
/// 64 was choosen because neovim uses that value.
369-
/// It has been choosen somewhat arbitrarly (https://github.com/neovim/neovim/pull/18397) mostly based
370-
/// upon how many issues occur in practice.
371-
/// So this could be changed if we ran into problems.
370+
/// A value of 64 was chosen because neovim uses that value.
371+
/// Neovim chose this value somewhat arbitrarily (https://github.com/neovim/neovim/pull/18397) adjusting it whenever issues occur in practice.
372+
/// However this value has been in use for a long time and due to the large userbase of neovim it is probably a good choice.
373+
/// If this limit causes problems for a grammar in the future, it could be increased.
374+
372375
const TREE_SITTER_MATCH_LIMIT: u32 = 64;
373376

374377
impl TextObjectQuery {

0 commit comments

Comments
 (0)