try to preserve display column rather than buffer column when moving line
This commit is contained in:
parent
5a6922a045
commit
486ebed098
|
@ -168,16 +168,20 @@ void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selectio
|
||||||
merge_overlapping(selections, main_selection, overlaps);
|
merge_overlapping(selections, main_selection, overlaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferCoord Editor::offset_coord(const BufferCoord& coord, CharCount offset)
|
||||||
|
{
|
||||||
|
auto& line = buffer()[coord.line];
|
||||||
|
auto character = std::max(0_char, std::min(line.char_count_to(coord.column) + offset,
|
||||||
|
line.char_length() - 2));
|
||||||
|
return {coord.line, line.byte_count_to(character)};
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::move_selections(CharCount offset, SelectMode mode)
|
void Editor::move_selections(CharCount offset, SelectMode mode)
|
||||||
{
|
{
|
||||||
kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend);
|
kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend);
|
||||||
for (auto& sel : m_selections)
|
for (auto& sel : m_selections)
|
||||||
{
|
{
|
||||||
auto last = sel.last();
|
auto last = offset_coord(sel.last(), offset);
|
||||||
auto& line = buffer()[last.line];
|
|
||||||
auto character = std::max(0_char, std::min(line.char_count_to(last.column) + offset,
|
|
||||||
line.char_length() - 2));
|
|
||||||
last.column = line.byte_count_to(character);
|
|
||||||
sel.first() = mode == SelectMode::Extend ? sel.first() : last;
|
sel.first() = mode == SelectMode::Extend ? sel.first() : last;
|
||||||
sel.last() = last;
|
sel.last() = last;
|
||||||
avoid_eol(*m_buffer, sel);
|
avoid_eol(*m_buffer, sel);
|
||||||
|
@ -185,17 +189,22 @@ void Editor::move_selections(CharCount offset, SelectMode mode)
|
||||||
sort_and_merge_overlapping(m_selections, m_main_sel);
|
sort_and_merge_overlapping(m_selections, m_main_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferCoord Editor::offset_coord(const BufferCoord& coord, LineCount offset)
|
||||||
|
{
|
||||||
|
auto character = (*m_buffer)[coord.line].char_count_to(coord.column);
|
||||||
|
auto line = clamp(coord.line + offset, 0_line, m_buffer->line_count()-1);
|
||||||
|
auto& content = (*m_buffer)[line];
|
||||||
|
|
||||||
|
character = std::max(0_char, std::min(character, content.char_length() - 2));
|
||||||
|
return {line, content.byte_count_to(character)};
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::move_selections(LineCount offset, SelectMode mode)
|
void Editor::move_selections(LineCount offset, SelectMode mode)
|
||||||
{
|
{
|
||||||
kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend);
|
kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend);
|
||||||
for (auto& sel : m_selections)
|
for (auto& sel : m_selections)
|
||||||
{
|
{
|
||||||
auto character = (*m_buffer)[sel.last().line].char_count_to(sel.last().column);
|
auto pos = offset_coord(sel.last(), offset);
|
||||||
auto line = clamp(sel.last().line + offset, 0_line, m_buffer->line_count()-1);
|
|
||||||
auto& content = (*m_buffer)[line];
|
|
||||||
|
|
||||||
character = std::max(0_char, std::min(character, content.char_length() - 2));
|
|
||||||
BufferCoord pos{line, content.byte_count_to(character)};
|
|
||||||
sel.first() = mode == SelectMode::Extend ? sel.first() : pos;
|
sel.first() = mode == SelectMode::Extend ? sel.first() : pos;
|
||||||
sel.last() = pos;
|
sel.last() = pos;
|
||||||
avoid_eol(*m_buffer, sel);
|
avoid_eol(*m_buffer, sel);
|
||||||
|
|
|
@ -91,6 +91,9 @@ private:
|
||||||
void begin_edition();
|
void begin_edition();
|
||||||
void end_edition();
|
void end_edition();
|
||||||
|
|
||||||
|
virtual BufferCoord offset_coord(const BufferCoord& coord, LineCount move);
|
||||||
|
virtual BufferCoord offset_coord(const BufferCoord& coord, CharCount move);
|
||||||
|
|
||||||
int m_edition_level;
|
int m_edition_level;
|
||||||
|
|
||||||
void check_invariant() const;
|
void check_invariant() const;
|
||||||
|
|
|
@ -167,31 +167,81 @@ void Window::scroll_to_keep_cursor_visible_ifn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
CharCount find_display_column(const DisplayLine& line, const Buffer& buffer,
|
||||||
|
const BufferCoord& coord)
|
||||||
|
{
|
||||||
|
kak_assert(coord.line == line.buffer_line());
|
||||||
|
CharCount column = 0;
|
||||||
|
for (auto& atom : line)
|
||||||
|
{
|
||||||
|
auto& content = atom.content;
|
||||||
|
if (content.has_buffer_range() and
|
||||||
|
coord >= content.begin() and coord < content.end())
|
||||||
|
{
|
||||||
|
if (content.type() == AtomContent::BufferRange)
|
||||||
|
column += utf8::distance(buffer.iterator_at(content.begin()),
|
||||||
|
buffer.iterator_at(coord));
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
column += content.length();
|
||||||
|
}
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferCoord find_buffer_coord(const DisplayLine& line, const Buffer& buffer,
|
||||||
|
CharCount column)
|
||||||
|
{
|
||||||
|
LineCount l = line.buffer_line();
|
||||||
|
for (auto& atom : line)
|
||||||
|
{
|
||||||
|
auto& content = atom.content;
|
||||||
|
CharCount len = content.length();
|
||||||
|
if (content.has_buffer_range() and column < len)
|
||||||
|
{
|
||||||
|
if (content.type() == AtomContent::BufferRange)
|
||||||
|
return utf8::advance(buffer.iterator_at(content.begin()), buffer.iterator_at(l+1),
|
||||||
|
std::max(0_char, column)).coord();
|
||||||
|
return content.begin();
|
||||||
|
}
|
||||||
|
column -= len;
|
||||||
|
}
|
||||||
|
return buffer.clamp({l, buffer[l].length()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DisplayCoord Window::display_position(const BufferCoord& coord)
|
DisplayCoord Window::display_position(const BufferCoord& coord)
|
||||||
{
|
{
|
||||||
DisplayCoord res{0,0};
|
LineCount l = 0;
|
||||||
for (auto& line : m_display_buffer.lines())
|
for (auto& line : m_display_buffer.lines())
|
||||||
{
|
{
|
||||||
if (line.buffer_line() == coord.line)
|
if (line.buffer_line() == coord.line)
|
||||||
{
|
return {l, find_display_column(line, buffer(), coord)};
|
||||||
for (auto& atom : line)
|
++l;
|
||||||
{
|
|
||||||
auto& content = atom.content;
|
|
||||||
if (content.has_buffer_range() and
|
|
||||||
coord >= content.begin() and coord < content.end())
|
|
||||||
{
|
|
||||||
res.column += utf8::distance(buffer().iterator_at(content.begin()),
|
|
||||||
buffer().iterator_at(coord));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res.column += content.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++res.line;
|
|
||||||
}
|
}
|
||||||
return { 0, 0 };
|
return { 0, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferCoord Window::offset_coord(const BufferCoord& coord, LineCount offset)
|
||||||
|
{
|
||||||
|
auto line = clamp(coord.line + offset, 0_line, buffer().line_count()-1);
|
||||||
|
DisplayBuffer display_buffer;
|
||||||
|
DisplayBuffer::LineList& lines = display_buffer.lines();
|
||||||
|
{
|
||||||
|
lines.emplace_back(coord.line);
|
||||||
|
lines.back().push_back({AtomContent(buffer(), coord.line, coord.line+1)});
|
||||||
|
lines.emplace_back(line);
|
||||||
|
lines.back().push_back({AtomContent(buffer(), line, line+1)});
|
||||||
|
}
|
||||||
|
display_buffer.compute_range();
|
||||||
|
m_highlighters(*this, display_buffer);
|
||||||
|
m_builtin_highlighters(*this, display_buffer);
|
||||||
|
|
||||||
|
CharCount column = find_display_column(lines[0], buffer(), coord);
|
||||||
|
return find_buffer_coord(lines[1], buffer(), column);
|
||||||
|
}
|
||||||
|
|
||||||
void Window::on_option_changed(const Option& option)
|
void Window::on_option_changed(const Option& option)
|
||||||
{
|
{
|
||||||
String desc = option.name() + "=" + option.get_as_string();
|
String desc = option.name() + "=" + option.get_as_string();
|
||||||
|
|
|
@ -56,6 +56,8 @@ private:
|
||||||
|
|
||||||
void scroll_to_keep_cursor_visible_ifn();
|
void scroll_to_keep_cursor_visible_ifn();
|
||||||
|
|
||||||
|
BufferCoord offset_coord(const BufferCoord& coord, LineCount move) override;
|
||||||
|
|
||||||
DisplayCoord m_position;
|
DisplayCoord m_position;
|
||||||
DisplayCoord m_dimensions;
|
DisplayCoord m_dimensions;
|
||||||
DisplayBuffer m_display_buffer;
|
DisplayBuffer m_display_buffer;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user