1

In case you're not familiar with how it works, in Pico and Nano you can hit ctrl-k multiple times and it will add each line to the clipboard. Then you can ctrl-u to "uncut" this. It's a very useful command. Vim does something similar with the dd command, but it only works one line at a time. Thus, you have to use visual mode to properly accomplish the above.

I couldn't find a good answer online so I rolled my own solution. You can add this to your vimrc file:

imap <C-k> <Esc>:execute @a ? 'normal! "Bdd' : 'normal! "bdd'<cr>:let @a=1<cr>:echo ''<cr>i
imap <C-u> <Esc>"bPi
autocmd CursorMovedI * execute(':let @a=0')

The register @a is used to track whether or not the cut line should be appended. The register @b is used as the clipboard register. Whenever the cursor position changes, you stop being in "append" mode. Thus, you can hit ctrl-k over and over to keep appending lines, but as soon as you move the cursor you go back to normal. I'm pretty sure this is how Nano and Pico implement it under the hood.

Is anyone aware of a cleaner solution?

Jonas
  • 121,568
  • 97
  • 310
  • 388
Billy
  • 185
  • 8

2 Answers2

6

Intro to Registers

The Vim commands you are looking for are delete/cut, dd and put/paste, p. Each of these commands by default use the unnamed register, "". So dd will delete a line and put the freshly deleted line into the unnamed register. p will put the contents from the unnamed register into your current buffer.

Vim has more than just the unnamed register, it also has named registers. These registers are a-z.

  • To see what your registers are set to you can execute :registers.
  • To use a named register prefix your command with quote and a lowercase letter, e.g. "add
  • Upper case letters will append instead of replace the contents of a register, e.g "Add"

The Vim Way

  • "add the first line, then append the next line via "Add. For repeated deletions use .
  • Use a text object. e.g. dap for delete a paragraph. See :h text-objects
  • Delete text via some motion. e.g. d} is delete till end of paragraph
  • Delete to a regex patter. e.g. d/foo<cr>
  • Lastly would be using visual mode, V6jd. Nothing wrong with using visual mode

Additionally you want to stay out of insert mode unless you are inserting text. You only want to be in insert move for short burst at a time. Most of the time you should be in Normal mode, hence the name.

For a nice post on the Vi/Vim way see this StackOverflow post: Your problem with Vim is that you don't grok vi.

Alternatives

If none of the standard Vim tricks satisfy your needs you may want to look into plugins that support line exchanging like Unimpaired or LineJuggler.

However if you really do want something similar this nano/pico features you can use the following by putting it in your ~/.vimrc file:

nnoremap Q :<c-u>call <SID>DeleteAppend()<cr>

function! s:DeleteAppend()
  let save = @a
  let @a = @@
  let reg = get(g:, 'append_tick', -1) == b:changedtick ? 'A' : 'a'
  execute 'normal! "' . reg .  'dd'
  let g:append_tick = b:changedtick
  let @@ = @a
  let @a = save
endfunction

The Q normal command will now delete a line and append additional deleted lines until a another command is executed. Example usage: QQjjQQQp

For more help please see

:h d
:h p
:h "
:h registers
:h :reg
:h motion
:h text-objects
:h .
:h visual-mode
Community
  • 1
  • 1
Peter Rincker
  • 43,539
  • 9
  • 74
  • 101
  • +1. For clarification, `"Add` has nothing to do with adding - it could just as well be `"Odd` or `"Mdd` - in `"Add`, `A` is the register name, `dd` is "delete line". (The typo, `"Add"`, doesn't help matters :P ) I know OP knows it (because he used `"Bdd`, but just in case a Vim newbie reads it. – Amadan Apr 11 '14 at 04:27
  • 1
    I think the OP understands what you are explaining here. The `:imap` in the question includes `"Bdd`. The question is just whether there is a better way to make an `:imap` so that it can be done with the preferred (single) keystrokes. – benjifisher Apr 11 '14 at 12:06
  • @benjifisher I wrote the register part for other nano/pico defectors not the OP. I believe it is best to discourage bad habits such as deleting lines of text in insert mode. These habits prevent deeper understand of normal mode that is gained through emersion. It is important to remember some of the benefits normal mode gives, e.g. simple redo's via `.`, chunky undo history, and easy to use motions. However I have edited my post to reflect some alternatives that might meet the OP's question properly – Peter Rincker Apr 11 '14 at 13:59
  • The function `s:DeleteAppend()` create one undo block each time you press `Ctrl+K`. I suggest an alternative implementation: https://gist.github.com/jerome-pouiller/bd177032bd13a077e5d3f6fb508ee7f2 (in addition, if it is called from the middle of the line, it only delete until the end of the line). – Jérôme Pouiller Jul 08 '20 at 14:30
0

Yes, there are many cleaner solutions:

12dd{motion}p         " cut 12 lines, move elsewhere, paste

d5j{motion}p          " cut from here to 5 lines down, move elsewhere, paste

d/foo<CR>{motion}p    " cut from here to next 'foo', move elsewhere, paste

:.,23d<CR>:12put<CR>  " cut from here to line 23, paste after line 12

:.,+5d<CR>:0put<CR>   " cut from here to fifth line below, paste at top of buffer

or the truly amazing:

:.,11m35<CR>          " move the lines between this one and 11 to after line 35 

You can even do:

Vjjjjjjjjjjd{motion}p

One of the big advantages of Vim over other editors is its expressive language: don't think in "nano", think in "Vim".

romainl
  • 186,200
  • 21
  • 280
  • 313