From 7187784936edc640d547ad497ef9b644a2483a2e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 17 Aug 2021 20:40:30 +1000 Subject: [PATCH] Move control character escaping responsibility to the terminal UI Fix atom text at display time, allow tabs/eol/etc... in display atoms and escape them just-in-time Fixes #4293 --- src/client.cc | 3 +-- src/client_manager.cc | 3 +-- src/commands.cc | 7 +++---- src/display_buffer.cc | 18 ------------------ src/display_buffer.hh | 1 - src/input_handler.cc | 8 ++++---- src/normal.cc | 2 +- src/terminal_ui.cc | 22 ++++++++++++++++++++-- 8 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/client.cc b/src/client.cc index 945b4d2f..af1c4add 100644 --- a/src/client.cc +++ b/src/client.cc @@ -107,8 +107,7 @@ bool Client::process_pending_inputs() catch (Kakoune::runtime_error& error) { write_to_debug_buffer(format("Error: {}", error.what())); - context().print_status({ fix_atom_text(error.what().str()), - context().faces()["Error"] }); + context().print_status({error.what().str(), context().faces()["Error"] }); context().hooks().run_hook(Hook::RuntimeError, error.what(), context()); } } diff --git a/src/client_manager.cc b/src/client_manager.cc index 7c03dabc..25d96c4d 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -74,8 +74,7 @@ Client* ClientManager::create_client(std::unique_ptr&& ui, int pi } catch (Kakoune::runtime_error& error) { - client->context().print_status({ fix_atom_text(error.what().str()), - client->context().faces()["Error"] }); + client->context().print_status({error.what().str(), client->context().faces()["Error"]}); client->context().hooks().run_hook(Hook::RuntimeError, error.what(), client->context()); } diff --git a/src/commands.cc b/src/commands.cc index 0ef205ee..d71ff183 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1359,13 +1359,12 @@ const CommandDesc echo_cmd = { if (auto filename = parser.get_switch("to-file")) return write_to_file(*filename, message); - message = fix_atom_text(message); if (parser.get_switch("debug")) write_to_debug_buffer(message); else if (parser.get_switch("markup")) context.print_status(parse_display_line(message, context.faces())); else - context.print_status({replace(message, '\t', ' '), context.faces()["StatusLine"]}); + context.print_status({message, context.faces()["StatusLine"]}); } }; @@ -2161,7 +2160,7 @@ const CommandDesc prompt_cmd = { } catch (Kakoune::runtime_error& error) { - context.print_status({fix_atom_text(error.what()), context.faces()["Error"]}); + context.print_status({error.what().str(), context.faces()["Error"]}); context.hooks().run_hook(Hook::RuntimeError, error.what(), context); } }); @@ -2542,7 +2541,7 @@ const CommandDesc fail_cmd = { CommandCompleter{}, [](const ParametersParser& parser, Context&, const ShellContext&) { - throw failure{fix_atom_text(join(parser, " "))}; + throw failure{join(parser, " ")}; } }; diff --git a/src/display_buffer.cc b/src/display_buffer.cc index b7564550..e7caed04 100644 --- a/src/display_buffer.cc +++ b/src/display_buffer.cc @@ -332,22 +332,4 @@ DisplayLine parse_display_line(StringView line, const FaceRegistry& faces, const return res; } -String fix_atom_text(StringView str) -{ - String res; - auto pos = str.begin(); - for (auto it = str.begin(), end = str.end(); it != end; ++it) - { - char c = *it; - if (c >= 0 and c <= 0x1F) - { - res += StringView{pos, it}; - res += String{Codepoint{(uint32_t)(0x2400 + c)}}; - pos = it+1; - } - } - res += StringView{pos, str.end()}; - return res; -} - } diff --git a/src/display_buffer.hh b/src/display_buffer.hh index 308b1993..855fa92d 100644 --- a/src/display_buffer.hh +++ b/src/display_buffer.hh @@ -156,7 +156,6 @@ private: using DisplayLineList = Vector; class FaceRegistry; -String fix_atom_text(StringView str); DisplayLine parse_display_line(StringView line, const FaceRegistry& faces, const HashMap& builtins = {}); class DisplayBuffer : public UseMemoryDomain diff --git a/src/input_handler.cc b/src/input_handler.cc index fde468d5..85904e7f 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -575,12 +575,12 @@ public: const Face cursor_face = m_faces["StatusCursor"]; if (m_cursor_pos == str.char_length()) - return DisplayLine{{ { fix_atom_text(str.substr(m_display_pos, width-1)), line_face }, + return DisplayLine{{ { str.substr(m_display_pos, width-1).str(), line_face }, { " "_str, cursor_face} } }; else - return DisplayLine({ { fix_atom_text(str.substr(m_display_pos, m_cursor_pos - m_display_pos)), line_face }, - { fix_atom_text(str.substr(m_cursor_pos,1)), cursor_face }, - { fix_atom_text(str.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1)), line_face } }); + return DisplayLine({ { str.substr(m_display_pos, m_cursor_pos - m_display_pos).str(), line_face }, + { str.substr(m_cursor_pos,1).str(), cursor_face }, + { str.substr(m_cursor_pos+1, width - m_cursor_pos + m_display_pos - 1).str(), line_face } }); } private: CharCount m_cursor_pos = 0; diff --git a/src/normal.cc b/src/normal.cc index ad21a8b1..42214a6e 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -966,7 +966,7 @@ void use_selection_as_search_pattern(Context& context, NormalParams params) const char reg = to_lower(params.reg ? params.reg : '/'); context.print_status({ - format("register '{}' set to '{}'", reg, fix_atom_text(pattern)), + format("register '{}' set to '{}'", reg, pattern), context.faces()["Information"] }); RegisterManager::instance()[reg].set(context, {pattern}); diff --git a/src/terminal_ui.cc b/src/terminal_ui.cc index 148376ea..c245ac19 100644 --- a/src/terminal_ui.cc +++ b/src/terminal_ui.cc @@ -23,6 +23,24 @@ namespace Kakoune using std::min; using std::max; +static String fix_atom_text(StringView str) +{ + String res; + auto pos = str.begin(); + for (auto it = str.begin(), end = str.end(); it != end; ++it) + { + char c = *it; + if (c >= 0 and c <= 0x1F) + { + res += StringView{pos, it}; + res += String{Codepoint{(uint32_t)(0x2400 + c)}}; + pos = it+1; + } + } + res += StringView{pos, str.end()}; + return res; +} + struct TerminalUI::Window::Line { struct Atom @@ -58,11 +76,11 @@ struct TerminalUI::Window::Line { if (not atoms.empty() and atoms.back().face == face and (atoms.back().skip == 0 or text.empty())) { - atoms.back().text += text; + atoms.back().text += fix_atom_text(text); atoms.back().skip += skip; } else - atoms.push_back({text.str(), skip, face}); + atoms.push_back({fix_atom_text(text), skip, face}); } void resize(ColumnCount width)