From d242daac8985fb6c0b94d24570241851a0c0f2c0 Mon Sep 17 00:00:00 2001 From: Daniel Ebert Date: Sun, 15 Oct 2023 11:43:28 +0200 Subject: [PATCH] Simplify implementation of `add_indent_level`. Increase hybrid indent heuristic attempt limit to 4. Clarify the fallback logic in indent heuristic docs. --- book/src/configuration.md | 2 +- helix-core/src/indent.rs | 41 ++++++++++++++++++--------------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index 5032f2bcc0b14..83eef44dbdb0a 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -65,7 +65,7 @@ Its settings will be merged with the configuration directory `config.toml` and t | `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` | | `default-line-ending` | The line ending to use for new documents. Can be `native`, `lf`, `crlf`, `ff`, `cr` or `nel`. `native` uses the platform's native line ending (`crlf` on Windows, otherwise `lf`). | `native` | | `insert-final-newline` | Whether to automatically insert a trailing line-ending on write if missing | `true` | -| `indent-heuristic` | How the indentation for a newly inserted line is computed: `simple` just copies the indentation level from the previous line, `tree-sitter` computes the indentation based on the syntax tree and `hybrid` combines both approaches | `hybrid` +| `indent-heuristic` | How the indentation for a newly inserted line is computed: `simple` just copies the indentation level from the previous line, `tree-sitter` computes the indentation based on the syntax tree and `hybrid` combines both approaches. If the chosen heuristic is not available, a different one will be used as a fallback (the fallback order being `hybrid` -> `tree-sitter` -> `simple`). | `hybrid` ### `[editor.statusline]` Section diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index ef0e848833f57..3a40f958b3a8c 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -8,7 +8,7 @@ use crate::{ graphemes::{grapheme_width, tab_width_at}, syntax::{IndentationHeuristic, LanguageConfiguration, RopeProvider, Syntax}, tree_sitter::Node, - Rope, RopeGraphemes, RopeSlice, + Position, Rope, RopeGraphemes, RopeSlice, }; /// Enum representing indentation style. @@ -225,27 +225,24 @@ fn add_indent_level( // Since the width of a tab depends on its offset, we cannot simply iterate over // the chars of `base_indent` in reverse until we have the desired indent reduction, // instead we iterate over them twice in forward direction. - let mut base_indent_width: usize = 0; - for c in base_indent.chars() { - base_indent_width += match c { - '\t' => tab_width_at(base_indent_width, tab_width as u16), - // This is only true since `base_indent` consists only of tabs and spaces - _ => 1, - }; - } + let base_indent_rope = RopeSlice::from(base_indent.as_str()); + #[allow(deprecated)] + let base_indent_width = + crate::visual_coords_at_pos(base_indent_rope, base_indent_rope.len_chars(), tab_width) + .col; let target_indent_width = base_indent_width .saturating_sub((-added_indent_level) as usize * indent_style.indent_width(tab_width)); - let mut reduced_indent_width = 0; - for (i, c) in base_indent.char_indices() { - if reduced_indent_width >= target_indent_width { - base_indent.truncate(i); - return base_indent; - } - reduced_indent_width += match c { - '\t' => tab_width_at(base_indent_width, tab_width as u16), - _ => 1, - }; - } + #[allow(deprecated)] + let char_end_idx = crate::pos_at_visual_coords( + base_indent_rope, + Position { + row: 0, + col: target_indent_width, + }, + tab_width, + ); + let byte_end_idx = base_indent_rope.char_to_byte(char_end_idx); + base_indent.truncate(byte_end_idx); base_indent } } @@ -955,7 +952,7 @@ pub fn indent_for_newline( line_before_end_pos, true, ) { - if let IndentationHeuristic::Hybrid = indent_heuristic { + if *indent_heuristic == IndentationHeuristic::Hybrid { // 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 @@ -965,7 +962,7 @@ pub fn indent_for_newline( // 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; + const MAX_ATTEMPTS: usize = 4; let mut num_attempts = 0; for line_idx in (0..=line_before).rev() { let line = text.line(line_idx);