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 git@github.com:lotabout/skim.git ~/.skim $ ~/.skim/install - 使用二进制文件:直接 下载 sk 可执行文件。
- 从 crates.io 安装:
cargo install skim - 手动构建
$ git clone --depth 1 git@github.com: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