on master help sign in
Replace incorrect usages of tab_width with indent_width. (#5918)
a1a6d5fTriton171
helix-core/src/indent.rs+32−7
@@ -56,6 +56,14 @@ impl IndentStyle {
56 }
56 }
57 }
57 }
58 }
58 }
59+
60+ #[inline]
61+ pub fn indent_width(&self, tab_width: usize) -> usize {
62+ match *self {
63+ IndentStyle::Tabs => tab_width,
64+ IndentStyle::Spaces(width) => width as usize,
65+ }
66+ }
59}
67}
60
68
61/// Attempts to detect the indentation style used in a document.
69/// Attempts to detect the indentation style used in a document.
@@ -177,7 +185,7 @@ pub fn auto_detect_indent_style(document_text: &Rope) -> Option<IndentStyle> {
177
185
178/// To determine indentation of a newly inserted line, figure out the indentation at the last col
186/// To determine indentation of a newly inserted line, figure out the indentation at the last col
179/// of the previous line.
187/// of the previous line.
180−pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
188+pub fn indent_level_for_line(line: RopeSlice, tab_width: usize, indent_width: usize) -> usize {
181 let mut len = 0;
189 let mut len = 0;
182 for ch in line.chars() {
190 for ch in line.chars() {
183 match ch {
191 match ch {
@@ -187,7 +195,7 @@ pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
187 }
195 }
188 }
196 }
189
197
190− len / tab_width
198+ len / indent_width
191}
199}
192
200
193/// Computes for node and all ancestors whether they are the first node on their line.
201/// Computes for node and all ancestors whether they are the first node on their line.
@@ -466,6 +474,7 @@ fn extend_nodes<'a>(
466 text: RopeSlice,
474 text: RopeSlice,
467 line: usize,
475 line: usize,
468 tab_width: usize,
476 tab_width: usize,
477+ indent_width: usize,
469) {
478) {
470 let mut stop_extend = false;
479 let mut stop_extend = false;
471
480
@@ -490,10 +499,12 @@ fn extend_nodes<'a>(
490 if deepest_preceding.end_position().row == line {
499 if deepest_preceding.end_position().row == line {
491 extend_node = true;
500 extend_node = true;
492 } else {
501 } else {
502+ let cursor_indent =
493− let cursor_indent = indent_level_for_line(text.line(line), tab_width);
503+ indent_level_for_line(text.line(line), tab_width, indent_width);
494 let node_indent = indent_level_for_line(
504 let node_indent = indent_level_for_line(
495 text.line(deepest_preceding.start_position().row),
505 text.line(deepest_preceding.start_position().row),
496 tab_width,
506 tab_width,
507+ indent_width,
497 );
508 );
498 if cursor_indent > node_indent {
509 if cursor_indent > node_indent {
499 extend_node = true;
510 extend_node = true;
@@ -562,6 +573,7 @@ pub fn treesitter_indent_for_pos(
562 syntax: &Syntax,
573 syntax: &Syntax,
563 indent_style: &IndentStyle,
574 indent_style: &IndentStyle,
564 tab_width: usize,
575 tab_width: usize,
576+ indent_width: usize,
565 text: RopeSlice,
577 text: RopeSlice,
566 line: usize,
578 line: usize,
567 pos: usize,
579 pos: usize,
@@ -622,6 +634,7 @@ pub fn treesitter_indent_for_pos(
622 text,
634 text,
623 line,
635 line,
624 tab_width,
636 tab_width,
637+ indent_width,
625 );
638 );
626 }
639 }
627 let mut first_in_line = get_first_in_line(node, new_line.then_some(byte_pos));
640 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(
709 line_before_end_pos: usize,
722 line_before_end_pos: usize,
710 current_line: usize,
723 current_line: usize,
711) -> String {
724) -> String {
725+ let indent_width = indent_style.indent_width(tab_width);
712 if let (Some(query), Some(syntax)) = (
726 if let (Some(query), Some(syntax)) = (
713 language_config.and_then(|config| config.indent_query()),
727 language_config.and_then(|config| config.indent_query()),
714 syntax,
728 syntax,
@@ -718,6 +732,7 @@ pub fn indent_for_newline(
718 syntax,
732 syntax,
719 indent_style,
733 indent_style,
720 tab_width,
734 tab_width,
735+ indent_width,
721 text,
736 text,
722 line_before,
737 line_before,
723 line_before_end_pos,
738 line_before_end_pos,
@@ -726,7 +741,7 @@ pub fn indent_for_newline(
726 return indent;
741 return indent;
727 };
742 };
728 }
743 }
729− let indent_level = indent_level_for_line(text.line(current_line), tab_width);
744+ let indent_level = indent_level_for_line(text.line(current_line), tab_width, indent_width);
730 indent_style.as_str().repeat(indent_level)
745 indent_style.as_str().repeat(indent_level)
731}
746}
732
747
@@ -763,12 +778,22 @@ mod test {
763 #[test]
778 #[test]
764 fn test_indent_level() {
779 fn test_indent_level() {
765 let tab_width = 4;
780 let tab_width = 4;
781+ let indent_width = 4;
766 let line = Rope::from(" fn new"); // 8 spaces
782 let line = Rope::from(" fn new"); // 8 spaces
783+ assert_eq!(
767− assert_eq!(indent_level_for_line(line.slice(..), tab_width), 2);
784+ indent_level_for_line(line.slice(..), tab_width, indent_width),
785+ 2
786+ );
768 let line = Rope::from("\t\t\tfn new"); // 3 tabs
787 let line = Rope::from("\t\t\tfn new"); // 3 tabs
788+ assert_eq!(
769− assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3);
789+ indent_level_for_line(line.slice(..), tab_width, indent_width),
790+ 3
791+ );
770 // mixed indentation
792 // mixed indentation
771 let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
793 let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
794+ assert_eq!(
772− assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3);
795+ indent_level_for_line(line.slice(..), tab_width, indent_width),
796+ 3
797+ );
773 }
798 }
774}
799}
helix-core/tests/indent.rs+4−2
@@ -46,11 +46,13 @@ fn test_treesitter_indent(file_name: &str, lang_scope: &str) {
46 for i in 0..doc.len_lines() {
46 for i in 0..doc.len_lines() {
47 let line = text.line(i);
47 let line = text.line(i);
48 if let Some(pos) = helix_core::find_first_non_whitespace_char(line) {
48 if let Some(pos) = helix_core::find_first_non_whitespace_char(line) {
49+ let tab_and_indent_width: usize = 4;
49 let suggested_indent = treesitter_indent_for_pos(
50 let suggested_indent = treesitter_indent_for_pos(
50 indent_query,
51 indent_query,
51 &syntax,
52 &syntax,
52− &IndentStyle::Spaces(4),
53+ &IndentStyle::Spaces(tab_and_indent_width as u8),
53− 4,
54+ tab_and_indent_width,
55+ tab_and_indent_width,
54 text,
56 text,
55 i,
57 i,
56 text.line_to_char(i) + pos,
58 text.line_to_char(i) + pos,
helix-term/src/commands.rs+6−13
@@ -3364,8 +3364,8 @@ pub mod insert {
3364 let count = cx.count();
3364 let count = cx.count();
3365 let (view, doc) = current_ref!(cx.editor);
3365 let (view, doc) = current_ref!(cx.editor);
3366 let text = doc.text().slice(..);
3366 let text = doc.text().slice(..);
3367− let indent_unit = doc.indent_style.as_str();
3367+ let tab_width = doc.tab_width();
3368− let tab_size = doc.tab_width();
3368+ let indent_width = doc.indent_width();
3369 let auto_pairs = doc.auto_pairs(cx.editor);
3369 let auto_pairs = doc.auto_pairs(cx.editor);
3370
3370
3371 let transaction =
3371 let transaction =
@@ -3386,18 +3386,11 @@ pub mod insert {
3386 None,
3386 None,
3387 )
3387 )
3388 } else {
3388 } else {
3389− let unit_len = indent_unit.chars().count();
3390− // NOTE: indent_unit always contains 'only spaces' or 'only tab' according to `IndentStyle` definition.
3391− let unit_size = if indent_unit.starts_with('\t') {
3392− tab_size * unit_len
3393− } else {
3394− unit_len
3395− };
3396 let width: usize = fragment
3389 let width: usize = fragment
3397 .chars()
3390 .chars()
3398 .map(|ch| {
3391 .map(|ch| {
3399 if ch == '\t' {
3392 if ch == '\t' {
3400− tab_size
3393+ tab_width
3401 } else {
3394 } else {
3402 // it can be none if it still meet control characters other than '\t'
3395 // it can be none if it still meet control characters other than '\t'
3403 // here just set the width to 1 (or some value better?).
3396 // here just set the width to 1 (or some value better?).
@@ -3405,9 +3398,9 @@ pub mod insert {
3405 }
3398 }
3406 })
3399 })
3407 .sum();
3400 .sum();
3408− let mut drop = width % unit_size; // round down to nearest unit
3401+ let mut drop = width % indent_width; // round down to nearest unit
3409 if drop == 0 {
3402 if drop == 0 {
3410− drop = unit_size
3403+ drop = indent_width
3411 }; // if it's already at a unit, consume a whole unit
3404 }; // if it's already at a unit, consume a whole unit
3412 let mut chars = fragment.chars().rev();
3405 let mut chars = fragment.chars().rev();
3413 let mut start = pos;
3406 let mut start = pos;
@@ -3949,7 +3942,7 @@ fn unindent(cx: &mut Context) {
3949 let lines = get_lines(doc, view.id);
3942 let lines = get_lines(doc, view.id);
3950 let mut changes = Vec::with_capacity(lines.len());
3943 let mut changes = Vec::with_capacity(lines.len());
3951 let tab_width = doc.tab_width();
3944 let tab_width = doc.tab_width();
3952− let indent_width = count * tab_width;
3945+ let indent_width = count * doc.indent_width();
3953
3946
3954 for line_idx in lines {
3947 for line_idx in lines {
3955 let line = doc.text().line(line_idx);
3948 let line = doc.text().line(line_idx);
helix-view/src/document.rs+6−1
@@ -1122,13 +1122,18 @@ impl Document {
1122 self.syntax.as_ref()
1122 self.syntax.as_ref()
1123 }
1123 }
1124
1124
1125− /// Tab size in columns.
1125+ /// The width that the tab character is rendered at
1126 pub fn tab_width(&self) -> usize {
1126 pub fn tab_width(&self) -> usize {
1127 self.language_config()
1127 self.language_config()
1128 .and_then(|config| config.indent.as_ref())
1128 .and_then(|config| config.indent.as_ref())
1129 .map_or(4, |config| config.tab_width) // fallback to 4 columns
1129 .map_or(4, |config| config.tab_width) // fallback to 4 columns
1130 }
1130 }
1131
1131
1132+ // The width (in spaces) of a level of indentation.
1133+ pub fn indent_width(&self) -> usize {
1134+ self.indent_style.indent_width(self.tab_width())
1135+ }
1136+
1132 pub fn changes(&self) -> &ChangeSet {
1137 pub fn changes(&self) -> &ChangeSet {
1133 &self.changes
1138 &self.changes
1134 }
1139 }