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命令行工具

Download history 12/week @ 2024-05-04 17/week @ 2024-05-11 162/week @ 2024-05-18 134/week @ 2024-05-25 33/week @ 2024-06-01 20/week @ 2024-06-08 30/week @ 2024-06-15 263/week @ 2024-06-22 78/week @ 2024-06-29 21/week @ 2024-07-06 84/week @ 2024-07-13 301/week @ 2024-07-20 369/week @ 2024-07-27 310/week @ 2024-08-03 596/week @ 2024-08-10 248/week @ 2024-08-17

1,557 每月下载量
3 个crate(2 个直接)中使用

MIT 许可证

440KB
10K SLoC

Rust 7.5K 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 Handlebars 67 SLoC

Crates.io Build & Test Packaging status Skim Discord

注意: two_percentskim 的分支,用于与 httm 一起使用。

生命短暂,使用 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 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可以动态调用其他命令。通常您希望将其与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 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 mainskim将搜索匹配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 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 有两种提示:用于指定查询模式的查询提示和用于指定命令“参数”的命令提示
  • -c 用于指定要执行的命令,默认为 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 相同。

如何贡献

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

故障排除

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