![如何在 zsh 中使用 fzf 获得模糊 xdg-open?](https://linux22.com/image/194364/%E5%A6%82%E4%BD%95%E5%9C%A8%20zsh%20%E4%B8%AD%E4%BD%BF%E7%94%A8%20fzf%20%E8%8E%B7%E5%BE%97%E6%A8%A1%E7%B3%8A%20xdg-open%EF%BC%9F.png)
问题
我一直在尝试使用弗兹夫绑定快捷方式(最好是Ctrl+ o)以交互方式搜索文件并将其通过管道传输到xdg-open
zsh 中。许多快捷方式已经成为fzf
实用程序的一部分,只要您源文件位于fzf/shell/键绑定.zsh。在那里,您将找到用于绑定Ctrl+r模糊搜索命令历史记录和Ctrl+t模糊完成当前命令行的片段。这是 fzf 源代码中第一个快捷方式的样子:
# CTRL-R - Paste the selected command from history into the command line
fzf-history-widget() {
local selected num
setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2> /dev/null
selected=( $(fc -rl 1 | perl -ne 'print if !$seen{(/^\s*[0-9]+\**\s+(.*)/, $1)}++' |
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS --query=${(qqq)LBUFFER} +m" $(__fzfcmd)) )
local ret=$?
if [ -n "$selected" ]; then
num=$selected[1]
if [ -n "$num" ]; then
zle vi-fetch-history -n $num
fi
fi
zle reset-prompt
return $ret
}
zle -N fzf-history-widget
bindkey '^R' fzf-history-widget
当然,它的行为与我想要的行为有点不同,因为它将所选结果粘贴到命令行,而不是直接通过管道将其传递到命令。不过,下面的 bash 脚本恰恰具有我所期望的行为,并且运行它比我自己在解释它方面做得更好。
bind -x '"\C-o": file="$(fzf --height 40% --reverse)" && [ -f "$file" ] && xdg-open "$file"'
我也发现了这个鱼功能具有相同的行为,但 Fish 的语法与 zsh 和 bash 等 POSIX 兼容 shell 有很大不同,所以我不知道这有多大帮助。
那么,有谁知道将Ctrl+绑定o到交互式 fzf 搜索,并将其结果直接通过管道传输到xdg-open
zsh 中?
提前致谢!
答案
这是我根据以下内容编写的工作脚本这堆栈溢出答案。
fuzzy-xdg-open() {
local output
output=$(fzf --height 40% --reverse </dev/tty) && xdg-open ${(q-)output}
zle reset-prompt
}
zle -N fuzzy-xdg-open
bindkey '^o' fuzzy-xdg-open
答案1
在 中zsh
,您将按键或按键组合(使用bindkey
)绑定到小部件,在行编辑器中执行特殊操作的小部件。
您可以使用内置函数定义自定义小部件zle
。
在该自定义小部件中,您可以运行任意命令,但您可能还需要考虑如何处理数字参数。
例如,如果用户输入Alt+ 3 Ctrl+ ,您是否要按照大多数小部件的惯例运行该命令三次?o
您还需要考虑是否应该在运行命令后重新绘制行编辑器缓冲区(到目前为止输入的内容)或提示符,或者在运行命令之前将其隐藏起来,以防您运行的命令碰巧向终端写入内容。此外,命令的退出状态是否应该确定小部件是否成功(例如导致视觉或听觉通知)。
如果您在小部件中运行的工具需要从用户获取输入,您还需要在 ZLE 重定向时恢复 tty 上的标准输入,/dev/null
以防止它们扰乱行编辑器中的正常输入流。您需要确保您的命令使终端处于与它发现时相同的状态(这应该是 的情况fzf
)。
例如,这可能是:
my-open-widget() {
zle -I # invalidate current zle display
local file ret=0
repeat ${NUMERIC-1} {
file="$(fzf --height 40% --reverse)" &&
[ -f "$file" ] &&
xdg-open "$file" ||
ret=$?
} < /dev/tty
return $ret
}
zle -N my-open-widget
bindkey '^o' my-open-widget
要根据请求多次运行代码并在失败时返回失败,请预先使显示无效以确保该代码输出的内容(如果有)不会扰乱提示。
或者,您可能希望在一个实例失败时立即中止(替换|| ret=$?
为|| return
)。或者,如果您知道代码不会弄乱显示并且更一般地不会与 tty 交互,请跳过zle -I
.或者您可以忽略数字参数并无条件运行代码一次且仅一次,因此最终,它可以像将代码放入该小部件函数的主体中一样简单。
答案2
这种键绑定在原版中不能直接实现桀骜。但是,如果您安装插件zsh-edit
,然后您可以使用以下内容:
bind '^O' 'file="$(fzf --height 40% --reverse)" && [ -f "$file" ] && xdg-open "$file"'
答案3
#!/bin/bash
xdg-open "$(rg --no-messages --files ~/Music ~/Series ~/Films ~/Documents ~/pdf \
~/Dropbox/calibre2 ~/Downloads \
-g "!{*.srt,*.rar,*.txt,*.zip,*.nfo}" | rofi -threads 0 \
-theme-str "#window { width: 900;}" \
-dmenu -sort -sorting-method fzf -i -p "find")"
不完全相同,但我发现这个脚本组合 xdg-open + rofi 对于打开文件很有用。 (没有 zsh 依赖)。
来源:https://www.reddit.com/r/i3wm/comments/c17m5e/launcher_to_open_files_with_xdgopen_using_fzf/