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
This commit is contained in:
parent
0a06d9acbd
commit
6942a4c0c9
|
@ -3,6 +3,11 @@
|
|||
This changelog contains major and/or breaking changes to Kakoune between
|
||||
released versions.
|
||||
|
||||
== Development version
|
||||
|
||||
* `+` only duplicates identical selections a single time to avoid surprising
|
||||
and slow exponential growth in the number of selections.
|
||||
|
||||
== Kakoune 2023.08.08
|
||||
|
||||
* Fix compilation errors on FreeBSD and MacOS using clang
|
||||
|
|
|
@ -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"
|
||||
}, {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
1
test/normal/duplicate-selections/cmd
Normal file
1
test/normal/duplicate-selections/cmd
Normal file
|
@ -0,0 +1 @@
|
|||
++ao<esc>
|
1
test/normal/duplicate-selections/in
Normal file
1
test/normal/duplicate-selections/in
Normal file
|
@ -0,0 +1 @@
|
|||
%(f) %(b) %(t)
|
1
test/normal/duplicate-selections/out
Normal file
1
test/normal/duplicate-selections/out
Normal file
|
@ -0,0 +1 @@
|
|||
fooo booo tooo
|
Loading…
Reference in New Issue
Block a user