From c54131c8c5e23a346c9c8d008252aa648cec6996 Mon Sep 17 00:00:00 2001 From: kerty Date: Sun, 26 Jan 2025 16:14:24 +0300 Subject: [PATCH] Make at least one character of the autosuggestion always shown Previously, there were situations where an autosuggestion existed but was not shown at all. This commit guarantees that at least the `ellipsis_char` is shown, regardless of the situation. --- src/screen.rs | 30 +++++------ src/tests/screen.rs | 119 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 123 insertions(+), 26 deletions(-) diff --git a/src/screen.rs b/src/screen.rs index de6385d1e..8a424519f 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -2022,7 +2022,7 @@ pub(crate) fn compute_layout( // 3. Newline separator (right prompt hidden). // // Left prompt and command line are always visible. - // Autosuggestion is truncated to fit on the line (possibly to zero or not at all). + // Autosuggestion is truncated to fit on the line (possibly to ellipsis_char or not at all). // // A remark about layout #3: if we've pushed the command line to a new line, why can't we draw // the right prompt? The issue is resizing: if you resize the window smaller, then the right @@ -2036,7 +2036,7 @@ pub(crate) fn compute_layout( result.left_prompt_space = left_prompt_width; // Hide the right prompt if it doesn't fit on the first line. - if left_prompt_width + first_command_line_width + right_prompt_width <= screen_width { + if left_prompt_width + first_command_line_width + right_prompt_width < screen_width { result.right_prompt = right_prompt; } else { right_prompt_width = 0; @@ -2046,29 +2046,25 @@ pub(crate) fn compute_layout( assert!(left_prompt_width + right_prompt_width <= screen_width); // Calculate space available for autosuggestion. - let pos = commandline_before_suggestion - .chars() - .rposition(|c| c == '\n'); let width = (left_prompt_width + autosuggestion_line_explicit_width - + pos.map_or(right_prompt_width, |pos| { - usize::try_from(indent[pos]).unwrap() * INDENT_STEP - })) + + commandline_before_suggestion + .chars() + .rposition(|c| c == '\n') + .map_or(right_prompt_width, |pos| { + usize::try_from(indent[pos]).unwrap() * INDENT_STEP + })) % screen_width; - let available_autosuggest_space = if width == 0 && pos.is_none() && right_prompt_width != 0 { - 0 - } else { - screen_width - width - }; + let available_autosuggest_space = screen_width - width; - // Need at least two characters to show an autosuggestion. + // Truncate the autosuggestion to fit on the line. let mut autosuggestion = WString::new(); - if available_autosuggest_space > autosuggest_total_width { + if available_autosuggest_space >= autosuggest_total_width { autosuggestion = autosuggestion_str.to_owned(); - } else if autosuggest_total_width > 0 && available_autosuggest_space > 2 { + } else if autosuggest_total_width > 0 { let truncation_offset = truncation_offset_for_width( &autosuggest_truncated_widths, - available_autosuggest_space - 2, + available_autosuggest_space - 1, ); autosuggestion = autosuggestion_str[..truncation_offset].to_owned(); autosuggestion.push(ellipsis_char); diff --git a/src/tests/screen.rs b/src/tests/screen.rs index 5ed37e3bd..4da65f41b 100644 --- a/src/tests/screen.rs +++ b/src/tests/screen.rs @@ -306,12 +306,12 @@ macro_rules! validate { ); validate!( ( - 30, "left>", "", " ( "left>", 5, "", "", " ( "left>", 5, "", "", " ( "left>", 5, "", "", " ( "left>", 5, "", " ( + "left>", + 5, + "", + " auto…", + ) + ); + validate!( + ( + 18, "left>", " ( + "left>", + 5, + "", + "s", + ) + ); + validate!( + ( + 18, "left>", " ( + "left>", + 5, + "", + "…", + ) + ); + validate!( + ( + 18, "left>", " ( + "left>", + 5, + "", + "uggestion long so…", + ) + ); + validate!( + ( + 18, "left>", " ( + "left>", + 5, + "", " ( + "left>", + 5, + "", " ( + "left>", + 5, + "", " ( + "left>", + 5, + "", + "and …", + ) + ); + validate!( + ( + 18, "left>", " ( + "left>", + 5, + "", + "…", + ) + ); + validate!( + ( + 18, "left>", " ( + "left>", + 5, + "", + "utosuggestion sof…", ) ); - assert_eq!(indent["if :\ncommand autosuggest…\n".len()], 1); }