7 个版本
0.9.14 | 2024年1月7日 |
---|---|
0.9.12 | 2023年2月27日 |
0.9.9 | 2023年1月1日 |
0.9.8 | 2022年12月31日 |
#1081 in 命令行工具
87 每月下载量
在 fm-tui 中使用
420KB
10K SLoC
生命短暂,使用 skim!
我们生命中有一半的时间都在导航:文件、行、命令……你需要 skim!它是一个节省时间的通用模糊查找器。
skim 提供一个可执行文件:sk
。基本上,你可以在任何想使用 grep
的地方尝试使用 sk
。
目录
安装
skim 项目包含几个组件
sk
可执行文件 -- 核心。sk-tmux
-- 在 tmux 窗格中启动sk
的脚本。- Vim/Nvim 插件 -- 在 Vim/Nvim 中调用
sk
。有关更多 Vim 支持,请查看 skim.vim。
包管理器
分发 | 包管理器 | 命令 |
---|---|---|
macOS | Homebrew | brewinstall sk |
macOS | MacPorts | sudoport install skim |
Fedora | dnf | dnf install skim |
Alpine | apk | apk add skim |
Arch | pacman | pacman -S skim |
作为 Vim 插件安装
通过 vim-plug (推荐)
Plug 'lotabout/skim', { 'dir': '~/.skim', 'do': './install' }
硬核
以下任何一项都适用
- 使用 Git
$ git clone --depth 1 [email protected]:lotabout/skim.git ~/.skim $ ~/.skim/install
- 使用二进制文件:直接 下载 sk 可执行文件。
- 从 crates.io 安装:
cargo install skim
- 手动构建
$ git clone --depth 1 [email protected]:lotabout/skim.git ~/.skim $ cd ~/.skim $ cargo install $ cargo build --release $ # put the resulting `target/release/sk` executable on your PATH.
用法
skim 可以用作通用过滤器(如 grep
)或作为调用命令的交互式界面。
作为过滤器
尝试以下命令
# directly invoke skim
sk
# or pipe some input to it: (press TAB key select multiple items with -m enabled)
vim $(find . -name "*.rs" | sk -m)
上述命令将允许您选择扩展名为 ".rs" 的文件,并在 Vim 中打开您选择的文件。
作为交互式界面
skim
可以动态调用其他命令。通常,您会希望将其与 grep、ack、ag 或 rg 集成,以在项目目录中搜索内容
# works with grep
sk --ansi -i -c 'grep -rI --color=always --line-number "{}" .'
# works with ack
sk --ansi -i -c 'ack --color "{}"'
# works with ag
sk --ansi -i -c 'ag --color "{}"'
# works with rg
sk --ansi -i -c 'rg --color=always --line-number "{}"'
快捷键
一些常用的键绑定
键 | 操作 |
---|---|
Enter | 接受(选择当前项并退出) |
ESC/Ctrl-G | 中止 |
Ctrl-P/Up | 向上移动光标 |
Ctrl-N/Down | 向下移动光标 |
TAB | 切换选择并向下移动(与 -m 一起使用) |
Shift-TAB | 切换选择并向上移动(与 -m 一起使用) |
要查看键绑定列表的完整列表,请查看 手册页面(《man sk》)。
搜索语法
skim
采用了 fzf
的语法来匹配项目
标记 | 匹配类型 | 描述 |
---|---|---|
text |
模糊匹配 | 匹配 text 的项目 |
^music |
前缀精确匹配 | 以 music 开头的项目 |
.mp3$ |
后缀精确匹配 | 以 .mp3 结尾的项目 |
'wild' |
精确匹配(引用) | 包含 wild 的项目 |
!fire |
非精确匹配 | 不包含 fire 的项目 |
!.mp3$ |
非后缀精确匹配 | 不以 .mp3 结尾的项目 |
skim
还支持标记的组合。
- 空白表示
AND
。对于src main
这个词,skim
将搜索同时匹配src
和main
的项目。 |
表示OR
(注意|
周围有空格)。对于.md$ | .markdown$
这个词,skim
将搜索以.md
或.markdown
结尾的项目。OR
的优先级更高。因此,readme .md$ | .markdown$
将分组为readme AND (.md$ OR .markdown$)
。
如果您想使用正则表达式,skim
提供了 regex
模式
sk --regex
您可以通过按 Ctrl-R
(旋转模式)动态切换到 regex
模式。
退出代码
退出代码 | 含义 |
---|---|
0 | 正常退出 |
1 | 未找到匹配项 |
130 | 通过 Ctrl-C/Ctrl-G/ESC 等... 中止 |
自定义
这里的文档仅是预览,请查看手册页面(《man sk》)以获取完整选项列表。
键映射
使用逗号分隔的配对指定绑定(不允许有空格),例如
sk --bind 'alt-a:select-all,alt-d:deselect-all'
此外,使用 +
来连接操作,例如 execute-silent(echo {} | pbcopy)+abort
。
请参阅手册页的 键盘绑定 部分以获取详细信息。
排序标准
有五个排序键用于结果: score, index, begin, end, length
,您可以通过 sk --tiebreak score, index,-begin
或您想要的任何其他顺序来指定记录的排序方式。
颜色方案
你很可能比我更擅长艺术。幸运的是,你不会困在默认的颜色中,skim
支持自定义颜色方案。
--color=[BASE_SCHEME][,COLOR:ANSI]
颜色配置从基本颜色方案名称开始,后跟自定义颜色映射。例如
sk --color=current_bg:24
sk --color=light,fg:232,bg:255,current_bg:116,info:27
请参阅手册页中的 --color
选项以获取详细信息。
杂项
--ansi
:解析数据源的 ANSI 颜色代码(例如,\e[32mABC
)--regex
:将查询用作正则表达式来匹配数据源
高级主题
交互模式
通过“交互模式”,您可以动态调用命令。尝试一下
sk --ansi -i -c 'rg --color=always --line-number "{}"'
它是如何工作的?
- Skim 可以接受两种类型的源:命令输出或管道输入
- Skim 有两种类型的提示:查询提示用于指定查询模式,命令提示用于指定命令的“参数”
-c
用于指定要执行的命令,默认为SKIM_DEFAULT_COMMAND
-
用于在启动时告诉 skim 打开命令提示符,默认显示c>
。
如果您想进一步缩小由命令返回的结果,请按 Ctrl-Q
切换到交互模式。
执行外部程序
您可以设置键绑定,以便在不离开 skim 的情况下启动外部进程(execute
、execute-silent
)。
# Press F1 to open the file with less without leaving skim
# Press CTRL-Y to copy the line to clipboard and aborts skim (requires pbcopy)
sk --bind 'f1:execute(less -f {}),ctrl-y:execute-silent(echo {} | pbcopy)+abort'
预览窗口
这是 fzf 的一个很棒的功能,Skim 借鉴了它。例如,我们使用 'ag' 来查找匹配的行,一旦我们缩小到目标行,我们最终想要通过检查行周围的上下文来决定选择哪些行。 grep
和 ag
有一个选项 --context
,Skim 可以通过预览窗口做得更好。例如
sk --ansi -i -c 'ag --color "{}"' --preview "preview.sh {}"
(注意 preview.sh 是一个脚本,用于根据文件名:行:列打印上下文)你会有这样的东西
它是如何工作的?
如果预览命令由 --preview
选项提供,Skim 将将 {}
替换为当前高亮显示的行(用单引号包围),调用命令获取输出,并在预览窗口中打印输出。
有时候你不需要整行来调用命令。在这种情况下,你可以使用 {}
、{1..}
、{..3}
或 {1..5}
来选择字段。语法在“字段支持”部分中解释。
最后,你可能想配置预览窗口的位置,使用 --preview-window
。
--preview-window up:30%
将窗口置于上方,高度为 skim 总高度的 30%。--preview-window left:10:wrap
,指定wrap
允许预览窗口包裹预览命令的输出。--preview-window wrap:hidden
在启动时隐藏预览窗口,之后可以通过操作toggle-preview
显示。
字段支持
通常只有插件用户需要理解这一点。
例如,你有以下格式的数据源
<filename>:<line number>:<column number>
然而,你希望在输入查询时仅搜索 <filename>
。这意味着当你输入 21
时,你希望找到一个包含 <filename>
的 21
,但不匹配行号或列号。
你可以使用 sk --delimiter ':' --nth 1
来实现这一点。
你还可以使用 --with-nth
来重新排列字段的顺序。
范围语法
<num>
-- 指定第num
个字段,从 1 开始。start..
-- 从第start
个字段开始,直到最后一个字段。..end
-- 从第end
个字段开始,直到第end
个字段,包括end
。start..end
-- 从第start
个字段开始,直到第end
个字段,包括end
。
作为库使用
Skim 可以在 Rust 的 crates 中作为库使用。
首先,将 skim 添加到你的 Cargo.toml
[dependencies]
skim = "*"
然后尝试运行这个简单的示例
extern crate skim;
use skim::prelude::*;
use std::io::Cursor;
pub fn main() {
let options = SkimOptionsBuilder::default()
.height(Some("50%"))
.multi(true)
.build()
.unwrap();
let input = "aaaaa\nbbbb\nccc".to_string();
// `SkimItemReader` is a helper to turn any `BufRead` into a stream of `SkimItem`
// `SkimItem` was implemented for `AsRef<str>` by default
let item_reader = SkimItemReader::default();
let items = item_reader.of_bufread(Cursor::new(input));
// `run_with` would read and show items from the stream
let selected_items = Skim::run_with(&options, Some(items))
.map(|out| out.selected_items)
.unwrap_or_else(|| Vec::new());
for item in selected_items.iter() {
print!("{}{}", item.output(), "\n");
}
}
给定一个 Option<SkimItemReceiver>
,skim 将相应地读取项目,执行其工作,并带回到用户选择,包括所选项目、查询等。注意
SkimItemReceiver
是crossbeam::channel::Receiver<Arc<dyn SkimItem>>
- 如果没有,它将调用给定的命令并从命令输出读取项目
- 否则,它将从(crossbeam)通道中读取项目。
特性 SkimItem
提供了自定义如何显示、比较和预览一行的方式。它默认实现了对 AsRef<str>
此外,SkimItemReader
是一个辅助工具,可以将 BufRead
转换为 SkimItemReceiver
(我们可以轻松地将 File
转换为 BufRead
)。这样你就可以轻松地处理字符串或文件。
更多示例请参阅 examples/ 目录。
常见问题解答
如何忽略文件?
Skim 使用 find .
命令来获取过滤文件列表。你可以通过设置环境变量 SKIM_DEFAULT_COMMAND
来覆盖它。例如
$ SKIM_DEFAULT_COMMAND="fd --type f || git ls-tree -r --name-only HEAD || rg --files || find ."
$ sk
如果你希望将其设置为默认值,可以将其放入 .bashrc
或 .zshrc
一些文件在 Vim 插件中没有显示
如果你使用 Vim 插件并执行 :SK
命令,你可能会发现一些文件没有显示。
如 #3 中所述,在 Vim 插件中,SKIM_DEFAULT_COMMAND
默认设置为命令
let $SKIM_DEFAULT_COMMAND = "git ls-tree -r --name-only HEAD || rg --files || ag -l -g \"\" || find ."
这意味着,git 未能识别的文件将不会显示。你可以通过 let $SKIM_DEFAULT_COMMAND = ''
覆盖默认设置,或者自行查找缺失的文件。
与 fzf 的区别
fzf 是一个用 Go 编写的命令行模糊查找器,skim 尝试在 Rust 中实现一个新版本!
此项目从头开始编写。一些实现决策与 fzf 不同。例如
skim
是一个二进制文件以及库,而 fzf 只是一个二进制文件。skim
有一个交互模式。skim
支持预选择- 模糊搜索算法不同。
显示匹配项的 UI。(fzf 现在有这个功能了)fzf
只会显示匹配的范围,而skim
会显示每个匹配的字符。:现在它与 fzf 相同。skim
的范围语法是 Git 风格的
如何贡献
如果你遇到任何错误或有任何想法,请创建新问题。拉取请求热烈欢迎。
qkzk 的注释
这是一个简单的分支,我在其中将一些属性公开,以便在另一个项目中使用 skim 作为内部程序,我在该项目中需要一个模糊查找器。
100% 的工作由原始作者完成,我对此不承担任何责任。
依赖项
~11–20MB
~275K SLoC