summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/normal.cc42
-rw-r--r--src/selection.cc16
-rw-r--r--src/selection.hh5
-rw-r--r--src/string.hh3
-rw-r--r--src/utils.hh6
5 files changed, 41 insertions, 31 deletions
diff --git a/src/normal.cc b/src/normal.cc
index 42214a6e..f8097645 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -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();
diff --git a/src/selection.cc b/src/selection.cc
index 350b3acc..a552526d 100644
--- a/src/selection.cc
+++ b/src/selection.cc
@@ -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,
diff --git a/src/selection.hh b/src/selection.hh
index c880aaf7..3c6d879d 100644
--- a/src/selection.hh
+++ b/src/selection.hh
@@ -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:
diff --git a/src/string.hh b/src/string.hh
index 6fa425e5..d14929f4 100644
--- a/src/string.hh
+++ b/src/string.hh
@@ -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
diff --git a/src/utils.hh b/src/utils.hh
index 31781907..8dffa9ac 100644
--- a/src/utils.hh
+++ b/src/utils.hh
@@ -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) {