Rename selections first,last to more explicit anchor,cursor

This commit is contained in:
Maxime Coste 2014-01-28 19:05:49 +00:00
parent dbd194cea8
commit 2159fc9563
12 changed files with 136 additions and 136 deletions

View File

@ -44,7 +44,7 @@ void Client::print_status(DisplayLine status_line)
DisplayLine Client::generate_mode_line() const DisplayLine Client::generate_mode_line() const
{ {
auto pos = context().selections().main().last(); auto pos = context().selections().main().cursor();
auto col = context().buffer()[pos.line].char_count_to(pos.column); auto col = context().buffer()[pos.line].char_count_to(pos.column);
std::ostringstream oss; std::ostringstream oss;
@ -90,7 +90,7 @@ void Client::redraw_ifn()
static void reload_buffer(Context& context, const String& filename) static void reload_buffer(Context& context, const String& filename)
{ {
DisplayCoord view_pos = context.window().position(); DisplayCoord view_pos = context.window().position();
BufferCoord cursor_pos = context.selections().main().last(); BufferCoord cursor_pos = context.selections().main().cursor();
Buffer* buf = create_buffer_from_file(filename); Buffer* buf = create_buffer_from_file(filename);
if (not buf) if (not buf)
return; return;

View File

@ -126,7 +126,7 @@ void edit(CommandParameters params, Context& context)
context.selections() = context.buffer().clamp({ line, column }); context.selections() = context.buffer().clamp({ line, column });
if (context.has_window()) if (context.has_window())
context.window().center_line(context.selections().main().last().line); context.window().center_line(context.selections().main().cursor().line);
} }
} }
@ -674,7 +674,7 @@ void info(CommandParameters params, Context& context)
{ {
style = MenuStyle::Inline; style = MenuStyle::Inline;
const auto& sel = context.selections().main(); const auto& sel = context.selections().main();
auto it = sel.last(); auto it = sel.cursor();
String anchor = parser.option_value("anchor"); String anchor = parser.option_value("anchor");
if (anchor == "left") if (anchor == "left")
it = sel.min(); it = sel.min();

View File

@ -26,12 +26,12 @@ void DynamicSelectionList::check_invariant() const
for (size_t i = 0; i < size(); ++i) for (size_t i = 0; i < size(); ++i)
{ {
auto& sel = (*this)[i]; auto& sel = (*this)[i];
kak_assert(buffer.is_valid(sel.first())); kak_assert(buffer.is_valid(sel.anchor()));
kak_assert(buffer.is_valid(sel.last())); kak_assert(buffer.is_valid(sel.cursor()));
kak_assert(not buffer.is_end(sel.first())); kak_assert(not buffer.is_end(sel.anchor()));
kak_assert(not buffer.is_end(sel.last())); kak_assert(not buffer.is_end(sel.cursor()));
kak_assert(utf8::is_character_start(buffer.iterator_at(sel.first()))); kak_assert(utf8::is_character_start(buffer.iterator_at(sel.anchor())));
kak_assert(utf8::is_character_start(buffer.iterator_at(sel.last()))); kak_assert(utf8::is_character_start(buffer.iterator_at(sel.cursor())));
} }
#endif #endif
} }

View File

