Take a function SelectionList::insert to get string to insert

This makes it unnecessary to allocate Vector<String> to insert and
allows to remove the insert_pos pointer hack by passing it to the
callback.
This commit is contained in:
Maxime Coste 2021-08-21 16:42:08 +10:00
parent bc11f972c5
commit 33a80e644c
5 changed files with 41 additions and 31 deletions

View File

@ -414,13 +414,10 @@ void replace_with_char(Context& context, NormalParams)
ScopedEdition edition(context); ScopedEdition edition(context);
Buffer& buffer = context.buffer(); Buffer& buffer = context.buffer();
SelectionList& selections = context.selections(); SelectionList& selections = context.selections();
Vector<String> strings; selections.insert([&](size_t index, BufferCoord) {
for (auto& sel : selections) CharCount count = char_length(buffer, selections[index]);
{ return String{*cp, count};
CharCount count = char_length(buffer, sel); }, InsertMode::Replace);
strings.emplace_back(*cp, count);
}
selections.insert(strings, InsertMode::Replace);
}, "replace with char", "enter char to replace with\n"); }, "replace with char", "enter char to replace with\n");
} }
@ -438,18 +435,16 @@ void for_each_codepoint(Context& context, NormalParams)
ScopedEdition edition(context); ScopedEdition edition(context);
Buffer& buffer = context.buffer(); Buffer& buffer = context.buffer();
SelectionList& selections = context.selections(); SelectionList& selections = context.selections();
Vector<String> strings;
for (auto& sel : selections) selections.insert([&](size_t index, BufferCoord) {
{ auto& sel = selections[index];
String str; String str;
for (auto begin = Utf8It{buffer.iterator_at(sel.min()), buffer}, for (auto begin = Utf8It{buffer.iterator_at(sel.min()), buffer},
end = Utf8It{buffer.iterator_at(sel.max()), buffer}+1; end = Utf8It{buffer.iterator_at(sel.max()), buffer}+1;
begin != end; ++begin) begin != end; ++begin)
utf8::dump(std::back_inserter(str), func(*begin)); utf8::dump(std::back_inserter(str), func(*begin));
return str;
strings.push_back(std::move(str)); }, InsertMode::Replace);
}
selections.insert(strings, InsertMode::Replace);
} }
void command(const Context& context, EnvVarMap env_vars, char reg = 0) void command(const Context& context, EnvVarMap env_vars, char reg = 0)
@ -649,15 +644,15 @@ void insert_output(Context& context, NormalParams params)
auto& selections = context.selections(); auto& selections = context.selections();
const size_t old_main = selections.main_index(); const size_t old_main = selections.main_index();
auto ins = selections | transform([&, i=0](auto& sel) mutable { selections.insert([&](size_t index, BufferCoord) {
selections.set_main_index(i++); selections.set_main_index(index);
return ShellManager::instance().eval( auto [out, status] = ShellManager::instance().eval(
cmdline, context, content(context.buffer(), sel), cmdline, context, content(context.buffer(), selections[index]),
ShellManager::Flags::WaitForStdout).first; ShellManager::Flags::WaitForStdout);
}) | gather<Vector>(); return out;
}, mode);
selections.set_main_index(old_main); selections.set_main_index(old_main);
selections.insert(ins, mode);
}); });
} }
@ -741,7 +736,10 @@ void paste_all(Context& context, NormalParams params)
auto& selections = context.selections(); auto& selections = context.selections();
{ {
ScopedEdition edition(context); ScopedEdition edition(context);
selections.insert(all, effective_mode, &insert_pos); selections.insert([&](size_t, BufferCoord pos) {
insert_pos.push_back(pos);
return String::no_copy(all);
}, effective_mode);
} }
const Buffer& buffer = context.buffer(); const Buffer& buffer = context.buffer();

View File

