From 2cbb0bb27f926701f2522c1a10e411e5c9181b4b Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 20 Jan 2014 21:01:26 +0000 Subject: [PATCH] Add a show_matching highlighter --- README.asciidoc | 2 ++ src/color_registry.cc | 3 ++- src/highlighters.cc | 53 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index ef09dd49..1b1ee992 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -566,6 +566,8 @@ existing highlighters are: * +flag_lines +: add a column in front of text, and display the given flag in it for everly lines contained in the int-list option named . + * +show_matching+: highlight matching char of the character under the selections + last char using +MatchingChar+ color alias. Shared Highlighters ~~~~~~~~~~~~~~~~~~~ diff --git a/src/color_registry.cc b/src/color_registry.cc index b275f392..ba07fb02 100644 --- a/src/color_registry.cc +++ b/src/color_registry.cc @@ -49,7 +49,8 @@ ColorRegistry::ColorRegistry() { "Error", { Colors::Black, Colors::Red } }, { "StatusLine", { Colors::Cyan, Colors::Default } }, { "StatusCursor", { Colors::Black, Colors::Cyan } }, - { "Prompt", { Colors::Yellow, Colors::Default} }, + { "Prompt", { Colors::Yellow, Colors::Default } }, + { "MatchingChar", { Colors::Default, Colors::Magenta } }, } {} diff --git a/src/highlighters.cc b/src/highlighters.cc index 553a6d27..2b1c2e9f 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -393,6 +393,58 @@ void show_line_numbers(const Context& context, HighlightFlags flags, DisplayBuff } } +void show_matching_char(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer) +{ + auto& colors = get_color("MatchingChar"); + using CodepointPair = std::pair; + constexpr CodepointPair matching_chars[] = { { '(', ')' }, { '{', '}' }, { '[', ']' }, { '<', '>' } }; + const auto range = display_buffer.range(); + const auto& buffer = context.buffer(); + for (auto& sel : context.selections()) + { + auto pos = sel.last(); + if (pos < range.first or pos >= range.second) + continue; + auto c = buffer.byte_at(pos); + for (auto& pair : matching_chars) + { + int level = 1; + if (c == pair.first) + { + auto it = buffer.iterator_at(pos)+1; + auto end = buffer.iterator_at(range.second); + skip_while(it, end, [&](char c) { + if (c == pair.first) + ++level; + else if (c == pair.second and --level == 0) + return false; + return true; + }); + if (it != end) + highlight_range(display_buffer, it.coord(), (it+1).coord(), false, + [&](DisplayAtom& atom) { atom.colors = colors; }); + break; + } + else if (c == pair.second) + { + auto it = buffer.iterator_at(pos)-1; + auto end = buffer.iterator_at(range.first); + skip_while_reverse(it, end, [&](char c) { + if (c == pair.second) + ++level; + else if (c == pair.first and --level == 0) + return false; + return true; + }); + if (it != end) + highlight_range(display_buffer, it.coord(), (it+1).coord(), false, + [&](DisplayAtom& atom) { atom.colors = colors; }); + break; + } + } + } +} + void highlight_selections(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer) { if (flags != HighlightFlags::Highlight) @@ -835,6 +887,7 @@ void register_highlighters() HighlighterRegistry& registry = HighlighterRegistry::instance(); registry.register_func("number_lines", SimpleHighlighterFactory("number_lines")); + registry.register_func("show_matching", SimpleHighlighterFactory("show_matching")); registry.register_func("regex", colorize_regex_factory); registry.register_func("regex_option", highlight_regex_option_factory); registry.register_func("search", highlight_search_factory);