/fzshell

Fuzzy shell completions you didn't know you needed

Primary LanguageGoMIT LicenseMIT

fzshell3

Test Join the chat at https://gitter.im/fzshell/community

fzshell is a fuzzy command line completer that fetches completions from sources predefined by a user. What does it mean? It means that now you can create custom completions for anything you want. All fzshell needs is a pattern to match and command to generate completion list. It can even insert a completion at any point in a line, not just at the end. See for yourself:

fzshell-petstore.mov

This can be accomplished with a few lines:

completions:
  - pattern: "jq '?(\\.[^']*)'? (\\w+.json)"
    replacement: jq '{{._1}}[{{ .item }}]' {{._2}}
    cmd: 'jq $1 $2 | jq keys | jq  ". []"'
    preview: jq -C '{{._1}}[{{.item}}]'  {{._2}}

If you find fzshell useful, consider giving it a star. Appreciated!

Why?

fzshell was born out of my frustration with performing the same manual tasks over and over. Like removing obsolete docker containers, deleting kubernetes pods with kubectl or browsing their logs and even copy pasting ticket id from a branch name to a commit message.

I tried to to solve this problem in the past using only shell scripts and the result was docker-fzf-completion. However, it was not extensible at all and I had to write a lot of unreadable bash scripts to make it work for any extra command. Additionally, it required from a user more keystrokes than one.

Enter fzshell. All of these tasks I mentioned can be automated at least partially by fzshell. It divides completions generation into familiar steps, namely: matching, mapping and filtering. A user only has to provide logic for those steps and doesn't have to worry about wiring it all together and edge cases. Check out the gallery of examples to get ideas on how fzshell can help you.

Want to show your completion definitions 🦚? Need help ❓

Visit πŸ—¨οΈ Discussions!

You can get your questions (probably) answered in πŸ™ Questions & Answers .

Show us your completion definitions in 🦾 Completions Expo.

Quickstart

Installation

using git

Execute these lines to install fzshell on your computer.

git clone https://github.com/mnowotnik/fzshell ~/.fzshell
cd ~/.fzshell/
./scripts/install.sh

Then follow printed instructions.

using plugin manager

If you use package manager like zplug you just need to add the following line in your .zshrc:

zplug "mnowotnik/fzshell", hook-build:"./scripts/install.sh --no-instructions"

fisher is also supported. Simply run:

fisher install mnowotnik/fzshell

Basic configuration

fzshell needs a configuration file to load completion definitions. By default, it loads them from:

~/.config/fzshell/fzshell.yaml

However, this can be changed by the variable $FZSHELL_CONFIG that should point to a valid configuration.

Below, you can see an example configuration file:

completions:
  - pattern: "docker rmi"
    cmd: docker images --format '{{.Repository}}:{{.Tag}}\t{{.ID}}'
    map: ' {{ .item | splitList "\t" | last }}'
    preview: docker image inspect {{.item}}

As you can see the completion definition here has several attributes:

  • pattern – regular expression parsable by Go. It can contain subexpressions ((xxx)) and named subexpressions ((?P<foo>xxx))
  • cmd – Bash shell expression
  • map – Go template expression that has access to sprig and subexpression matches:
    • .item – whole line returned by the command in cmd
    • ._1,._2,... – variables that store non-named subexpression matches
    • .foo – named subexpression matches
  • preview – Just like map, but returns a preview of a matched item

Visit wiki for a complete configuration guide.

Usage

The hardest part of using fzshell is writing a correct configuration. If that is the case, all you need to do is press Ctrl-n when a cursor is just after a matching pattern.

Let's consider the example above. Assume the command line looks like this:

jq . pets.jsonβ–‰

You just need to press Ctrl-n to activate fzshell and get a match. However, if the line deviates from a pattern even a bit nothing will happen. No match for this line:

jq . pets.json β–‰

You would need to modify the pattern a bit to handle extra spaces at the end:

pattern: "jq '?(\\.[^']*)'? (\\w+.json) *"

By default the completion will be inserted at the cursor position, however you can have complete control over the insertion by defining the replacement template. It replaces the left part of the line buffer (meaning: to the left of the cursor). Check wiki for more details.

Development

Development setup is smooth and easy thanks to Go modules.

  • requirement: go version 1.18+
  • command: go build
  • manual testing: source fzshell.bash/fzshell.fish/fzshell.plugin.zsh
  • automatic tests: make test
  • linting: make lint (requires staticcheck)
  • coverage report: make cover-report

On the way to 1.0.0

fzshell is still in beta, however the specification is unlikely to change, unless by popular demand. fzshell will advance to 1.0 after user feedback in the coming weeks.

Similar tools

Default zsh completions turned into fuzzy ones thanks to fzf.

Dropdown for different completions computed from context and also framework for additional terminal apps. Only for MacOS.

Acknowledgments

This tool is possible thanks to open source fuzzy finders. First fuzzy finder used was go-fuzzyfinder. After that fzshell embedded a more feature complete finder, the excellent fzf.

Disclaimer

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.