From 6bc5f8c3a3f0ef2e0a4bfb51beb756608554597e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 19 Sep 2015 12:19:17 +0100 Subject: [PATCH] Add simple markup support to generate display lines from strings The syntax is simply {face} to enable the given face, use \{ to escape a {, and \\ to escape a \. --- src/commands.cc | 3 +++ src/display_buffer.cc | 53 +++++++++++++++++++++++++++++++++++++++++++ src/display_buffer.hh | 2 ++ src/string.hh | 2 ++ 4 files changed, 60 insertions(+) diff --git a/src/commands.cc b/src/commands.cc index b93114a8..0c35cb26 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -891,6 +891,7 @@ const CommandDesc echo_cmd = { "echo ...: display given parameters in the status line", ParameterDesc{ { { "color", { true, "set message color" } }, + { "markup", { false, "parse markup" } }, { "debug", { false, "write to debug buffer instead of status line" } } }, ParameterDesc::Flags::SwitchesOnlyAtStart }, @@ -902,6 +903,8 @@ const CommandDesc echo_cmd = { String message = join(parser, ' ', false); if (parser.get_switch("debug")) write_to_debug_buffer(message); + else if (parser.get_switch("markup")) + context.print_status(parse_display_line(message, get_face("StatusLine"))); else { auto face = get_face(parser.get_switch("color").value_or("StatusLine").str()); diff --git a/src/display_buffer.cc b/src/display_buffer.cc index 8cda0c47..0a1b3503 100644 --- a/src/display_buffer.cc +++ b/src/display_buffer.cc @@ -4,6 +4,8 @@ #include "buffer.hh" #include "utf8.hh" +#include "face_registry.hh" + namespace Kakoune { @@ -250,4 +252,55 @@ void DisplayBuffer::optimize() for (auto& line : m_lines) line.optimize(); } + +DisplayLine parse_display_line(StringView line, Face default_face) +{ + DisplayLine res; + bool was_antislash = false; + auto pos = line.begin(); + String content; + Face face = default_face; + for (auto it = line.begin(), end = line.end(); it != end; ++it) + { + const char c = *it; + if (c == '{') + { + if (was_antislash) + { + content += StringView{pos, it}; + content.back() = '{'; + pos = it + 1; + } + else + { + content += StringView{pos, it}; + res.push_back({std::move(content), face}); + content.clear(); + auto closing = std::find(it+1, end, '}'); + if (closing == end) + throw runtime_error("unclosed face definition"); + face = merge_faces(default_face, get_face({it+1, closing})); + it = closing; + pos = closing + 1; + } + was_antislash = false; + } + if (c == '\\') + { + if (was_antislash) + { + content += StringView{pos, it}; + pos = it + 1; + was_antislash = false; + } + else + was_antislash = true; + } + } + content += StringView{pos, line.end()}; + if (not content.empty()) + res.push_back({std::move(content), face}); + return res; +} + } diff --git a/src/display_buffer.hh b/src/display_buffer.hh index 97b717b1..9670325a 100644 --- a/src/display_buffer.hh +++ b/src/display_buffer.hh @@ -140,6 +140,8 @@ private: AtomList m_atoms; }; +DisplayLine parse_display_line(StringView line, Face default_face); + class DisplayBuffer : public UseMemoryDomain { public: diff --git a/src/string.hh b/src/string.hh index 6970e74a..d15baa34 100644 --- a/src/string.hh +++ b/src/string.hh @@ -118,6 +118,8 @@ public: [[gnu::always_inline]] void append(const char* data, ByteCount count) { m_data.append(data, (size_t)(int)count); } + void clear() { m_data.clear(); } + void push_back(char c) { m_data.push_back(c); } void resize(ByteCount size) { m_data.resize((size_t)(int)size); } void reserve(ByteCount size) { m_data.reserve((size_t)(int)size); }