@@ -77,7 +77,62 @@ func NewCmdRoot(changelog string) *cobra.Command {
7777 _ = k .Load (fileProvider , utils .ConfigParser ())
7878 })
7979 },
80- SilenceUsage : true ,
80+ ValidArgsFunction : completePlugins ,
81+ Args : cobra .MinimumNArgs (1 ),
82+ SilenceUsage : true ,
83+ RunE : func (cmd * cobra.Command , args []string ) error {
84+ if env , ok := os .LookupEnv ("SMALLWEB_DISABLE_PLUGINS" ); ok {
85+ if disablePlugins , _ := strconv .ParseBool (env ); disablePlugins {
86+ return cmd .Help ()
87+ }
88+ }
89+
90+ for _ , pluginDir := range []string {
91+ filepath .Join (k .String ("dir" ), ".smallweb" , "plugins" ),
92+ filepath .Join (xdg .DataHome , "smallweb" , "plugins" ),
93+ } {
94+ entries , err := os .ReadDir (pluginDir )
95+ if err != nil {
96+ continue
97+ }
98+
99+ for _ , entry := range entries {
100+ if entry .IsDir () {
101+ continue
102+ }
103+
104+ plugin := strings .TrimSuffix (entry .Name (), filepath .Ext (entry .Name ()))
105+ if plugin != args [0 ] {
106+ continue
107+ }
108+
109+ entrypoint := filepath .Join (pluginDir , entry .Name ())
110+
111+ if ok , err := isExecutable (entrypoint ); err != nil {
112+ return fmt .Errorf ("failed to check if plugin is executable: %w" , err )
113+ } else if ! ok {
114+ if err := os .Chmod (entrypoint , 0755 ); err != nil {
115+ return fmt .Errorf ("failed to make plugin executable: %w" , err )
116+ }
117+ }
118+
119+ command := exec .Command (entrypoint , args ... )
120+ command .Env = os .Environ ()
121+ command .Env = append (command .Env , fmt .Sprintf ("SMALLWEB_VERSION=%s" , build .Version ))
122+ command .Env = append (command .Env , fmt .Sprintf ("SMALLWEB_DIR=%s" , k .String ("dir" )))
123+ command .Env = append (command .Env , fmt .Sprintf ("SMALLWEB_DOMAIN=%s" , k .String ("domain" )))
124+
125+ command .Stdin = os .Stdin
126+ command .Stdout = os .Stdout
127+ command .Stderr = os .Stderr
128+
129+ cmd .SilenceErrors = true
130+ return command .Run ()
131+ }
132+ }
133+
134+ return fmt .Errorf ("unknown command \" %s\" for \" smallweb\" " , args [0 ])
135+ },
81136 }
82137
83138 rootCmd .PersistentFlags ().String ("dir" , "" , "The root directory for smallweb" )
@@ -127,16 +182,41 @@ func NewCmdRoot(changelog string) *cobra.Command {
127182 }
128183 }
129184
130- if env , ok := os .LookupEnv ("SMALLWEB_DISABLE_PLUGINS" ); ok {
131- if disablePlugins , _ := strconv .ParseBool (env ); disablePlugins {
132- return rootCmd
185+ return rootCmd
186+ }
187+
188+ func GetCommand (cmd * cobra.Command , name string ) (* cobra.Command , bool ) {
189+ for _ , c := range cmd .Commands () {
190+ if c .Name () == name {
191+ return c , true
133192 }
134193 }
135194
195+ return nil , false
196+ }
197+
198+ func isExecutable (path string ) (bool , error ) {
199+ fileInfo , err := os .Stat (path )
200+ if err != nil {
201+ return false , err
202+ }
203+ return fileInfo .Mode ().Perm ()& 0111 != 0 , nil
204+ }
205+
206+ func completePlugins (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
207+ flagProvider := posflag .Provider (cmd .Root ().PersistentFlags (), "." , k )
208+ _ = k .Load (flagProvider , nil )
209+
210+ if len (args ) > 0 {
211+ return nil , cobra .ShellCompDirectiveDefault
212+ }
213+
214+ var plugins []string
136215 for _ , pluginDir := range []string {
137216 filepath .Join (k .String ("dir" ), ".smallweb" , "plugins" ),
138217 filepath .Join (xdg .DataHome , "smallweb" , "plugins" ),
139218 } {
219+
140220 entries , err := os .ReadDir (pluginDir )
141221 if err != nil {
142222 continue
@@ -148,57 +228,11 @@ func NewCmdRoot(changelog string) *cobra.Command {
148228 }
149229
150230 plugin := strings .TrimSuffix (entry .Name (), filepath .Ext (entry .Name ()))
151- rootCmd .AddCommand (& cobra.Command {
152- Use : strings .TrimSuffix (entry .Name (), filepath .Ext (entry .Name ())),
153- Short : fmt .Sprintf ("Run the %s plugin" , plugin ),
154- RunE : func (cmd * cobra.Command , args []string ) error {
155- entrypoint := filepath .Join (pluginDir , entry .Name ())
156-
157- if ok , err := isExecutable (entrypoint ); err != nil {
158- return fmt .Errorf ("failed to check if plugin is executable: %w" , err )
159- } else if ! ok {
160- if err := os .Chmod (entrypoint , 0755 ); err != nil {
161- return fmt .Errorf ("failed to make plugin executable: %w" , err )
162- }
163- }
164-
165- command := exec .Command (entrypoint , args ... )
166- command .Env = os .Environ ()
167- command .Env = append (command .Env , fmt .Sprintf ("SMALLWEB_VERSION=%s" , build .Version ))
168- command .Env = append (command .Env , fmt .Sprintf ("SMALLWEB_DIR=%s" , k .String ("dir" )))
169- command .Env = append (command .Env , fmt .Sprintf ("SMALLWEB_DOMAIN=%s" , k .String ("domain" )))
170-
171- command .Stdin = os .Stdin
172- command .Stdout = os .Stdout
173- command .Stderr = os .Stderr
174-
175- cmd .SilenceErrors = true
176- return command .Run ()
177- },
178- })
179-
180- }
181- }
182-
183- return rootCmd
184- }
185-
186- func GetCommand (cmd * cobra.Command , name string ) (* cobra.Command , bool ) {
187- for _ , c := range cmd .Commands () {
188- if c .Name () == name {
189- return c , true
231+ plugins = append (plugins , plugin )
190232 }
191233 }
192234
193- return nil , false
194- }
195-
196- func isExecutable (path string ) (bool , error ) {
197- fileInfo , err := os .Stat (path )
198- if err != nil {
199- return false , err
200- }
201- return fileInfo .Mode ().Perm ()& 0111 != 0 , nil
235+ return plugins , cobra .ShellCompDirectiveDefault
202236}
203237
204238func completeApp (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
0 commit comments