From cd541575b4c5d09cfa26814403d15ce057ee0175 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sat, 19 Oct 2024 12:26:44 +0200 Subject: [PATCH] Fix completion failing on unclosed brace with wildcard Completion on ": {*," used to work but nowadays our attempt to wildcard-expand it fails with a syntax error and we do nothing. This behavior probably only makes sense for the overflow case, so do that. --- src/builtins/commandline.rs | 6 ++++-- src/complete.rs | 29 ++++++++++++++++------------- src/expand.rs | 14 +++++++++++--- src/parse_execution.rs | 8 ++++---- src/parse_util.rs | 21 ++++++++++++--------- src/parser.rs | 7 ++++--- src/reader.rs | 3 ++- tests/checks/tmux-complete.fish | 4 ++++ 8 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/builtins/commandline.rs b/src/builtins/commandline.rs index 8a57d3dd9..95dbd17f7 100644 --- a/src/builtins/commandline.rs +++ b/src/builtins/commandline.rs @@ -151,8 +151,10 @@ fn write_part( ) .result { - ExpandResultCode::error | ExpandResultCode::wildcard_no_match => { - // Hit expansion limit, forward the unexpanded string. + ExpandResultCode::error + | ExpandResultCode::overflow + | ExpandResultCode::wildcard_no_match => { + // Maybe hit expansion limit, forward the unexpanded string. args.push(Completion::from_completion(token_text.to_owned())); } ExpandResultCode::cancel => { diff --git a/src/complete.rs b/src/complete.rs index 571704001..057a52387 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -1566,16 +1566,17 @@ impl<'ctx> Completer<'ctx> { if let Some(sep_index) = sep_index { let sep_string = s.slice_from(sep_index + 1); let mut local_completions = Vec::new(); - if expand_string( - sep_string.to_owned(), - &mut local_completions, - flags, - self.ctx, - None, - ) - .result - == ExpandResultCode::error - { + if matches!( + expand_string( + sep_string.to_owned(), + &mut local_completions, + flags, + self.ctx, + None, + ) + .result, + ExpandResultCode::error | ExpandResultCode::overflow + ) { FLOGF!(complete, "Error while expanding string '%ls'", sep_string); } @@ -1606,9 +1607,11 @@ impl<'ctx> Completer<'ctx> { } let first = self.completions.len(); - if expand_to_receiver(s.to_owned(), &mut self.completions, flags, self.ctx, None).result - == ExpandResultCode::error - { + if matches!( + expand_to_receiver(s.to_owned(), &mut self.completions, flags, self.ctx, None) + .result, + ExpandResultCode::error | ExpandResultCode::overflow, + ) { FLOGF!(complete, "Error while expanding string '%ls'", s); } Self::escape_opening_brackets(&mut self.completions[first..], s); diff --git a/src/expand.rs b/src/expand.rs index b54766f20..d8f694ff1 100644 --- a/src/expand.rs +++ b/src/expand.rs @@ -1275,14 +1275,20 @@ impl<'a, 'b, 'c> Expander<'a, 'b, 'c> { } let this_result = (stage)(&mut expand, comp.completion, &mut output_storage); total_result = this_result; - if total_result == ExpandResultCode::error { + if matches!( + total_result.result, + ExpandResultCode::error | ExpandResultCode::overflow + ) { break; } } // Output becomes our next stage's input. completions = output_storage.take(); - if total_result == ExpandResultCode::error { + if matches!( + total_result.result, + ExpandResultCode::error | ExpandResultCode::overflow + ) { break; } } @@ -1487,7 +1493,7 @@ impl<'a, 'b, 'c> Expander<'a, 'b, 'c> { let mut expanded = expanded_recv.take(); expanded.sort_by(|a, b| wcsfilecmp_glob(&a.completion, &b.completion)); if !out.extend(expanded) { - result = ExpandResult::new(ExpandResultCode::error); + result = ExpandResult::new(ExpandResultCode::overflow); } } else { // Can't fully justify this check. I think it's that SKIP_WILDCARDS is used when completing @@ -1558,6 +1564,8 @@ impl<'a, 'b, 'c> Expander<'a, 'b, 'c> { pub enum ExpandResultCode { /// There was an error, for example, unmatched braces. error, + /// Expansion would exceed the maximum number of elements. + overflow, /// Expansion succeeded. ok, /// Expansion was cancelled (e.g. control-C). diff --git a/src/parse_execution.rs b/src/parse_execution.rs index 0f55607e5..8a511577f 100644 --- a/src/parse_execution.rs +++ b/src/parse_execution.rs @@ -498,7 +498,7 @@ impl<'a> ExecutionContext { false, ); match expand_err.result { - ExpandResultCode::error => { + ExpandResultCode::error | ExpandResultCode::overflow => { // Issue #5812 - the expansions were done on the command token, // excluding prefixes such as " " or "if ". // This means that the error positions are relative to the beginning @@ -630,7 +630,7 @@ impl<'a> ExecutionContext { variable_assignment.range().unwrap().start() + equals_pos + 1, ); match expand_ret.result { - ExpandResultCode::error => { + ExpandResultCode::error|ExpandResultCode::overflow => { return self.report_errors(ctx, expand_ret.status, &errors); } ExpandResultCode::cancel => { @@ -1103,7 +1103,7 @@ impl<'a> ExecutionContext { parse_error_offset_source_start(&mut errors, statement.argument.range().unwrap().start()); match expand_ret.result { - ExpandResultCode::error => { + ExpandResultCode::error | ExpandResultCode::overflow => { return self.report_errors(ctx, expand_ret.status, &errors); } ExpandResultCode::cancel => { @@ -1386,7 +1386,7 @@ impl<'a> ExecutionContext { ); parse_error_offset_source_start(&mut errors, arg_node.range().unwrap().start()); match expand_ret.result { - ExpandResultCode::error => { + ExpandResultCode::error | ExpandResultCode::overflow => { return self.report_errors(ctx, expand_ret.status, &errors); } ExpandResultCode::cancel => { diff --git a/src/parse_util.rs b/src/parse_util.rs index c898db131..e9fd6e423 100644 --- a/src/parse_util.rs +++ b/src/parse_util.rs @@ -1669,15 +1669,18 @@ fn detect_errors_in_decorated_statement( // Make a new error list so we can fix the offset for just those, then append later. let mut new_errors = ParseErrorList::new(); let mut command = WString::new(); - if expand_to_command_and_args( - unexp_command, - &OperationContext::empty(), - &mut command, - None, - Some(&mut new_errors), - true, /* skip wildcards */ - ) == ExpandResultCode::error - { + if matches!( + expand_to_command_and_args( + unexp_command, + &OperationContext::empty(), + &mut command, + None, + Some(&mut new_errors), + true, /* skip wildcards */ + ) + .result, + ExpandResultCode::error | ExpandResultCode::overflow + ) { errored = true; } diff --git a/src/parser.rs b/src/parser.rs index ded236947..e48a55f87 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -652,9 +652,10 @@ impl Parser { let list = ast.top().as_freestanding_argument_list().unwrap(); for arg in &list.arguments { let arg_src = arg.source(arg_list_src); - if expand_string(arg_src.to_owned(), &mut result, flags, ctx, None) - == ExpandResultCode::error - { + if matches!( + expand_string(arg_src.to_owned(), &mut result, flags, ctx, None).result, + ExpandResultCode::error | ExpandResultCode::overflow + ) { break; // failed to expand a string } } diff --git a/src/reader.rs b/src/reader.rs index 594e33d12..a817d0e63 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -5648,7 +5648,8 @@ impl<'a> Reader<'a> { position_in_token, &mut wc_expanded, ) { - ExpandResultCode::error => { + ExpandResultCode::error => {} + ExpandResultCode::overflow => { // This may come about if we exceeded the max number of matches. // Return "success" to suppress normal completions. self.flash(); diff --git a/tests/checks/tmux-complete.fish b/tests/checks/tmux-complete.fish index 9c6498e0a..9137a05b1 100644 --- a/tests/checks/tmux-complete.fish +++ b/tests/checks/tmux-complete.fish @@ -112,3 +112,7 @@ tmux-sleep isolated-tmux send-keys C-s C-s C-s 'x' isolated-tmux capture-pane -p # CHECK: prompt 10> echo do not accept thix +isolated-tmux send-keys C-u C-l ': {*,' Tab Tab Space , +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 10> : {*,cmake/ ,{{.*}}