diff --git a/README.asciidoc b/README.asciidoc index c1333405..21f2b6d1 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -179,7 +179,6 @@ Changes * _i_: insert before current selection * _a_: insert after current selection * _d_: yank and delete current selection - * _D_: yank concatenated and delete current selection (see _Y_) * _c_: yank and delete current selection and insert * _._: repeat last insert mode change (_i_, _a_, or _c_, including the inserted text) @@ -190,11 +189,15 @@ Changes * _O_: insert in a new line above current selection begin * _y_: yank selections - * _Y_: yank selections concatenated (only one yank, containing - all selection concatenated) * _p_: paste after current selection end * _P_: paste before current selection begin - * _alt-p_: replace current selection with yanked text + * _alt-p_: paste all after current selection end, and + select each pasted string. + * _alt-P_: paste all before current selection begin, and + select each pasted string. + * _R_: replace current selection with yanked text + + * _r_: replace each character with the next entered one * _alt-j_: join selected lines * _alt-J_: join selected lines and select spaces inserted @@ -215,7 +218,6 @@ Changes * _u_: undo last change * _U_: redo last change - * _r_: replace each character with the next entered one * _&_: align selection, align the cursor of selections by inserting spaces before the first character of the selection * _alt-&_: copy indent, copy the indentation of the main selection diff --git a/src/normal.cc b/src/normal.cc index 5aaa79ae..4af47ada 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -446,17 +446,6 @@ void yank(Context& context, int) " selections", get_color("Information") }); } -void cat_yank(Context& context, int) -{ - auto sels = context.selections_content(); - String str; - for (auto& sel : sels) - str += sel; - RegisterManager::instance()['"'] = memoryview(str); - context.print_status({ "concatenated and yanked " + - to_string(sels.size()) + " selections", get_color("Information") }); -} - void erase_selections(Context& context, int) { RegisterManager::instance()['"'] = context.selections_content(); @@ -465,18 +454,6 @@ void erase_selections(Context& context, int) context.selections().avoid_eol(); } -void cat_erase_selections(Context& context, int) -{ - auto sels = context.selections_content(); - String str; - for (auto& sel : sels) - str += sel; - RegisterManager::instance()['"'] = memoryview(str); - context.selections().erase(); - context.selections().avoid_eol(); -} - - void change(Context& context, int param) { RegisterManager::instance()['"'] = context.selections_content(); @@ -510,6 +487,42 @@ void paste(Context& context, int) context.selections().insert(strings, effective_mode); } +template +void paste_all(Context& context, int) +{ + auto strings = RegisterManager::instance()['"'].values(context); + InsertMode effective_mode = mode; + String all; + std::vector offsets; + for (auto& str : strings) + { + if (not str.empty() and str.back() == '\n') + effective_mode = adapt_for_linewise(mode); + all += str; + offsets.push_back(all.length()); + } + + auto& selections = context.selections(); + { + ScopedEdition edition(context); + selections.insert(all, effective_mode, true); + } + + const Buffer& buffer = context.buffer(); + std::vector result; + for (auto& selection : selections) + { + ByteCount pos = 0; + for (auto offset : offsets) + { + result.push_back({ buffer.advance(selection.min(), pos), + buffer.advance(selection.min(), offset-1) }); + pos = offset; + } + } + selections = std::move(result); +} + template void regex_prompt(Context& context, const String prompt, T func) { @@ -1250,7 +1263,6 @@ KeyMap keymap = { alt('F'), select_to_next_char }, { 'd', erase_selections }, - { 'D', cat_erase_selections }, { 'c', change }, { 'i', enter_insert_mode }, { 'I', enter_insert_mode }, @@ -1266,10 +1278,11 @@ KeyMap keymap = { 'v', view_commands }, { 'y', yank }, - { 'Y', cat_yank }, { 'p', repeated(paste) }, { 'P', repeated(paste) }, - { alt('p'), paste }, + { alt('p'), paste_all }, + { alt('P'), paste_all }, + { 'R', paste }, { 's', select_regex }, { 'S', split_regex }, diff --git a/src/selection.cc b/src/selection.cc index bd18bf85..f6eab856 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -463,7 +463,8 @@ BufferIterator prepare_insert(Buffer& buffer, const Selection& sel, InsertMode m return {}; } -void SelectionList::insert(memoryview strings, InsertMode mode) +void SelectionList::insert(memoryview strings, InsertMode mode, + bool select_inserted) { if (strings.empty()) return; @@ -496,7 +497,7 @@ void SelectionList::insert(memoryview strings, InsertMode mode) changes_tracker.update(change); m_timestamp = m_buffer->timestamp(); - if (mode == InsertMode::Replace) + if (select_inserted or mode == InsertMode::Replace) { sel.anchor() = change.begin; sel.cursor() = m_buffer->char_prev(change.end); diff --git a/src/selection.hh b/src/selection.hh index cdfca6b6..c1db3dd6 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -124,7 +124,8 @@ struct SelectionList size_t timestamp() const { return m_timestamp; } void update_timestamp() { m_timestamp = m_buffer->timestamp(); } - void insert(memoryview strings, InsertMode mode); + void insert(memoryview strings, InsertMode mode, + bool select_inserted = false); void erase(); private: