diff --git a/src/common.cpp b/src/common.cpp index 5627862a5..b6029b933 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -883,6 +883,8 @@ static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring const bool no_quoted = static_cast(flags & ESCAPE_NO_QUOTED); const bool no_tilde = static_cast(flags & ESCAPE_NO_TILDE); const bool no_qmark = feature_test(features_t::qmark_noglob); + const bool symbolic = static_cast(flags & ESCAPE_SYMBOLIC) && (MB_CUR_MAX > 1); + assert((!symbolic || !escape_printables) && "symbolic implies escape-no-printables"); bool need_escape = false; bool need_complex_escape = false; @@ -911,47 +913,57 @@ static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring wchar_t c = *in; switch (c) { case L'\t': { - out += L'\\'; - out += L't'; + if (symbolic) + out += L'␉'; + else + out += L"\\t"; need_escape = need_complex_escape = true; break; } case L'\n': { - out += L'\\'; - out += L'n'; + if (symbolic) + out += L'␤'; + else + out += L"\\n"; need_escape = need_complex_escape = true; break; } case L'\b': { - out += L'\\'; - out += L'b'; + if (symbolic) + out += L'␈'; + else + out += L"\\b"; need_escape = need_complex_escape = true; break; } case L'\r': { - out += L'\\'; - out += L'r'; + if (symbolic) + out += L'␍'; + else + out += L"\\r"; need_escape = need_complex_escape = true; break; } case L'\x1B': { - out += L'\\'; - out += L'e'; + if (symbolic) + out += L'␛'; + else + out += L"\\e"; need_escape = need_complex_escape = true; break; } case L'\x7F': { - out += L'\\'; - out += L'x'; - out += L'7'; - out += L'f'; + if (symbolic) + out += L'␡'; + else + out += L"\\x7f"; need_escape = need_complex_escape = true; break; } case L'\\': case L'\'': { need_escape = need_complex_escape = true; - if (escape_printables || c == L'\\') out += L'\\'; + if (escape_printables || (c == L'\\' && !symbolic)) out += L'\\'; out += *in; break; } @@ -1001,6 +1013,11 @@ static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring if (*in >= 0 && *in < 32) { need_escape = need_complex_escape = true; + if (symbolic) { + out += L'\u2400' + *in; + break; + } + if (*in < 27 && *in != 0) { out += L'\\'; out += L'c'; diff --git a/src/common.h b/src/common.h index e19cb4db9..46ebac2ae 100644 --- a/src/common.h +++ b/src/common.h @@ -148,7 +148,9 @@ enum { /// string. ESCAPE_NO_QUOTED = 1 << 1, /// Do not escape tildes. - ESCAPE_NO_TILDE = 1 << 2 + ESCAPE_NO_TILDE = 1 << 2, + /// Replace nonprintable control characters with Unicode symbols. + ESCAPE_SYMBOLIC = 1 << 3 }; typedef unsigned int escape_flags_t; diff --git a/src/pager.cpp b/src/pager.cpp index 8294603b4..14d841016 100644 --- a/src/pager.cpp +++ b/src/pager.cpp @@ -313,8 +313,8 @@ static comp_info_list_t process_completions_into_infos(const completion_list_t & comp_t *comp_info = &result.at(i); // Append the single completion string. We may later merge these into multiple. - comp_info->comp.push_back( - escape_string(comp.completion, ESCAPE_NO_PRINTABLES | ESCAPE_NO_QUOTED)); + comp_info->comp.push_back(escape_string( + comp.completion, ESCAPE_NO_PRINTABLES | ESCAPE_NO_QUOTED | ESCAPE_SYMBOLIC)); // Append the mangled description. comp_info->desc = comp.description;