fzf 里设了选项却不生效?它其实被拼了三次,后写的赢
fzf 是命令行里的模糊查找工具,装了之后 Ctrl+R 搜历史、Ctrl+T 找文件都很顺手。我想把它的界面改成上下布局、加个边框,网上的做法是在环境变量里设:
export FZF_DEFAULT_OPTS="--height=40% --layout=reverse --info=inline --border --margin=1 --padding=1"
设完直接敲 fzf 是生效的。但按 Ctrl+R 搜历史命令,界面还是老样子,我设的那些参数一个都没出现。
根因:选项不是「一份」,是三层拼出来的
翻 fzf 的 shell 集成脚本,里面有个函数负责拼参数:
__fzf_defaults() {
# $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
# $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
builtin printf '%s\n' "--height ${FZF_TMUX_HEIGHT:-40%} --min-height 20+ --bind=ctrl-z:ignore $1"
command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
builtin printf '%s\n' "${FZF_DEFAULT_OPTS-} $2"
}
看这三行 printf/cat 的顺序,就能还原出优先级从低到高的拼接链:
① --height ${FZF_TMUX_HEIGHT:-40%} --min-height 20+ --bind=ctrl-z:ignore 加上 prepend 参数
② $FZF_DEFAULT_OPTS_FILE 文件内容
③ $FZF_DEFAULT_OPTS 环境变量 加上 append 参数
后出现的位置更高,同名的选项会被后面的覆盖。 这就解释了我的现象:Ctrl+R 那条绑定自己带了一串 append 参数,正好把我设的 --layout 之类盖掉了。
第一层坑:FZF_DEFAULT_OPTS_FILE 排在环境变量前面
新版加了一个 FZF_DEFAULT_OPTS_FILE,用途是把参数写进文件(方便版本管理)。注意它在链里排在第 ② 位,比环境变量早。
所以如果你把参数写进文件、又在 .bashrc 里设了环境变量,环境变量会赢。反过来,有人先设环境变量、后来加了文件,发现文件里的不生效——因为它被环境变量盖了。
两个都设了还查不出原因时,先确认自己用的是哪一条。
第二层坑:快捷键绑定会在最后追加参数
Ctrl+T(找文件)、Alt+C(切目录)、Ctrl+R(搜历史)这几个快捷键,各自有不同的追加参数。比如 fish 的绑定里是这样的:
--bind=alt-r:toggle-raw --multi --wrap=word --reverse
这些是最后追加的,优先级最高。--reverse 在这里出现,意味着你就算在环境变量里写了别的布局,走这个快捷键时也会被改回 reverse。
所以「直接敲 fzf 好用、按快捷键不好用」是正常现象,不是配置写错了。它们走的不是同一条参数链。
怎么查「实际生效的参数」
fzf 没有 --print-opts 这类命令,但有两个办法能看到真相。
办法一:打开 shell 的调试输出,看绑定到底传了什么。
# bash
set -x
# 然后按 Ctrl+R,屏幕上会打出完整的 fzf 调用和它的全部参数
set +x
办法二:直接调那个拼接函数,把结果打印出来。 以 bash 为例,先 source key-bindings,再调它:
source /usr/share/fzf/shell/key-bindings.bash
__fzf_defaults "" "" # 打印基础链
__fzf_defaults "" "--multi" # 看追加了 --multi 之后的样子
输出的就是最终传给 fzf 的那串参数。判据很直接:你写的选项如果出现在输出里、且没有更靠后的同名选项,它才真的生效。
三个实用结论
一、想改布局这类会被快捷键覆盖的选项,别只改环境变量。 要么改 key-bindings 脚本里的 append 部分,要么在绑定命令后面手动追加你的参数。
二、不确定有没有生效时,用 set -x 看一眼。 比反复改配置、反复试快得多。我一开始是猜着改了三轮,全错。
三、别把 FZF_DEFAULT_OPTS_FILE 和环境变量混着用。 只留一处,否则下次忘了哪个在生效,又要重查一遍。
最后
这类工具的通病是:配置写了没生效,它不会报错,只是安静地用别的值。 你以为是缓存、是没 reload、是版本问题,其实是被更高优先级的东西盖住了。
遇到「配置不生效」,先找它的合并顺序,再确认自己写的那一层排第几。这一步问对了,后面的排查会快很多。
- 点赞
- 收藏
- 关注作者
评论(0)