14

I recently removed the YankRing plugin from my setup partly because it was causing some problems with macros, but mostly because I decided it would be better to train myself to use Vim's registers instead — in particular, the way that deleted text is stored initially in register "1 and then shifted up through "2, "3, etc. as further deletions are made is very useful.

However, when a deletion/change removes less than one line of text, it is instead stored in the "- small delete register (with a few exceptions for certain movement commands). If subsequent small deletions are made, that bit of text is lost.

Is it possible to get Vim to store all deletions in register "1?

nnoremap d "1d almost works, but you end up with the text in both registers "1 and "2.

I don't mind whether or not the functionality of the small delete register is affected. Suggesting I change my behaviour to save small deletions to a named register would definitely not be a helpful answer — that's what I'm currently doing.

10

This used to work in older Vim 7.3 versions when you :set clipboard=unnamed (see this Reddit discussion, as a result of a bug, which I've reported here.

That thread contains a patch by Aryeh Leib Taurog which introduces a 'regone' option. This has made it into the (overly long) todo list, but it's unlikely to be incorporated soon. So, you currently only have the option to downgrade to an outdated Vim, or build Vim yourself with that patch (and push for adoption on the vim_dev mailing list).

  • 1
    Interesting! (Especially your idea about the threshold.) Thanks for the info. Gonna hold off on the upvote/accept for the time being in an attempt to encourage someone to come up with some crazy VimScript to do this in the interim. – Rich Mar 11 '15 at 13:35
5

I've got a proof-of-concept solution that works for the d command with motions and in visual mode. It's not a fully robust solution yet (for example, d[count]d doesn't work, and neither does [count]D), but it very nearly covers all my actual use cases.

It works by setting a customer operator function that:

  1. stores the contents of the registers 1–8 in a dictionary,
  2. performs the deletion into register 1,
  3. sets registers 2–9 to the previously saved contents of registers 1–8.

See :help map-operator for an explanation of how operator functions work.

function! ShiftingDeleteOperator(type)
  let reg_dict = {}
  for k in range(1, 8)
    execute printf("let reg_dict[%d]=getreg('%d', 1)", k, k)
  endfor

  if a:type ==# 'v'
    execute 'normal! `<v`>d'
  elseif a:type ==# 'V'
    execute 'normal! `<V`>d'
  elseif a:type ==# "\<C-V>"
    execute "normal! `<\<C-V>`>d"
  elseif a:type ==# 'char'
    execute 'normal! `[v`]d'
  elseif a:type ==# 'line'
    execute "normal! '[V']d"
  else
    return
  endif

  let deleted = getreg('"', 1)
  call setreg(1, deleted)

  for [k, v] in items(reg_dict)
    execute printf("call setreg(%d, v)", k + 1)
  endfor
endfunction

" Call the function for d{motion} via operatorfunc
nnoremap <silent> d :set operatorfunc=ShiftingDeleteOperator<CR>g@
" Call the function when d or x are hit in visual mode
vnoremap d :<C-U>call ShiftingDeleteOperator(visualmode())<CR>
vnoremap x :<C-U>call ShiftingDeleteOperator(visualmode())<CR>
" Use the d{motion} as defined above to add limited support for `D` command
nmap D d$
" Use the standard dd command
nnoremap dd dd 
  • Sorry for commenting on an old answer. I adopted this solution to y and c but for c my nvim doesn't enter insert mode after the action... Currently I have to execute l and startinsert which isn't a proper fix (like c$ would put the cursor in the wrong position). Any ideas? – Sunny Pun Jun 28 '18 at 4:53
2

Check out the Pull Request into the neovim editor:

[RFC] Add an option to use numbered registers for smaller deletions #8169

I've tried to add the smalldel option, which allows you to configure the minimum number of deleted characters to be pushed into the numbered registers "1.."9

The next neovim release after this PR is merged (if this happens) will contain this option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.