Respect columns when copying selection, not just bytes
This commit is contained in:
parent
46f37a6050
commit
00bde4ef48
|
@ -26,6 +26,26 @@ CharCount get_column(const Buffer& buffer,
|
|||
return col;
|
||||
}
|
||||
|
||||
ByteCount get_byte_to_column(const Buffer& buffer, CharCount tabstop, CharCoord coord)
|
||||
{
|
||||
auto line = buffer[coord.line];
|
||||
auto col = 0_char;
|
||||
auto it = line.begin();
|
||||
while (it != line.end() and coord.column > col)
|
||||
{
|
||||
if (*it == '\t')
|
||||
{
|
||||
col = (col / tabstop + 1) * tabstop;
|
||||
if (col > coord.column) // the target column was in the tab
|
||||
break;
|
||||
}
|
||||
else
|
||||
++col;
|
||||
it = utf8::next(it, line.end());
|
||||
}
|
||||
return (int)(it - line.begin());
|
||||
}
|
||||
|
||||
Buffer* create_buffer_from_data(StringView data, StringView name,
|
||||
Buffer::Flags flags, time_t fs_timestamp)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,9 @@ inline CharCount char_length(const Buffer& buffer, const Selection& range)
|
|||
CharCount get_column(const Buffer& buffer,
|
||||
CharCount tabstop, ByteCoord coord);
|
||||
|
||||
ByteCount get_byte_to_column(const Buffer& buffer, CharCount tabstop,
|
||||
CharCoord coord);
|
||||
|
||||
Buffer* create_fifo_buffer(String name, int fd, bool scroll = false);
|
||||
|
||||
Buffer* create_buffer_from_data(StringView data, StringView name,
|
||||
|
|
|
@ -976,20 +976,32 @@ void copy_selections_on_next_lines(Context& context, NormalParams params)
|
|||
{
|
||||
auto& selections = context.selections();
|
||||
auto& buffer = context.buffer();
|
||||
const CharCount tabstop = context.options()["tabstop"].get<int>();
|
||||
Vector<Selection> result;
|
||||
for (auto& sel : selections)
|
||||
{
|
||||
auto anchor = sel.anchor();
|
||||
auto cursor = sel.cursor();
|
||||
CharCount cursor_col = get_column(buffer, tabstop, cursor);
|
||||
CharCount anchor_col = get_column(buffer, tabstop, anchor);
|
||||
result.push_back(std::move(sel));
|
||||
for (int i = 0; i < std::max(params.count, 1); ++i)
|
||||
{
|
||||
LineCount offset = (direction == Forward ? 1 : -1) * (i + 1);
|
||||
ByteCoord new_anchor{anchor.line + offset, anchor.column};
|
||||
ByteCoordAndTarget new_cursor{cursor.line + offset, cursor.column, cursor.target};
|
||||
if (buffer.is_valid(new_anchor) and not buffer.is_end(new_anchor) and
|
||||
buffer.is_valid(new_cursor) and not buffer.is_end(new_cursor))
|
||||
result.emplace_back(new_anchor, new_cursor);
|
||||
|
||||
const LineCount anchor_line = anchor.line + offset;
|
||||
const LineCount cursor_line = cursor.line + offset;
|
||||
|
||||
if (anchor_line >= buffer.line_count() or cursor_line >= buffer.line_count())
|
||||
continue;
|
||||
|
||||
ByteCount anchor_byte = get_byte_to_column(buffer, tabstop, {anchor_line, anchor_col});
|
||||
ByteCount cursor_byte = get_byte_to_column(buffer, tabstop, {cursor_line, cursor_col});
|
||||
|
||||
if (anchor_byte != buffer[anchor_line].length() and
|
||||
cursor_byte != buffer[cursor_line].length())
|
||||
result.emplace_back(ByteCoord{anchor_line, anchor_byte},
|
||||
ByteCoordAndTarget{cursor_line, cursor_byte, cursor.target});
|
||||
}
|
||||
}
|
||||
selections = std::move(result);
|
||||
|
|
Loading…
Reference in New Issue
Block a user