Match only lines starting with white space because there are a lot
of option like strings in the discussion section that follows that
are not necessarily what we are after.
Make it obvious that the option expects an argument by appending
the equal sign on completion. Suspend space in this case. The
regular expression in `output-options.sh` is adjusted to take into
account this on processing option strings.
I was looking at how other programs that have an overwhelming
number of sub-commands and options deal with completion, namely
how git does it, and I liked the clean workflow not spitting every
available option until asked for. Hledger's main workflow is:
> hledger COMMAND QUERY
so I have tried to reproduce this with this change. Options are of
course still there, but not shown until you ask for them by entering
a dash on the command line. Also, the `acct:` filter proposes only top
level accounts until there is some input from the user because accounts
tend to be numerous as well.
Commit #64282f3f broke that somehow so I need to force the match on
an empty string after the equal sign, not the equal sign itself.
I think that _init_completion() does a bit more than I need...
This is about the looks of the completion list -- if we have a
directory with the name of a subcommand it will be presented with
a trailing slash. This avoids that.
This allows more flexibility when generating completion candidates
and we don't need to resort to external help from `sed` or others.
_hledger_compgen's arguments become:
$1 -> $wordlist:
a newline separated wordlist with completion cadidates
$2 -> $prefix:
(optional) a prefix string to add to generated completions
$3 -> $match:
(optional) a word to match instead of $cur, the default.
If $match is null and $prefix is defined the match is done against $cur
stripped of $prefix. If both $prefix and $match are null we match against
$cur and no prefix is added to completions. Of course you can also pass
an empty string as $prefix and set $match to whatever you wish.
This handles a lot that we have to do manually otherwise. Without
this we need to handle e.g. redirections to get completion for say:
> hledger payees > <TAB>
Also because this function assumes that we use `cur`, `prev`, `words`
and `cword` and sets them up for us, `wordToComplete`, `COMP_WORDS`
and `COMP_CWORD` are renamed accordingly. Those names are pretty much
hard-coded in bash completion so it is easier to follow the lead than
go with custom variable names.
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.
For clarity; infer-value was too vague. The old spelling remains
supported for compatibility, but is now deprecated.
When typing, --infer-market or even --infer (for now) is sufficient.
It seems to be convention to start the completion function name with an
underscore. I also prepend an underscore to the global variable.
(I still don't understand why env does not show this global variable
defined in the hledger-completion.bash script.)