Support shell completion in vic-machine#7785
Conversation
1d3d54f to
713abdc
Compare
Codecov Report
@@ Coverage Diff @@
## master #7785 +/- ##
==========================================
+ Coverage 25.69% 26.52% +0.83%
==========================================
Files 35 36 +1
Lines 5125 5183 +58
==========================================
+ Hits 1317 1375 +58
Misses 3701 3701
Partials 107 107
Continue to review full report at Codecov.
|
b76cca6 to
652d50d
Compare
|
Testing of changes to |
652d50d to
0804d00
Compare
cmd/vic-machine/common/completion.go
Outdated
| func getNames(flag cli.Flag) []string { | ||
| names := strings.Split(flag.GetName(), ",") | ||
|
|
||
| var trimmedNames []string |
There was a problem hiding this comment.
Commenting on this doesn't make much sense, but I will still comment it from the future standpoint.
Since you know the lengths of trimmed names array you could preallocate it all at once, thus resulting in a less memory allocations.
trimmedNames := make([]string, len(names))
for i, name := range names {
trimmedNames[i] = strings.Trim(name, " ")
}There was a problem hiding this comment.
Looking at this blog post, it seems like I might be able to specify the desired capacity without setting a length:
trimmedNames := make([]string, 0, len(names))
for _, name := range names {
trimmedNames = append(trimmedNames, strings.Trim(name, " "))
}I find that more intuitive than setting a length up-front, since this way the length is always accurate (after the second iteration through the loop the length would be 2, and so on).
Would there be disadvantages to doing it this way, versus what you suggest?
|
|
||
| // findFlag searches a haystack of cli.Flag objects for the first with a name matching the needle. | ||
| func findFlag(needle string, haystack []cli.Flag) cli.Flag { | ||
| for _, f := range haystack { |
There was a problem hiding this comment.
O(m*n) :(
sure... it works fine.
There was a problem hiding this comment.
A couple of factors led me here:
- To do better, I need a sorted list. With the sorted list, I could do searches in
O(log(n*m)). However initializing that sorted list actually takesO(n*m*log(n*m)). If I needed to find a lot of things (more thanlog(n*m)), that might be worth it, but in this case I'm only ever searching once so the initialization cost would dominate. - In our code,
getNamesalways returns 1-2 elements (a long flag and maybe a short flag), so that's essential a constant factor. - The current pattern allows us to bail out as soon as we've found what we're looking for.
There was a problem hiding this comment.
Yah, that's why I said it works fine. Even if there were hundreds of elements in each list, it would not be really noticeable.
cmd/vic-machine/common/completion.go
Outdated
|
|
||
| // If the argument begins with a hypen, we *guess* that it's probably a flag. | ||
| if strings.HasPrefix(lastArg, "-") { | ||
| lastFlag := findFlag(strings.Trim(os.Args[len(os.Args)-2], "-"), flags) |
There was a problem hiding this comment.
didn't you get lastArg already? it would simplify this code
60c682b to
55acd80
Compare
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users.
714042c to
2bbb2f0
Compare
2bbb2f0 to
68105bb
Compare
|
Don't we need integration tests for this? At least, just to make sure autocomplete can be enabled? |
I'm not sure how to write an integration test for this. We'd need a way to open a shell, source a script, and enter characters as a user would (including pressing "tab"). That doesn't seem possible from Robot. Edit: For what it's worth, the autocomplete scripts will not be changing frequently (even across the history of urfave/cli, each only has a handful of revisions). It seems like the easiest thing might be to manually test those any time we do have to make changes to them; the go code is entirely covered by unit tests. |
|
@zjs I agree its complicated to write such tests but I think its possible. We already execute lot of shell commands in existing robot tests but tab press would complicate it a little. I would suggest at least creating an issue to add tests later. Otherwise, LGTM. |
|
Issue to track integration testing: #7850 |
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users. (cherry picked from commit 26ee2f9)
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users. (cherry picked from commit 26ee2f9)
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users. (cherry picked from commit 26ee2f9)
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users. (cherry picked from commit 26ee2f9)
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users. (cherry picked from commit 26ee2f9)
Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine. Package bash and zsh completion scripts for use by users. (cherry picked from commit 26ee2f9)
Implement a
cli.BashCompleteFuncfactory and use it to supply an appropriate instance with eachcli.Commandinvic-machine.To try this functionality on Linux, you could run the following command after checking out and building this topic branch. (Replace
linuxwithdarwinorwindowsand/orbashwithzshas necessary.)A customer would just run a command like the following from the root of the extracted
vic_*.tar.gz.Some example output showing completion suggestions: