diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2015-12-12 11:45:45 +0000 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2015-12-12 11:45:45 +0000 |
| commit | 4cb74623bbfd489b46edfadde5529e07a0dc557a (patch) | |
| tree | 121c950258da7007886fe5e349e76048fc9aaa6b /src | |
| parent | 70250fc1e344e50b4af96e0963e22f18a1978eb5 (diff) | |
Store the buffer timestamp in line flags options respect it for highlighting
Option content is auto updated to match current buffer, so that line flags
are updated according to buffer modifications.
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands.cc | 6 | ||||
| -rw-r--r-- | src/highlighters.cc | 37 | ||||
| -rw-r--r-- | src/option_manager.hh | 7 | ||||
| -rw-r--r-- | src/option_types.hh | 39 |
4 files changed, 83 insertions, 6 deletions
diff --git a/src/commands.cc b/src/commands.cc index d468dc59..dcee70cd 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1104,7 +1104,7 @@ const CommandDesc declare_option_cmd = { " regex: regular expression\n" " int-list: list of integers\n" " str-list: list of character strings\n" - " line-flag-list: list of line flags\n", + " line-flags: list of line flags\n", ParameterDesc{ { { "hidden", { false, "do not display option name when completing" } }, { "docstring", { true, "specify option description" } } }, @@ -1136,8 +1136,8 @@ const CommandDesc declare_option_cmd = { opt = ®.declare_option<Vector<int, MemoryDomain::Options>>(parser[1], docstring, {}, flags); else if (parser[0] == "str-list") opt = ®.declare_option<Vector<String, MemoryDomain::Options>>(parser[1], docstring, {}, flags); - else if (parser[0] == "line-flag-list") - opt = ®.declare_option<Vector<LineAndFlag, MemoryDomain::Options>>(parser[1], docstring, {}, flags); + else if (parser[0] == "line-flags") + opt = ®.declare_option<TimestampedList<LineAndFlag>>(parser[1], docstring, {}, flags); else throw runtime_error(format("unknown type {}", parser[0])); diff --git a/src/highlighters.cc b/src/highlighters.cc index 68f0bdb5..28e36660 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -904,13 +904,44 @@ HighlighterAndId create_flag_lines_highlighter(HighlighterParameters params) get_face(default_face); // validate param // throw if wrong option type - GlobalScope::instance().options()[option_name].get<Vector<LineAndFlag, MemoryDomain::Options>>(); + GlobalScope::instance().options()[option_name].get<TimestampedList<LineAndFlag>>(); auto func = [=](const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange) { - auto& lines_opt = context.options()[option_name]; - auto& lines = lines_opt.get<Vector<LineAndFlag, MemoryDomain::Options>>(); + auto& line_flags = context.options()[option_name].get_mutable<TimestampedList<LineAndFlag>>(); + auto& lines = line_flags.list; + + auto& buffer = context.buffer(); + if (line_flags.timestamp != buffer.timestamp()) + { + std::sort(lines.begin(), lines.end(), + [](const LineAndFlag& lhs, const LineAndFlag& rhs) + { return std::get<0>(lhs) < std::get<0>(rhs); }); + + auto modifs = compute_line_modifications(buffer, line_flags.timestamp); + 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; + } + line_flags.timestamp = buffer.timestamp(); + } auto def_face = get_face(default_face); diff --git a/src/option_manager.hh b/src/option_manager.hh index 8e21808c..6c4dce18 100644 --- a/src/option_manager.hh +++ b/src/option_manager.hh @@ -44,6 +44,7 @@ public: virtual ~Option() = default; template<typename T> const T& get() const; + template<typename T> T& get_mutable(); template<typename T> void set(const T& val, bool notify=true); template<typename T> bool is_of_type() const; @@ -122,6 +123,7 @@ public: } } const T& get() const { return m_value; } + T& get_mutable() { return m_value; } String get_as_string() const override { @@ -167,6 +169,11 @@ template<typename T> const T& Option::get() const return typed_opt->get(); } +template<typename T> T& Option::get_mutable() +{ + return const_cast<T&>(get<T>()); +} + template<typename T> void Option::set(const T& val, bool notify) { auto* typed_opt = dynamic_cast<TypedOption<T>*>(this); diff --git a/src/option_types.hh b/src/option_types.hh index 12f5e4fd..73a8bcfb 100644 --- a/src/option_types.hh +++ b/src/option_types.hh @@ -223,6 +223,45 @@ constexpr Array<EnumDesc<DebugFlags>, 3> enum_desc(DebugFlags) } }; } +template<typename T> +struct TimestampedList +{ + size_t timestamp; + Vector<T, MemoryDomain::Options> list; +}; + +template<typename T> +inline bool operator==(const TimestampedList<T>& lhs, const TimestampedList<T>& rhs) +{ + return lhs.timestamp == rhs.timestamp and lhs.list == rhs.list; +} + +template<typename T> +inline bool operator!=(const TimestampedList<T>& lhs, const TimestampedList<T>& rhs) +{ + return not (lhs == rhs); +} + +template<typename T> +inline String option_to_string(const TimestampedList<T>& opt) +{ + return format("{}:{}", opt.timestamp, option_to_string(opt.list)); +} + +template<typename T> +inline void option_from_string(StringView str, TimestampedList<T>& opt) +{ + auto it = find(str, ':'); + opt.timestamp = str_to_int({str.begin(), it}); + option_from_string({it+1, str.end()}, opt.list); +} + +template<typename T> +inline bool option_add(TimestampedList<T>& opt, StringView str) +{ + return option_add(opt.list, str); +} + } #endif // option_types_hh_INCLUDED |
