Fix regression causing crash in "commandline -j"

Commit 3fcc6482cb (Fix parse_util_process_extent including too much
on the left, 2024-12-24) changed the process extent based on the
observation that "A\n\n\nB" comprises three tokens with ranges 0..1,
1..2 and 4..5. Prior to that commit, the second process extent was
2..5, which seems a bit weird because it includes newlines.

Weirdness aside, the real reason for changing it was this snippet in
the autosuggestion performer, where we compute the process extent
around cursor, and check if the line at process start matches the
cached search string.

        // Search history for a matching item unless this line is not a continuation line or quoted.
        if range_of_line_at_cursor(
            &command_line,
            parse_util_process_extent(&command_line, cursor_pos, None).start,
        ) == search_string_range

Given "A\n\n\nB" and cursor_pos=1 commit 3fcc6482cb changed the output
from 2..5 to 4..5. This brings problems:
1. leading spaces will not be included (which is probably
   inconsequential but still ugly).
2. the specified cursor position is not included in the given range.

We could paper over 2 by computing min(cursor_pos)
but that would leave 1.

For now let's revert and solve the autosuggestion issue in a less
brittle way.
This commit is contained in:
Johannes Altmanninger 2025-01-12 14:12:26 +01:00
parent a1b7c36db5
commit 4f3d6427ce
4 changed files with 28 additions and 15 deletions

View file

@ -401,7 +401,6 @@ fn job_or_process_extent(
let pos = cursor_pos - cmdsub_range.start; let pos = cursor_pos - cmdsub_range.start;
let mut result = cmdsub_range.clone(); let mut result = cmdsub_range.clone();
let mut found_start = false;
for token in Tokenizer::new( for token in Tokenizer::new(
&buff[cmdsub_range.clone()], &buff[cmdsub_range.clone()],
TOK_ACCEPT_UNFINISHED | TOK_SHOW_COMMENTS, TOK_ACCEPT_UNFINISHED | TOK_SHOW_COMMENTS,
@ -423,17 +422,13 @@ fn job_or_process_extent(
result.end = cmdsub_range.start + tok_begin; result.end = cmdsub_range.start + tok_begin;
} else { } else {
// Statement at cursor might start after this token. // Statement at cursor might start after this token.
found_start = false; result.start = cmdsub_range.start + tok_begin + token.length();
out_tokens.as_mut().map(|tokens| tokens.clear()); out_tokens.as_mut().map(|tokens| tokens.clear());
} }
continue; // Do not add this to tokens continue; // Do not add this to tokens
} }
_ => (), _ => (),
} }
if !found_start {
result.start = cmdsub_range.start + tok_begin;
found_start = true;
}
out_tokens.as_mut().map(|tokens| tokens.push(token)); out_tokens.as_mut().map(|tokens| tokens.push(token));
} }
result result

View file

@ -4646,11 +4646,16 @@ fn get_autosuggestion_performer(
}; };
// Search history for a matching item unless this line is not a continuation line or quoted. // Search history for a matching item unless this line is not a continuation line or quoted.
if range_of_line_at_cursor( if {
&command_line, let mut tokens = vec![];
parse_util_process_extent(&command_line, cursor_pos, None).start, parse_util_process_extent(&command_line, cursor_pos, Some(&mut tokens));
) == search_string_range tokens
{ .first()
.map(|tok| {
range_of_line_at_cursor(&command_line, tok.offset()) == search_string_range
})
.unwrap_or_default()
} {
let mut searcher = HistorySearch::new_with_type( let mut searcher = HistorySearch::new_with_type(
history, history,
search_string.to_owned(), search_string.to_owned(),

View file

@ -102,7 +102,8 @@ fn test_parse_util_process_extent() {
}; };
} }
validate!("for file in (path base\necho", 22, 13..22); validate!("for file in (path base\necho", 22, 13..22);
validate!("begin\n\n\nec", 10, 8..10); validate!("begin\n\n\nec", 10, 6..10);
validate!("begin; echo; end", 12, 12..16);
} }
#[test] #[test]

View file

@ -3,6 +3,11 @@
# Somehow $LINES is borked on NetBSD? # Somehow $LINES is borked on NetBSD?
#REQUIRES: test $(uname) != NetBSD #REQUIRES: test $(uname) != NetBSD
set -g isolated_tmux_fish_extra_args -C '
bind ctrl-q "functions --erase fish_right_prompt" "commandline \'\'" clear-screen
set -g fish_autosuggestion_enabled 0
bind ctrl-g "__fish_echo commandline --current-job"
'
isolated-tmux-start isolated-tmux-start
isolated-tmux send-keys 'echo LINES $LINES' Enter isolated-tmux send-keys 'echo LINES $LINES' Enter
@ -33,9 +38,7 @@ isolated-tmux capture-pane -p
# CHECK: scroll_here # CHECK: scroll_here
# Soft-wrapped commandline with omitted right prompt. # Soft-wrapped commandline with omitted right prompt.
isolated-tmux send-keys C-c isolated-tmux send-keys C-q '
tmux-sleep
isolated-tmux send-keys C-l '
function fish_right_prompt function fish_right_prompt
echo right-prompt echo right-prompt
end end
@ -47,3 +50,12 @@ isolated-tmux capture-pane -p | sed 1,5d
# CHECK: 000000000000000 # CHECK: 000000000000000
# CHECK: 00000000000000000000000000000000000000000000000000000000000000000000000000000000 # CHECK: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
# CHECK: prompt {{\d+}}> right-prompt # CHECK: prompt {{\d+}}> right-prompt
isolated-tmux send-keys C-q 'echo | echo\;' M-Enter 'another job' C-b C-b C-g
tmux-sleep
isolated-tmux capture-pane -p
# CHECK: prompt {{\d+}}> echo | echo;
# CHECK: another job
# CHECK: another job
# CHECK: prompt {{\d+}}> echo | echo;
# CHECK: another job