diff options
Diffstat (limited to 'helix-core/src/indent.rs')
-rw-r--r-- | helix-core/src/indent.rs | 61 |
1 files changed, 20 insertions, 41 deletions
diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index ca042172..fc253f91 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -1,6 +1,6 @@ use crate::{ find_first_non_whitespace_char, - syntax::Syntax, + syntax::{IndentQuery, LanguageConfiguration, Syntax}, tree_sitter::{Node, Tree}, Rope, RopeSlice, }; @@ -43,40 +43,11 @@ fn get_highest_syntax_node_at_bytepos(syntax: &Syntax, pos: usize) -> Option<Nod Some(node) } -fn calculate_indentation(node: Option<Node>, newline: bool) -> usize { - let mut increment: i32 = 0; - - // Hardcoded for rust for now - let indent_scopes = &[ - "while_expression", - "for_expression", - "loop_expression", - "if_expression", - "if_let_expression", - // "match_expression", - // "match_arm", - "tuple_expression", - "array_expression", - // indent_except_first_scopes - "use_list", - "block", - "match_block", - "arguments", - "parameters", - "declaration_list", - "field_declaration_list", - "field_initializer_list", - "struct_pattern", - "tuple_pattern", - "enum_variant_list", - // "function_item", - // "closure_expression", - "binary_expression", - "field_expression", - "where_clause", - ]; +fn calculate_indentation(query: &IndentQuery, node: Option<Node>, newline: bool) -> usize { + // NOTE: can't use contains() on query because of comparing Vec<String> and &str + // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.contains - let outdent = &["where", "}", "]", ")"]; + let mut increment: i32 = 0; let mut node = match node { Some(node) => node, @@ -88,7 +59,7 @@ fn calculate_indentation(node: Option<Node>, newline: bool) -> usize { // if we're calculating indentation for a brand new line then the current node will become the // parent node. We need to take it's indentation level into account too. let node_kind = node.kind(); - if newline && indent_scopes.contains(&node_kind) { + if newline && query.indent.contains(node_kind) { increment += 1; } @@ -102,14 +73,14 @@ fn calculate_indentation(node: Option<Node>, newline: bool) -> usize { // }) <-- }) is two scopes let starts_same_line = start == prev_start; - if outdent.contains(&node.kind()) && !starts_same_line { + if query.outdent.contains(node.kind()) && !starts_same_line { // we outdent by skipping the rules for the current level and jumping up // node = parent; increment -= 1; // continue; } - if indent_scopes.contains(&parent_kind) // && not_first_or_last_sibling + if query.indent.contains(parent_kind) // && not_first_or_last_sibling && !starts_same_line { // println!("is_scope {}", parent_kind); @@ -128,6 +99,7 @@ fn calculate_indentation(node: Option<Node>, newline: bool) -> usize { } fn suggested_indent_for_line( + language_config: &LanguageConfiguration, syntax: Option<&Syntax>, text: RopeSlice, line_num: usize, @@ -137,7 +109,7 @@ fn suggested_indent_for_line( let current = indent_level_for_line(line, tab_width); if let Some(start) = find_first_non_whitespace_char(text, line_num) { - return suggested_indent_for_pos(syntax, text, start, false); + return suggested_indent_for_pos(Some(language_config), syntax, text, start, false); }; // if the line is blank, indent should be zero @@ -148,18 +120,24 @@ fn suggested_indent_for_line( // - it should return 0 when mass indenting stuff // - it should look up the wrapper node and count it too when we press o/O pub fn suggested_indent_for_pos( + language_config: Option<&LanguageConfiguration>, syntax: Option<&Syntax>, text: RopeSlice, pos: usize, new_line: bool, ) -> usize { - if let Some(syntax) = syntax { + if let (Some(query), Some(syntax)) = ( + language_config.and_then(|config| config.indent_query()), + syntax, + ) { let byte_start = text.char_to_byte(pos); let node = get_highest_syntax_node_at_bytepos(syntax, byte_start); + // let config = load indentation query config from Syntax(should contain language_config) + // TODO: special case for comments // TODO: if preserve_leading_whitespace - calculate_indentation(node, new_line) + calculate_indentation(query, node, new_line) } else { // TODO: heuristics for non-tree sitter grammars 0 @@ -286,6 +264,7 @@ where tab_width: 4, unit: String::from(" "), }), + indent_query: OnceCell::new(), }], }); @@ -304,7 +283,7 @@ where let line = text.line(i); let indent = indent_level_for_line(line, tab_width); assert_eq!( - suggested_indent_for_line(Some(&syntax), text, i, tab_width), + suggested_indent_for_line(&language_config, Some(&syntax), text, i, tab_width), indent, "line {}: {}", i, |