diff --git a/Userland/Shell/Shell.cpp b/Userland/Shell/Shell.cpp index 27088c1782..a195c1e6af 100644 --- a/Userland/Shell/Shell.cpp +++ b/Userland/Shell/Shell.cpp @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -1341,11 +1343,35 @@ Shell::SpecialCharacterEscapeMode Shell::special_character_escape_mode(u32 code_ } } -static DeprecatedString do_escape(Shell::EscapeMode escape_mode, auto& token) +template +static DeprecatedString do_escape(Shell::EscapeMode escape_mode, auto& token, Offsets&... offsets) { StringBuilder builder; + size_t offset_from_original = 0; + + auto set_offset = [&](auto& offset) { + offset.value() = builder.length(); + offset.clear(); + return true; + }; + auto check_offset = [&](auto& offset) { + if (offset == offset_from_original) + set_offset(offset); + }; + + auto maybe_offsets = Tuple { Optional { offsets }... }; + auto check_offsets = [&] { + maybe_offsets.apply_as_args([&](Args&... args) { + (check_offset(args), ...); + }); + }; + for (auto c : token) { static_assert(sizeof(c) == sizeof(u32) || sizeof(c) == sizeof(u8)); + + check_offsets(); + offset_from_original++; + switch (Shell::special_character_escape_mode(c, escape_mode)) { case Shell::SpecialCharacterEscapeMode::Untouched: if constexpr (sizeof(c) == sizeof(u8)) @@ -1402,7 +1428,7 @@ static DeprecatedString do_escape(Shell::EscapeMode escape_mode, auto& token) break; } } - + check_offsets(); return builder.to_deprecated_string(); } @@ -2019,13 +2045,20 @@ ErrorOr> Shell::complete_via_program_itself(s dbgln("Proxy completion for {}", argv); suggestions.extend(complete(argv)); } else if (kind == "plain") { - Line::CompletionSuggestion suggestion { - object.get_deprecated_string("completion"sv).value_or(""), - object.get_deprecated_string("trailing_trivia"sv).value_or(""), - object.get_deprecated_string("display_trivia"sv).value_or(""), - }; - suggestion.static_offset = object.get_u64("static_offset"sv).value_or(0); - suggestion.invariant_offset = object.get_u64("invariant_offset"sv).value_or(0); + auto completion_text = object.get_deprecated_string("completion"sv).value_or(""); + auto trailing_text = object.get_deprecated_string("trailing_trivia"sv).value_or(""); + auto display_text = object.get_deprecated_string("display_trivia"sv).value_or(""); + auto static_offset = object.get_u64("static_offset"sv).value_or(0); + auto invariant_offset = object.get_u64("invariant_offset"sv).value_or(0); + if (!object.get_bool("treat_as_code"sv).value_or(false)) { + completion_text = do_escape(EscapeMode::Bareword, completion_text, static_offset, invariant_offset); + trailing_text = escape_token(trailing_text, EscapeMode::Bareword); + display_text = escape_token(display_text, EscapeMode::Bareword); + } + Line::CompletionSuggestion suggestion { move(completion_text), move(trailing_text), move(display_text) }; + + suggestion.static_offset = static_offset; + suggestion.invariant_offset = invariant_offset; suggestion.allow_commit_without_listing = object.get_bool("allow_commit_without_listing"sv).value_or(true); suggestions.append(move(suggestion)); } else {