@@ -7,7 +7,10 @@ import (
7
7
"os"
8
8
"runtime/debug"
9
9
10
- "github.com/posener/complete/v2"
10
+ "github.com/pkg/errors"
11
+ "github.com/posener/complete"
12
+ "github.com/rs/zerolog"
13
+ "github.com/symfony-cli/terminal"
11
14
)
12
15
13
16
func init () {
@@ -47,41 +50,50 @@ func registerAutocompleteCommands(a *Application) {
47
50
}
48
51
49
52
func AutocompleteAppAction (c * Context ) error {
53
+ // connect posener/complete logger to our logging facilities
54
+ logger := terminal .Logger .WithLevel (zerolog .DebugLevel )
55
+ complete .Log = func (format string , args ... interface {}) {
56
+ logger .Msgf ("completion | " + format , args ... )
57
+ }
58
+
50
59
cmd := complete.Command {
51
- Flags : map [ string ] complete.Predictor {} ,
52
- Sub : map [ string ] * complete.Command {} ,
60
+ GlobalFlags : make ( complete.Flags ) ,
61
+ Sub : make ( complete.Commands ) ,
53
62
}
54
63
55
64
// transpose registered commands and flags to posener/complete equivalence
56
65
for _ , command := range c .App .VisibleCommands () {
57
66
subCmd := command .convertToPosenerCompleteCommand (c )
58
67
59
68
for _ , name := range command .Names () {
60
- cmd .Sub [name ] = & subCmd
69
+ cmd .Sub [name ] = subCmd
61
70
}
62
71
}
63
72
64
73
for _ , f := range c .App .VisibleFlags () {
65
74
if vf , ok := f .(* verbosityFlag ); ok {
66
- vf .addToPosenerFlags (c , cmd .Flags )
75
+ vf .addToPosenerFlags (c , cmd .GlobalFlags )
67
76
continue
68
77
}
69
78
70
79
predictor := ContextPredictor {f , c }
71
80
72
81
for _ , name := range f .Names () {
73
82
name = fmt .Sprintf ("%s%s" , prefixFor (name ), name )
74
- cmd .Flags [name ] = predictor
83
+ cmd .GlobalFlags [name ] = predictor
75
84
}
76
85
}
77
86
78
- cmd .Complete (c .App .HelpName )
87
+ if ! complete .New (c .App .HelpName , cmd ).Complete () {
88
+ return errors .New ("Could not run auto-completion" )
89
+ }
90
+
79
91
return nil
80
92
}
81
93
82
94
func (c * Command ) convertToPosenerCompleteCommand (ctx * Context ) complete.Command {
83
95
command := complete.Command {
84
- Flags : map [ string ] complete.Predictor {} ,
96
+ Flags : make ( complete.Flags , 0 ) ,
85
97
}
86
98
87
99
for _ , f := range c .VisibleFlags () {
@@ -98,16 +110,16 @@ func (c *Command) convertToPosenerCompleteCommand(ctx *Context) complete.Command
98
110
return command
99
111
}
100
112
101
- func (c * Command ) PredictArgs (ctx * Context , prefix string ) []string {
113
+ func (c * Command ) PredictArgs (ctx * Context , a complete. Args ) []string {
102
114
if c .ShellComplete != nil {
103
- return c .ShellComplete (ctx , prefix )
115
+ return c .ShellComplete (ctx , a )
104
116
}
105
117
106
118
return nil
107
119
}
108
120
109
121
type Predictor interface {
110
- PredictArgs (* Context , string ) []string
122
+ PredictArgs (* Context , complete. Args ) []string
111
123
}
112
124
113
125
// ContextPredictor determines what terms can follow a command or a flag
@@ -119,6 +131,6 @@ type ContextPredictor struct {
119
131
}
120
132
121
133
// Predict invokes the predict function and implements the Predictor interface
122
- func (p ContextPredictor ) Predict (prefix string ) []string {
123
- return p .predictor .PredictArgs (p .ctx , prefix )
134
+ func (p ContextPredictor ) Predict (a complete. Args ) []string {
135
+ return p .predictor .PredictArgs (p .ctx , a )
124
136
}
0 commit comments