try to preserve display column rather than buffer column when moving line

This commit is contained in:
Maxime Coste 2013-07-17 21:17:32 +02:00
parent 5a6922a045
commit 486ebed098
4 changed files with 91 additions and 27 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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;