0

在这个 bash 教程视频链接的末尾,Spencer Krum 展示了一个巧妙的技巧:如何在 vim 中打开一个文件,该文件位于紧接在前面的 'git grep -n' 搜索字符串所在的行号处。看起来很整洁,但他的代码在我尝试过的两个不同的 linux 机器上并不像描述的那样工作。它总是打开一个空白文件。 原代码在这里

我的步骤:

首先,我确保已初始化 git 并在 grep 目录中设置文件。例如,我有一个包含三行单词的 somefile.txt:

  • 它的
  • 一种
  • 神秘

然后我跑了:git init;git add .; git commit

然后,修改您的 .bashrc 文件以重新定义 vim,如下所示。确保在完成后获取 .bashrc 文件: source ~/.bashrc

最后,运行 git grep -n 命令,并使用您知道在 git 目录中的文件中的搜索词,该文件是您当前的工作目录。最后,运行 vim。它应该打开您的文件,光标位于搜索词行。但它没有:git grep -n mystery;vim

#Spencers Original
vim () {
    last_command=$(history | tail -n 2 | head -n 1)
    if [[ $last_command =~ 'git grep' ]] && [[ "$*" =~ :[0-9]+:$ ]]; then
        line_number=$(echo $* | awk -F: '{print $(NF-1)}')
        /usr/bin/vim +${line_number} ${*%:${line_number}:}
    else
        /usr/bin/vim "$@"
    fi
}

为了得到想要的结果,我必须在第一个 if 语句的第二个子句中简化正则表达式,并创建一些临时变量来运行额外的 eval 逻辑。

以下是我修改后的代码:

#My revised version
vim () { 
    last_command=$(history | tail -n 2 | head -n 1)

    rempws="${last_command#*"  "}"
    remtws="${rempws%*" "}"

    file_name="$(eval $remtws | awk -F: '{print $(NF-2)}')"
    line_number="$(eval $remtws | awk -F: '{print $(NF-1)}')"

    if [[ $last_command =~ 'git grep' ]] && [[ $line_number =~ [0-9] ]]
    then
        /usr/bin/vim +${line_number} ${file_name}
    else
        /usr/bin/vim "$@"
    fi
}

这与 2015 年以来的 bash 更新有关吗?我认为它与 git 无关,因为我的 git grep -n 命令确实返回了一个格式为“somefile.txt:3:mystery”的字符串。观众中的每个人都喜欢它,它仍然在 github 上以非功能形式存在,所以我担心我错过了一些关于 bash 的基本知识。

告诉我为什么我很笨。

4

1 回答 1

1

好吧,我终于明白这是怎么回事了。

他的代码从来没有真正打算以某种方式访问git grep​​命令的输出。

取而代之的是,您意识到在 a 之后git grep您可能想要打开其中一个结果。

但是,在他的工作流程中,他仍然依赖于将git grep结果复制并粘贴到 Vim 命令行中。

唯一的区别是,在 a 之后git grep,您可以传递给 Vim 一个文件名,其中行号由 by 分隔,:而不必传递两个单独的参数。

在他的示例中,结果git grep开始于:

CHANGELOG.rst:75: ...

因此,如果在下一个命令中执行:

$ vim CHANGELOG.rst:75:

(假设您从结果中复制了最后一部分git grep。)

然后 bash 函数将触发此命令:

$ vim +75 CHANGELOG.rst

这将在第 75 行打开此文件。

如果你喜欢这个特性的想法,一个更简洁的实现方法是安装和启用bogado/file-line Vim 插件,它实现了对 Vim 本身中那种文件名 + 行号参数的支持。

(此外,确实没有充分的理由识别.file:line之后的语法git grep。如果你想要这种行为,最好总是得到它,而不仅仅是有时。它应该是一致的。)

一个更好的选择是使用 Vim 的quickfix功能,它就是为这种情况而设计的。您可以'grepprg'手动设置,git grep使用适当的参数调用,也可以采用插件,例如vim-fugitive,它实现了一个命令,该命令使用 quickfix 列表:Ggrep调用和显示结果。git grep

正如@romainl 所指出的,您可能还想查看git jumpgit 命令,您可以在系统上启用它以让 git 找到有趣的位置(例如git grepgit diff输出)并让 git 本身在 Vim 中打开这些结果(使用适当时的快速修复列表。)

于 2020-12-24T04:21:50.483 回答