hledger/shell-completion/Makefile
Vladimir Zhelezov 72b737a42f Fix #1404, and more...
This was supposed to be just a fix for #1404 but upon visiting the source
several issues became apparent and that is why the commit grew a bit more than
expected. A complete list of changes bellow:

* Fix #1404
No more orphaned temporary directories. Commands, options, etc. that used to be
stored in there are included at build-time as here documents in the source.

* Fix artifacts in =/tmp= after build
Upon fixing the above I became aware that the build itself was leaving behind a
heap of artifacts in =/tmp= that were not taken care of with a ~make clean~.
Fixed by using temporary files and directories in the build directory. Makefile
and build scripts adjusted.

* Produce command aliases
Regular expressions in build scripts changed to produce all command aliases
except single letter ones (see below)

* Do not propose single letters completions
It is simply not useful and adds a lot of noise. It makes completion slower as
well because you need to hit yes on the prompt:
> Display all 200 possibilities? (y or n)
=output-options.sh= now excludes those.

* Query filters simplified
Keep only the prefix of the filter with the colon in =query-filters.txt=. This
change has two reasons:
- Single letter completions are not useful (see above)
- It allows for completion suggestions specific to each
- Bonus reason: it's a completion engine, not a user manual.

* Fix completion impacts on global environment
The completion script was making a couple of changes to the global environment
which had an impact for the rest of the shell session.

~set -o pipefail~: the change is hidden from the user and could lead to subtle
errors throughout the shell session

COMP_WORDBREAKS=" ": this affects subsequent completions for us and other
programs too. I exclude the colon =:= from its value and use
~compopt -o filenames~ to handle escaping of special characters for us. I would
like to find a solution without messing with COMP_WORDBREAKS but it is not
straight forward.

* Fix hiding of legit subcommands
Completion was hiding all possibilities if a subcommand happens to be the prefix
of another. On typing ~balance~, one should be proposed ~balancesheet~ and
~balancesheetequity~ as well.

* Return early
Try to complete depending on the current context and return immediately if
successful. Keep completion list relevant and as short as possible.

* Context aware completion
- Add handlers for option parameter completion, see _hledger_compreply_optarg()
- Add handlers for query filters:, see _hledger_compreply_query()
- Use --file and --rules-file arguments when proposing completions for the
  above, see _hledger()
- Propose only top level accounts at first. Again, keep it short and focused.

* Custom ~compgen~ wrapper
~compgen~ is fairly complicated. There is no way to feed it a word list with
literals. It will mangle your input in so many ways that we cannot trust it. To
work around this several wrappers are used: _hledger_compgen() works with
_hledger_quote_by_ref() to process and escape newline separated input which is
then fed to ~compgen~ and finally in ~COMPREPLY~ through _hledger_compreply()
and _hledger_compreply_append(). It sounds messy and I guess it is, I would like
to find a more straight forward way to do it. I think it is still a way better
and safer interface with ~readline~ than trying to ~grep~ our way through.

* Replace ~declare~ with ~local~
Again, this script is sourced by the shell -- keep variable scopes as narrow as
possible.

* Use ~compopt -o nosort~
Often I resort to using it to keep different groups of completions together.
Whether this is more ergonomic or not is subjective. But our input lists are
already sorted at build-time so why not. Sort manually =query-filters.txt= when
changing it.

* Remove irrelevant comments
And add some new ones :)

I think that is all. Give it a spin, try to abuse it, in and outside of quotes,
with some funky accounts, payees, tags, whatever, and tell me where it breaks or
behaves unexpectedly.
2021-02-28 08:33:16 +01:00

32 lines
867 B
Makefile

.PHONY: command-options clean
all: command-options hledger-completion.bash
hledger-completion.bash: hledger-completion.bash.m4 commands-list.txt query-filters.txt generic-options.txt
m4 hledger-completion.bash.m4 > $@
generic-options.txt:
hledger -h | ./output-options.sh | sort -u > $@
commands.txt:
hledger | ./output-commands.sh | grep -v ^hledger | sort -u > $@
echo ui >> $@
echo web >> $@
echo api >> $@
commands-list.txt: commands.txt
paste -sd, $^ | tr -d '\n' > $@
#query-filters.txt:
# The query filters are hard to extract!
# hledger help --cat hledger | sed -n '/^QUERIES/,/^[A-Z]/p'
command-options: commands.txt
parallel -j8 'hledger {} -h | ./output-options.sh {} | sort -u > options-{}.txt' < commands.txt
clean:
rm -f commands*.txt generic-options.txt options-*.txt
rm -f hledger-completion.bash
rm -rf _{commands,options}.tmp