从外部命令传递行号以运行宏

时间:2015-11-13 14:08:02

标签: vim

我已经看到了几个关于将Vim中的行号传递给外部命令的问题,但我想做相反的事情。我想通过jshint运行一个文件,然后根据jshint输出对每个行号应用更正。

例如,我正在尝试在缺少一行的每一行上附加分号。现在我正在炮轰jshint并解析输出,但我不知道如何使用它来在多行上运行宏。

我目前的想法是:

  • 调用jshint并解析“Missing decmicon”错误的行号
  • 遍历行号
  • 对于每个行号,请运行G<LINE_NUMBER>A;

这是我到目前为止解析jshint输出的内容:

:r ! jshint % | grep 'Missing semicolon' | awk '{ print $3 }' | sed 's/,//'

我是否可以方便地在Vim中执行xargs之类的操作,或者将外部命令的输出解析为可以循环的数组?

1 个答案:

答案 0 :(得分:2)

嗯,让我们看看。您可以尝试使用errorformat

let lines = split(system('jshint --verbose ' . shellescape(expand('%', 1))), "\n", 1)
let &errorformat = '%f: line %l\, col %v\, %m'
cgetexpr lines
for line in uniq(sort(map(filter(getqflist(), 'v:val["valid"] && v:val["text"] =~# "\\m^Missing semicolon"'), 'v:val["lnum"]')))
    execute line . 's/$/;/'
endfor

不是我所谓的“方便”,但我知道什么。

然后你可能会发现丢失的分号可能并不总是在行尾。所以你要修改这样的代码:

function! Cmp(a, b)
    return a:a[0] == a:b[0] ? a:b[1] - a:a[1] : a:b[0] - a:a[0]
endfunction

let lines = split(system('jshint --verbose ' . shellescape(expand('%', 1))), "\n", 1)
let &errorformat = '%f: line %l\, col %v\, %m'
cgetexpr lines
for p in uniq(sort(map(filter(getqflist(), 'v:val["valid"] && v:val["text"] =~# "\\m^Missing semicolon"'),
        \ '[str2nr(v:val["lnum"]), str2nr(v:val["col"])]'), 'Cmp'))
    let line = getline(p[0])
    call setline(p[0], line[ : p[1]-2] . ';' . line[p[1]-1 :])
endfor

然后你可能会发现这不处理标签的情况。这是一个问题,因为默认情况下JSHint的选项卡的概念是tab stop = 4,而Vim是tab stop = 8.然后你...可以修复它作为练习,或者你可能会理解并使用真正的JavaScript解析器修复这个而不是Vim。 :)