diff --git a/src/fish_indent.cpp b/src/fish_indent.cpp index cdbca5db2..b6dca2fa1 100644 --- a/src/fish_indent.cpp +++ b/src/fish_indent.cpp @@ -46,6 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include "parse_constants.h" #include "parse_util.h" #include "print_help.h" +#include "wcstringutil.h" #include "wutil.h" // IWYU pragma: keep // The number of spaces per indent isn't supposed to be configurable. @@ -87,17 +88,6 @@ namespace { template using enable_if_t = typename std::enable_if::type; -/// \return the number of escaping backslashes before a character. -/// \p idx may be "one past the end." -size_t count_preceding_backslashes(const wcstring &text, size_t idx) { - assert(idx <= text.size() && "Out of bounds"); - size_t backslashes = 0; - while (backslashes < idx && text.at(idx - backslashes - 1) == L'\\') { - backslashes++; - } - return backslashes; -} - /// \return whether a character at a given index is escaped. /// A character is escaped if it has an odd number of backslashes. bool char_is_escaped(const wcstring &text, size_t idx) { diff --git a/src/reader.cpp b/src/reader.cpp index 3fde89910..cd63a15da 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -3227,28 +3227,11 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat // Historical behavior is to trim trailing spaces. // However, escaped spaces ('\ ') should not be trimmed (#7661) - while (!text.empty() && text.back() == L' ') { - // This can be done by counting pre-trailing '\' - // If there's an odd number, this must be an excaped space - - // first check if the trailing space can be escaped at all - // (making the common case fast) - if(text.length() == 1 || text[text.length()-2] != L'\\') { - text.pop_back(); - } else { - // We've found one backslash so far, count the rest - size_t num_pretrailing_backslashes = 1; - for(size_t i_offset=text.length()-2; - i_offset > 0 && text[i_offset-1] == L'\\'; --i_offset) - num_pretrailing_backslashes++; - if(num_pretrailing_backslashes%2 == 0) { - // even; this space is not escaped and should be removed - text.pop_back(); - } - // Because the above accounts for the final character, - // we're done here. Break so there's not an infinite loop - break; - } + // This can be done by counting pre-trailing '\' + // If there's an odd number, this must be an escaped space. + while (!text.empty() && text.back() == L' ' && + count_preceding_backslashes(text, text.size() - 1) % 2 == 0) { + text.pop_back(); } if (history && !conf.in_silent_mode) { diff --git a/src/wcstringutil.cpp b/src/wcstringutil.cpp index b84efa44a..df246a503 100644 --- a/src/wcstringutil.cpp +++ b/src/wcstringutil.cpp @@ -74,6 +74,15 @@ wcstring wcstolower(wcstring input) { return result; } +size_t count_preceding_backslashes(const wcstring &text, size_t idx) { + assert(idx <= text.size() && "Out of bounds"); + size_t backslashes = 0; + while (backslashes < idx && text.at(idx - backslashes - 1) == L'\\') { + backslashes++; + } + return backslashes; +} + bool string_prefixes_string(const wchar_t *proposed_prefix, const wcstring &value) { return string_prefixes_string(proposed_prefix, value.c_str()); } diff --git a/src/wcstringutil.h b/src/wcstringutil.h index e815d67db..5a99224fa 100644 --- a/src/wcstringutil.h +++ b/src/wcstringutil.h @@ -220,6 +220,10 @@ wcstring trim(wcstring input, const wchar_t *any_of); /// Converts a string to lowercase. wcstring wcstolower(wcstring input); +/// \return the number of escaping backslashes before a character. +/// \p idx may be "one past the end." +size_t count_preceding_backslashes(const wcstring &text, size_t idx); + // Out-of-line helper for wcs2string_callback. void wcs2string_bad_char(wchar_t);