Shell completion for CLI
========================

This code generates shell completion scripts for hledger's command line
interface.
Shell completion is usually triggered by pressing the tab key once or twice
after typing the command `hledger `.
(The exact behavior may differ in shells other than Bash.)

Currently, only Bash is supported but Zsh or Fish can be added.

[![asciicast](https://asciinema.org/a/227935.svg)](https://asciinema.org/a/227935)

The completions can handle hledger's CLI:

- commands and generic options
- command-specific options
- most option arguments
- account names, tags, payees, etc. from journal files
- query filter keywords like `status:`, `tag:`, or `amt:`

Installation for end users
--------------------------

Completions are currently only implemented for the Bash shell.

Please check first if the completions for hledger are already installed on your
distribution. Refer to the last paragraph of this section for how to test that.

To install from the repository, do:

```sh
cd /path-to-repo/shell-completion
make install
```

Completions installed this way will be loaded dynamically after you use the hledger
command. Upon the first invocation of a command that has no predefined completion
bash looks for a file with the same name in a set of predefined locations in this order:

- `$BASH_COMPLETION_USER_DIR/completions`
- `$XDG_DATA_HOME/bash-completion/completions`
- `$HOME/.local/share/bash-completion/completions`
- etc.

You can manually achieve the effects of `make install` by copying
`shell-completion/hledger-completion.bash` to one of the above, and renaming it
to `hledger`, `_hledger` or `hledger.bash`. For the gory details, type this in a
bash shell:

```sh
type __load_completion
```

To install the completions manually, you can also just download and copy
`shell-completion/hledger-completion.bash` to a directory of your choosing, and
source it from your shell start up files. This way completions are loaded
eagerly and that adds a delay to shell start up time.

Example:

```sh
cp hledger-completion.bash ~/.bash_completion.d/hledger
echo 'source ~/.bash_completion.d/hledger' >> ~/.bashrc
# Restart shell
exec bash
# Confirm that completion is loaded
complete -p hledger
```

Now, try it by typing `hledger` (with a space after the command) and press the
tab key twice. You should see a list of appropriate completions for hledger.
Then you can type a part of one of the suggestions and press tab again to
complete it.

Background
----------

The Bash completion script is generated (GNU make) by parsing output of `hledger`,
`hledger -h`, and `hledger <cmd> -h`. The script also uses `hledger accounts` for
account name completion. I propose that the Makefile is not run at every built
but rather manually when the CLI changes.

Information for developers
--------------------------

Generate the completion script for Bash:

```sh
# change into this folder:
cd shell-completion/
make
```

Hint: GNU make and  GNU m4 must be installed to call `make`.
These are present on most systems anyway.
Additionally the build will run a lot faster with parallell jobs.
Use `make -j$(nproc)` for best effect.

The generated completion script must be installed. The package maintainer for
your distribution should be responsible for this.

For now, or to live-test the script, you can use these two commands:

```sh
ln -s hledger-completion.bash ~/.hledger-completion.bash
echo 'source ~/.hledger-completion.bash' >> ~/.bashrc
```

After that, you have to start a new Bash, e.g. by typing `bash` on the current
shell.

Now, try it by typing `hledger` (with a space after the command) and press the
tab key twice. You know how completions work – if not, see above in the
Installation section.

Completion scripts for other shells (e.g. Fish or Zsh)
------------------------------------------------------

You're welcome to add completion scripts for other shells. It should not be too
hard! All available hledger options and commands are already there (generated by
the Makefile).

The generated text files with options and commands are: `commands.txt`,
`generic-options.txt`, and `options-*.txt` where `*` is the subcommand.

Instructions to add support for another shell:

1. Create e.g. `hledger-completion.fish.m4` as a template file.

2. Add a Make rule to transform it to `hledger-completion.fish`.

3. Use m4 commands to include hledger options and commands into your script
   template. See `hledger-completion.bash.m4` as a reference.

4. Use `make` and then `make hledger-completion.fish` to create and test the
   completion script.

5. Finally, if everything is working, also add the generated artifact
   `hledger-completion.fish` to the repo so that people can use it directly.
