@@ -203,8 +203,6 @@ type Invocation struct {
203203 // Args is reduced into the remaining arguments after parsing flags
204204 // during Run.
205205 Args []string
206- // CurWord is the word the terminal cursor is currently in
207- CurWord string
208206
209207 // Environ is a list of environment variables. Use EnvsWithPrefix to parse
210208 // os.Environ.
@@ -297,7 +295,7 @@ func copyFlagSetWithout(fs *pflag.FlagSet, without string) *pflag.FlagSet {
297295 return fs2
298296}
299297
300- func (inv * Invocation ) curWords () (prev string , cur string ) {
298+ func (inv * Invocation ) CurWords () (prev string , cur string ) {
301299 if len (inv .Args ) == 1 {
302300 cur = inv .Args [0 ]
303301 prev = ""
@@ -407,7 +405,7 @@ func (inv *Invocation) run(state *runState) error {
407405 // Outputted completions are not filtered based on the word under the cursor, as every shell we support does this already.
408406 // We only look at the current word to figure out handler to run, or what directory to inspect.
409407 if inv .IsCompletionMode () {
410- for _ , e := range inv .doCompletions () {
408+ for _ , e := range inv .complete () {
411409 fmt .Fprintln (inv .Stdout , e )
412410 }
413411 return nil
@@ -590,24 +588,36 @@ func (inv *Invocation) with(fn func(*Invocation)) *Invocation {
590588 return & i2
591589}
592590
593- func (inv * Invocation ) doCompletions () []string {
594- prev , cur := inv .curWords ()
595- inv .CurWord = cur
596- // If the current word is a flag set using `=`, use it's handler
597- if strings .HasPrefix (cur , "--" ) && strings .Contains (cur , "=" ) {
598- if out := inv .equalsFlagCompletions (cur ); out != nil {
599- return out
591+ func (inv * Invocation ) complete () []string {
592+ prev , cur := inv .CurWords ()
593+
594+ if strings .HasPrefix (cur , "--" ) {
595+ // If the current word is a flag set using `=`, use it's handler
596+ if strings .Contains (cur , "=" ) {
597+ words := strings .Split (cur , "=" )
598+ flagName := words [0 ][2 :]
599+ if out := inv .completeFlag (flagName ); out != nil {
600+ for i , o := range out {
601+ out [i ] = fmt .Sprintf ("--%s=%s" , flagName , o )
602+ }
603+ return out
604+ }
605+ } else if out := inv .Command .Options .ByFlag (cur [2 :]); out != nil {
606+ // If the current word is a complete flag, auto-complete it so the
607+ // shell moves the cursor
608+ return []string {cur }
600609 }
601610 }
602611 // If the previous word is a flag, then we're writing it's value
603612 // and we should check it's handler
604613 if strings .HasPrefix (prev , "--" ) {
605- if out := inv .flagCompletions (prev ); out != nil {
614+ word := prev [2 :]
615+ if out := inv .completeFlag (word ); out != nil {
606616 return out
607617 }
608618 }
609- // If the current word is the command, auto-complete it so the shell moves the cursor
610- if inv .Command .Name () == inv . CurWord {
619+ // If the current word is the command, move the shell cursor
620+ if inv .Command .Name () == cur {
611621 return []string {inv .Command .Name ()}
612622 }
613623 var completions []string
@@ -621,43 +631,17 @@ func (inv *Invocation) doCompletions() []string {
621631 return completions
622632}
623633
624- func (inv * Invocation ) flagCompletions (word string ) []string {
625- return inv .doFlagCompletions ("" , word )
626- }
627-
628- func (inv * Invocation ) equalsFlagCompletions (word string ) []string {
629- words := strings .Split (word , "=" )
630- word = words [0 ]
631- if len (words ) > 1 {
632- inv .CurWord = words [1 ]
633- } else {
634- inv .CurWord = ""
635- }
636- prefix := word + "="
637- return inv .doFlagCompletions (prefix , word )
638- }
639-
640- func (inv * Invocation ) doFlagCompletions (prefix , word string ) []string {
641- opt := inv .Command .Options .ByFlag (word [2 :])
634+ func (inv * Invocation ) completeFlag (word string ) []string {
635+ opt := inv .Command .Options .ByFlag (word )
642636 if opt == nil {
643637 return nil
644638 }
645639 if opt .CompletionHandler != nil {
646- completions := opt .CompletionHandler (inv )
647- out := make ([]string , 0 , len (completions ))
648- for _ , completion := range completions {
649- out = append (out , fmt .Sprintf ("%s%s" , prefix , completion ))
650- }
651- return out
640+ return opt .CompletionHandler (inv )
652641 }
653642 val , ok := opt .Value .(* Enum )
654643 if ok {
655- completions := val .Choices
656- out := make ([]string , 0 , len (completions ))
657- for _ , choice := range completions {
658- out = append (out , fmt .Sprintf ("%s%s" , prefix , choice ))
659- }
660- return out
644+ return val .Choices
661645 }
662646 return nil
663647}
0 commit comments