Scout is a small fuzzy finder for your terminal built in Rust.
It is heavily inspired by other tools like selecta and the omnipresent fzf.
The main features of scout
are:
- Async architecture thanks to the
async-std
library. This means that it won't block the UI to wait for theSTDIN
to finish, you can start typing right away. - Customizable UI. You can change the colors and symbols of all the elements in the UI.
- Fast fuzzy matching algorithm based on the
fuzzaldrin-plug
package used in the Atom editor.
This tool uses the system's pseudo terminal located in /dev/tty
to print the UI and capture inputs, which means it only works on UNIX systems (like Linux or macOS) as far as I know.
Each release, since version v1.0.0
(not included), has a package with scout
compiled for different architectures. You can try to donwload and install the package that match your architecture.
You can find the releases in their GitHub page.
Scout is in the main crates repository, so you can install it with cargo
:
$ cargo install scout
Remember to put cargo
bin path to the main $PATH
env variable:
export PATH=$PATH:~/.cargo/bin
You can use my custom tap repository to install scout
with homebrew:
$ brew tap jhbabon/tap
$ brew install scout
On macOS, you can also install scout
via MacPorts:
$ sudo port install scout
Since scout
is a Rust project, you will need to have Rust installed in your system. Check rustup
to see how to install Rust. To build scout
you will need Rust v1.43
or higher.
Clone the repository and run cargo install
from it:
$ git clone https://github.com/jhbabon/scout.git path/to/scout
$ cd path/to/scout
$ cargo install --path .
You can also run cargo build --release
if you just want to play with it. The binary file will be in the ./target/release/scout
path.
The main idea behind scout
, or any other fuzzy finder, is to filter a list of items (for example a list of paths to files) and then do something with the selection. For that you run a command, pipe its output to scout
and then pipe scout
's output to another command.
For example, you can try to find a file and cat
its contents:
$ find * -type f | scout | xargs -n1 cat
scout
has a set of options that allows you to control how it looks. It also supports a set of control sequences and keys to navigate the UI.
You can see these options in the main help of the program with the --help
flag:
scout 2.0.0
Your friendly fuzzy finder
USAGE:
scout [FLAGS] [OPTIONS]
FLAGS:
-f, --full-screen Show scout in full screen (default)
-h, --help Prints help information
-i, --inline Show scout under the current line
-p, --preserve-order Do not sort the result by score
-v, --version Prints version information
OPTIONS:
-c, --config <FILE> Uses a custom config file
-l, --lines <LINES> Number of lines to display in inline mode, including prompt
-s, --search <QUERY> Start searching with the given query
SUPPORTED KEYS:
- Enter to select the current highlighted match and print it to STDOUT
- ^u to clear the prompt
- ^n or Down arrow key to select the next match
- ^p or Up arrow key to select the previous match
- ^e to go to the end of the prompt
- ^a to go to the beginning of the prompt
- Left arrow key to move the cursor to the left in the prompt
- Right arrow key to move the cursor to the right in the prompt
- ESC to quit without selecting a match
EXAMPLE:
$ find * -type f | scout
# Pass an initial query to start filtering right away
$ find * -type f | scout --search=foo
# Use a custom config file
$ find * -type f | scout --config="./config.toml"
# Select a git branch and check it out with an inline menu
$ git branch --sort=-committerdate| cut -c 3- | scout -i -p | xargs git checkout
You can configure scout
's UI with a config file. By default the program will try to find this file in the path $HOME/.config/scout.toml
, but you can pass a custom path with the --config
option.
This is how scout
looks like without any defined style:
This is an example of a configuration file with all the possible settings:
# General screen options
[screen]
# Display inline (under the current line) or in full screen
mode = "inline" # or "full"
# Max number of lines to display the whole UI. Only used in inline mode
lines = 8
# The prompt is where you type your query
[prompt]
# Symbol displayed before the text you will type
symbol = "❯ "
# Style for the query (your text)
style = "bold underline"
# Style for the symbol
style_symbol = "fg:green"
# The gauge indicates the number of matches vs total number of lines
[gauge]
# Symbol used to separate both numbers
symbol = " ⚡"
# Text before the numbers
prefix = "- "
# Style for the numbers
style = "fg:bright-yellow"
# A candidate is an item in the list that is not selected
[candidate]
# Symbol displayed before the candidate's text
symbol = "❔ "
# Style for the candidate's text
style = "bg:red fg:black"
# Style for the symbol
style_symbol = "bg:red"
# A match is a character that is in both the query and the candidate
style_match = "underline bg:black fg:red bold"
# The selected candidate
[selection]
# Symbol displayed before the selection's text
symbol = "✅ "
# Style for the selection's text
style = "bg:green fg:black"
# Style for the symbol
style_symbol = "bg:green"
# A match is a character that is in both the query and the selection
style_match = "underline fg:bright-green bg:black"
That configuration placed in the $HOME/.config/scout.toml
would generate this UI:
It is not the prettiest, but it is just an example of what you can do.
A style is defined with a string
of space separated values. I copied based the syntax on starship.rs configuration system.
These are the possible values you can use to define a style:
underline
: Put a line under the textstrikethrough
: Cross the text with a linereverse
: Reverse the current terminal colorsbold
: Use bold fontitalic
: Use italic font (if the terminal supports it)dimmed
: Fade the foreground color a bitnone
: Reset any color, using terminal's defaults. This will ignore any other rule in the style definitionfg:<color-name>
: Use the named color as foreground (text) color. Possible names areblack
,red
,yellow
,green
,blue
,purple
,cyan
,white
. You can also use their bright version with thebright-*
prefixfg:<number>
: Use the given ANSI Color number as the foreground colorfg:#<hex>
: Use the given hexadecimal representation of an RGB color as the foreground color. For examplefg:#ffbbcc
would bergb(255, 187, 204)
bg:<color-name>
: Same as withfg:
but for the backgroundbg:<number>
: Same as withfg:
but for the backgroundbg:#<hex>
: Same as withfg:
but for the background
For color setting it really depends on your terminal color capabilities. Most modern terminals allow you to set any color, though.
You can learn more about the fuzzy matching algorithm in the README
in the repository page of the fuzzaldrin-plus
package. The only missing part from that algorithm is the path scoring bonus.
From all the algorithms for fuzzy matching out there this is one of the most complete I found, so I decided to try to port it.
Check the contributing guidelines.
One of the main reasons I've built this was to have a general purpose fuzzy finder I could use inside Neovim. If you want to do the same you can use my scout.vim
plugin.
I don't know. Maybe? It really depends on your needs. I built this tool first to learn some Rust and second because I didn't like much other more heavy tools. That doesn't mean is better or worse. It is probably simpler. Give scout
a try, see if it works for you, and if not try any other tool, it's cool.
I don't know, I haven't run any benchmark, to be honest. It is fast enough for me and most probably for most of the people.
Yes.