Reputation: 81
As my experience with vim is quite limited I'm having difficulties writing a regex and editing my vimrc. I have this function call which would be very long:
dothis(123, [1, 2], [2, [7,8]], 'text (), []', [], fn([123], 'abc, def', [[], [123]]));
I often need to change to following, or vice versa.
dothis(
123,
[1, 2],
[2, [7,8]],
'text (), []',
[],
fn([123], 'abc, def', [[], [123]])
);
Would I be able to do this with :%s/search/replace/
syntax?
Or should this be a ToggleFnCall function in my vimrc to be called as :call ToggleFnCall()
?
Or should this better be as a recorded macro rather than regex?
Does everyone write their efficiency scripts from scratch? Or is there something that I don't know that almost every vim users extend on?
Upvotes: 0
Views: 261
Reputation: 196546
I don't think the time needed to come up with the right substitution/macro is worth it.
Without an external formatter, here's how I would deal with this task:
place the cursor on the first parenthese,
f(
put the content of the parentheses on its own line,
ci(
<CR>
<C-r>"
<CR>
<Esc>
k
change some comma+space into comma+cr with an interactive substitution,
:.,/);/s/, /,\r/gc<CR>
and then format the whole thing properly,
:'{,'}norm ==<CR>
You could put all of that in a dedicated function:
function! Foo()
normal! 0f(
" ^M is obtained with <C-v><CR> and ^R with <C-v><C-r>
normal! ci(^M^R"^M
normal! k
.,/);/s/, /,\r/gc
'{,'}normal! ==
endfunction
and assign a mapping to it:
nnoremap <key> :call Foo()<CR>
To revert to the one-line version, select the block and press J
.
As for your last question, a seasoned vimmer never looks for the one and only silver bullet that will fit every possible scenario. Instead, he/she builds small, specialized, solutions from a vast array of smaller parts made available by Vim. Some ad-hoc solutions can easily and quikly become generic and reusable like the one above.
I recommend this short and awesome screencast by Gary Bernhardt that demonstrates how to turn a repetitive task into a specialized macro first, then into a generic mapping.
I followed the same method for this answer.
Upvotes: 0
Reputation: 198324
It's hardly nice, and I don't promise it won't break, or that it will work in all cases ("not well tested" is an understatement; and I am not nowhere near a VimL expert), but this might work:
function! SplayFnCall()
let magic = &magic
set magic
exe "normal _f(vi(\<Esc>a\<CR>\<Esc>gvo\<Esc>i\<CR>\<Esc>"
while 1
norm "zyl
if (@z =~ "[a-zA-Z0-9_]")
exe "norm /[^a-zA-Z0-9_ ]\<CR>\"zyl``"
endif
if (@z == "[" || @z == "(" || @z == "{" || @z == "'" || @z == '"')
exe "norm va".@z."\<Esc>"
endif
norm f,
norm "zyl
if (@z == ",")
exe "norm a\<CR>\<Esc>_"
else
let &magic = magic
return
endif
endwhile
endfunction
nmap <leader>fs :call SplayFnCall()<CR>
nmap <leader>fu va(J%l"_x
Try not to be inside sub-parentheses, and hit \fs
to splay, and \fu
to unsplay (unless you redefined your leader, then adjust accordingly). Obviously, you can change the mapping.
As Ingo says, it is impossible to write this as regexp (because of nested delimiters), and it is impossible to do it in a simple macro (because of the branching logic). You really need the full power of a programming language.
Also, I didn't do it as a toggle because I wasn't too sure what would be the criterion for when you want to splay, and when to unsplay, so two different mappings.
Upvotes: 1
Reputation: 172540
Matching (nested) parentheses requires regular expression extensions that Vim doesn't have, see match parenthesised block using regular expressions in vim.
Instead, you'd better rely on the built-in %
command to go to the matching parenthesis. Also, the argtextobj.vim - Text-object like motion for arguments (my improved fork here) works pretty well on your example.
With that, I would write a function (as the logic to proceed to the next argument, and checks where to stop will be rather complex) that is then invoked by a mapping. But if you're new to Vimscript, be aware that isn't trivial, and you may be better off to just use the mentioned plugin to speed up your manual reformatting. (On the other hand, if you manage to turn this into a plugin and post it on vim.org, it would certainly be well received by other Vim users.)
Upvotes: 0