Docfd
TUI多行模糊文档查找器
将其视为交互式文本文件、PDF、DOCX等的grep工具, 但基于单词/标记而非正则表达式和行, 因此您可以轻松地跨行搜索。
Docfd旨在通过与常用文本编辑器和PDF查看器的集成提供良好的用户体验, 让您可以通过单次按键直接跳转到搜索结果。
浏览存储库:
使用非交互模式快速搜索:
通过PDF查看器集成浏览PDF并打开到最接近所选搜索结果的位置:
功能特性
-
多线程索引和搜索
-
多个文件或单个文件的多行模糊搜索
-
随时切换多文件视图和单文件视图
-
内容视图窗格,显示所选搜索结果周围的片段
-
文本编辑器和PDF查看器集成
文本编辑器集成
Docfd使用由$VISUAL
(优先检查)或$EDITOR
指定的文本编辑器。
Docfd为以下编辑器打开文件到搜索结果的第一行:
nano
nvim
/vim
/vi
kak
hx
emacs
micro
jed
/xjed
PDF查看器集成
Docfd根据xdg-mime query default application/pdf
的输出猜测默认PDF查看器,
并根据在$XDG_DATA_DIRS
指定的目录列表中首次找到桌面文件的位置,
直接调用查看器或通过flatpak调用。
Docfd为以下查看器打开文件到搜索结果的第一页, 并在同一页内开始对匹配短语中最独特的单词进行文本搜索:
- okular
- evince
- xreader
- atril
Docfd为以下查看器打开文件到搜索结果的第一页:
- mupdf
安装
通过GitHub发布可获得Linux和macOS的静态链接二进制文件。
Docfd也在以下Linux平台上打包:
- opam
- AUR (作为
docfd-bin
) 由kseistrup提供 - Nix (作为
docfd
) 由chewblacka提供
目前在Windows上使用Docfd的唯一方法是通过WSL。
打包者注意事项: 除了用于构建的OCaml工具链(如果您从源代码打包)之外,Docfd还需要以下外部工具才能在运行时提供完整功能:
- 来自
poppler-utils
的pdftotext
,用于PDF支持 pandoc
,用于支持.epub
、.odt
、.docx
、.fb2
、.ipynb
、.html
和.htm
文件fzf
,用于文件选择菜单
启动
从管道stdin读取
command | docfd
当文档源为管道stdin时,Docfd使用单文件视图。
在这种情况下不应提供任何路径作为参数。 如果指定了任何路径,则忽略stdin。
扫描文件
docfd [路径]...
路径列表可以包含目录。 默认情况下,列表中的每个目录都会递归扫描以下扩展名的文件:
- 对于多行搜索模式:
.txt
,.md
,.pdf
,.epub
,.odt
,.docx
,.fb2
,.ipynb
,.html
,.htm
- 对于单行搜索模式:
.log
,.csv
,.tsv
您可以通过--exts
和--single-line-exts
更改要使用的文件扩展名,
或通过--add-exts
和--single-line-add-exts
添加到扩展名列表中。
如果路径列表为空,
则Docfd默认扫描当前目录.
,
除非使用了以下任何一项:
--paths-from
、--glob
、--single-line-glob
。
如果在路径列表中只指定了一个文件, 则Docfd使用单文件视图。 否则,Docfd使用多文件视图。
扫描文件然后用fzf选择
docfd [路径]... ?
?
可以在路径列表中的任何位置。
如果任何路径是?
,则通过fzf
调用发现文件的文件选择。
使用文件中的路径列表
docfd [路径]... --paths-from paths.txt
最终使用的路径列表是路径
和paths.txt
中列出的路径的连接,
其中paths.txt
每行一个路径。
使用通配符
docfd --glob 'relative/path/glob' --glob '/absolute/path/glob'
文件收集规则
-
首先根据以下内容收集第一组文件:
- 来自
--exts
、--add-exts
、--single-line-exts
、--single-line-add-exts
的扩展名--exts
默认为txt,md,pdf,epub,odt,docx,fb2,ipynb,html,htm
--single-line-exts
默认为log,csv,tsv
--add-exts
和--single-line-add-exts
均默认为空字符串
- 作为命令行参数提供的
路径
,例如docfd dir0 dir1 file0
中的dir0
、dir1
、file0
- 仅当未指定
--paths-from
、--glob
、--single-line-glob
时,路径
默认为.
- 仅当未指定
- 从
--paths-from 文件
中指定的文件
中的路径
- 来自
-
第二组文件根据
--glob
收集 -
第三组文件根据
--single-line-glob
收集 -
通配符捕获的目录不会递归扫描,即文件必须直接被通配符拾取才能被考虑为第二组和第三组文件
-
文件被分类为单行搜索模式和默认搜索模式
- 默认搜索模式是多行搜索模式,除非使用
--single-line
- 默认搜索模式是多行搜索模式,除非使用
-
如果文件满足以下任一条件,则归类为单行搜索模式:
- 文件位于
PATH
中或--paths-from FILE
的FILE
中,且扩展名属于--single-line-exts
或--single-line-add-exts
- 文件被
--single-line-glob
捕获 - 文件被
--glob
捕获,且扩展名属于--single-line-exts
或--single-line-add-exts
- 文件位于
-
否则,文件归类为默认搜索模式
搜索
搜索字段接受搜索表达式作为输入。搜索表达式是以下之一:
- 搜索短语
?expression
(可选)(expression)
expression | expression
(或),例如go ( left | right )
要使用字面意义上的 ?
、(
、)
或 |
,需要在字符前加反斜杠(\
)。
搜索短语是一系列标记,其中每个标记是以下之一:
- 无注释(模糊匹配,例如
hello
表示模糊匹配hello
) 'tok
('
前缀表示精确匹配该标记)^tok
(^
前缀表示前缀匹配该标记)tok$
($
后缀表示后缀匹配该标记)~
(显式空格,即连续的空格、制表符等序列)
未被空格、运算符或括号分隔的标记会被特殊处理,我们称之为链接标记。例如,在 12:30
中 12
、:
和 30
是链接的,但在 12 : 30
中则不是。默认情况下,链接标记的搜索距离更加严格,例如在 12:30
中,Docfd 只会在距离 12
几个标记的范围内搜索 :
,以此类推。这允许用户表明减少模糊性的意图。
要将空格链接到标记,需要使用 ~
。例如,要搜索 "John Smith"("John" 和 "Smith" 之间有若干个空格),可以使用 John~Smith
来建立链接。
对于 '
、^
、$
被视为注释标记,标记与标记之间不能有空格,例如 ^abc
表示"前缀匹配 abc
",但 ^ abc
表示"模糊匹配 ^
和模糊匹配 abc
"。
带注释的链接标记也会被特殊处理:
^12:30
等同于'12
':
^30
'12:30
等同于'12
':
'30
12:30$
等同于12$
':
'30
但比普通链接标记有更严格的搜索限制,即下一个匹配的标记必须紧跟当前匹配,例如 ^12:3
不会匹配 12 : 30
但会匹配 12:30
搜索是异步的,具体来说:
- 搜索字段的编辑不会被搜索进度阻塞
- 更新/清除搜索字段会取消当前搜索并立即开始新的搜索
多文件视图和单文件视图的通用控制
导航模式
- 切换到搜索模式
/
- 退出 Docfd
Esc
Ctrl
+C
- 进入打印模式以将项目打印到 stderr
p
搜索模式
- 此模式下搜索字段处于活动状态
- 按
Enter
确认搜索表达式并退出搜索模式
多文件视图
默认 TUI 分为四个部分:
- 左侧是满足搜索表达式的文档列表
- 右上是跟踪所选搜索结果的文档内容视图
- 右下是排序后的搜索结果列表
- 底部面板包括:
- 状态栏
- 按键绑定信息
- 文件路径过滤栏
- 搜索栏
文件路径过滤栏包括文件路径过滤状态指示器和文件路径过滤字段。 文件路径过滤状态指示器显示以下值之一:
OK
- 文件路径过滤 glob 已成功应用
ERR
- Docfd 无法解析字段中的 glob
搜索栏包括搜索状态指示器和搜索字段。 搜索状态指示器显示以下值之一:
OK
- Docfd 处于空闲状态/搜索已完成
...
- Docfd 仍在搜索
ERR
- Docfd 无法解析字段中的搜索表达式
控制
Docfd 以模式运行,初始模式为导航模式。
导航模式
- 向下滚动文档列表
j
- 向下箭头
- 向下翻页
- 鼠标悬停在该区域上时向下滚动鼠标滚轮
- 向上滚动文档列表
k
- 向上箭头
- 向上翻页
- 鼠标悬停在该区域上时向上滚动鼠标滚轮
- 向下滚动搜索结果列表
Shift
+J
Shift
+向下箭头Shift
+向下翻页- 鼠标悬停在该区域上时向下滚动鼠标滚轮
- 向上滚动文档列表
Shift
+K
Shift
+向上箭头Shift
+向上翻页- 鼠标悬停在该区域上时向上滚动鼠标滚轮
- 打开文档
Enter
- Docfd 首先尝试使用
$VISUAL
,如果失败则尝试$EDITOR
- Docfd 首先尝试使用
- 切换到单文件视图
Tab
- 进入清除模式
x
- 进入丢弃模式
d
- 撤销文档存储更改
u
Ctrl
+Z
- 重做文档存储更改
Ctrl
+R
Ctrl
+Y
清除模式
- 清除搜索字段
/
- 清除文件路径过滤字段
f
丢弃模式
- 丢弃当前选中的文档
d
- 丢弃所有未列出的文档
u
- 丢弃所有已列出的文档
l
- 取消/退出丢弃模式
Esc
Ctrl
+C
打印模式
- 打印当前选中的搜索结果
p
- 选中文档的样本
s
- 选中文档的所有结果
a
- 选中文档的路径
Shift
+P
- 已列出文档的路径
l
- 未列出文档的路径
u
- 所有文档的样本
Shift
+S
- 所有文档的全部结果
Shift
+A
- 取消/退出打印模式
Esc
Ctrl
+C
单文件视图
如果指定给Docfd的路径不是一个目录,则会使用单文件视图。
在这个视图中,TUI被分为三个部分:
- 顶部是内容视图
- 中间是排序后的搜索结果列表
- 底部面板与多文件视图中显示的相同,但键绑定信息不同
控制
单文件视图中的控制被简化了,具体来说,滚动搜索结果列表时Shift
键是可选的。
导航模式
- 向下滚动搜索结果列表
j
- 向下箭头
- 向下翻页
Shift
+J
Shift
+向下箭头Shift
+向下翻页- 当鼠标悬停在该区域上方时,用鼠标滚轮向下滚动
- 向上滚动文档列表
k
- 向上箭头
- 向上翻页
Shift
+K
Shift
+向上箭头Shift
+向上翻页- 当鼠标悬停在该区域上方时,用鼠标滚轮向上滚动
- 打开文档
Enter
- Docfd首先尝试使用
$VISUAL
,如果失败则尝试$EDITOR
- Docfd首先尝试使用
- 切换到多文件视图
Tab
- 清除搜索字段
x
打印模式
- 打印当前选中的搜索结果
p
- 样本
s
- 所有结果
a
- 路径
Shift
+P
- 取消/退出打印模式
Esc
Ctrl+C
限制
-
PDF文件不支持自动重新加载,因为PDF查看器是通过shell在后台调用的。虽然可以通过以下方式正确支持此功能,但需要大量工程工作,而潜在收益可能很小:
-
Docfd等待PDF查看器完全终止后再恢复,但这会阻止同时在不同的PDF查看器实例中查看多个搜索结果。
-
Docfd完全管理启动的PDF查看器,但当Docfd终止时,这些查看器会被关闭。
-
Docfd通过shell调用PDF查看器,使它们在Docfd终止时保持打开状态。Docfd则通过PDF查看器的进程ID定期检查它们是否仍在运行,但这需要处理分叉问题。
-
除了跟踪与文件交互的PDF查看器实例是否仍在运行外,Docfd还需要通过
inotify
或定期检查文件修改时间来设置文件更新处理。
-
致谢
- 非常感谢@lunacookies和@jthvai进行的多次UI/UX讨论和建议
- 演示gif和一些截图是使用vhs制作的
- ripgrep-all被用作文本提取软件选择的参考
- Marc Coquand(Stitch的作者)提供了结果缩小功能的讨论和灵感
- 部分搜索语法从fzf复制而来