@ -385,12 +385,18 @@ static void fix_overflowing_selections(Vector<Selection>& selections,
} }
} }
void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode, void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode)
Vector<BufferCoord>* out_insert_pos)
{ {
if (strings.empty()) if (strings.empty())
return; return;
insert([&](size_t index, BufferCoord) {
return String::no_copy(strings[std::min(strings.size()-1, index)]);
}, mode);
}
void SelectionList::insert(ContentFunc get_content, InsertMode mode)
{
update(); update();
Vector<BufferCoord> insert_pos; Vector<BufferCoord> insert_pos;
@ -410,11 +416,11 @@ void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
kak_assert(m_buffer->is_valid(sel.anchor()) and kak_assert(m_buffer->is_valid(sel.anchor()) and
m_buffer->is_valid(sel.cursor())); m_buffer->is_valid(sel.cursor()));
const String& str = strings[std::min(index, strings.size()-1)];
const auto pos = (mode == InsertMode::Replace) ? const auto pos = (mode == InsertMode::Replace) ?
sel.min() : changes_tracker.get_new_coord(insert_pos[index]); sel.min() : changes_tracker.get_new_coord(insert_pos[index]);
String str = get_content(index, pos);
if (mode == InsertMode::Replace) if (mode == InsertMode::Replace)
{ {
auto range = replace(*m_buffer, sel, str); auto range = replace(*m_buffer, sel, str);
@ -432,8 +438,6 @@ void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
} }
changes_tracker.update(*m_buffer, m_timestamp); changes_tracker.update(*m_buffer, m_timestamp);
if (out_insert_pos)
out_insert_pos->push_back(pos);
} }
// We might just have been deleting text if strings were empty, // We might just have been deleting text if strings were empty,

View File

@ -145,8 +145,9 @@ struct SelectionList
size_t timestamp() const { return m_timestamp; } size_t timestamp() const { return m_timestamp; }
void force_timestamp(size_t timestamp) { m_timestamp = timestamp; } void force_timestamp(size_t timestamp) { m_timestamp = timestamp; }
void insert(ConstArrayView<String> strings, InsertMode mode, void insert(ConstArrayView<String> strings, InsertMode mode);
Vector<BufferCoord>* out_insert_pos = nullptr); using ContentFunc = FunctionRef<String (size_t index, BufferCoord insert_pos)>;
void insert(ContentFunc get_content, InsertMode mode);
void erase(); void erase();
private: private:

View File

@ -124,6 +124,8 @@ public:
struct NoCopy{}; struct NoCopy{};
String(NoCopy, StringView str); String(NoCopy, StringView str);
static String no_copy(StringView str);
[[gnu::always_inline]] [[gnu::always_inline]]
char* data() { return m_data.data(); } char* data() { return m_data.data(); }
@ -274,6 +276,7 @@ template<> struct HashCompatible<StringView, String> : std::true_type {};
inline String::String(StringView str) : String{str.begin(), str.length()} {} inline String::String(StringView str) : String{str.begin(), str.length()} {}
inline String::String(NoCopy, StringView str) : m_data{NoCopy{}, str.begin(), (size_t)str.length()} {} inline String::String(NoCopy, StringView str) : m_data{NoCopy{}, str.begin(), (size_t)str.length()} {}
inline String String::no_copy(StringView str) { return {NoCopy{}, str}; }
template<typename Type, typename CharType> template<typename Type, typename CharType>
inline StringView StringOps<Type, CharType>::substr(ByteCount from, ByteCount length) const inline StringView StringOps<Type, CharType>::substr(ByteCount from, ByteCount length) const

View File

@ -173,7 +173,11 @@ public:
}} }}
{} {}
template<typename Target, typename = std::enable_if_t<!std::is_same_v<FunctionRef, std::decay_t<Target>>>> template<typename Target,
typename = std::enable_if_t<
not std::is_same_v<FunctionRef, std::decay_t<Target>> and
std::is_convertible_v<decltype(std::declval<Target>()(std::declval<Args>()...)), Res>
>>
FunctionRef(Target&& target) FunctionRef(Target&& target)
: m_target{&target}, : m_target{&target},
m_invoker{[](void* target, Args... args) { m_invoker{[](void* target, Args... args) {