summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commands.cc6
-rw-r--r--src/highlighters.cc37
-rw-r--r--src/option_manager.hh7
-rw-r--r--src/option_types.hh39
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 = &reg.declare_option<Vector<int, MemoryDomain::Options>>(parser[1], docstring, {}, flags);
else if (parser[0] == "str-list")
opt = &reg.declare_option<Vector<String, MemoryDomain::Options>>(parser[1], docstring, {}, flags);
- else if (parser[0] == "line-flag-list")
- opt = &reg.declare_option<Vector<LineAndFlag, MemoryDomain::Options>>(parser[1], docstring, {}, flags);
+ else if (parser[0] == "line-flags")
+ opt = &reg.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