summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2015-02-25 13:40:19 +0000
committerMaxime Coste <frrrwww@gmail.com>2015-02-25 13:41:00 +0000
commit00bde4ef483b11cdea59e2d693c2afee2e1576f0 (patch)
tree4bd916948c5a61ce9ec323681795a37c64a3c467 /src
parent46f37a6050e02a958d1cafbd7da42500df88e458 (diff)
Respect columns when copying selection, not just bytes
Diffstat (limited to 'src')
-rw-r--r--src/buffer_utils.cc20
-rw-r--r--src/buffer_utils.hh3
-rw-r--r--src/normal.cc22
3 files changed, 40 insertions, 5 deletions
diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc
index 0b5941b9..c768a9eb 100644
--- a/src/buffer_utils.cc
+++ b/src/buffer_utils.cc
@@ -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)
{
diff --git a/src/buffer_utils.hh b/src/buffer_utils.hh
index 80bd3112..591ea455 100644
--- a/src/buffer_utils.hh
+++ b/src/buffer_utils.hh
@@ -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,
diff --git a/src/normal.cc b/src/normal.cc
index 611698e7..f587a513 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -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);