31 个版本

0.10.4 2023 年 3 月 2 日
0.10.2 2022 年 11 月 8 日
0.9.4 2021 年 2 月 15 日
0.9.3 2020 年 11 月 2 日
0.2.1-beta.22017 年 1 月 19 日

#28 in 命令行工具

Download history 4147/week @ 2024-04-20 3628/week @ 2024-04-27 3971/week @ 2024-05-04 4118/week @ 2024-05-11 4625/week @ 2024-05-18 4101/week @ 2024-05-25 4479/week @ 2024-06-01 3731/week @ 2024-06-08 3882/week @ 2024-06-15 4087/week @ 2024-06-22 3499/week @ 2024-06-29 3643/week @ 2024-07-06 4373/week @ 2024-07-13 4101/week @ 2024-07-20 3672/week @ 2024-07-27 3978/week @ 2024-08-03

16,643 个月下载量
用于 108 个包(81 个直接使用)

MIT 许可证

420KB
10K SLoC

Rust 7K SLoC // 0.0% comments Vim Script 1K SLoC // 0.0% comments Python 848 SLoC // 0.1% comments BASH 373 SLoC // 0.1% comments Zsh 333 SLoC // 0.2% comments Shell 100 SLoC // 0.1% comments

Crates.io Build & Test Packaging status

生命短暂,使用 skim!

我们的一半生命花在导航上:文件、行、命令……你需要 skim!它是一个节省时间的通用模糊查找器。

skim demo

skim 提供了一个单独的可执行文件:sk。基本上任何你想使用 grep 的地方,都尝试使用 sk

目录

安装

skim 项目包含几个组件

  1. sk 可执行文件 -- 核心。
  2. sk-tmux -- 在 tmux 窗格中启动 sk 的脚本。
  3. Vim/Nvim 插件 -- 在 Vim/Nvim 中调用 sk。有关更多 Vim 支持,请参阅 skim.vim

包管理器

分发 包管理器 命令
macOS Homebrew brew安装 sk
macOS MacPorts sudoport install skim
Fedora dnf dnf install skim
Alpine apk apk add skim
Arch pacman pacman -S 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 可以动态调用其他命令。通常您会希望将其与 grepackagrg 集成,以在项目目录中搜索内容

# 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 "{}"'

interactive mode demo

快捷键绑定

一些常用的快捷键

操作
Enter 接受(选择当前项并退出)
ESC/Ctrl-G 中断
Ctrl-P/Up 向上移动光标
Ctrl-N/Down 向下移动光标
TAB 切换选择并向下移动(与 -m 结合使用)
Shift-TAB 切换选择并向上移动(与 -m 结合使用)

有关快捷键的完整列表,请参阅 man 页面man sk)。

搜索语法

skim 借用了 fzf 的语法进行项目匹配

令牌 匹配类型 描述
text 模糊匹配 匹配 text 的项目
^music 前缀精确匹配 music 开头的项目
.mp3$ 后缀精确匹配 .mp3 结尾的项目
'wild' 精确匹配(引用) 包含 wild 的项目
!fire 否定精确匹配 不包含 fire 的项目
!.mp3$ 否定后缀精确匹配 不以 .mp3 结尾的项目

skim 还支持令牌的组合。

  • 空白符表示 AND。对于 src main 这个词,skim 将搜索同时匹配 srcmain 的项目。
  • | 表示 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 页面(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's interactive mode

  • Skim 可以接受两种类型的源:命令输出或管道输入
  • Skim 有两种类型的提示:查询提示用于指定查询模式,命令提示用于指定命令的“参数”
  • - 用于指定要执行的命令,默认为 SKIM_DEFAULT_COMMAND
  • - 用于在启动时打开命令提示,默认显示 c>

如果您想进一步缩小命令返回的结果,请按 Ctrl-Q 切换到交互模式。

执行外部程序

您可以设置键盘绑定来启动外部进程而无需离开 skim(executeexecute-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' 来查找匹配的行,一旦我们缩小到目标行,我们最终想要通过检查行周围的上下文来决定选择哪些行。 grepag 有一个选项 --context,Skim 可以通过预览窗口做得更好。例如

sk --ansi -i -c 'ag --color "{}"' --preview "preview.sh {}"

(注意:preview.sh 是一个脚本,用于打印给定文件名:行:列的上下文)您会得到如下内容

preview demo

它是如何工作的?

如果通过 --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 将根据其读取项目,执行其任务,并返回用户选择,包括选定的项目、查询等。注意

  • SkimItemReceivercrossbeam::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 不同。例如

  1. skim 是一个二进制文件以及库,而 fzf 只是一个二进制文件。
  2. skim 有一个交互式模式。
  3. skim 支持预选择
  4. 模糊搜索算法不同。
  5. 显示匹配项的 UI。 fzf 将只显示匹配的范围,而 skim 将显示每个匹配的字符。(fzf 现在有这个功能了)
  6. skim 的范围语法是 Git 风格:现在它与 fzf 相同。

如何贡献

如果您遇到任何错误或有任何想法,请创建新问题。拉取请求非常受欢迎。

依赖项

~9–19MB
~257K SLoC