fzf 中的预览窗口是一个强大的功能,它允许您在不实际选择项目的情况下检查所选项目的内容。本文档将介绍如何配置和使用预览窗口,包括其外观、位置、大小和交互功能。有关自定义预览窗口颜色的信息,请参阅 颜色和主题。有关预览窗口导航相关按键绑定的详细信息,请参阅 按键绑定自定义。
预览窗口显示的是使用 --preview 选项指定的命令的输出。该命令针对当前高亮的搜索结果项执行,使您可以在选择项目之前查看其附加信息。
预览窗口系统架构
来源:src/terminal.go363-365 src/terminal.go139-148
最基本的预览功能可以通过 --preview 选项启用,该选项指定了用于生成预览内容的要执行的命令。
fzf --preview 'cat {}'
占位符 {} 会被当前行(或与字段索引表达式一起使用时,会被特定字段)替换。
预览窗口的外观和行为可以通过 --preview-window 选项进行自定义,该选项接受一个由逗号分隔的规范列表。
预览窗口配置选项
预览窗口可以放置在主窗口的任何一侧。
--preview-window up:预览窗口位于搜索结果上方。--preview-window down:预览窗口位于搜索结果下方(默认)。--preview-window left:预览窗口位于搜索结果左侧。--preview-window right:预览窗口位于搜索结果右侧。大小可以指定为终端的百分比或绝对数值。
fzf --preview 'cat {}' --preview-window right:50%
fzf --preview 'cat {}' --preview-window up:10
您可以自定义预览窗口的边框。
fzf --preview 'cat {}' --preview-window border-rounded
fzf --preview 'cat {}' --preview-window border-sharp
fzf --preview 'cat {}' --preview-window border-bold
fzf --preview 'cat {}' --preview-window border-double
fzf --preview 'cat {}' --preview-window border-block
fzf --preview 'cat {}' --preview-window border-thinblock
fzf --preview 'cat {}' --preview-window border-horizontal
fzf --preview 'cat {}' --preview-window border-top
fzf --preview 'cat {}' --preview-window border-bottom
fzf --preview 'cat {}' --preview-window border-left
fzf --preview 'cat {}' --preview-window border-right
fzf --preview 'cat {}' --preview-window border-none
您也可以使用简写 --preview-border 选项。
fzf --preview 'cat {}' --preview-border=rounded
您可以为预览窗口边框添加一个标签。
fzf --preview 'cat {}' --preview-label='File Content'
标签的位置可以自定义。
fzf --preview 'cat {}' --preview-label='File Content' --preview-label-pos=center
fzf --preview 'cat {}' --preview-label='File Content' --preview-label-pos=3
fzf --preview 'cat {}' --preview-label='File Content' --preview-label-pos=-3:bottom
预览命令可以使用各种占位符表达式。
| 占位符 | 描述 |
|---|---|
{} | 当前行 |
{n} | 当前行的第 n 个字段 |
{n..m} | 当前行的第 n 个到第 m 个字段 |
{..m} | 当前行的第一个到第 m 个字段 |
{n..} | 当前行的第 n 个到最后一个字段 |
{q} | 当前查询字符串 |
{q:n} | 查询字符串的第 n 个字段 |
{+} | 所有选中的项目(与 --multi 一起使用) |
{+n} | 选中项目的第 n 个字段 |
占位符表达式可以包含标志。
| 标志 | 描述 |
|---|---|
+ | 用于多选 |
s | 保留空格 |
f | 替换为临时文件路径 |
32位指针 | 原始(未加引号) |
示例
fzf --multi --preview 'head -10 {+f}'
预览窗口功能是 fzf 中 Terminal 结构的一部分。该系统包括管理预览选项、渲染预览窗口以及处理预览内容用户交互的组件。
预览窗口核心数据结构
来源:src/terminal.go139-159 src/terminal.go229-397
fzf 提供了几个与预览窗口交互的操作。
| 操作 | 描述 |
|---|---|
preview(CMD) | 执行给定的命令并在预览窗口中显示结果。 |
refresh-preview | 刷新预览窗口。 |
toggle-preview | 切换预览窗口的可见性。 |
toggle-preview-wrap | 切换预览窗口中的文本换行。 |
preview-up | 向上滚动预览。 |
preview-down | 向下滚动预览。 |
preview-page-up | 向上翻页滚动预览。 |
preview-page-down | 向下翻页滚动预览。 |
preview-half-page-up | 向上滚动预览半页。 |
preview-half-page-down | 向下滚动预览半页。 |
preview-top | 滚动到预览的顶部。 |
preview-bottom | 滚动到预览的底部。 |
show-preview | 如果预览窗口被隐藏,则显示它。 |
hide-preview | 隐藏预览窗口。 |
这些操作可以使用 --bind 选项绑定到按键。
fzf --preview 'cat {}' --bind 'ctrl-/:toggle-preview'
默认情况下,shift-up 和 shift-down 分别绑定到 preview-up 和 preview-down。
来源:man/man1/fzf.11671-1679 src/terminal.go727-730
在执行预览命令时,fzf 会设置几个环境变量,预览命令可以使用这些环境变量来适当地格式化其输出。
| 可变 | 描述 |
|---|---|
FZF_PREVIEW_LINES | 预览窗口中的行数。 |
FZF_PREVIEW_COLUMNS | 预览窗口中的列数。 |
FZF_PREVIEW_TOP | 预览窗口的顶部位置。 |
FZF_PREVIEW_LEFT | 预览窗口的左侧位置。 |
LINES | 与 FZF_PREVIEW_LINES 相同(仅为预览命令设置)。 |
COLUMNS | 与 FZF_PREVIEW_COLUMNS 相同(仅为预览命令设置)。 |
此外,fzf 还导出了通用的环境变量,这些环境变量也可供预览命令使用。
| 可变 | 描述 |
|---|---|
FZF_QUERY | 当前查询字符串。 |
FZF_PROMPT | 当前提示符字符串。 |
FZF_PREVIEW_LABEL | 预览窗口标签。 |
FZF_BORDER_LABEL | 边框标签。 |
FZF_TOTAL_COUNT | 项目总数。 |
FZF_MATCH_COUNT | 匹配的项目数。 |
FZF_SELECT_COUNT | 选中项目的数量。 |
FZF_POS | 列表中光标的位置。 |
使用示例
fzf --preview 'echo "Window size: $FZF_PREVIEW_COLUMNS x $FZF_PREVIEW_LINES"'
环境变量是在 environForPreview() 方法中设置的,该方法使用预览特定的环境变量来扩展通用环境变量。
来源:man/man1/fzf.1754-762 src/terminal.go1078-1138 src/terminal.go1091-1117
您可以根据尺寸阈值指定预览窗口的备用布局。这是通过 previewOpts 结构体中的 threshold 和 alternative 字段实现的。
fzf --preview 'cat {}' --preview-window 'right,border-left,<50(up,30%,border-bottom)'
在此示例中,如果预览窗口的宽度小于 50 列,它将切换到预览显示在搜索结果上方、高度为 30%、带有一个底部边框的布局。
该实现会在窗口调整大小时检查阈值。
您也可以在达到阈值时完全隐藏预览窗口。
fzf --preview 'cat {}' --preview-window '<50(hidden)'
阈值检查在 resizePreviewWindows() 方法中执行,如果满足阈值条件,该方法会递归调用自身并使用备用布局。
来源:man/man1/fzf.1958-966 src/terminal.go1971-1989
您可以设置预览窗口的初始滚动位置。
fzf --preview 'cat {}' --preview-window '+5' # Scroll to line 5
fzf --preview 'cat {}' --preview-window '+{2}' # Scroll to line from the 2nd field
fzf --preview 'cat {}' --preview-window '+{2}-5' # 5 lines before the line from the 2nd field
fzf --preview 'cat {}' --preview-window '+{2}+3/2' # Put the target line in the middle with 3-line offset
您可以将特定行数固定在预览窗口的顶部。
fzf --preview 'cat {}' --preview-window '~3'
这会将预览内容的前 3 行固定,而其余内容可以滚动。
预览窗口可以自动滚动以跟随新内容,类似于 tail -f 的行为。这是通过 previewer 结构体中的 following 字段实现的,该字段是一个 resumableState 类型,可以处于三种状态之一:disabledState、pausedState 或 enabledState。
fzf --preview 'tail -f /var/log/system.log' --preview-window follow
跟随行为的工作方式如下:
follow 时,following 状态被设置为 enabledState。pausedState)。enabledState)。resumableState 类型具有控制此行为的方法。
Enabled():检查跟随功能当前是否已启用。Force(flag bool):强制将状态设置为启用或禁用。Set(flag bool):在未禁用时设置状态。这使得与预览窗口中的流式内容进行直观的交互成为可能。
来源: man/man1/fzf.1890-902 src/terminal.go98-128 src/terminal.go146
fzf 支持通过各种终端图形协议在预览窗口中显示图像,目前处于实验阶段。这是通过对特定终端转义序列进行特殊传递处理来实现的。
| 协议 | 支持 |
|---|---|
| Kitty 图形协议 | 通过以 \x1b_G 开头的转义序列支持。 |
| Sixel 图形 | 通过以 \x1bP 开头的转义序列支持。 |
| iTerm2 内联图像协议 | 通过以 \x1b]1337; 开头的转义序列支持。 |
该实现使用正则表达式来识别这些特殊序列,并将它们直接传递给终端,而不进行任何处理。
passThroughBeginRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b|\x1b(_G|P[0-9;]*q)|\x1b]1337;`)
passThroughEndTmuxRegex = regexp.MustCompile(`[^\x1b]\x1b\\`)
使用辅助脚本的示例
fzf --preview='fzf-preview.sh {}'
当在预览内容中检测到图像时,previewed.image 标志将被设置为 true,这会影响预览窗口的渲染方式。
来源: man/man1/fzf.1819-825 src/terminal.go74-87 src/terminal.go152-159
以下图表说明了预览窗口内容是如何渲染的。
预览窗口渲染过程
来源: src/terminal.go658 src/terminal.go139-159 src/terminal.go444-446
预览窗口是通过几个内部结构和方法实现的。
previewOpts 结构体:存储预览窗口的配置选项。previewer 结构体:管理预览的内容和状态。previewed 结构体:跟踪预览显示的当前状态。previewRequest 结构体:封装了生成预览内容请求。previewResult 结构体:包含预览命令执行的结果。fzf 通过其事件系统处理预览窗口的调整大小和内容更新,事件包括 reqPreviewReady、reqPreviewEnqueue、reqPreviewDisplay 和 reqPreviewRefresh。
来源: src/terminal.go139-159 src/terminal.go645-658 src/terminal.go444-446