0

I want to replace all Box::new(x) with x, e.g. Box::new(A(B()) + C()) becomes A(B()) + C().

Does neovim (0.8.1) support that?

I expect that there must be some feature for such a likely developer-demanded operation. But I know that regexes typically don't support matching arbitrarily-deep nested brackets. However VIM regexes often deviate from normal regexes, and there might even be a special function for this. I just don't know about it.

1
  • What did you try?
    – romainl
    Commented Nov 28, 2022 at 6:08

1 Answer 1

1

The following function works for the first occurrence of Box::new on the current line:

function DeleteBox() abort
  let [match, start, _end] = getline('.')->matchstrpos('Box::new')
  if empty(match) | return | endif
  call setcharpos('.', [0, line('.'), start+1, 0])
  execute "normal! %x\<C-o>df("
endfunction

You can map dsx to perform the action:

nnoremap dsx <cmd>call DeleteBox()<cr>

Or run it on every line:

:global/Box::new/call DeleteBox()
" or
:global/Box::new/normal dsx

If you have multiple Box::new per line, repeat the :global command with @: until it errors (using a high count like 99@: is usually sufficient).

With some tweaks, you could try to make it work anywhere in the current Box::new expression, but that will be more difficult. Assuming you multiple Box::new per line almost never occurs, this should be sufficient.

If you don't care for positioning so much, the following will delete just about any parenthesized wrapper starting from the cursor position:

nnoremap dsX %x<C-o>df(

Tweaks for {} and [] are of course possible.

This differs from https://github.com/tpope/vim-surround in that it deletes text, too; but with vim-surround I prefer to /Box::new<cr>dgndsb or similar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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