@ -403,7 +403,7 @@ void show_matching_char(const Context& context, HighlightFlags flags, DisplayBuf
const auto& buffer = context.buffer(); const auto& buffer = context.buffer();
for (auto& sel : context.selections()) for (auto& sel : context.selections())
{ {
auto pos = sel.last(); auto pos = sel.cursor();
if (pos < range.first or pos >= range.second) if (pos < range.first or pos >= range.second)
continue; continue;
auto c = buffer.byte_at(pos); auto c = buffer.byte_at(pos);
@ -454,16 +454,16 @@ void highlight_selections(const Context& context, HighlightFlags flags, DisplayB
for (size_t i = 0; i < context.selections().size(); ++i) for (size_t i = 0; i < context.selections().size(); ++i)
{ {
auto& sel = context.selections()[i]; auto& sel = context.selections()[i];
const bool forward = sel.first() <= sel.last(); const bool forward = sel.anchor() <= sel.cursor();
BufferCoord begin = forward ? sel.first() : buffer.char_next(sel.last()); BufferCoord begin = forward ? sel.anchor() : buffer.char_next(sel.cursor());
BufferCoord end = forward ? sel.last() : buffer.char_next(sel.first()); BufferCoord end = forward ? sel.cursor() : buffer.char_next(sel.anchor());
const bool primary = (i == context.selections().main_index()); const bool primary = (i == context.selections().main_index());
ColorPair sel_colors = get_color(primary ? "PrimarySelection" : "SecondarySelection"); ColorPair sel_colors = get_color(primary ? "PrimarySelection" : "SecondarySelection");
highlight_range(display_buffer, begin, end, false, highlight_range(display_buffer, begin, end, false,
[&](DisplayAtom& atom) { atom.colors = sel_colors; }); [&](DisplayAtom& atom) { atom.colors = sel_colors; });
ColorPair cur_colors = get_color(primary ? "PrimaryCursor" : "SecondaryCursor"); ColorPair cur_colors = get_color(primary ? "PrimaryCursor" : "SecondaryCursor");
highlight_range(display_buffer, sel.last(), buffer.char_next(sel.last()), false, highlight_range(display_buffer, sel.cursor(), buffer.char_next(sel.cursor()), false,
[&](DisplayAtom& atom) { atom.colors = cur_colors; }); [&](DisplayAtom& atom) { atom.colors = cur_colors; });
} }
} }

View File

@ -612,7 +612,7 @@ public:
if (m_current_candidate < 0) if (m_current_candidate < 0)
m_current_candidate += m_matching_candidates.size(); m_current_candidate += m_matching_candidates.size();
const String& candidate = m_matching_candidates[m_current_candidate]; const String& candidate = m_matching_candidates[m_current_candidate];
const auto& cursor_pos = m_context.selections().main().last(); const auto& cursor_pos = m_context.selections().main().cursor();
const auto prefix_len = buffer.distance(m_completions.begin, cursor_pos); const auto prefix_len = buffer.distance(m_completions.begin, cursor_pos);
const auto suffix_len = std::max(0_byte, buffer.distance(cursor_pos, m_completions.end)); const auto suffix_len = std::max(0_byte, buffer.distance(cursor_pos, m_completions.end));
const auto buffer_len = buffer.byte_count(); const auto buffer_len = buffer.byte_count();
@ -620,8 +620,8 @@ public:
auto ref = buffer.string(m_completions.begin, m_completions.end); auto ref = buffer.string(m_completions.begin, m_completions.end);
for (auto& sel : m_context.selections()) for (auto& sel : m_context.selections())
{ {
auto offset = buffer.offset(sel.last()); auto offset = buffer.offset(sel.cursor());
auto pos = buffer.iterator_at(sel.last()); auto pos = buffer.iterator_at(sel.cursor());
if (offset >= prefix_len and offset + suffix_len < buffer_len and if (offset >= prefix_len and offset + suffix_len < buffer_len and
std::equal(ref.begin(), ref.end(), pos - prefix_len)) std::equal(ref.begin(), ref.end(), pos - prefix_len))
{ {
@ -650,7 +650,7 @@ public:
for (auto& candidate : m_completions.candidates) for (auto& candidate : m_completions.candidates)
longest_completion = std::max(longest_completion, candidate.length()); longest_completion = std::max(longest_completion, candidate.length());
BufferCoord cursor = m_context.selections().main().last(); BufferCoord cursor = m_context.selections().main().cursor();
BufferCoord compl_beg = m_completions.begin; BufferCoord compl_beg = m_completions.begin;
if (cursor.line == compl_beg.line and if (cursor.line == compl_beg.line and
is_in_range(cursor.column - compl_beg.column, is_in_range(cursor.column - compl_beg.column,
@ -694,7 +694,7 @@ public:
bool try_complete() bool try_complete()
{ {
auto& buffer = m_context.buffer(); auto& buffer = m_context.buffer();
BufferCoord cursor_pos = m_context.selections().main().last(); BufferCoord cursor_pos = m_context.selections().main().cursor();
m_completions = (this->*complete_func)(buffer, cursor_pos); m_completions = (this->*complete_func)(buffer, cursor_pos);
if (not m_completions.is_valid()) if (not m_completions.is_valid())
return false; return false;
@ -948,9 +948,9 @@ public:
{ {
for (auto& sel : context().selections()) for (auto& sel : context().selections())
{ {
if (sel.last() == BufferCoord{0,0}) if (sel.cursor() == BufferCoord{0,0})
continue; continue;
auto pos = buffer.iterator_at(sel.last()); auto pos = buffer.iterator_at(sel.cursor());
buffer.erase(utf8::previous(pos), pos); buffer.erase(utf8::previous(pos), pos);
} }
} }
@ -958,7 +958,7 @@ public:
{ {
for (auto& sel : context().selections()) for (auto& sel : context().selections())
{ {
auto pos = buffer.iterator_at(sel.last()); auto pos = buffer.iterator_at(sel.cursor());
buffer.erase(pos, utf8::next(pos)); buffer.erase(pos, utf8::next(pos));
} }
} }
@ -1027,9 +1027,9 @@ private:
auto& selections = context().selections(); auto& selections = context().selections();
for (auto& sel : selections) for (auto& sel : selections)
{ {
auto last = context().has_window() ? context().window().offset_coord(sel.last(), offset) auto cursor = context().has_window() ? context().window().offset_coord(sel.cursor(), offset)
: context().buffer().offset_coord(sel.last(), offset); : context().buffer().offset_coord(sel.cursor(), offset);
sel.first() = sel.last() = last; sel.anchor() = sel.cursor() = cursor;
} }
selections.sort_and_merge_overlapping(); selections.sort_and_merge_overlapping();
} }
@ -1041,7 +1041,7 @@ private:
for (size_t i = 0; i < selections.size(); ++i) for (size_t i = 0; i < selections.size(); ++i)
{ {
size_t index = std::min(i, strings.size()-1); size_t index = std::min(i, strings.size()-1);
buffer.insert(buffer.iterator_at(selections[i].last()), buffer.insert(buffer.iterator_at(selections[i].cursor()),
strings[index]); strings[index]);
} }
} }
@ -1051,7 +1051,7 @@ private:
auto str = codepoint_to_str(key); auto str = codepoint_to_str(key);
auto& buffer = context().buffer(); auto& buffer = context().buffer();
for (auto& sel : context().selections()) for (auto& sel : context().selections())
buffer.insert(buffer.iterator_at(sel.last()), str); buffer.insert(buffer.iterator_at(sel.cursor()), str);
context().hooks().run_hook("InsertChar", str, context()); context().hooks().run_hook("InsertChar", str, context());
} }
@ -1062,54 +1062,54 @@ private:
for (auto& sel : selections) for (auto& sel : selections)
{ {
BufferCoord first, last; BufferCoord anchor, cursor;
switch (mode) switch (mode)
{ {
case InsertMode::Insert: case InsertMode::Insert:
first = sel.max(); anchor = sel.max();
last = sel.min(); cursor = sel.min();
break; break;
case InsertMode::Replace: case InsertMode::Replace:
first = last = Kakoune::erase(buffer, sel).coord(); anchor = cursor = Kakoune::erase(buffer, sel).coord();
break; break;
case InsertMode::Append: case InsertMode::Append:
first = sel.min(); anchor = sel.min();
last = sel.max(); cursor = sel.max();
// special case for end of lines, append to current line instead // special case for end of lines, append to current line instead
if (last.column != buffer[last.line].length() - 1) if (cursor.column != buffer[cursor.line].length() - 1)
last = buffer.char_next(last); cursor = buffer.char_next(cursor);
break; break;
case InsertMode::OpenLineBelow: case InsertMode::OpenLineBelow:
case InsertMode::AppendAtLineEnd: case InsertMode::AppendAtLineEnd:
first = last = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1}; anchor = cursor = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
break; break;
case InsertMode::OpenLineAbove: case InsertMode::OpenLineAbove:
case InsertMode::InsertAtLineBegin: case InsertMode::InsertAtLineBegin:
first = sel.min().line; anchor = sel.min().line;
if (mode == InsertMode::OpenLineAbove) if (mode == InsertMode::OpenLineAbove)
first = buffer.char_prev(first); anchor = buffer.char_prev(anchor);
else else
{ {
auto first_non_blank = buffer.iterator_at(first); auto anchor_non_blank = buffer.iterator_at(anchor);
while (*first_non_blank == ' ' or *first_non_blank == '\t') while (*anchor_non_blank == ' ' or *anchor_non_blank == '\t')
++first_non_blank; ++anchor_non_blank;
if (*first_non_blank != '\n') if (*anchor_non_blank != '\n')
first = first_non_blank.coord(); anchor = anchor_non_blank.coord();
} }
last = first; cursor = anchor;
break; break;
case InsertMode::InsertAtNextLineBegin: case InsertMode::InsertAtNextLineBegin:
kak_assert(false); // not implemented kak_assert(false); // not implemented
break; break;
} }
if (buffer.is_end(first)) if (buffer.is_end(anchor))
first = buffer.char_prev(first); anchor = buffer.char_prev(anchor);
if (buffer.is_end(last)) if (buffer.is_end(cursor))
last = buffer.char_prev(last); cursor = buffer.char_prev(cursor);
sel.first() = first; sel.anchor() = anchor;
sel.last() = last; sel.cursor() = cursor;
} }
if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove) if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
{ {
@ -1119,8 +1119,8 @@ private:
for (auto& sel : selections) for (auto& sel : selections)
{ {
// special case, the --first line above did nothing, so we need to compensate now // special case, the --first line above did nothing, so we need to compensate now
if (sel.first() == buffer.char_next({0,0})) if (sel.anchor() == buffer.char_next({0,0}))
sel.first() = sel.last() = BufferCoord{0,0}; sel.anchor() = sel.cursor() = BufferCoord{0,0};
} }
} }
} }
@ -1133,8 +1133,8 @@ private:
{ {
for (auto& sel : context().selections()) for (auto& sel : context().selections())
{ {
if (m_insert_mode == InsertMode::Append and sel.last().column > 0) if (m_insert_mode == InsertMode::Append and sel.cursor().column > 0)
sel.last() = context().buffer().char_prev(sel.last()); sel.cursor() = context().buffer().char_prev(sel.cursor());
avoid_eol(context().buffer(), sel); avoid_eol(context().buffer(), sel);
} }
} }

View File

@ -108,15 +108,15 @@ void register_env_vars()
}, { }, {
"cursor_line", "cursor_line",
[](const String& name, const Context& context) [](const String& name, const Context& context)
{ return to_string(context.selections().main().last().line + 1); } { return to_string(context.selections().main().cursor().line + 1); }
}, { }, {
"cursor_column", "cursor_column",
[](const String& name, const Context& context) [](const String& name, const Context& context)
{ return to_string(context.selections().main().last().column + 1); } { return to_string(context.selections().main().cursor().column + 1); }
}, { }, {
"cursor_char_column", "cursor_char_column",
[](const String& name, const Context& context) [](const String& name, const Context& context)
{ auto coord = context.selections().main().last(); { auto coord = context.selections().main().cursor();
return to_string(context.buffer()[coord.line].char_count_to(coord.column) + 1); } return to_string(context.buffer()[coord.line].char_count_to(coord.column) + 1); }
}, { }, {
"selection_desc", "selection_desc",

View File

@ -70,9 +70,9 @@ void insert(Buffer& buffer, SelectionList& selections, const String& str)
pos = buffer.insert(pos, str); pos = buffer.insert(pos, str);
if (mode == InsertMode::Replace and pos != buffer.end()) if (mode == InsertMode::Replace and pos != buffer.end())
{ {
sel.first() = pos.coord(); sel.anchor() = pos.coord();
sel.last() = str.empty() ? sel.cursor() = str.empty() ?
pos.coord() : (pos + str.byte_count_to(str.char_length() - 1)).coord(); pos.coord() : (pos + str.byte_count_to(str.char_length() - 1)).coord();
} }
avoid_eol(buffer, sel); avoid_eol(buffer, sel);
} }
@ -93,9 +93,9 @@ void insert(Buffer& buffer, SelectionList& selections, memoryview<String> string
pos = buffer.insert(pos, str); pos = buffer.insert(pos, str);
if (mode == InsertMode::Replace and pos != buffer.end()) if (mode == InsertMode::Replace and pos != buffer.end())
{ {
sel.first() = pos.coord(); sel.anchor() = pos.coord();
sel.last() = (str.empty() ? sel.cursor() = (str.empty() ?
pos : pos + str.byte_count_to(str.char_length() - 1)).coord(); pos : pos + str.byte_count_to(str.char_length() - 1)).coord();
} }
avoid_eol(buffer, sel); avoid_eol(buffer, sel);
} }
@ -131,8 +131,8 @@ void select(Context& context, Func func)
{ {
auto& sel = selections.main(); auto& sel = selections.main();
auto res = func(buffer, sel); auto res = func(buffer, sel);
sel.first() = res.first(); sel.anchor() = res.anchor();
sel.last() = res.last(); sel.cursor() = res.cursor();
if (not res.captures().empty()) if (not res.captures().empty())
sel.captures() = std::move(res.captures()); sel.captures() = std::move(res.captures());
} }
@ -145,8 +145,8 @@ void select(Context& context, Func func)
sel.merge_with(res); sel.merge_with(res);
else else
{ {
sel.first() = res.first(); sel.anchor() = res.anchor();
sel.last() = res.last(); sel.cursor() = res.cursor();
} }
if (not res.captures().empty()) if (not res.captures().empty())
sel.captures() = std::move(res.captures()); sel.captures() = std::move(res.captures());
@ -181,7 +181,7 @@ void select_coord(const Buffer& buffer, BufferCoord coord, SelectionList& select
else if (mode == SelectMode::Extend) else if (mode == SelectMode::Extend)
{ {
for (auto& sel : selections) for (auto& sel : selections)
sel.last() = coord; sel.cursor() = coord;
selections.sort_and_merge_overlapping(); selections.sort_and_merge_overlapping();
} }
} }
@ -335,7 +335,7 @@ void view_commands(Context& context, int param)
if (key.modifiers != Key::Modifiers::None or not context.has_window()) if (key.modifiers != Key::Modifiers::None or not context.has_window())
return; return;
LineCount cursor_line = context.selections().main().last().line; LineCount cursor_line = context.selections().main().cursor().line;
Window& window = context.window(); Window& window = context.window();
switch (tolower(key.key)) switch (tolower(key.key))
{ {
@ -688,7 +688,7 @@ void split_lines(Context& context, int)
SelectionList res; SelectionList res;
for (auto& sel : selections) for (auto& sel : selections)
{ {
if (sel.first().line == sel.last().line) if (sel.anchor().line == sel.cursor().line)
{ {
res.push_back(std::move(sel)); res.push_back(std::move(sel));
continue; continue;
@ -1030,8 +1030,8 @@ void align(Context& context, int)
size_t column = 0; size_t column = 0;
for (auto& sel : selections) for (auto& sel : selections)
{ {
auto line = sel.last().line; auto line = sel.cursor().line;
if (sel.first().line != line) if (sel.anchor().line != line)
throw runtime_error("align cannot work with multi line selections"); throw runtime_error("align cannot work with multi line selections");
column = (line == last_line) ? column + 1 : 0; column = (line == last_line) ? column + 1 : 0;
@ -1046,11 +1046,11 @@ void align(Context& context, int)
{ {
CharCount maxcol = 0; CharCount maxcol = 0;
for (auto& sel : col) for (auto& sel : col)
maxcol = std::max(get_column(buffer, tabstop, sel->last()), maxcol); maxcol = std::max(get_column(buffer, tabstop, sel->cursor()), maxcol);
for (auto& sel : col) for (auto& sel : col)
{ {
auto insert_coord = sel->min(); auto insert_coord = sel->min();
auto lastcol = get_column(buffer, tabstop, sel->last()); auto lastcol = get_column(buffer, tabstop, sel->cursor());
String padstr; String padstr;
if (not use_tabs) if (not use_tabs)
padstr = String{ ' ', maxcol - lastcol }; padstr = String{ ' ', maxcol - lastcol };
@ -1196,11 +1196,11 @@ void move(Context& context, int count)
auto& selections = context.selections(); auto& selections = context.selections();
for (auto& sel : selections) for (auto& sel : selections)
{ {
auto last = context.has_window() ? context.window().offset_coord(sel.last(), offset) auto cursor = context.has_window() ? context.window().offset_coord(sel.cursor(), offset)
: context.buffer().offset_coord(sel.last(), offset); : context.buffer().offset_coord(sel.cursor(), offset);
sel.first() = mode == SelectMode::Extend ? sel.first() : last; sel.anchor() = mode == SelectMode::Extend ? sel.anchor() : cursor;
sel.last() = last; sel.cursor() = cursor;
avoid_eol(context.buffer(), sel); avoid_eol(context.buffer(), sel);
} }
selections.sort_and_merge_overlapping(); selections.sort_and_merge_overlapping();

View File

@ -7,11 +7,11 @@ namespace Kakoune
void Range::merge_with(const Range& range) void Range::merge_with(const Range& range)
{ {
m_last = range.m_last; m_cursor = range.m_cursor;
if (m_first < m_last) if (m_anchor < m_cursor)
m_first = std::min(m_first, range.m_first); m_anchor = std::min(m_anchor, range.m_anchor);
if (m_first > m_last) if (m_anchor > m_cursor)
m_first = std::max(m_first, range.m_first); m_anchor = std::max(m_anchor, range.m_anchor);
} }
namespace namespace
@ -22,27 +22,27 @@ void on_buffer_change(const Buffer& buffer, SelectionList& sels,
BufferCoord begin, BufferCoord end, LineCount end_line) BufferCoord begin, BufferCoord end, LineCount end_line)
{ {
auto update_beg = std::lower_bound(sels.begin(), sels.end(), begin, auto update_beg = std::lower_bound(sels.begin(), sels.end(), begin,
[](const Selection& s, BufferCoord c) { return std::max(s.first(), s.last()) < c; }); [](const Selection& s, BufferCoord c) { return std::max(s.anchor(), s.cursor()) < c; });
auto update_only_line_beg = std::upper_bound(sels.begin(), sels.end(), end_line, auto update_only_line_beg = std::upper_bound(sels.begin(), sels.end(), end_line,
[](LineCount l, const Selection& s) { return l < std::min(s.first(), s.last()).line; }); [](LineCount l, const Selection& s) { return l < std::min(s.anchor(), s.cursor()).line; });
if (update_beg != update_only_line_beg) if (update_beg != update_only_line_beg)
{ {
// for the first one, we are not sure if min < begin // for the first one, we are not sure if min < begin
UpdateFunc<false, false>{}(buffer, update_beg->first(), begin, end); UpdateFunc<false, false>{}(buffer, update_beg->anchor(), begin, end);
UpdateFunc<false, false>{}(buffer, update_beg->last(), begin, end); UpdateFunc<false, false>{}(buffer, update_beg->cursor(), begin, end);
} }
for (auto it = update_beg+1; it < update_only_line_beg; ++it) for (auto it = update_beg+1; it < update_only_line_beg; ++it)
{ {
UpdateFunc<false, true>{}(buffer, it->first(), begin, end); UpdateFunc<false, true>{}(buffer, it->anchor(), begin, end);
UpdateFunc<false, true>{}(buffer, it->last(), begin, end); UpdateFunc<false, true>{}(buffer, it->cursor(), begin, end);
} }
if (end.line > begin.line) if (end.line > begin.line)
{ {
for (auto it = update_only_line_beg; it != sels.end(); ++it) for (auto it = update_only_line_beg; it != sels.end(); ++it)
{ {
UpdateFunc<true, true>{}(buffer, it->first(), begin, end); UpdateFunc<true, true>{}(buffer, it->anchor(), begin, end);
UpdateFunc<true, true>{}(buffer, it->last(), begin, end); UpdateFunc<true, true>{}(buffer, it->cursor(), begin, end);
} }
} }
} }

View File

@ -10,28 +10,28 @@ namespace Kakoune
struct Range struct Range
{ {
public: public:
Range(BufferCoord first, BufferCoord last) Range(BufferCoord anchor, BufferCoord cursor)
: m_first{first}, m_last{last} {} : m_anchor{anchor}, m_cursor{cursor} {}
void merge_with(const Range& range); void merge_with(const Range& range);
BufferCoord& first() { return m_first; } BufferCoord& anchor() { return m_anchor; }
BufferCoord& last() { return m_last; } BufferCoord& cursor() { return m_cursor; }
const BufferCoord& first() const { return m_first; } const BufferCoord& anchor() const { return m_anchor; }
const BufferCoord& last() const { return m_last; } const BufferCoord& cursor() const { return m_cursor; }
bool operator== (const Range& other) const bool operator== (const Range& other) const
{ {
return m_first == other.m_first and m_last == other.m_last; return m_anchor == other.m_anchor and m_cursor == other.m_cursor;
} }
const BufferCoord& min() const { return std::min(m_first, m_last); } const BufferCoord& min() const { return std::min(m_anchor, m_cursor); }
const BufferCoord& max() const { return std::max(m_first, m_last); } const BufferCoord& max() const { return std::max(m_anchor, m_cursor); }
private: private:
BufferCoord m_first; BufferCoord m_anchor;
BufferCoord m_last; BufferCoord m_cursor;
}; };
inline bool overlaps(const Range& lhs, const Range& rhs) inline bool overlaps(const Range& lhs, const Range& rhs)
@ -68,8 +68,8 @@ inline void avoid_eol(const Buffer& buffer, BufferCoord& coord)
inline void avoid_eol(const Buffer& buffer, Range& sel) inline void avoid_eol(const Buffer& buffer, Range& sel)
{ {
avoid_eol(buffer, sel.first()); avoid_eol(buffer, sel.anchor());
avoid_eol(buffer, sel.last()); avoid_eol(buffer, sel.cursor());
} }
@ -79,9 +79,9 @@ using CaptureList = std::vector<String>;
struct Selection : public Range struct Selection : public Range
{ {
explicit Selection(BufferCoord pos) : Range(pos,pos) {} explicit Selection(BufferCoord pos) : Range(pos,pos) {}
Selection(BufferCoord first, BufferCoord last, Selection(BufferCoord anchor, BufferCoord cursor,
CaptureList captures = {}) CaptureList captures = {})
: Range(first, last), m_captures(std::move(captures)) {} : Range(anchor, cursor), m_captures(std::move(captures)) {}
Selection(const Range& range) Selection(const Range& range)
: Range(range) {} : Range(range) {}

View File

@ -11,7 +11,7 @@ namespace Kakoune
Selection select_line(const Buffer& buffer, const Selection& selection) Selection select_line(const Buffer& buffer, const Selection& selection)
{ {
Utf8Iterator first = buffer.iterator_at(selection.last()); Utf8Iterator first = buffer.iterator_at(selection.cursor());
if (*first == '\n' and first + 1 != buffer.end()) if (*first == '\n' and first + 1 != buffer.end())
++first; ++first;
@ -27,7 +27,7 @@ Selection select_line(const Buffer& buffer, const Selection& selection)
Selection select_matching(const Buffer& buffer, const Selection& selection) Selection select_matching(const Buffer& buffer, const Selection& selection)
{ {
std::vector<Codepoint> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' }; std::vector<Codepoint> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
Utf8Iterator it = buffer.iterator_at(selection.last()); Utf8Iterator it = buffer.iterator_at(selection.cursor());
std::vector<Codepoint>::iterator match = matching_pairs.end(); std::vector<Codepoint>::iterator match = matching_pairs.end();
while (not is_eol(*it)) while (not is_eol(*it))
{ {
@ -142,7 +142,7 @@ Selection select_surrounding(const Buffer& buffer, const Selection& selection,
ObjectFlags flags) ObjectFlags flags)
{ {
const bool nestable = matching.first != matching.second; const bool nestable = matching.first != matching.second;
auto pos = selection.last(); auto pos = selection.cursor();
if (not nestable or flags & ObjectFlags::Inner) if (not nestable or flags & ObjectFlags::Inner)
{ {
if (auto res = find_surrounding(buffer, pos, matching, flags, level)) if (auto res = find_surrounding(buffer, pos, matching, flags, level))
@ -171,7 +171,7 @@ Selection select_surrounding(const Buffer& buffer, const Selection& selection,
Selection select_to(const Buffer& buffer, const Selection& selection, Selection select_to(const Buffer& buffer, const Selection& selection,
Codepoint c, int count, bool inclusive) Codepoint c, int count, bool inclusive)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
Utf8Iterator end = begin; Utf8Iterator end = begin;
do do
{ {
@ -188,7 +188,7 @@ Selection select_to(const Buffer& buffer, const Selection& selection,
Selection select_to_reverse(const Buffer& buffer, const Selection& selection, Selection select_to_reverse(const Buffer& buffer, const Selection& selection,
Codepoint c, int count, bool inclusive) Codepoint c, int count, bool inclusive)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
Utf8Iterator end = begin; Utf8Iterator end = begin;
do do
{ {
@ -204,7 +204,7 @@ Selection select_to_reverse(const Buffer& buffer, const Selection& selection,
Selection select_to_eol(const Buffer& buffer, const Selection& selection) Selection select_to_eol(const Buffer& buffer, const Selection& selection)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
Utf8Iterator end = begin; Utf8Iterator end = begin;
skip_while(end, buffer.end(), [](Codepoint cur) { return not is_eol(cur); }); skip_while(end, buffer.end(), [](Codepoint cur) { return not is_eol(cur); });
return utf8_range(begin, end != begin ? end-1 : end); return utf8_range(begin, end != begin ? end-1 : end);
@ -212,7 +212,7 @@ Selection select_to_eol(const Buffer& buffer, const Selection& selection)
Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection) Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
Utf8Iterator end = begin - 1; Utf8Iterator end = begin - 1;
skip_while_reverse(end, buffer.begin(), [](Codepoint cur) { return not is_eol(cur); }); skip_while_reverse(end, buffer.begin(), [](Codepoint cur) { return not is_eol(cur); });
return utf8_range(begin, end == buffer.begin() ? end : end+1); return utf8_range(begin, end == buffer.begin() ? end : end+1);
@ -220,7 +220,7 @@ Selection select_to_eol_reverse(const Buffer& buffer, const Selection& selection
Selection select_whole_sentence(const Buffer& buffer, const Selection& selection, ObjectFlags flags) Selection select_whole_sentence(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{ {
BufferIterator first = buffer.iterator_at(selection.last()); BufferIterator first = buffer.iterator_at(selection.cursor());
BufferIterator last = first; BufferIterator last = first;
if (flags & ObjectFlags::ToBegin) if (flags & ObjectFlags::ToBegin)
@ -271,7 +271,7 @@ Selection select_whole_sentence(const Buffer& buffer, const Selection& selection
Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, ObjectFlags flags) Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{ {
BufferIterator first = buffer.iterator_at(selection.last()); BufferIterator first = buffer.iterator_at(selection.cursor());
BufferIterator last = first; BufferIterator last = first;
if (flags & ObjectFlags::ToBegin and first != buffer.begin()) if (flags & ObjectFlags::ToBegin and first != buffer.begin())
@ -329,7 +329,7 @@ static CharCount get_indent(const String& str, int tabstop)
Selection select_whole_indent(const Buffer& buffer, const Selection& selection, ObjectFlags flags) Selection select_whole_indent(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{ {
int tabstop = buffer.options()["tabstop"].get<int>(); int tabstop = buffer.options()["tabstop"].get<int>();
LineCount line = selection.last().line; LineCount line = selection.cursor().line;
auto indent = get_indent(buffer[line], tabstop); auto indent = get_indent(buffer[line], tabstop);
LineCount begin_line = line - 1; LineCount begin_line = line - 1;
@ -367,8 +367,8 @@ Selection select_whole_indent(const Buffer& buffer, const Selection& selection,
Selection select_whole_lines(const Buffer& buffer, const Selection& selection) Selection select_whole_lines(const Buffer& buffer, const Selection& selection)
{ {
// no need to be utf8 aware for is_eol as we only use \n as line seperator // no need to be utf8 aware for is_eol as we only use \n as line seperator
BufferIterator first = buffer.iterator_at(selection.first()); BufferIterator first = buffer.iterator_at(selection.anchor());
BufferIterator last = buffer.iterator_at(selection.last()); BufferIterator last = buffer.iterator_at(selection.cursor());
BufferIterator& to_line_start = first <= last ? first : last; BufferIterator& to_line_start = first <= last ? first : last;
BufferIterator& to_line_end = first <= last ? last : first; BufferIterator& to_line_end = first <= last ? last : first;
@ -387,8 +387,8 @@ Selection select_whole_lines(const Buffer& buffer, const Selection& selection)
Selection trim_partial_lines(const Buffer& buffer, const Selection& selection) Selection trim_partial_lines(const Buffer& buffer, const Selection& selection)
{ {
// same as select_whole_lines // same as select_whole_lines
BufferIterator first = buffer.iterator_at(selection.first()); BufferIterator first = buffer.iterator_at(selection.anchor());
BufferIterator last = buffer.iterator_at(selection.last()); BufferIterator last = buffer.iterator_at(selection.cursor());
BufferIterator& to_line_start = first <= last ? first : last; BufferIterator& to_line_start = first <= last ? first : last;
BufferIterator& to_line_end = first <= last ? last : first; BufferIterator& to_line_end = first <= last ? last : first;

View File

@ -11,9 +11,9 @@ namespace Kakoune
inline void clear_selections(const Buffer& buffer, SelectionList& selections) inline void clear_selections(const Buffer& buffer, SelectionList& selections)
{ {
auto& sel = selections.main(); auto& sel = selections.main();
auto& pos = sel.last(); auto& pos = sel.cursor();
avoid_eol(buffer, pos); avoid_eol(buffer, pos);
sel.first() = pos; sel.anchor() = pos;
selections = SelectionList{ std::move(sel) }; selections = SelectionList{ std::move(sel) };
} }
@ -21,7 +21,7 @@ inline void clear_selections(const Buffer& buffer, SelectionList& selections)
inline void flip_selections(SelectionList& selections) inline void flip_selections(SelectionList& selections)
{ {
for (auto& sel : selections) for (auto& sel : selections)
std::swap(sel.first(), sel.last()); std::swap(sel.anchor(), sel.cursor());
selections.check_invariant(); selections.check_invariant();
} }
@ -61,7 +61,7 @@ using RegexIterator = boost::regex_iterator<BufferIterator>;
template<WordType word_type> template<WordType word_type>
Selection select_to_next_word(const Buffer& buffer, const Selection& selection) Selection select_to_next_word(const Buffer& buffer, const Selection& selection)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
if (begin+1 == buffer.end()) if (begin+1 == buffer.end())
return selection; return selection;
if (categorize<word_type>(*begin) != categorize<word_type>(*(begin+1))) if (categorize<word_type>(*begin) != categorize<word_type>(*(begin+1)))
@ -85,7 +85,7 @@ Selection select_to_next_word(const Buffer& buffer, const Selection& selection)
template<WordType word_type> template<WordType word_type>
Selection select_to_next_word_end(const Buffer& buffer, const Selection& selection) Selection select_to_next_word_end(const Buffer& buffer, const Selection& selection)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
if (begin+1 == buffer.end()) if (begin+1 == buffer.end())
return selection; return selection;
if (categorize<word_type>(*begin) != categorize<word_type>(*(begin+1))) if (categorize<word_type>(*begin) != categorize<word_type>(*(begin+1)))
@ -108,7 +108,7 @@ Selection select_to_next_word_end(const Buffer& buffer, const Selection& selecti
template<WordType word_type> template<WordType word_type>
Selection select_to_previous_word(const Buffer& buffer, const Selection& selection) Selection select_to_previous_word(const Buffer& buffer, const Selection& selection)
{ {
Utf8Iterator begin = buffer.iterator_at(selection.last()); Utf8Iterator begin = buffer.iterator_at(selection.cursor());
if (begin == buffer.begin()) if (begin == buffer.begin())
return selection; return selection;
if (categorize<word_type>(*begin) != categorize<word_type>(*(begin-1))) if (categorize<word_type>(*begin) != categorize<word_type>(*(begin-1)))
@ -160,7 +160,7 @@ constexpr ObjectFlags operator|(ObjectFlags lhs, ObjectFlags rhs)
template<WordType word_type> template<WordType word_type>
Selection select_whole_word(const Buffer& buffer, const Selection& selection, ObjectFlags flags) Selection select_whole_word(const Buffer& buffer, const Selection& selection, ObjectFlags flags)
{ {
Utf8Iterator first = buffer.iterator_at(selection.last()); Utf8Iterator first = buffer.iterator_at(selection.cursor());
Utf8Iterator last = first; Utf8Iterator last = first;
if (is_word<word_type>(*first)) if (is_word<word_type>(*first))
{ {
@ -242,7 +242,7 @@ bool find_match_in_buffer(const Buffer& buffer, const BufferIterator pos,
template<Direction direction> template<Direction direction>
Selection find_next_match(const Buffer& buffer, const Selection& sel, const Regex& regex) Selection find_next_match(const Buffer& buffer, const Selection& sel, const Regex& regex)
{ {
auto begin = buffer.iterator_at(sel.last()); auto begin = buffer.iterator_at(sel.cursor());
auto end = begin; auto end = begin;
CaptureList captures; CaptureList captures;

View File

@ -162,22 +162,22 @@ static CharCount adapt_view_pos(const DisplayBuffer& display_buffer,
void Window::scroll_to_keep_selection_visible_ifn(const Context& context) void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
{ {
auto& selection = context.selections().main(); auto& selection = context.selections().main();
const auto& first = selection.first(); const auto& anchor = selection.anchor();
const auto& last = selection.last(); const auto& cursor = selection.cursor();
const LineCount offset = std::min<LineCount>(options()["scrolloff"].get<int>(), const LineCount offset = std::min<LineCount>(options()["scrolloff"].get<int>(),
(m_dimensions.line - 1) / 2); (m_dimensions.line - 1) / 2);
// scroll lines if needed, try to get as much of the selection visible as possible // scroll lines if needed, try to get as much of the selection visible as possible
m_position.line = adapt_view_pos(first.line, offset, m_position.line, m_position.line = adapt_view_pos(anchor.line, offset, m_position.line,
m_dimensions.line, buffer().line_count()); m_dimensions.line, buffer().line_count());
m_position.line = adapt_view_pos(last.line, offset, m_position.line, m_position.line = adapt_view_pos(cursor.line, offset, m_position.line,
m_dimensions.line, buffer().line_count()); m_dimensions.line, buffer().line_count());
// highlight only the line containing the cursor // highlight only the line containing the cursor
DisplayBuffer display_buffer; DisplayBuffer display_buffer;
DisplayBuffer::LineList& lines = display_buffer.lines(); DisplayBuffer::LineList& lines = display_buffer.lines();
lines.emplace_back(AtomList{ {buffer(), last.line, last.line+1} }); lines.emplace_back(AtomList{ {buffer(), cursor.line, cursor.line+1} });
display_buffer.compute_range(); display_buffer.compute_range();
m_highlighters(context, HighlightFlags::MoveOnly, display_buffer); m_highlighters(context, HighlightFlags::MoveOnly, display_buffer);
@ -188,9 +188,9 @@ void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
// the cursor in the same position, however I do not find any sane example // the cursor in the same position, however I do not find any sane example
// of highlighters not doing that) // of highlighters not doing that)
m_position.column = adapt_view_pos(display_buffer, m_position.column = adapt_view_pos(display_buffer,
first.line == last.line ? first : last.line, anchor.line == cursor.line ? anchor : cursor.line,
m_position.column, m_dimensions.column); m_position.column, m_dimensions.column);
m_position.column = adapt_view_pos(display_buffer, last, m_position.column = adapt_view_pos(display_buffer, cursor,
m_position.column, m_dimensions.column); m_position.column, m_dimensions.column);
} }