Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jhbabon/scout

Friendly fuzzy finder made with rust
https://github.com/jhbabon/scout

async cli fuzzy-search fuzzyfinder rust terminal tui

Last synced: 1 day ago
JSON representation

Friendly fuzzy finder made with rust

Awesome Lists containing this project

README

        

# Scout

[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fjhbabon%2Fscout%2Fbadge%3Fref%3Dmain&style=flat-square)](https://actions-badge.atrox.dev/jhbabon/scout/goto?ref=main)

Scout is a small fuzzy finder for your terminal built in [Rust][rustlang].


scout demo

It is heavily inspired by other tools like [selecta][selecta] and the omnipresent [fzf][fzf].

The main features of `scout` are:

* Async architecture thanks to the [`async-std`][asyncstd] library. This means that it won't block the UI to wait for the `STDIN` 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`][fuzzaldrin-plus] package used in the Atom editor.

## WARNING

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.

## Installation

### Install via release packages

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][github-releases].

### Install via cargo

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
```

### Install via homebrew (macOS only)

You can use my custom tap repository to install `scout` with [homebrew](https://brew.sh):

```
$ brew tap jhbabon/tap
$ brew install scout
```

### Install via MacPorts (macOS)

On macOS, you can also install `scout` via [MacPorts](https://www.macports.org):

```
$ sudo port install scout
```

### Install from source

Since `scout` is a Rust project, you will need to have Rust installed in your system. Check [`rustup`][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.

## Usage

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 Uses a custom config file
-l, --lines Number of lines to display in inline mode, including prompt
-s, --search 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
```

### Configuration

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:

default UI

This is an example of a configuration file with all the possible settings:

```toml
# 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:

customized 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][starship] configuration system.

These are the possible values you can use to define a style:

* `underline`: Put a line under the text
* `strikethrough`: Cross the text with a line
* `reverse`: Reverse the current terminal colors
* `bold`: Use bold font
* `italic`: Use italic font (if the terminal supports it)
* `dimmed`: Fade the foreground color a bit
* `none`: Reset any color, using terminal's defaults. This will ignore any other rule in the style definition
* `fg:`: Use the named color as foreground (text) color. Possible names are `black`, `red`, `yellow`, `green`, `blue`, `purple`, `cyan`, `white`. You can also use their bright version with the `bright-*` prefix
* `fg:`: Use the given [ANSI Color][ansi-color] number as the foreground color
* `fg:#`: Use the given hexadecimal representation of an RGB color as the foreground color. For example `fg:#ffbbcc` would be `rgb(255, 187, 204)`
* `bg:`: Same as with `fg:` but for the background
* `bg:`: Same as with `fg:` but for the background
* `bg:#`: Same as with `fg:` 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.

## Fuzzy matching algorithm

You can learn more about the fuzzy matching algorithm in the `README` in the repository page of the [`fuzzaldrin-plus`][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.

## Development

Check the [contributing][contributing] guidelines.

## Neovim integration

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`][scoutvim] plugin.

## FAQ

##### Is this better than X?

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.

##### Is this faster than X?

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.

##### Is this any good?

Yes.

[rustlang]: https://www.rust-lang.org/
[selecta]: https://github.com/garybernhardt/selecta
[fzf]: https://github.com/junegunn/fzf
[asyncstd]: https://async.rs/
[starship]: https://starship.rs/
[fuzzaldrin-plus]: https://github.com/jeancroy/fuzz-aldrin-plus/
[crates]: https://crates.io/crates/scout
[github-releases]: https://github.com/jhbabon/scout/releases
[rustup]: https://rustup.rs/
[ansi-color]: https://i.stack.imgur.com/KTSQa.png
[rustfmt]: https://github.com/rust-lang/rustfmt
[scoutvim]: https://github.com/jhbabon/scout.vim
[Neovim]: https://neovim.io/
[contributing]: ./CONTRIBUTING.md