56 个版本
新版本 0.11.23 | 2024 年 8 月 24 日 |
---|---|
0.11.16 | 2024 年 7 月 31 日 |
0.11.12 | 2024 年 3 月 29 日 |
0.10.34 | 2023 年 12 月 1 日 |
0.10.4 | 2023 年 3 月 16 日 |
#86 在 命令行工具
1,557 每月下载量
在 3 个crate(2 个直接)中使用
440KB
10K SLoC
注意: two_percent
是 skim 的分支,用于与 httm 一起使用。
生命短暂,使用 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 |
Gentoo | Portage | emerge--ask app-misc/skim |
请参见repology获取包可用性的全面概述。
作为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 |
fuzzy-match | 匹配text 的项 |
^music |
prefix-exact-match | 以music 开头的项 |
.mp3$ |
suffix-exact-match | 以.mp3 结尾的项 |
'wild' |
exact-match (quoted) | 包含wild 的项 |
!fire |
inverse-exact-match | 不包含fire 的项 |
!.mp3$ |
inverse-suffix-exact-match | 不以.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
-
表示在启动时打开命令提示,默认显示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
-- 从第0
个字段开始,一直到第end
个字段,包括end
。start..end
-- 从第start
个字段开始,一直到第end
个字段,包括end
。
作为库使用
Skim 可以作为 Rust 包的库使用。
首先,将 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 风格的
如何贡献
如果您遇到任何错误或有任何想法,请 创建新问题。欢迎提交拉取请求。
故障排除
nix、FreeBSD、termux 无换行问题
如果您遇到显示问题,例如:
$ for n in {1..10}; do echo "$n"; done | sk
0/10 0/0.> 10/10 10 9 8 7 6 5 4 3 2> 1
例如
您需要将 TERMINFO 或 TERMINFO_DIRS 设置为正确的 terminfo 数据库路径
例如,在 termux 中,您可以在 bashr 中添加以下内容:
export TERMINFO=/data/data/com.termux/files/usr/share/terminfo
依赖关系
~8-20MB
~285K SLoC