Do not add a space after completing inside brace expansion

Another everyday annoyance, has been for many years.
This commit is contained in:
Johannes Altmanninger 2024-10-19 17:07:10 +02:00
parent c41dbe4551
commit 2e4f98b51c
5 changed files with 32 additions and 18 deletions

View file

@ -739,6 +739,7 @@ impl<'ctx> Completer<'ctx> {
&current_token[pos + 1..],
/*do_file=*/ true,
/*handle_as_special_cd=*/ false,
cur_tok.is_unterminated_brace,
);
return;
}
@ -837,7 +838,13 @@ impl<'ctx> Completer<'ctx> {
}
// This function wants the unescaped string.
self.complete_param_expand(L!(""), current_argument, do_file, handle_as_special_cd);
self.complete_param_expand(
L!(""),
current_argument,
do_file,
handle_as_special_cd,
cur_tok.is_unterminated_brace,
);
// Lastly mark any completions that appear to already be present in arguments.
self.mark_completions_duplicating_arguments(&cmdline, current_token, tokens);
@ -1511,6 +1518,7 @@ impl<'ctx> Completer<'ctx> {
s: &wstr,
do_file: bool,
handle_as_special_cd: bool,
is_unterminated_brace: bool,
) {
if self.ctx.check_cancel() {
return;
@ -1522,6 +1530,9 @@ impl<'ctx> Completer<'ctx> {
if !do_file {
flags |= ExpandFlags::SKIP_WILDCARDS;
}
if is_unterminated_brace {
flags |= ExpandFlags::NO_SPACE_FOR_UNCLOSED_BRACE;
}
if handle_as_special_cd && do_file {
if self.flags.autosuggestion {

View file

@ -72,6 +72,8 @@ bitflags! {
/// Do expansions specifically to support external command completions. This means using PATH as
/// a list of potential working directories.
const SPECIAL_FOR_COMMAND = 1 << 13;
/// The token has an unclosed brace, so don't add a space.
const NO_SPACE_FOR_UNCLOSED_BRACE = 1 << 14;
}
}

View file

@ -159,6 +159,12 @@ fn test_complete() {
};
}
unique_completion_applies_as!(
"touch test/complete_test/{testfi",
r"le",
"touch test/complete_test/{testfile",
);
// Brackets - see #5831
unique_completion_applies_as!(
"touch test/complete_test/bracket[",

View file

@ -67,6 +67,8 @@ pub struct Tok {
// If an error, this is the error code.
pub error: TokenizerError,
pub is_unterminated_brace: bool,
// The type of the token.
pub type_: TokenType,
}
@ -206,6 +208,7 @@ impl Tok {
error_offset_within_token: SOURCE_OFFSET_INVALID.try_into().unwrap(),
error_length: 0,
error: TokenizerError::none,
is_unterminated_brace: false,
type_: r#type,
}
}
@ -550,6 +553,7 @@ impl<'c> Tokenizer<'c> {
error_offset_within_token: (error_loc - token_start) as u32,
error_length: error_len as u32,
error: error_type,
is_unterminated_brace: false,
type_: TokenType::error,
}
}
@ -785,6 +789,7 @@ impl<'c> Tokenizer<'c> {
let mut result = Tok::new(TokenType::string);
result.set_offset(buff_start);
result.set_length(self.token_cursor - buff_start);
result.is_unterminated_brace = mode & TOK_MODE_CURLY_BRACES;
result
}
}

View file

@ -341,6 +341,10 @@ fn wildcard_test_flags_then_complete(
) -> bool {
let executables_only = expand_flags.contains(ExpandFlags::EXECUTABLES_ONLY);
let need_directory = expand_flags.contains(ExpandFlags::DIRECTORIES_ONLY);
let mut flags = CompleteFlags::default();
if expand_flags.contains(ExpandFlags::NO_SPACE_FOR_UNCLOSED_BRACE) {
flags |= CompleteFlags::NO_SPACE;
}
// Fast path: If we need directories, and we already know it is one,
// and we don't need to do anything else, just return it.
// This is a common case for cd completions, and removes the `stat` entirely in case the system
@ -357,15 +361,7 @@ fn wildcard_test_flags_then_complete(
) == WildcardResult::Match;
}
// Check if it will match before stat().
if wildcard_complete(
filename,
wc,
None,
None,
expand_flags,
CompleteFlags::default(),
) != WildcardResult::Match
{
if wildcard_complete(filename, wc, None, None, expand_flags, flags) != WildcardResult::Match {
return false;
}
@ -432,14 +428,8 @@ fn wildcard_test_flags_then_complete(
) == WildcardResult::Match;
}
wildcard_complete(
filename,
wc,
desc_func,
Some(out),
expand_flags,
CompleteFlags::empty(),
) == WildcardResult::Match
wildcard_complete(filename, wc, desc_func, Some(out), expand_flags, flags)
== WildcardResult::Match
}
use expander::WildCardExpander;