summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2023-08-13 03:33:32 +1000
committerMaxime Coste <mawww@kakoune.org>2023-08-14 22:50:22 +1000
commit6942a4c0c9428a9e2ddb65de3969d2dcb5c5eb2f (patch)
treefb1e95ea1f0adeff258a4f0147be64e42f0ff60b /src
parent0a06d9acbdebf428f4945f0d1575c091a0619b1d (diff)
Change `+` command not to duplicate identical selections more than once
The current exponential behaviour does not seem that useful, it seems more predictible that pressing `+` twice would end up with 3 copies of the original selections instead of 4. Fixes #4533
Diffstat (limited to 'src')
-rw-r--r--src/main.cc3
-rw-r--r--src/normal.cc12
-rw-r--r--src/selection.hh35
3 files changed, 32 insertions, 18 deletions
diff --git a/src/main.cc b/src/main.cc
index 2e844d62..db0fb5f4 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -45,6 +45,9 @@ struct {
unsigned int version;
StringView notes;
} constexpr version_notes[] = { {
+ 0,
+ "» {+b}+{} only duplicates identical selections a single time\n"
+ }, {
20230805,
"» Fix FreeBSD/MacOS clang compilation\n"
}, {
diff --git a/src/normal.cc b/src/normal.cc
index 27c1e47e..b16b9c37 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -2191,9 +2191,17 @@ void duplicate_selections(Context& context, NormalParams params)
SelectionList& sels = context.selections();
Vector<Selection> new_sels;
const int count = params.count ? params.count : 2;
+ BasicSelection last{BufferCoord{-1,-1}};
+ size_t index = 0;
+ size_t main_index = 0;
for (const auto& sel : sels)
- new_sels.insert(new_sels.end(), count, sel);
- context.selections().set(std::move(new_sels), sels.main_index() * count);
+ {
+ new_sels.insert(new_sels.end(), sel != last ? count : 1, sel);
+ last = sel;
+ if (index++ == sels.main_index())
+ main_index = new_sels.size() - 1;
+ }
+ context.selections().set(std::move(new_sels), main_index);
}
void force_redraw(Context& context, NormalParams)
diff --git a/src/selection.hh b/src/selection.hh
index bdfd7d41..7794e093 100644
--- a/src/selection.hh
+++ b/src/selection.hh
@@ -13,17 +13,14 @@ using CaptureList = Vector<String, MemoryDomain::Selections>;
constexpr ColumnCount max_column{std::numeric_limits<int>::max()};
constexpr ColumnCount max_non_eol_column{max_column-1};
-// A selection is a Selection, associated with a CaptureList
-struct Selection
+struct BasicSelection
{
static constexpr MemoryDomain Domain = MemoryDomain::Selections;
- Selection() = default;
- Selection(BufferCoord pos) : Selection(pos,pos) {}
- Selection(BufferCoord anchor, BufferCoordAndTarget cursor,
- CaptureList captures = {})
- : m_anchor{anchor}, m_cursor{cursor},
- m_captures(std::move(captures)) {}
+ BasicSelection() = default;
+ BasicSelection(BufferCoord pos) : BasicSelection(pos,pos) {}
+ BasicSelection(BufferCoord anchor, BufferCoordAndTarget cursor)
+ : m_anchor{anchor}, m_cursor{cursor} {}
BufferCoord& anchor() { return m_anchor; }
BufferCoordAndTarget& cursor() { return m_cursor; }
@@ -39,13 +36,7 @@ struct Selection
void set(BufferCoord coord) { set(coord, coord); }
- CaptureList& captures() { return m_captures; }
- const CaptureList& captures() const { return m_captures; }
-
- bool operator== (const Selection& other) const
- {
- return m_anchor == other.m_anchor and m_cursor == other.m_cursor;
- }
+ friend bool operator==(const BasicSelection&, const BasicSelection&) = default;
// When selections are single char, we want the anchor to be considered min, and cursor max
const BufferCoord& min() const { return m_anchor <= m_cursor ? m_anchor : m_cursor; }
@@ -57,11 +48,23 @@ struct Selection
private:
BufferCoord m_anchor;
BufferCoordAndTarget m_cursor;
+};
+;
+struct Selection : BasicSelection
+{
+ Selection() = default;
+ Selection(BufferCoord pos) : BasicSelection(pos,pos) {}
+ Selection(BufferCoord anchor, BufferCoordAndTarget cursor, CaptureList captures = {})
+ : BasicSelection{anchor, cursor}, m_captures(std::move(captures)) {}
+ CaptureList& captures() { return m_captures; }
+ const CaptureList& captures() const { return m_captures; }
+
+private:
CaptureList m_captures;
};
-inline bool overlaps(const Selection& lhs, const Selection& rhs)
+inline bool overlaps(const BasicSelection& lhs, const BasicSelection& rhs)
{
return lhs.min() <= rhs.min() ? lhs.max() >= rhs.min()
: lhs.min() <= rhs.max();