在 Zsh/Bash 中使用 Netrw 或 Nerdtree 通过浏览选择文件?

在 Zsh/Bash 中使用 Netrw 或 Nerdtree 通过浏览选择文件?

我经常发现自己在 shell 中,想要将文件名插入到冗长的命令中。

我想走捷径,使用 Netrw 或 Nerdtree 来浏览对于文件或目录,并将其粘贴到我正在构建的命令中。

因此,如果我在一个文件夹中,并且想要比较 2 个文件:

  • 我会输入diff

  • 然后我想点击快捷方式,使用 Netrw 或 Nerdtree 进行可视化浏览,然后选择一个文件。

  • 该文件名现在已添加到我的 diff 命令中...例如diff /tmp/file1.txt

  • 我再次点击快捷方式,浏览第二个文件, /super/ez/another/file/somewhere/else/compare.txt

  • 然后将第二个文件添加到我的diff命令中,所以我现在有:

      diff /tmp/file1.txt /super/ez/another/file/somewhere/else/compare.txt
    

这可以使用吗任何工具?我喜欢 Vim 中的 Netrw,但愿意尝试新事物!

Tab请注意,我对使用通配符完成文件名不感兴趣。这有时有效,但并非总是有效。我喜欢 Netrw,并且很想弄清楚如何使用它通过浏览来选择文件名。

答案1

Zsh 允许您将 shell 函数绑定到一个键,并且还有一个内置函数可以将文本放入命令行中。所以你可以做这样的事情(在 zsh 中):

# define a function that does the work
function my_browser_function () {
  local result
  result=$( some command that returns the filename )
  # print -z $result (see comments)
  LBUFFER+=$result
}
# turn the function into a widget
zle -N my_browser_function
# bind it to some key ("CTRL-X I" for example)
bindkey '\Cxi' my_browser_function

现在您只需要让一个命令起作用,它可以让您以您想要的方式浏览文件系统并将结果打印在标准输出上。

编辑:这是使用 vim 的上述函数的一个非常基本的版本:

function my_browser_function () {
  local file=$(mktemp)
  vim -c "map <C-A> :cal system('echo '.expand('%').'/'.getline('.').'>$file')<bar>q<cr>" .
  LBUFFER+=$(<$file)
  rm $file
}

您可以像往常一样在 vim/netrw 中导航,然后使用 <CA> (Ctrl-A) 来A接受文件/目录名称。

显然这只是一个非常基本的功能。如果您想要更多功能,您还可以编写一个 vim 自动加载函数,并使用 -c 从 vim 命令行调用该函数。

答案2

2022年版答案

Vifm v0.8 或更高版本提供了一种通过选项实现此功能的更好方法 --choose-files,这使得它独立于配置目录的位置。

zsh版本

function insert_files() {
    local file
    while read file; do
        LBUFFER+="$(printf %q "$file") "
    done <<< "$(vifm --choose-files - < /dev/tty)"

    zle reset-prompt
}
zle -N insert_files
bindkey '^t' insert_files

bash版本

function _insert_files() {
    local file
    local files
    while read -r file; do
        files="$files$(printf %q "$file") "
    done <<< "$(vifm --choose-files - < /dev/tty)"

    local prefix=${READLINE_LINE::READLINE_POINT}
    local suffix=${READLINE_LINE:READLINE_POINT}
    READLINE_LINE=${prefix}${files}${suffix}
    READLINE_POINT=$(( READLINE_POINT + ${#files} ))
}
bind -x '"\C-T": _insert_files'

原始答案(2014)

你基本上已经知道答案了这里。将所有这些放在一起非常容易,如下所示:

function insert_files() {
    vifm -f < /dev/tty > /dev/tty

    while read l; do
        LBUFFER+="'$l' "
    done < ~/.vifm/vimfiles

    zle reset-prompt
}
zle -N insert_files
bindkey '^t' insert_files

我不是 zsh 用户,所以我从 Lucas 的回答中窃取了代码结构。至于bash,我曾经寻找一种在快捷方式内处理外部命令输出的方法,但没有找到。

示范

PS 我的代码包含相当原始的转义,您可能想要改进它,并且可能更改参数之间添加间距的方式。

相关内容