From a1a6d5f3340ba8a587bbf8c178fe65589f36a51a Mon Sep 17 00:00:00 2001 From: Triton171 Date: Thu, 16 Feb 2023 15:47:59 +0100 Subject: [PATCH] Replace incorrect usages of tab_width with indent_width. (#5918) --- helix-core/src/indent.rs | 39 +++++++++++++++++++++++++++++++------- helix-core/tests/indent.rs | 6 ++++-- helix-term/src/commands.rs | 19 ++++++------------- helix-view/src/document.rs | 7 ++++++- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index 3aa59fa31..950a7f652 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -56,6 +56,14 @@ impl IndentStyle { } } } + + #[inline] + pub fn indent_width(&self, tab_width: usize) -> usize { + match *self { + IndentStyle::Tabs => tab_width, + IndentStyle::Spaces(width) => width as usize, + } + } } /// Attempts to detect the indentation style used in a document. @@ -177,7 +185,7 @@ pub fn auto_detect_indent_style(document_text: &Rope) -> Option { /// To determine indentation of a newly inserted line, figure out the indentation at the last col /// of the previous line. -pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize { +pub fn indent_level_for_line(line: RopeSlice, tab_width: usize, indent_width: usize) -> usize { let mut len = 0; for ch in line.chars() { match ch { @@ -187,7 +195,7 @@ pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize { } } - len / tab_width + len / indent_width } /// Computes for node and all ancestors whether they are the first node on their line. @@ -466,6 +474,7 @@ fn extend_nodes<'a>( text: RopeSlice, line: usize, tab_width: usize, + indent_width: usize, ) { let mut stop_extend = false; @@ -490,10 +499,12 @@ fn extend_nodes<'a>( if deepest_preceding.end_position().row == line { extend_node = true; } else { - let cursor_indent = indent_level_for_line(text.line(line), tab_width); + let cursor_indent = + indent_level_for_line(text.line(line), tab_width, indent_width); let node_indent = indent_level_for_line( text.line(deepest_preceding.start_position().row), tab_width, + indent_width, ); if cursor_indent > node_indent { extend_node = true; @@ -562,6 +573,7 @@ pub fn treesitter_indent_for_pos( syntax: &Syntax, indent_style: &IndentStyle, tab_width: usize, + indent_width: usize, text: RopeSlice, line: usize, pos: usize, @@ -622,6 +634,7 @@ pub fn treesitter_indent_for_pos( text, line, tab_width, + indent_width, ); } let mut first_in_line = get_first_in_line(node, new_line.then_some(byte_pos)); @@ -709,6 +722,7 @@ pub fn indent_for_newline( line_before_end_pos: usize, current_line: usize, ) -> String { + let indent_width = indent_style.indent_width(tab_width); if let (Some(query), Some(syntax)) = ( language_config.and_then(|config| config.indent_query()), syntax, @@ -718,6 +732,7 @@ pub fn indent_for_newline( syntax, indent_style, tab_width, + indent_width, text, line_before, line_before_end_pos, @@ -726,7 +741,7 @@ pub fn indent_for_newline( return indent; }; } - let indent_level = indent_level_for_line(text.line(current_line), tab_width); + let indent_level = indent_level_for_line(text.line(current_line), tab_width, indent_width); indent_style.as_str().repeat(indent_level) } @@ -763,12 +778,22 @@ mod test { #[test] fn test_indent_level() { let tab_width = 4; + let indent_width = 4; let line = Rope::from(" fn new"); // 8 spaces - assert_eq!(indent_level_for_line(line.slice(..), tab_width), 2); + assert_eq!( + indent_level_for_line(line.slice(..), tab_width, indent_width), + 2 + ); let line = Rope::from("\t\t\tfn new"); // 3 tabs - assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3); + assert_eq!( + indent_level_for_line(line.slice(..), tab_width, indent_width), + 3 + ); // mixed indentation let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab - assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3); + assert_eq!( + indent_level_for_line(line.slice(..), tab_width, indent_width), + 3 + ); } } diff --git a/helix-core/tests/indent.rs b/helix-core/tests/indent.rs index f74b576ac..b3c543d6c 100644 --- a/helix-core/tests/indent.rs +++ b/helix-core/tests/indent.rs @@ -46,11 +46,13 @@ fn test_treesitter_indent(file_name: &str, lang_scope: &str) { for i in 0..doc.len_lines() { let line = text.line(i); if let Some(pos) = helix_core::find_first_non_whitespace_char(line) { + let tab_and_indent_width: usize = 4; let suggested_indent = treesitter_indent_for_pos( indent_query, &syntax, - &IndentStyle::Spaces(4), - 4, + &IndentStyle::Spaces(tab_and_indent_width as u8), + tab_and_indent_width, + tab_and_indent_width, text, i, text.line_to_char(i) + pos, diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index a3c9f0b4a..fb55ca2a8 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -3364,8 +3364,8 @@ pub mod insert { let count = cx.count(); let (view, doc) = current_ref!(cx.editor); let text = doc.text().slice(..); - let indent_unit = doc.indent_style.as_str(); - let tab_size = doc.tab_width(); + let tab_width = doc.tab_width(); + let indent_width = doc.indent_width(); let auto_pairs = doc.auto_pairs(cx.editor); let transaction = @@ -3386,18 +3386,11 @@ pub mod insert { None, ) } else { - let unit_len = indent_unit.chars().count(); - // NOTE: indent_unit always contains 'only spaces' or 'only tab' according to `IndentStyle` definition. - let unit_size = if indent_unit.starts_with('\t') { - tab_size * unit_len - } else { - unit_len - }; let width: usize = fragment .chars() .map(|ch| { if ch == '\t' { - tab_size + tab_width } else { // it can be none if it still meet control characters other than '\t' // here just set the width to 1 (or some value better?). @@ -3405,9 +3398,9 @@ pub mod insert { } }) .sum(); - let mut drop = width % unit_size; // round down to nearest unit + let mut drop = width % indent_width; // round down to nearest unit if drop == 0 { - drop = unit_size + drop = indent_width }; // if it's already at a unit, consume a whole unit let mut chars = fragment.chars().rev(); let mut start = pos; @@ -3949,7 +3942,7 @@ fn unindent(cx: &mut Context) { let lines = get_lines(doc, view.id); let mut changes = Vec::with_capacity(lines.len()); let tab_width = doc.tab_width(); - let indent_width = count * tab_width; + let indent_width = count * doc.indent_width(); for line_idx in lines { let line = doc.text().line(line_idx); diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 11a0dbf8b..bbcc86664 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -1122,13 +1122,18 @@ impl Document { self.syntax.as_ref() } - /// Tab size in columns. + /// The width that the tab character is rendered at pub fn tab_width(&self) -> usize { self.language_config() .and_then(|config| config.indent.as_ref()) .map_or(4, |config| config.tab_width) // fallback to 4 columns } + // The width (in spaces) of a level of indentation. + pub fn indent_width(&self) -> usize { + self.indent_style.indent_width(self.tab_width()) + } + pub fn changes(&self) -> &ChangeSet { &self.changes }