@@ -14,7 +14,11 @@ import (
1414)
1515
1616func newBudgetsCommand (ctx context.Context , state * runtimeState , stdout io.Writer ) * cobra.Command {
17- cmd := & cobra.Command {Use : "budgets" }
17+ cmd := & cobra.Command {
18+ Use : "budgets" ,
19+ Short : "Manage budgets" ,
20+ Example : " money budgets list\n money budgets create --name Groceries --period monthly --start-date 2024-01-01 --end-date 2024-12-31 --confirm\n money budgets get <id>\n money budgets delete <id>" ,
21+ }
1822 cmd .AddCommand (newBudgetsListCommand (ctx , state , stdout ))
1923 cmd .AddCommand (newBudgetsCreateCommand (ctx , state , stdout ))
2024 cmd .AddCommand (newBudgetsGetCommand (ctx , state , stdout ))
@@ -26,8 +30,9 @@ func newBudgetsCommand(ctx context.Context, state *runtimeState, stdout io.Write
2630func newBudgetsListCommand (ctx context.Context , state * runtimeState , stdout io.Writer ) * cobra.Command {
2731 var verbose bool
2832 cmd := & cobra.Command {
29- Use : "list" ,
30- Short : "List budgets" ,
33+ Use : "list" ,
34+ Short : "List budgets" ,
35+ Example : " money budgets list\n money budgets list --verbose --json" ,
3136 RunE : func (cmd * cobra.Command , args []string ) error {
3237 activeStore , err := requireStore (state )
3338 if err != nil {
@@ -68,8 +73,9 @@ func newBudgetsCreateCommand(ctx context.Context, state *runtimeState, stdout io
6873 var name , currency , period , startDate , endDate string
6974 var dryRun , confirm bool
7075 cmd := & cobra.Command {
71- Use : "create" ,
72- Short : "Create a budget" ,
76+ Use : "create" ,
77+ Short : "Create a budget" ,
78+ Example : " money budgets create --name Groceries --period monthly --start-date 2024-01-01 --end-date 2024-12-31 --confirm\n money budgets create --name Rent --period yearly --start-date 2024-01-01 --end-date 2024-12-31 --dry-run" ,
7379 RunE : func (cmd * cobra.Command , args []string ) error {
7480 if state .json && ! dryRun && ! confirm {
7581 return cliError {
@@ -100,7 +106,7 @@ func newBudgetsCreateCommand(ctx context.Context, state *runtimeState, stdout io
100106 env .Meta .Demo = state .demo
101107 return contracts .WriteJSON (stdout , env )
102108 }
103- fmt .Fprintf (stdout , "Would create budget %q (%s, %s to %s)\n " , budget .Name , budget .Period , budget .StartDate , budget .EndDate )
109+ _ , _ = fmt .Fprintf (stdout , "Would create budget %q (%s, %s to %s)\n " , budget .Name , budget .Period , budget .StartDate , budget .EndDate )
104110 return nil
105111 }
106112 activeStore , err := requireStore (state )
@@ -116,13 +122,16 @@ func newBudgetsCreateCommand(ctx context.Context, state *runtimeState, stdout io
116122 env .Meta .Demo = state .demo
117123 return contracts .WriteJSON (stdout , env )
118124 }
119- fmt .Fprintf (stdout , "Created budget %s (%s)\n " , created .Name , created .ID )
125+ _ , _ = fmt .Fprintf (stdout , "Created budget %s (%s)\n " , created .Name , created .ID )
120126 return nil
121127 },
122128 }
123129 cmd .Flags ().StringVar (& name , "name" , "" , "budget name" )
124130 cmd .Flags ().StringVar (& currency , "currency" , "USD" , "budget currency" )
125131 cmd .Flags ().StringVar (& period , "period" , "monthly" , "budget period: monthly or yearly" )
132+ _ = cmd .RegisterFlagCompletionFunc ("period" , func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
133+ return []string {"monthly" , "yearly" }, cobra .ShellCompDirectiveNoFileComp
134+ })
126135 cmd .Flags ().StringVar (& startDate , "start-date" , "" , "budget start date (YYYY-MM-DD)" )
127136 cmd .Flags ().StringVar (& endDate , "end-date" , "" , "budget end date (YYYY-MM-DD)" )
128137 cmd .Flags ().BoolVar (& dryRun , "dry-run" , false , "show write plan without saving" )
@@ -135,6 +144,21 @@ func newBudgetsGetCommand(ctx context.Context, state *runtimeState, stdout io.Wr
135144 Use : "get <id>" ,
136145 Short : "Get a budget with its categories" ,
137146 Args : cobra .ExactArgs (1 ),
147+ ValidArgsFunction : func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
148+ activeStore , err := requireStore (state )
149+ if err != nil {
150+ return nil , cobra .ShellCompDirectiveNoFileComp
151+ }
152+ budgets , err := activeStore .ListBudgets (ctx )
153+ if err != nil {
154+ return nil , cobra .ShellCompDirectiveNoFileComp
155+ }
156+ var ids []string
157+ for _ , b := range budgets {
158+ ids = append (ids , b .ID + "\t " + b .Name )
159+ }
160+ return ids , cobra .ShellCompDirectiveNoFileComp
161+ },
138162 RunE : func (cmd * cobra.Command , args []string ) error {
139163 activeStore , err := requireStore (state )
140164 if err != nil {
@@ -145,12 +169,12 @@ func newBudgetsGetCommand(ctx context.Context, state *runtimeState, stdout io.Wr
145169 return err
146170 }
147171 if ! state .json {
148- fmt .Fprintf (stdout , "Budget: %s (%s)\n " , budget .Name , budget .ID )
149- fmt .Fprintf (stdout , "Period: %s\n " , budget .Period )
150- fmt .Fprintf (stdout , "Range: %s to %s\n " , budget .StartDate , budget .EndDate )
151- fmt .Fprintf (stdout , "Currency: %s\n " , budget .Currency )
172+ _ , _ = fmt .Fprintf (stdout , "Budget: %s (%s)\n " , budget .Name , budget .ID )
173+ _ , _ = fmt .Fprintf (stdout , "Period: %s\n " , budget .Period )
174+ _ , _ = fmt .Fprintf (stdout , "Range: %s to %s\n " , budget .StartDate , budget .EndDate )
175+ _ , _ = fmt .Fprintf (stdout , "Currency: %s\n " , budget .Currency )
152176 if len (budget .Categories ) > 0 {
153- fmt .Fprintln (stdout , "Categories:" )
177+ _ , _ = fmt .Fprintln (stdout , "Categories:" )
154178 table := tablewriter .NewWriter (stdout )
155179 table .SetHeader ([]string {"NAME" , "LIMIT" , "CATEGORY ID" })
156180 table .SetBorder (false )
@@ -177,6 +201,21 @@ func newBudgetsDeleteCommand(ctx context.Context, state *runtimeState, stdout io
177201 Use : "delete <id>" ,
178202 Short : "Delete a budget" ,
179203 Args : cobra .ExactArgs (1 ),
204+ ValidArgsFunction : func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
205+ activeStore , err := requireStore (state )
206+ if err != nil {
207+ return nil , cobra .ShellCompDirectiveNoFileComp
208+ }
209+ budgets , err := activeStore .ListBudgets (ctx )
210+ if err != nil {
211+ return nil , cobra .ShellCompDirectiveNoFileComp
212+ }
213+ var ids []string
214+ for _ , b := range budgets {
215+ ids = append (ids , b .ID + "\t " + b .Name )
216+ }
217+ return ids , cobra .ShellCompDirectiveNoFileComp
218+ },
180219 RunE : func (cmd * cobra.Command , args []string ) error {
181220 activeStore , err := requireStore (state )
182221 if err != nil {
@@ -190,14 +229,18 @@ func newBudgetsDeleteCommand(ctx context.Context, state *runtimeState, stdout io
190229 env .Meta .Demo = state .demo
191230 return contracts .WriteJSON (stdout , env )
192231 }
193- fmt .Fprintf (stdout , "Deleted budget %s\n " , args [0 ])
232+ _ , _ = fmt .Fprintf (stdout , "Deleted budget %s\n " , args [0 ])
194233 return nil
195234 },
196235 }
197236}
198237
199238func newBudgetCategoriesCommand (ctx context.Context , state * runtimeState , stdout io.Writer ) * cobra.Command {
200- cmd := & cobra.Command {Use : "categories" }
239+ cmd := & cobra.Command {
240+ Use : "categories" ,
241+ Short : "Manage budget categories" ,
242+ Example : " money budgets categories create --budget-id <id> --name Groceries --limit 50000 --confirm\n money budgets categories delete <id>" ,
243+ }
201244 cmd .AddCommand (newBudgetCategoriesCreateCommand (ctx , state , stdout ))
202245 cmd .AddCommand (newBudgetCategoriesDeleteCommand (ctx , state , stdout ))
203246 return cmd
@@ -208,8 +251,9 @@ func newBudgetCategoriesCreateCommand(ctx context.Context, state *runtimeState,
208251 var limitMinor int64
209252 var dryRun , confirm bool
210253 cmd := & cobra.Command {
211- Use : "create" ,
212- Short : "Create a budget category" ,
254+ Use : "create" ,
255+ Short : "Create a budget category" ,
256+ Example : " money budgets categories create --budget-id <id> --name Groceries --limit 50000 --confirm\n money budgets categories create --budget-id <id> --name Dining --limit 30000 --currency USD --dry-run" ,
213257 RunE : func (cmd * cobra.Command , args []string ) error {
214258 if state .json && ! dryRun && ! confirm {
215259 return cliError {
@@ -240,7 +284,7 @@ func newBudgetCategoriesCreateCommand(ctx context.Context, state *runtimeState,
240284 env .Meta .Demo = state .demo
241285 return contracts .WriteJSON (stdout , env )
242286 }
243- fmt .Fprintf (stdout , "Would create budget category %q with limit %s %s\n " , bc .Name , core .FormatMinorUnits (bc .LimitMinorUnits , bc .Currency ), bc .Currency )
287+ _ , _ = fmt .Fprintf (stdout , "Would create budget category %q with limit %s %s\n " , bc .Name , core .FormatMinorUnits (bc .LimitMinorUnits , bc .Currency ), bc .Currency )
244288 return nil
245289 }
246290 activeStore , err := requireStore (state )
@@ -256,7 +300,7 @@ func newBudgetCategoriesCreateCommand(ctx context.Context, state *runtimeState,
256300 env .Meta .Demo = state .demo
257301 return contracts .WriteJSON (stdout , env )
258302 }
259- fmt .Fprintf (stdout , "Created budget category %s (%s)\n " , created .Name , created .ID )
303+ _ , _ = fmt .Fprintf (stdout , "Created budget category %s (%s)\n " , created .Name , created .ID )
260304 return nil
261305 },
262306 }
@@ -275,6 +319,23 @@ func newBudgetCategoriesDeleteCommand(ctx context.Context, state *runtimeState,
275319 Use : "delete <id>" ,
276320 Short : "Delete a budget category" ,
277321 Args : cobra .ExactArgs (1 ),
322+ ValidArgsFunction : func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
323+ activeStore , err := requireStore (state )
324+ if err != nil {
325+ return nil , cobra .ShellCompDirectiveNoFileComp
326+ }
327+ budgets , err := activeStore .ListBudgets (ctx )
328+ if err != nil {
329+ return nil , cobra .ShellCompDirectiveNoFileComp
330+ }
331+ var ids []string
332+ for _ , b := range budgets {
333+ for _ , bc := range b .Categories {
334+ ids = append (ids , bc .ID + "\t " + bc .Name + " (" + b .Name + ")" )
335+ }
336+ }
337+ return ids , cobra .ShellCompDirectiveNoFileComp
338+ },
278339 RunE : func (cmd * cobra.Command , args []string ) error {
279340 activeStore , err := requireStore (state )
280341 if err != nil {
@@ -288,7 +349,7 @@ func newBudgetCategoriesDeleteCommand(ctx context.Context, state *runtimeState,
288349 env .Meta .Demo = state .demo
289350 return contracts .WriteJSON (stdout , env )
290351 }
291- fmt .Fprintf (stdout , "Deleted budget category %s\n " , args [0 ])
352+ _ , _ = fmt .Fprintf (stdout , "Deleted budget category %s\n " , args [0 ])
292353 return nil
293354 },
294355 }
0 commit comments