From d823444c6e57df280809af716664fdbcb74c0477 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Fri, 3 Jan 2025 12:15:55 +0100 Subject: [PATCH] Apply autosuggestions from completions also if cursor is not at EOL Before 1c4e5cadf2 (Autosuggestions in multi-line command lines, 2024-12-15), the completion code path in the autosuggestion performer used to do something weird: it used to request completions for the entire command line (with the implied cursor at end) but try to apply the same completion at the actual cursor. That commit changed this to request completions only up to the cursor position, which could in theory make us produce valid completions even if the cursor is not at end of the line. However, that doesn't really work since autosuggestions can only be rendered at the end of the line. And the worst of it, that commit tries to compute line_at_cursor(&full_line, search_string_range.end) which crashes as out-of-bounds if the completion needs to replace the token (like a case-correcting completion does). Let's apply completions to the end, matching how autosuggestions work in general. --- src/reader.rs | 8 ++++---- tests/checks/tmux-autosuggestion.fish | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/reader.rs b/src/reader.rs index e75519816..c6018df28 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -4573,23 +4573,23 @@ fn get_autosuggestion_performer( // Try normal completions. let complete_flags = CompletionRequestOptions::autosuggest(); + let mut would_be_cursor = search_string_range.end; let (mut completions, needs_load) = - complete(&command_line[..cursor_pos], complete_flags, &ctx); + complete(&command_line[..would_be_cursor], complete_flags, &ctx); let suggestion = if completions.is_empty() { WString::new() } else { sort_and_prioritize(&mut completions, complete_flags); let comp = &completions[0]; - let mut cursor = cursor_pos; let full_line = completion_apply_to_command_line( &comp.completion, comp.flags, &command_line, - &mut cursor, + &mut would_be_cursor, /*append_only=*/ true, ); - line_at_cursor(&full_line, search_string_range.end).to_owned() + line_at_cursor(&full_line, would_be_cursor).to_owned() }; let mut result = AutosuggestionResult::new( command_line, diff --git a/tests/checks/tmux-autosuggestion.fish b/tests/checks/tmux-autosuggestion.fish index f573e5aac..fc536bb5f 100644 --- a/tests/checks/tmux-autosuggestion.fish +++ b/tests/checks/tmux-autosuggestion.fish @@ -9,3 +9,17 @@ isolated-tmux send-keys M-Right isolated-tmux capture-pane -p # CHECK: prompt 1> echo "foo bar baz" tmux-sleep + +touch COMPL + +# Regression test. +isolated-tmux send-keys C-u C-l ': sometoken' M-b c +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 1> : csometoken + +# Test that we get completion autosuggestions also when the cursor is not at EOL. +isolated-tmux send-keys C-u 'complete nofilecomp -f' Enter C-l 'nofilecomp ./CO' C-a M-d : +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 2> : ./COMPL