diff --git a/src/common.cpp b/src/common.cpp index ab211f731..85c8b2ce9 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -997,7 +997,6 @@ static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring const bool escape_all = static_cast(flags & ESCAPE_ALL); const bool no_quoted = static_cast(flags & ESCAPE_NO_QUOTED); const bool no_tilde = static_cast(flags & ESCAPE_NO_TILDE); - const bool escape_separators = static_cast(flags & ESCAPE_SEPARATORS); const bool no_caret = feature_test(features_t::stderr_nocaret); const bool no_qmark = feature_test(features_t::qmark_noglob); @@ -1097,12 +1096,9 @@ static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring case L';': case L'"': case L'%': - case L'~': - case L':': - case L'=': { + case L'~': { bool char_is_normal = (c == L'~' && no_tilde) || (c == L'^' && no_caret) || - (c == L'?' && no_qmark) || - ((c == L':' || c == L'=') && !escape_separators); + (c == L'?' && no_qmark); if (!char_is_normal) { need_escape = 1; if (escape_all) out += L'\\'; diff --git a/src/common.h b/src/common.h index da3135c06..1065ac2db 100644 --- a/src/common.h +++ b/src/common.h @@ -134,9 +134,7 @@ enum { /// string. ESCAPE_NO_QUOTED = 1 << 1, /// Do not escape tildes. - ESCAPE_NO_TILDE = 1 << 2, - /// Escape colon and equal sign. - ESCAPE_SEPARATORS = 1 << 3, + ESCAPE_NO_TILDE = 1 << 2 }; typedef unsigned int escape_flags_t; diff --git a/src/complete.cpp b/src/complete.cpp index 512611346..b7a89f5df 100644 --- a/src/complete.cpp +++ b/src/complete.cpp @@ -1100,7 +1100,6 @@ void completer_t::complete_param_expand(const wcstring &str, bool do_file, // Squelch file descriptions per issue #254. if (this->type() == COMPLETE_AUTOSUGGEST || do_file) flags |= expand_flag::no_descriptions; - // Expand words separated by '=' separately, unless '=' is escaped or quoted. // We have the following cases: // // --foo=bar => expand just bar @@ -1108,16 +1107,14 @@ void completer_t::complete_param_expand(const wcstring &str, bool do_file, // foo=bar => expand the whole thing, and also just bar // // We also support colon separator (#2178). If there's more than one, prefer the last one. - size_t sep_index = str.size(); - do { - sep_index = sep_index == 0 ? wcstring::npos : str.find_last_of(L"=:", sep_index - 1); - } while (sep_index != wcstring::npos && is_backslashed(str, sep_index)); - wchar_t quote = L'\0'; - parse_util_get_parameter_info(str, str.size(), "e, NULL, NULL); - bool complete_from_separator = (quote == L'\0') && (sep_index != wcstring::npos); + size_t sep_index = str.find_last_of(L"=:"); + bool complete_from_separator = (sep_index != wcstring::npos); bool complete_from_start = !complete_from_separator || !string_prefixes_string(L"-", str); if (complete_from_separator) { + // FIXME: This just cuts the token, + // so any quoting or braces gets lost. + // See #4954. const wcstring sep_string = wcstring(str, sep_index + 1); std::vector local_completions; if (expand_string(sep_string, &local_completions, flags, vars, parser, NULL) == diff --git a/src/parse_util.cpp b/src/parse_util.cpp index 8b2df7565..9b6c987d4 100644 --- a/src/parse_util.cpp +++ b/src/parse_util.cpp @@ -523,8 +523,7 @@ void parse_util_get_parameter_info(const wcstring &cmd, const size_t pos, wchar_ wcstring parse_util_escape_string_with_quote(const wcstring &cmd, wchar_t quote, bool no_tilde) { wcstring result; if (quote == L'\0') { - escape_flags_t flags = - ESCAPE_ALL | ESCAPE_NO_QUOTED | (no_tilde ? ESCAPE_NO_TILDE : 0) | ESCAPE_SEPARATORS; + escape_flags_t flags = ESCAPE_ALL | ESCAPE_NO_QUOTED | (no_tilde ? ESCAPE_NO_TILDE : 0); result = escape_string(cmd, flags); } else { // Here we are going to escape a string with quotes. diff --git a/src/reader.cpp b/src/reader.cpp index 0249e7d18..cc7dae99f 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -488,6 +488,7 @@ class reader_data_t : public std::enable_shared_from_this { static volatile sig_atomic_t interrupted = 0; // Prototypes for a bunch of functions defined later on. +static bool is_backslashed(const wcstring &str, size_t pos); static wchar_t unescaped_quote(const wcstring &str, size_t pos); /// Mode on startup, which we restore on exit. @@ -2298,7 +2299,9 @@ static int can_read(int fd) { return select(fd + 1, &fds, 0, 0, &can_read_timeout) == 1; } -bool is_backslashed(const wcstring &str, size_t pos) { +/// Test if the specified character in the specified string is backslashed. pos may be at the end of +/// the string, which indicates if there is a trailing backslash. +static bool is_backslashed(const wcstring &str, size_t pos) { // note pos == str.size() is OK. if (pos > str.size()) return false; diff --git a/src/reader.h b/src/reader.h index cfa0c73ac..76d7a6137 100644 --- a/src/reader.h +++ b/src/reader.h @@ -232,8 +232,4 @@ void reader_bg_job_warning(const parser_t &parser); /// been executed between invocations of code. uint64_t reader_run_count(); -/// Test if the specified character in the specified string is backslashed. pos may be at the end of -/// the string, which indicates if there is a trailing backslash. -bool is_backslashed(const wcstring &str, size_t pos); - #endif