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

View File

@ -385,12 +385,18 @@ static void fix_overflowing_selections(Vector<Selection>& selections,
}
}
void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode,
Vector<BufferCoord>* out_insert_pos)
void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode)
{
if (strings.empty())
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();
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
m_buffer->is_valid(sel.cursor()));
const String& str = strings[std::min(index, strings.size()-1)];
const auto pos = (mode == InsertMode::Replace) ?
sel.min() : changes_tracker.get_new_coord(insert_pos[index]);
String str = get_content(index, pos);
if (mode == InsertMode::Replace)
{
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);
if (out_insert_pos)
out_insert_pos->push_back(pos);
}
// 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; }
void force_timestamp(size_t timestamp) { m_timestamp = timestamp; }
void insert(ConstArrayView<String> strings, InsertMode mode,
Vector<BufferCoord>* out_insert_pos = nullptr);
void insert(ConstArrayView<String> strings, InsertMode mode);
using ContentFunc = FunctionRef<String (size_t index, BufferCoord insert_pos)>;
void insert(ContentFunc get_content, InsertMode mode);
void erase();
private:

View File

@ -124,6 +124,8 @@ public:
struct NoCopy{};
String(NoCopy, StringView str);
static String no_copy(StringView str);
[[gnu::always_inline]]
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(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>
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)
: m_target{&target},
m_invoker{[](void* target, Args... args) {