高效的vim正则表达式切换多行函数调用

时间:2014-10-22 06:27:37

标签: regex vim

由于我对vim的体验非常有限,我在编写正则表达式和编辑我的vimrc时遇到了困难。 我有这个函数调用很长:

dothis(123, [1, 2], [2, [7,8]], 'text (), []', [], fn([123], 'abc, def', [[], [123]]));

我经常需要改为跟随,反之亦然。

dothis(
    123,
    [1, 2],
    [2, [7,8]],
    'text (), []',
    [],
    fn([123], 'abc, def', [[], [123]])
);

我是否可以使用:%s/search/replace/语法执行此操作?

或者这应该是我的vimrc中的ToggleFnCall函数被调用为:call ToggleFnCall()

或者这应该更好地作为录制的宏而不是正则表达式?

每个人都从头开始编写效率脚本吗?或者有什么东西我不知道几乎每个vim用户都会延伸?

3 个答案:

答案 0 :(得分:1)

这并不好,而且我不保证它不会破坏,或者它会在所有情况下都有效(“未经过充分测试”是轻描淡写的;我并不是VimL专家附近),但是这个可能有用:

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

尽量不要在子括号内,并点击\fs以显示,\fu取消播放(除非您重新定义了您的领导者,然后进行相应调整)。显然,您可以更改映射。

正如Ingo所说,不可能把它写成regexp(因为嵌套分隔符),并且不可能在一个简单的宏中(因为分支逻辑)这样做。你真的需要编程语言的全部功能。

另外,我没有把它作为一个切换,因为我不太确定什么时候你想要显示什么,什么时候不显示,所以两个不同的映射。

答案 1 :(得分:0)

匹配(嵌套)括号需要Vim没有的正则表达式扩展,请参阅match parenthesised block using regular expressions in vim

相反,您最好依靠内置的%命令转到匹配的括号。此外,argtextobj.vim - Text-object like motion for argumentsmy improved fork here)在您的示例中运作良好。

有了这个,我会编写一个函数(作为继续下一个参数的逻辑,并检查停止的位置将相当复杂),然后由映射调用。但是,如果您是Vimscript的新手,请注意这并不重要,您可能最好只使用上述插件来加速手动重新格式化。 (另一方面,如果您设法将其转换为插件并将其发布在vim.org上,那么其他Vim用户肯定会很好地接受它。)

答案 2 :(得分:0)

我认为提出正确替换/宏所需的时间是值得的。

如果没有外部格式化程序,请按照以下方式处理此任务:

  1. 将光标放在第一个括号

    f(
    
  2. 将括号的内容放在自己的行上,

    ci(
    <CR>
    <C-r>"
    <CR>
    <Esc>
    k
    
  3. 使用交互式替换将某些逗号+空格更改为逗号+ cr,

    :.,/);/s/, /,\r/gc<CR>
    
  4. 然后正确地格式化整个事物,

    :'{,'}norm ==<CR>
    
  5. 你可以把所有这些都放在专用的功能中:

    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
    

    并为其指定映射:

    nnoremap <key> :call Foo()<CR>
    

    example


    要恢复为单行版本,请选择该块并按J


    关于你的最后一个问题,一个经验丰富的调光器永远不会寻找适合每种可能场景的独一无二的银弹。相反,他/她从Vim提供的大量小零件构建小型专业解决方案。一些临时解决方案可以像上面那样轻松快捷地变得通用和可重用。

    我建议this short and awesome screencast by Gary Bernhardt演示如何首先将重复性任务转换为专用宏,然后转换为通用映射。

    我按照相同的方法接受了这个答案。