@@ -59,7 +59,7 @@ type Command struct {
5959 Middleware MiddlewareFunc
6060 Handler HandlerFunc
6161 HelpHandler HandlerFunc
62- // CompletionHandler is called when the command is run is completion
62+ // CompletionHandler is called when the command is run in completion
6363 // mode. If nil, only the default completion handler is used.
6464 //
6565 // Flag and option parsing is best-effort in this mode, so even if an Option
@@ -187,7 +187,6 @@ func (c *Command) Invoke(args ...string) *Invocation {
187187 return & Invocation {
188188 Command : c ,
189189 Args : args ,
190- AllArgs : args ,
191190 Stdout : io .Discard ,
192191 Stderr : io .Discard ,
193192 Stdin : strings .NewReader ("" ),
@@ -204,9 +203,6 @@ type Invocation struct {
204203 // Args is reduced into the remaining arguments after parsing flags
205204 // during Run.
206205 Args []string
207- // AllArgs is the original arguments passed to the command, including flags.
208- // When invoked `WithOS`, this includes argv[0], otherwise it is the same as Args.
209- AllArgs []string
210206 // CurWord is the word the terminal cursor is currently in
211207 CurWord string
212208
@@ -233,7 +229,6 @@ func (inv *Invocation) WithOS() *Invocation {
233229 i .Stdout = os .Stdout
234230 i .Stderr = os .Stderr
235231 i .Stdin = os .Stdin
236- i .AllArgs = os .Args
237232 i .Args = os .Args [1 :]
238233 i .Environ = ParseEnviron (os .Environ (), "" )
239234 i .Net = osNet {}
@@ -302,13 +297,13 @@ func copyFlagSetWithout(fs *pflag.FlagSet, without string) *pflag.FlagSet {
302297 return fs2
303298}
304299
305- func (inv * Invocation ) GetCurWords () (prev string , cur string ) {
306- if len (inv .AllArgs ) == 1 {
307- cur = inv .AllArgs [0 ]
300+ func (inv * Invocation ) curWords () (prev string , cur string ) {
301+ if len (inv .Args ) == 1 {
302+ cur = inv .Args [0 ]
308303 prev = ""
309304 } else {
310- cur = inv .AllArgs [len (inv .AllArgs )- 1 ]
311- prev = inv .AllArgs [len (inv .AllArgs )- 2 ]
305+ cur = inv .Args [len (inv .Args )- 1 ]
306+ prev = inv .Args [len (inv .Args )- 2 ]
312307 }
313308 return
314309}
@@ -409,7 +404,39 @@ func (inv *Invocation) run(state *runState) error {
409404 }
410405 }
411406
412- ignoreFlagParseErrors := inv .Command .RawArgs || inv .IsCompletionMode ()
407+ // Outputted completions are not filtered based on the word under the cursor, as every shell we support does this already.
408+ // We only look at the current word to figure out handler to run, or what directory to inspect.
409+ if inv .IsCompletionMode () {
410+ prev , cur := inv .curWords ()
411+ inv .CurWord = cur
412+ // If the current word is a flag set using `=`, use it's handler
413+ if strings .HasPrefix (cur , "--" ) && strings .Contains (cur , "=" ) {
414+ if inv .equalsFlagHandler (cur ) {
415+ return nil
416+ }
417+ }
418+ // If the previous word is a flag, then we're writing it's value
419+ // and we should check it's handler
420+ if strings .HasPrefix (prev , "--" ) {
421+ if inv .flagHandler (prev ) {
422+ return nil
423+ }
424+ }
425+ // If the current word is the command, auto-complete it so the shell moves the cursor
426+ if inv .Command .Name () == inv .CurWord {
427+ fmt .Fprintf (inv .Stdout , "%s\n " , inv .Command .Name ())
428+ return nil
429+ }
430+ if inv .Command .CompletionHandler == nil {
431+ inv .Command .CompletionHandler = DefaultCompletionHandler
432+ }
433+ for _ , e := range inv .Command .CompletionHandler (inv ) {
434+ fmt .Fprintf (inv .Stdout , "%s\n " , e )
435+ }
436+ return nil
437+ }
438+
439+ ignoreFlagParseErrors := inv .Command .RawArgs
413440
414441 // Flag parse errors are irrelevant for raw args commands.
415442 if ! ignoreFlagParseErrors && state .flagParseErr != nil && ! errors .Is (state .flagParseErr , pflag .ErrHelp ) {
@@ -464,39 +491,6 @@ func (inv *Invocation) run(state *runState) error {
464491 defer cancel ()
465492 inv = inv .WithContext (ctx )
466493
467- // Outputted completions are not filtered based on the word under the cursor, as every shell we support does this already.
468- // We only look at the current word to figure out handler to run, or what directory to inspect.
469- if inv .IsCompletionMode () {
470- prev , cur := inv .GetCurWords ()
471- inv .CurWord = cur
472- // If the current word is a flag set using `=`, use it's handler
473- if strings .HasPrefix (cur , "--" ) && strings .Contains (cur , "=" ) {
474- if inv .equalsFlagHandler (cur ) {
475- return nil
476- }
477- }
478- // If the previous word is a flag, then we're writing it's value
479- // and we should check it's handler
480- if strings .HasPrefix (prev , "--" ) {
481- if inv .flagHandler (prev ) {
482- return nil
483- }
484- }
485- if inv .Command .Name () == inv .CurWord {
486- fmt .Fprintf (inv .Stdout , "%s\n " , inv .Command .Name ())
487- return nil
488- }
489- if inv .Command .CompletionHandler != nil {
490- for _ , e := range inv .Command .CompletionHandler (inv ) {
491- fmt .Fprintf (inv .Stdout , "%s\n " , e )
492- }
493- }
494- for _ , e := range DefaultCompletionHandler (inv ) {
495- fmt .Fprintf (inv .Stdout , "%s\n " , e )
496- }
497- return nil
498- }
499-
500494 if inv .Command .Handler == nil || errors .Is (state .flagParseErr , pflag .ErrHelp ) {
501495 if inv .Command .HelpHandler == nil {
502496 return defaultHelpFn ()(inv )
@@ -743,5 +737,3 @@ func RequireRangeArgs(start, end int) MiddlewareFunc {
743737type HandlerFunc func (i * Invocation ) error
744738
745739type CompletionHandlerFunc func (i * Invocation ) []string
746-
747- var NopHandler HandlerFunc = func (i * Invocation ) error { return nil }
0 commit comments