使 vim 命令作用于视觉选择或整个缓冲区

Make a vim command act on a visual selection OR the whole buffer

我有这个 vim function/command 格式 json

function! JSON()
  %!python -m json.tool
  setlocal ft=json
endfunction

command! Json call JSON()

我想将其改进为:

我怀疑我必须在 command! 上使用 -range 标志,但无法弄清楚如何调整函数以仅替换当前选择。
也无法弄清楚如何根据是否给定范围使其表现不同。

主要是合并:help command-range:help function-range的问题。

首先,让我们通过删除 &filetype 逻辑来稍微简化问题:

function! JSON()
    %!python -m json.tool
endfunction
command! Json call JSON()

现在,让我们使用 -range=% 以便命令默认在给定范围或整个缓冲区上运行:

function! JSON()
    %!python -m json.tool
endfunction
command! -range=% Json call JSON()

然后,让我们调用给定范围的函数:

function! JSON()
    %!python -m json.tool
endfunction
command! -range=% Json <line1>,<line2>call JSON()

修改它,让它知道如何处理一个范围:

function! JSON() range
    %!python -m json.tool
endfunction
command! -range=% Json <line1>,<line2>call JSON()

最后,使用函数内的范围:

function! JSON() range
    execute a:firstline . ',' . a:lastline . '!python -m json.tool'
endfunction
command! -range=% Json <line1>,<line2>call JSON()

最后一部分,我们来看看&filetype逻辑。了解函数是否对整个缓冲区进行操作的唯一方法是将 a:firstlinea:lastline 与缓冲区的第一行和最后一行进行比较。我们必须在使用格式化程序之前这样做,因为它的输出可能有与给定范围不同的行数。

function! JSON() range
    if a:firstline == 1 && a:lastline == line('$')
        setlocal filetype=json
    endif
    execute a:firstline . ',' . a:lastline . '!python -m json.tool'
endfunction
command! -range=% Json <line1>,<line2>call JSON()

我们完成了。