Hi, I’m Erika Rowland (a.k.a. erikareads). Hi, I’m Erika. I’m an Ops-shaped Software Engineer, Toolmaker, and Resilience Engineering fan. I like Elixir and Gleam, Reading, and Design. She/Her. Constellation Webring Published on

Mix Completions

I’ve released mix_completions, a mix task that allows you to add shell completions for mix. mix_completions supports completions for bash and zsh.fish already had community contributions adding completions for mix: fish completions

How it works

mix_completions adds three tasks to work with shell completions:

mix complete

mix complete caches the available completions from mix help. If mix complete detects a mix.exs file, it will cache these completions in the project in .mix_complete.cache. Otherwise it will store the cache in $XDG_CACHE_HOME/.mix_complete.cache.

This means that you can have a separate set of completions for a project with custom tasks than what is generally available to mix globally.

mix complete.bash

mix complete.bash will refresh the cache a la mix complete, and outputs bash that when sourced enables shell completions for mix.

mix complete.zsh

mix complete.zsh, like its bash counterpart, refreshes the cache and generates output that can be loaded by zsh. Instructions on where to put this output can be found in the README.

Why Cache Completions

With shell completions there seem to be two ways of sourcing the completions:

  1. Ask the program for the completions available. This is the approach that cobra and click take. The shell completions they output are simply a parser for completions output by the program itself.

  2. Caching completions outside of the program. This is the approach that tools like completely take. Saving the completions in plain text or directly in the shell output.

I chose to use option 2, because Elixir has a non-trivial startup time. Recently work has reduced the startup time of the BEAM for Elixir, but mix still takes a few seconds to run on my machine. Instead of waiting multiple seconds for completions to come back, I chose to cache the completions in a TSV that can parsed and handled by the shell completions directly.

Where to store the cache?

This project led me to learn about the XDG Base Directory Specification. I’ve known about these environment variables for a while, but I didn’t know how to use them as a software author.

The XDG specification gives guidance on where to put configuration or cache files on unix systems. The recommendations were simple to use: XDG_CACHE_HOME is configurable by a user, and defaults to $HOME/.local/cache if unset.

I can either put my cache as a file in that directory or create a subdirectory if I have multiple cached things to store. mix_completions only stores one TSV for its cache, so it’s stored directly in the XDG_CACHE_HOME directory.

Finding all the tasks

Initially, when I wanted to find all of the available mix tasks, I used System.shell to call mix help and then processed the output with awk. This got the job done, but felt fragile.

While explaining this to a friend, they pointed out that mix help --names does this work for me.Thanks Jeff! Though I did have to filter iex from the list, and I was still invoking System.shell.

Then I realized that if mix had an option for this, it must know how to find (and print) all of the available tasks. Now, mix_completions uses vendored versions of the same functions that mix help uses. This proved to be useful when I switched from a simple list of tasks to a tab-separated values file of both tasks and their shortsdocs, since Mix.Task provides helpers to fetch things like a task’s shortdoc.

Limitations

Since I chose to work in a project agnostic way, I have no way of knowing what arguments and flag are available for subcommands. Thus I chose to only provide completions for available tasks, since I can ask mix for these directly. The fish community completions provide more granularity, at the cost of pre-assuming which tasks you have available.

I chose to use caching over hard-coding so that you can detect new tasks and add completions for them, if only at the surface level.

Try It Now

If you would like to try mix_completions run:

mix archive.install hex mix_completions

Instructions on how to source the completions for your chosen shell are in the README.

Please report any issues you find. :)

mix completions example gif


Constellation Webring