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:
parent
bc11f972c5
commit
33a80e644c
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user