diff --git a/README.asciidoc b/README.asciidoc index 9c6d376a..eb1cdcd3 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -334,6 +334,9 @@ _alt-k_ allows you to enter a regex and keep only the selections that contains a match for this regex. using _alt-K_ you can keep the selections not containing a match. +_C_ copies the current selection to the next line (or lines if a count is given) +_alt-C_ does the same to previous lines. + _$_ allows you to enter a shell command and pipe each selections to it. Selections whose shell command returns 0 will be kept, other will be dropped. diff --git a/src/normal.cc b/src/normal.cc index 893b945a..f2315eca 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -971,6 +971,30 @@ void scroll(Context& context, NormalParams) window.set_position(position); } +template +void copy_selections_on_next_lines(Context& context, NormalParams params) +{ + auto& selections = context.selections(); + auto& buffer = context.buffer(); + Vector result; + for (auto& sel : selections) + { + auto anchor = sel.anchor(); + auto cursor = sel.cursor(); + 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 buffer.is_valid(new_cursor)) + result.emplace_back(new_anchor, new_cursor); + } + } + selections = std::move(result); + selections.sort_and_merge_overlapping(); +} + void rotate_selections(Context& context, NormalParams params) { context.selections().rotate_main(params.count != 0 ? params.count : 1); @@ -1466,6 +1490,9 @@ KeyMap keymap = { '@', { "convert tabs to spaces in selections", tabs_to_spaces } }, { alt('@'), { "convert spaces to tabs in selections", spaces_to_tabs } }, + { 'C', { "copy selection on next lines", copy_selections_on_next_lines } }, + { alt('C'), { "copy selection on previous lines", copy_selections_on_next_lines } }, + { ',', { "user mappings", exec_user_mappings } }, { Key::Left, { "move left", move } },