From 8d6426295edc91dbf6a526a9ef2f089fa10c84b5 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Fri, 17 Apr 2026 00:48:01 +0800 Subject: [PATCH] complete: automatically resolve REPLACES_TOKEN flag This flag is implied by matches that require replacements. Reflect that in the Completion::new, reducing the number of places where we raise the flag. This slightly simplifies tasks like proving the parent commit. There are other scenarios (e.g. wildcards) where we currently set the flag additionally. --- src/complete.rs | 35 +++++++++++++++++------------------ src/wildcard.rs | 7 +------ 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/complete.rs b/src/complete.rs index c01cf241b..e7f1c0d4d 100644 --- a/src/complete.rs +++ b/src/complete.rs @@ -158,15 +158,16 @@ pub fn new( r#match: StringFuzzyMatch, /* = exact_match */ flags: CompleteFlags, ) -> Self { - let flags = resolve_auto_space(&completion, flags); - let zelf = Self { + let mut flags = resolve_auto_space(&completion, flags); + if r#match.requires_full_replacement() { + flags |= CompleteFlags::REPLACES_TOKEN; + } + Self { completion, description, r#match, flags, - }; - assert!(!zelf.r#match.requires_full_replacement() || zelf.replaces_token()); - zelf + } } pub fn from_completion(completion: WString) -> Self { @@ -1484,14 +1485,12 @@ fn complete_param_for_command( continue; }; - let mut offset = 0; - let mut flags = CompleteFlags::empty(); - - if r#match.requires_full_replacement() { - flags = CompleteFlags::REPLACES_TOKEN; + let offset = if r#match.requires_full_replacement() { + 0 } else { - offset = s.len(); - } + s.len() + }; + let completion = whole_opt.slice_from(offset); // does this switch have any known arguments let has_arg = !o.comp.is_empty(); @@ -1503,14 +1502,14 @@ fn complete_param_for_command( // a completion. By default we avoid using '=' and instead rely on '--switch // switch-arg', since it is more commonly supported by homebrew getopt-like // functions. - let completion = sprintf!("%s=", whole_opt.slice_from(offset)); + let completion = sprintf!("%s=", completion); // Append a long-style option with a mandatory trailing equal sign if !self.completions.add(Completion::new( completion, o.desc.localize().to_owned(), r#match, - flags | CompleteFlags::NO_SPACE, + CompleteFlags::NO_SPACE, )) { return false; } @@ -1518,10 +1517,10 @@ fn complete_param_for_command( // Append a long-style option if !self.completions.add(Completion::new( - whole_opt.slice_from(offset).to_owned(), + completion.to_owned(), o.desc.localize().to_owned(), r#match, - flags, + CompleteFlags::empty(), )) { return false; } @@ -1667,7 +1666,7 @@ fn complete_variable(&mut self, s: &wstr, start_offset: usize) -> bool { // Take only the suffix. env_name.slice_from(varlen).to_owned() } else { - flags |= CompleteFlags::REPLACES_TOKEN | CompleteFlags::DONT_ESCAPE; + flags |= CompleteFlags::DONT_ESCAPE; whole_var.slice_to(start_offset).to_owned() + env_name.as_utfstr() }; @@ -1830,7 +1829,7 @@ fn getpwent_name() -> Option { // TODO: propagate overflow? let mut flags = CompleteFlags::NO_SPACE; if r#match.requires_full_replacement() { - flags |= CompleteFlags::REPLACES_TOKEN | CompleteFlags::DONT_ESCAPE; + flags |= CompleteFlags::DONT_ESCAPE; } let _ = self.completions.add(Completion::new( if r#match.requires_full_replacement() { diff --git a/src/wildcard.rs b/src/wildcard.rs index 00d18c7d1..2741c6d2f 100644 --- a/src/wildcard.rs +++ b/src/wildcard.rs @@ -149,16 +149,11 @@ fn wildcard_complete_internal( // Note: out_completion may be empty if the completion really is empty, e.g. tab-completing // 'foo' when a file 'foo' exists. - let local_flags = if full_replacement { - flags | CompleteFlags::REPLACES_TOKEN - } else { - flags - }; if !out.add(Completion::new( out_completion.to_owned(), out_desc, m, - local_flags, + flags, )) { return WildcardResult::Overflow; }