diff options
author | Daniel Ebert | 2023-09-19 13:31:38 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2023-12-15 06:59:54 +0000 |
commit | 938a710904ae6d328d4008626d98acb9e907813a (patch) | |
tree | df6a641d82d0c82b61ecc7ffe68011d0dca24453 /helix-core/src/indent.rs | |
parent | 559bfc1f5ef1bd43fd94325c0363058e32c76df4 (diff) |
Make the indent heuristic configurable
Diffstat (limited to 'helix-core/src/indent.rs')
-rw-r--r-- | helix-core/src/indent.rs | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index dfb33939..26186ee8 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -6,7 +6,7 @@ use crate::{ chars::{char_is_line_ending, char_is_whitespace}, find_first_non_whitespace_char, graphemes::{grapheme_width, tab_width_at}, - syntax::{LanguageConfiguration, RopeProvider, Syntax}, + syntax::{IndentationHeuristic, LanguageConfiguration, RopeProvider, Syntax}, tree_sitter::Node, Rope, RopeGraphemes, RopeSlice, }; @@ -931,6 +931,7 @@ pub fn treesitter_indent_for_pos<'a>( pub fn indent_for_newline( language_config: Option<&LanguageConfiguration>, syntax: Option<&Syntax>, + indent_heuristic: &IndentationHeuristic, indent_style: &IndentStyle, tab_width: usize, text: RopeSlice, @@ -939,7 +940,12 @@ pub fn indent_for_newline( current_line: usize, ) -> String { let indent_width = indent_style.indent_width(tab_width); - if let (Some(query), Some(syntax)) = ( + if let ( + IndentationHeuristic::TreeSitter | IndentationHeuristic::Hybrid, + Some(query), + Some(syntax), + ) = ( + indent_heuristic, language_config.and_then(|config| config.indent_query()), syntax, ) { @@ -953,49 +959,51 @@ pub fn indent_for_newline( line_before_end_pos, true, ) { - // We want to compute the indentation not only based on the - // syntax tree but also on the actual indentation of a previous - // line. This makes indentation computation more resilient to - // incomplete queries, incomplete source code & differing indentation - // styles for the same language. - // However, using the indent of a previous line as a baseline may not - // make sense, e.g. if it has a different alignment than the new line. - // In order to prevent edge cases with long running times, we only try - // a constant number of (non-empty) lines. - const MAX_ATTEMPTS: usize = 2; - let mut num_attempts = 0; - for line_idx in (0..=line_before).rev() { - let line = text.line(line_idx); - let first_non_whitespace_char = match find_first_non_whitespace_char(line) { - Some(i) => i, - None => { - continue; + if let IndentationHeuristic::Hybrid = indent_heuristic { + // We want to compute the indentation not only based on the + // syntax tree but also on the actual indentation of a previous + // line. This makes indentation computation more resilient to + // incomplete queries, incomplete source code & differing indentation + // styles for the same language. + // However, using the indent of a previous line as a baseline may not + // make sense, e.g. if it has a different alignment than the new line. + // In order to prevent edge cases with long running times, we only try + // a constant number of (non-empty) lines. + const MAX_ATTEMPTS: usize = 2; + let mut num_attempts = 0; + for line_idx in (0..=line_before).rev() { + let line = text.line(line_idx); + let first_non_whitespace_char = match find_first_non_whitespace_char(line) { + Some(i) => i, + None => { + continue; + } + }; + if let Some(indent) = (|| { + let computed_indent = treesitter_indent_for_pos( + query, + syntax, + tab_width, + indent_width, + text, + line_idx, + text.line_to_char(line_idx) + first_non_whitespace_char, + false, + )?; + let leading_whitespace = line.slice(0..first_non_whitespace_char); + indent.relative_indent( + &computed_indent, + leading_whitespace, + indent_style, + tab_width, + ) + })() { + return indent; + } + num_attempts += 1; + if num_attempts == MAX_ATTEMPTS { + break; } - }; - if let Some(indent) = (|| { - let computed_indent = treesitter_indent_for_pos( - query, - syntax, - tab_width, - indent_width, - text, - line_idx, - text.line_to_char(line_idx) + first_non_whitespace_char, - false, - )?; - let leading_whitespace = line.slice(0..first_non_whitespace_char); - indent.relative_indent( - &computed_indent, - leading_whitespace, - indent_style, - tab_width, - ) - })() { - return indent; - } - num_attempts += 1; - if num_attempts == MAX_ATTEMPTS { - break; } } return indent.to_string(indent_style, tab_width); |