Closed Drugoy closed 4 months ago
This is more involved than it initially seems. The reason is we go through all the GRAMMAR
-> REGEX
-> MINIMAL DFA
-> SHELL SCRIPT
transformations. While it is easy to keep track the order of alternatives at the GRAMMAR
and REGEX
steps, keeping track of them at the DFA
stage is I think impossible in the general case. Consider this extended grammar:
fake (<I> | <J>);
<I> ::= c | b | a ;
<J> ::= a | b | c ;
The resulting minimal DFA is going to look like this:
As you can see, there are conflicting expectations as to the order of transitions in the DFA: on one hand we expect (a, b, c), on the other (c, b, a). There’s no right answer in this case.
I think what you described is a corner case, so let's exclude it from the initial FR:
suppose that all arguments to be autocompleted are named args (as in --host
being the arg name in the psql --host blah
).
The list of such args shouldn't be alphabetically ordered.
Then there are lists of possible values for a specific named arg - nor those lists should be alphabetically ordered.
Is the task in such a reduced case achievable?
For cases like psql
above, you can simply specify options as a sequence in the grammar. E.g. for psql
to first complete —host
, only then —dbname
you write:
psql --host <HOST> --dbname <DBNAME>;
--host
and --dbname
as non-optional. But they are both optional. And I even might use --service
instead. Or any combination of these. So I wrote such a .usage:
psql [<OPTION>];
What shell are you on?
zsh 5.8
It’s zsh that’s doing the sorting, not complgen:
complgen produces completions in this order: --host --service --port --dbname
whereas they get displayed sorted by zsh
I am sorry, I don't understand zsh completions. Guys on #zsh @ irc.freenode.net said that it's just the way your util generates the completion rules that makes them sorted.
I've found that built-in zsh's completion list for gcc -{TAB}
is not sorted, for example (in particular -imacros
going way after -Wzerotrip
). I've tried to compare the file produced by complgen and /usr/share/zsh/functions/Completion/Unix/_gcc zsh's native autocompletion file and they are simply too different for me to figure out how to make complgen's artifact not sort suggested values.
I figured out the how to disable zsh’s sorting. It’s a matter of passing the right options to compadd
.
The way it’s currently called: compadd -d descrs -a args
.
The way it’s ought to be called to preserve order: compadd -J unsorted -o nosort -d descrs -a args
.
That’s not the whole story though. Hash tables are used extensively throughout complgen to represent DFA transitions. In order to get the order of options from the grammar, the hash table would need to be replaced with something that preserves the insertion order.
Guys on the channel first only suggested adding -o nosort
, which I tried and which didn't affect the result (so I hadn't even mentioned it to you).
But then they wrote this:
the autogenerating zsh completions cli tool doesn't use the helper functions that allow the user to change the sorting order if they desired but adding
-V
matches tocompadd
will leave them in the unsorted order, or if you truly want to use-o nosort
, you still need-J
matches thesort
style is for helper functions to know what to pass to the eventualcompadd
call:-V
,-J
and/or-o
directly callingcompadd
in your completer like that is ill advised in my opinion tho. you miss out on a lot of the perks that zsh completion system offers
After replacing compadd
in the script, produced by complgen
with compadd -J unsorted -o nosort
I got the desired behavior and became a tad bit happier :)
After replacing
compadd
in the script, produced bycomplgen
withcompadd -J unsorted -o nosort
I got the desired behavior and became a tad bit happier :)
Nice! If you get tired of editing it manually after every compilation and you’re up for a contribution, this functionality could be encoded in an additional option, like complgen compile --disable-sorting
. For zsh, it would do compadd -J unsorted -o nosort
, for bash complete -o nosort, for fish, complete --keep-order
. Should be a pretty short and easy patch.
Workaround is described in the comments, there's no known solution that would work in the general case, so I'm closing as not planned. The assumptions is complgen presents completions in the sorted order. That makes it easier to skim through completions and works across all shells.
Currently such such .usage's:
produce shell autocompletion rules where the items are suggested in alphabetical order (
1 2 3
in the first case anda b c
in the second) instead of the way they were ordered in the .usage files (I'd expect3 2 1
in the first case andc b a
in the second).