5

我正在尝试以下列方式使用 fzf,我希望能够在我的代码库中搜索一个术语,然后通过预览窗口能够在其中看到包含我正在搜索的字符串的文件找到字符串

到目前为止,我已经设法通过管道对目录和下面的所有文件进行 ripgrep 搜索,在代码库中模糊搜索各种术语。我已经使用 cut 来解析 cat 或 tail 的文件名以读取并打印到预览窗口。这是用于此的命令。

rg . -n | fzf --preview-"cut -d":" -f1 <<< {} | xargs cat"

注意 {} 表示的字符串格式如下:

myfile.c:72:The string I am fuzzy searching

我的问题是我无法同时解析文件名行号。

我尝试在预览命令中传递 bashscript 以及在以下示例中使用 $()。(注意这里我使用 tail 和--lines+N参数在第 N 行之后打印文件)

rg . -n | fzf --preview-"tail $(cut -d":" -f1 <<< {}) --lines=+$(cut -d":" -f2 <<< {})"

这不起作用,也没有这种尝试的各种变体。任何帮助或反馈表示赞赏。

编辑(1):

我试图将它拆分成这样的数组

rg . -n | fzf --preview="IFS=":" read -r -a arr <<< {}| xargs tail ${arr[0]} --lines=+${arr[1]}"

这样做的原因是预览确实在找到字符串的行显示了文件,但是当我循环浏览其他模糊找到的建议时它不会更新。

4

1 回答 1

7

所以我最终想出了一个可行的解决方案。

它涉及从我在 --preview 中运行的子进程调用一个单独的脚本。我使用以下脚本获取 fzf 传递给 --preview 的字符串(格式为 filename:linenumber:found_string),然后使用bat呈现带有语法突出显示的预览窗口。

这种方法非常好,但有点耗费资源。我希望通过添加到忽略 glob 并使用 ripgrep 而不是 find 来减轻负载,因为它似乎更有效。

我称之为 string2arg.sh 的 bashscript

#!/bin/bash

string2arg() {
    export arg_filename=$(cut -d":" -f1 <<< $1);
    export arg_linenum=$(cut -d":" -f2 <<< $1);
    min_offset=25
    let max_offset="min_offset*3"
    min=0
    if (($min_offset < $arg_linenum)); then
        let min="arg_linenum-$min_offset"
    fi
    let max="arg_linenum+$max_offset"
    bat --color=always --highlight-line $arg_linenum --style=header,grid,numbers --line-range $min:$max $arg_filename;
}

然后从我的 fzf 别名中调用它来进行搜索:

alias fsearch='rg . -n -g "!*.html" | fzf --preview="source $SC/string2arg.sh; string2arg {}"'

其中 $SC 是我的 bashscript string2arg.sh 的路径。

如果我正在搜索一个术语以打开它在其找到的行中找到的文件,我使用以下 bash 别名。

alias vfsearch='export vfile=$(fsearch);vim +$(cut -d":" -f2 <<< $vfile) $(cut -d":" -f1 <<< $vfile)'

此外,我碰巧为 fzf 使用了以下默认值,并发现它们对我有用,尽管自从我搬到 tmux 后,我发现有时在上方而不是侧面显示预览窗口会更好。

export FZF_DEFAULT_COMMAND="fd --type file --color=always"
export FZF_DEFAULT_OPTS="--reverse --inline-info --ansi"
export FZF_COMPLETION_TRIGGER=']]'

我发现这非常有用,并计划将它移到我的 vim 会话中。希望它可以帮助别人!

屏幕截图以更好地说明用例。

在此处输入图像描述

于 2019-03-21T18:00:17.900 回答