From 83d85df26e68687ca124c3affb42e246fd77188a Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 25 May 2017 08:38:11 +0100 Subject: [PATCH] Add an update-option command to update range-descs/line-descs options update-option will make the range-descs and line-descs option up to date with the latest buffer modfications, changing the ranges/lines to where they moved according the modifications since the timestamp on the option. --- src/commands.cc | 59 +++++++++++++++----------- src/highlighters.cc | 98 +++++++++++++++++++++++-------------------- src/highlighters.hh | 16 +++++++ src/option_manager.hh | 6 +++ src/option_types.hh | 5 +++ 5 files changed, 115 insertions(+), 69 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index b11db6a5..34908f28 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -43,16 +43,6 @@ namespace Kakoune { -StringView option_type_name(Meta::Type>) -{ - return "line-specs"; -} - -StringView option_type_name(Meta::Type>) -{ - return "range-specs"; -} - namespace { @@ -1289,6 +1279,21 @@ const CommandDesc set_option_cmd = { } }; +Completions complete_option(const Context& context, CompletionFlags, + CommandParameters params, size_t token_to_complete, + ByteCount pos_in_token) +{ + if (token_to_complete == 0) + { + static constexpr auto scopes = { "buffer", "window", "current" }; + return { 0_byte, params[0].length(), complete(params[0], pos_in_token, scopes) }; + } + else if (token_to_complete == 1) + return { 0_byte, params[1].length(), + GlobalScope::instance().option_registry().complete_option_name(params[1], pos_in_token) }; + return Completions{}; +} + const CommandDesc unset_option_cmd = { "unset-option", "unset", @@ -1298,20 +1303,7 @@ const CommandDesc unset_option_cmd = { ParameterDesc{ {}, ParameterDesc::Flags::None, 2, 2 }, CommandFlags::None, option_doc_helper, - [](const Context& context, CompletionFlags, - CommandParameters params, size_t token_to_complete, - ByteCount pos_in_token) -> Completions - { - if (token_to_complete == 0) - { - static constexpr auto scopes = { "buffer", "window", "current" }; - return { 0_byte, params[0].length(), complete(params[0], pos_in_token, scopes) }; - } - else if (token_to_complete == 1) - return { 0_byte, params[1].length(), - GlobalScope::instance().option_registry().complete_option_name(params[1], pos_in_token) }; - return Completions{}; - }, + complete_option, [](const ParametersParser& parser, Context& context, const ShellContext&) { auto& options = get_options(parser[0], context, parser[1]); @@ -1321,6 +1313,24 @@ const CommandDesc unset_option_cmd = { } }; +const CommandDesc update_option_cmd = { + "update-option", + nullptr, + "update-option : update option from scope\n" + "some option types, such as line-descs or range-descs can be updated to latest buffer timestamp\n" + " can be buffer, window, or current which refers to the narrowest\n" + "scope the option is set in", + ParameterDesc{ {}, ParameterDesc::Flags::None, 2, 2 }, + CommandFlags::None, + option_doc_helper, + complete_option, + [](const ParametersParser& parser, Context& context, const ShellContext&) + { + Option& opt = get_options(parser[0], context, parser[1]).get_local_option(parser[1]); + opt.update(context); + } +}; + const CommandDesc declare_option_cmd = { "declare-option", "decl", @@ -2142,6 +2152,7 @@ void register_commands() register_command(source_cmd); register_command(set_option_cmd); register_command(unset_option_cmd); + register_command(update_option_cmd); register_command(declare_option_cmd); register_command(map_key_cmd); register_command(unmap_key_cmd); diff --git a/src/highlighters.cc b/src/highlighters.cc index 610ddffd..3df17ccb 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -1177,6 +1177,47 @@ void expand_unprintable(const Context& context, HighlightPass, DisplayBuffer& di } } +static void update_line_specs_ifn(const Buffer& buffer, LineAndSpecList& line_flags) +{ + if (line_flags.prefix == buffer.timestamp()) + return; + + auto& lines = line_flags.list; + + std::sort(lines.begin(), lines.end(), + [](const LineAndSpec& lhs, const LineAndSpec& rhs) + { return std::get<0>(lhs) < std::get<0>(rhs); }); + + auto modifs = compute_line_modifications(buffer, line_flags.prefix); + auto ins_pos = lines.begin(); + for (auto it = lines.begin(); it != lines.end(); ++it) + { + auto& line = std::get<0>(*it); // that line is 1 based as it comes from user side + auto modif_it = std::upper_bound(modifs.begin(), modifs.end(), line-1, + [](const LineCount& l, const LineModification& c) + { return l < c.old_line; }); + if (modif_it != modifs.begin()) + { + auto& prev = *(modif_it-1); + if (line-1 < prev.old_line + prev.num_removed) + continue; // line removed + + line += prev.diff(); + } + + if (ins_pos != it) + *ins_pos = std::move(*it); + ++ins_pos; + } + lines.erase(ins_pos, lines.end()); + line_flags.prefix = buffer.timestamp(); +} + +void option_update(LineAndSpecList& opt, const Context& context) +{ + update_line_specs_ifn(context.buffer(), opt); +} + struct FlagLinesHighlighter : Highlighter { FlagLinesHighlighter(String option_name, String default_face) @@ -1184,8 +1225,6 @@ struct FlagLinesHighlighter : Highlighter m_option_name{std::move(option_name)}, m_default_face{std::move(default_face)} {} - using LineAndSpecList = TimestampedList; - static HighlighterAndId create(HighlighterParameters params) { if (params.size() != 2) @@ -1207,7 +1246,7 @@ private: { auto& line_flags = context.options()[m_option_name].get_mutable(); auto& buffer = context.buffer(); - update_line_flags_ifn(buffer, line_flags); + update_line_specs_ifn(buffer, line_flags); auto def_face = get_face(m_default_face); Vector display_lines; @@ -1257,7 +1296,7 @@ private: { auto& line_flags = context.options()[m_option_name].get_mutable(); auto& buffer = context.buffer(); - update_line_flags_ifn(buffer, line_flags); + update_line_specs_ifn(buffer, line_flags); ColumnCount width = 0; try @@ -1274,42 +1313,6 @@ private: setup.window_range.column -= width; } - void update_line_flags_ifn(const Buffer& buffer, LineAndSpecList& line_flags) - { - if (line_flags.prefix == buffer.timestamp()) - return; - - auto& lines = line_flags.list; - - std::sort(lines.begin(), lines.end(), - [](const LineAndSpec& lhs, const LineAndSpec& rhs) - { return std::get<0>(lhs) < std::get<0>(rhs); }); - - auto modifs = compute_line_modifications(buffer, line_flags.prefix); - auto ins_pos = lines.begin(); - for (auto it = lines.begin(); it != lines.end(); ++it) - { - auto& line = std::get<0>(*it); // that line is 1 based as it comes from user side - auto modif_it = std::upper_bound(modifs.begin(), modifs.end(), line-1, - [](const LineCount& l, const LineModification& c) - { return l < c.old_line; }); - if (modif_it != modifs.begin()) - { - auto& prev = *(modif_it-1); - if (line-1 < prev.old_line + prev.num_removed) - continue; // line removed - - line += prev.diff(); - } - - if (ins_pos != it) - *ins_pos = std::move(*it); - ++ins_pos; - } - lines.erase(ins_pos, lines.end()); - line_flags.prefix = buffer.timestamp(); - } - String m_option_name; String m_default_face; }; @@ -1348,7 +1351,7 @@ void option_from_string(StringView str, InclusiveBufferRange& opt) BufferCoord& get_first(RangeAndString& r) { return std::get<0>(r).first; } BufferCoord& get_last(RangeAndString& r) { return std::get<0>(r).last; } -static void update_ranges_ifn(const Buffer& buffer, TimestampedList& range_and_faces) +static void update_ranges_ifn(const Buffer& buffer, RangeAndStringList& range_and_faces) { if (range_and_faces.prefix == buffer.timestamp()) return; @@ -1373,6 +1376,11 @@ static void update_ranges_ifn(const Buffer& buffer, TimestampedList>(); + GlobalScope::instance().options()[option_name].get(); return {"hlranges_" + params[0], make_unique(option_name)}; } @@ -1395,7 +1403,7 @@ private: void do_highlight(const Context& context, HighlightPass, DisplayBuffer& display_buffer, BufferRange) override { auto& buffer = context.buffer(); - auto& range_and_faces = context.options()[m_option_name].get_mutable>(); + auto& range_and_faces = context.options()[m_option_name].get_mutable(); update_ranges_ifn(buffer, range_and_faces); for (auto& range : range_and_faces.list) @@ -1428,7 +1436,7 @@ struct ReplaceRangesHighlighter : Highlighter const String& option_name = params[0]; // throw if wrong option type - GlobalScope::instance().options()[option_name].get>(); + GlobalScope::instance().options()[option_name].get(); return {"replace_ranges_" + params[0], make_unique(option_name)}; } @@ -1437,7 +1445,7 @@ private: void do_highlight(const Context& context, HighlightPass, DisplayBuffer& display_buffer, BufferRange) override { auto& buffer = context.buffer(); - auto& range_and_faces = context.options()[m_option_name].get_mutable>(); + auto& range_and_faces = context.options()[m_option_name].get_mutable(); update_ranges_ifn(buffer, range_and_faces); for (auto& range : range_and_faces.list) diff --git a/src/highlighters.hh b/src/highlighters.hh index a3f1971d..cae0d63e 100644 --- a/src/highlighters.hh +++ b/src/highlighters.hh @@ -3,6 +3,7 @@ #include "color.hh" #include "highlighter.hh" +#include "option.hh" namespace Kakoune { @@ -19,7 +20,22 @@ String option_to_string(InclusiveBufferRange range); void option_from_string(StringView str, InclusiveBufferRange& opt); using LineAndSpec = std::tuple; +using LineAndSpecList = TimestampedList; + +constexpr StringView option_type_name(Meta::Type) +{ + return "line-specs"; +} +void option_update(LineAndSpecList& opt, const Context& context); + using RangeAndString = std::tuple; +using RangeAndStringList = TimestampedList; + +constexpr StringView option_type_name(Meta::Type) +{ + return "range-specs"; +} +void option_update(RangeAndStringList& opt, const Context& context); } diff --git a/src/option_manager.hh b/src/option_manager.hh index 2970d4e2..97556749 100644 --- a/src/option_manager.hh +++ b/src/option_manager.hh @@ -14,6 +14,7 @@ namespace Kakoune { class OptionManager; +class Context; enum class OptionFlags { @@ -52,6 +53,7 @@ public: virtual String get_as_string() const = 0; virtual void set_from_string(StringView str) = 0; virtual void add_from_string(StringView str) = 0; + virtual void update(const Context& context) = 0; virtual Option* clone(OptionManager& manager) const = 0; OptionManager& manager() const { return m_manager; } @@ -140,6 +142,10 @@ public: if (option_add(m_value, str)) m_manager.on_option_changed(*this); } + void update(const Context& context) override + { + option_update(m_value, context); + } private: virtual void validate(const T& value) const {} T m_value; diff --git a/src/option_types.hh b/src/option_types.hh index 81dca3bd..56b32e99 100644 --- a/src/option_types.hh +++ b/src/option_types.hh @@ -218,6 +218,11 @@ inline bool option_add(WorstMatch, StringView) throw runtime_error("no add operation supported for this option type"); } +inline void option_update(WorstMatch, const Context&) +{ + throw runtime_error("no update operation supported for this option type"); +} + template inline void option_from_string(StringView str, LineAndColumn& opt) {