diff options
| author | Maxime Coste <mawww@kakoune.org> | 2023-08-13 03:33:32 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2023-08-14 22:50:22 +1000 |
| commit | 6942a4c0c9428a9e2ddb65de3969d2dcb5c5eb2f (patch) | |
| tree | fb1e95ea1f0adeff258a4f0147be64e42f0ff60b /src | |
| parent | 0a06d9acbdebf428f4945f0d1575c091a0619b1d (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.cc | 3 | ||||
| -rw-r--r-- | src/normal.cc | 12 | ||||
| -rw-r--r-- | src/selection.hh | 35 |
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(); |
