Skip to content

Commit 2bd68e7

Browse files
committed
feat: add subcommand help
1 parent 087385d commit 2bd68e7

2 files changed

Lines changed: 287 additions & 5 deletions

File tree

apps/go-cli/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
deckops

apps/go-cli/main.go

Lines changed: 286 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ func newAppContext(jsonOut bool) (*appContext, error) {
185185
}
186186

187187
func dispatch(ctx *appContext, args []string) error {
188+
if len(args) > 1 && hasHelpFlag(args[1:]) {
189+
if printCommandHelp(args) {
190+
return nil
191+
}
192+
}
193+
188194
switch args[0] {
189195
case "config":
190196
return ctx.runConfig(args[1:])
@@ -233,6 +239,281 @@ Commands:
233239
run Run a task with explicit type`)
234240
}
235241

242+
func hasHelpFlag(args []string) bool {
243+
for _, arg := range args {
244+
if arg == "-h" || arg == "--help" {
245+
return true
246+
}
247+
}
248+
return false
249+
}
250+
251+
func printCommandHelp(args []string) bool {
252+
switch args[0] {
253+
case "config":
254+
return printConfigHelp(args[1:])
255+
case "login":
256+
fmt.Println(`Usage:
257+
deckops login [options]
258+
259+
Login to Deckflow and save authentication token
260+
261+
Options:
262+
--port <port> Local server port for callback (default: 3737)
263+
-h, --help display help for command`)
264+
case "task":
265+
return printTaskHelp(args[1:])
266+
case "compress":
267+
fmt.Println(`Usage:
268+
deckops compress [options] <input-file>
269+
270+
Compress a file
271+
272+
Options:
273+
-o, --out <path> Write completed task output to a file or directory
274+
--no-wait Do not wait for task completion
275+
--timeout <seconds> Timeout in seconds (default: 300)
276+
-h, --help display help for command`)
277+
case "extract":
278+
fmt.Println(`Usage:
279+
deckops extract [options] <input-file>
280+
281+
Extract information from a file (fonts, text-shapes)
282+
283+
Options:
284+
--type <type> Extract type: fonts, text-shapes
285+
-o, --out <path> Write completed task output to a file or directory
286+
--no-wait Do not wait for task completion
287+
--timeout <seconds> Timeout in seconds (default: 300)
288+
-h, --help display help for command`)
289+
case "ocr":
290+
fmt.Printf(`Usage:
291+
deckops ocr [options] <input-file>
292+
293+
Extract text from images using OCR
294+
295+
Options:
296+
--language <lang> OCR language (%s) (default: %s)
297+
-o, --out <path> Write completed task output to a file or directory
298+
--no-wait Do not wait for task completion
299+
--timeout <seconds> Timeout in seconds (default: 300)
300+
-h, --help display help for command
301+
`, strings.Join(ocrLanguages, ", "), defaultOCRLanguage)
302+
case "convert":
303+
fmt.Printf(`Usage:
304+
deckops convert [options] <input-files...>
305+
306+
Convert file(s) to a different format
307+
308+
Options:
309+
--to <format> Output format: %s
310+
--width <number> Width for html->pptx/html->png conversion (only applies to .html --to pptx/png)
311+
--height <number> Height for html->pptx/html->png conversion (only applies to .html --to pptx/png)
312+
--need-embed-fonts [bool] Whether to embed fonts for html->pptx conversion (default: false)
313+
-o, --out <path> Write completed task output to a file or directory
314+
--no-wait Do not wait for task completion
315+
--timeout <seconds> Timeout in seconds (default: 300)
316+
-h, --help display help for command
317+
318+
Examples:
319+
$ deckops convert slides.pptx --to pdf
320+
$ deckops convert page1.html page2.html --to pptx
321+
322+
Multiple input files create one ordered conversion task only for html -> pptx.
323+
`, strings.Join(keysNested(renderFormats), ", "))
324+
case "join":
325+
fmt.Println(`Usage:
326+
deckops join [options] <input-files...>
327+
328+
Merge multiple pptx files into one (in the given order)
329+
330+
Options:
331+
--name <name> Output task name (defaults to first input file name)
332+
-o, --out <path> Write completed task output to a file or directory
333+
--no-wait Do not wait for task completion
334+
--timeout <seconds> Timeout in seconds (default: 300)
335+
-h, --help display help for command
336+
337+
Example:
338+
$ deckops join intro.pptx body.pptx appendix.pptx
339+
340+
Files are merged into one task in the order provided.`)
341+
case "create":
342+
fmt.Println(`Usage:
343+
deckops create [options] [input-files...]
344+
345+
Create document content
346+
347+
Options:
348+
--input-text <text> Input text from user
349+
--enable-search [bool] Enable search
350+
--advanced-model [bool] Use advanced model
351+
--fast-mode [bool] Enable fast mode
352+
--intent <intent> Content generation intent
353+
--audience <audience> Target audience
354+
--page-count <number> Expected page count
355+
--author <name> Document author
356+
-o, --out <path> Write completed task output to a file or directory
357+
--no-wait Do not wait for task completion
358+
--timeout <seconds> Timeout in seconds (default: 300)
359+
-h, --help display help for command`)
360+
case "translate":
361+
fmt.Printf(`Usage:
362+
deckops translate [options] <input-file>
363+
364+
Translate a document file
365+
366+
Options:
367+
--from <language> Source language (%s)
368+
--to <language> Target language (%s)
369+
--model <model> Translation model (Standard, Pro)
370+
--use-glossary [bool] Use glossary (default: false)
371+
--image-translate [bool] Translate images (default: false)
372+
-o, --out <path> Write completed task output to a file or directory
373+
--no-wait Do not wait for task completion
374+
--timeout <seconds> Timeout in seconds (default: 300)
375+
-h, --help display help for command
376+
`, strings.Join(sourceLanguages, ", "), strings.Join(targetLanguages, ", "))
377+
case "run":
378+
fmt.Printf(`Usage:
379+
deckops run [options] <task-type> <input-files...>
380+
381+
Run a task with explicit type
382+
383+
Options:
384+
--param <key=value> Task parameters (can be used multiple times)
385+
-o, --out <path> Write completed task output to a file or directory
386+
--no-wait Do not wait for task completion
387+
--timeout <seconds> Timeout in seconds (default: 300)
388+
-h, --help display help for command
389+
390+
Examples:
391+
$ deckops run convertor.ppt2pdf demo.ppt
392+
$ deckops run pptx.join part1.pptx part2.pptx
393+
$ deckops run convertor.html2pptx page1.html page2.html
394+
395+
Multiple input files are passed as one ordered source set only for: %s.
396+
`, strings.Join(multiSourceTaskTypes, ", "))
397+
default:
398+
return false
399+
}
400+
return true
401+
}
402+
403+
func printConfigHelp(args []string) bool {
404+
sub := firstNonHelpArg(args)
405+
switch sub {
406+
case "":
407+
fmt.Println(`Usage:
408+
deckops config <command>
409+
410+
Manage configuration
411+
412+
Commands:
413+
set-token <token> Set authentication token
414+
set-space <space-id> Set workspace/space ID
415+
set-api-base <url> Set API base URL
416+
show Show current configuration
417+
418+
Options:
419+
-h, --help display help for command`)
420+
case "set-token":
421+
fmt.Println(`Usage:
422+
deckops config set-token <token>
423+
424+
Set authentication token
425+
426+
Options:
427+
-h, --help display help for command`)
428+
case "set-space":
429+
fmt.Println(`Usage:
430+
deckops config set-space <space-id>
431+
432+
Set workspace/space ID
433+
434+
Options:
435+
-h, --help display help for command`)
436+
case "set-api-base":
437+
fmt.Println(`Usage:
438+
deckops config set-api-base <url>
439+
440+
Set API base URL
441+
442+
Options:
443+
-h, --help display help for command`)
444+
case "show":
445+
fmt.Println(`Usage:
446+
deckops config show
447+
448+
Show current configuration
449+
450+
Options:
451+
-h, --help display help for command`)
452+
default:
453+
return false
454+
}
455+
return true
456+
}
457+
458+
func printTaskHelp(args []string) bool {
459+
sub := firstNonHelpArg(args)
460+
switch sub {
461+
case "":
462+
fmt.Println(`Usage:
463+
deckops task <command>
464+
465+
Manage tasks
466+
467+
Commands:
468+
list List all tasks
469+
get <task-id> Get task details
470+
delete <task-id> Delete a task
471+
472+
Options:
473+
-h, --help display help for command`)
474+
case "list":
475+
fmt.Println(`Usage:
476+
deckops task list [options]
477+
478+
List all tasks
479+
480+
Options:
481+
--type <type> Filter by task type
482+
--limit <n> Maximum number of results (default: 50)
483+
--offset <n> Start index for pagination (default: 0)
484+
-h, --help display help for command`)
485+
case "get":
486+
fmt.Println(`Usage:
487+
deckops task get [options] <task-id>
488+
489+
Get task details
490+
491+
Options:
492+
-o, --out <path> Write completed task output to a file or directory
493+
-h, --help display help for command`)
494+
case "delete":
495+
fmt.Println(`Usage:
496+
deckops task delete <task-id>
497+
498+
Delete a task
499+
500+
Options:
501+
-h, --help display help for command`)
502+
default:
503+
return false
504+
}
505+
return true
506+
}
507+
508+
func firstNonHelpArg(args []string) string {
509+
for _, arg := range args {
510+
if arg != "-h" && arg != "--help" {
511+
return arg
512+
}
513+
}
514+
return ""
515+
}
516+
236517
func (c *appContext) loadConfig() error {
237518
data, err := os.ReadFile(c.configPath)
238519
if err != nil {
@@ -456,8 +737,8 @@ func (c *appContext) runLogin(args []string) error {
456737
return err
457738
}
458739
if !c.json {
459-
fmt.Println("\nToken saved successfully!\n")
460-
fmt.Println("You can now use Deckflow CLI commands.\n")
740+
fmt.Println("\nToken saved successfully!")
741+
fmt.Println("\nYou can now use Deckflow CLI commands.")
461742
}
462743
c.output(map[string]any{"success": true, "message": "Login successful"}, func() string { return "Login successful!" })
463744
return nil
@@ -471,9 +752,9 @@ func (c *appContext) ensureLoggedIn(ctx context.Context, port int, reason string
471752
}
472753
if !c.json {
473754
if reason == "unauthorized" {
474-
fmt.Println("\nAuthentication expired. Please log in again.\n")
755+
fmt.Println("\nAuthentication expired. Please log in again.")
475756
} else {
476-
fmt.Println("\nDeckflow Login\n")
757+
fmt.Println("\nDeckflow Login")
477758
}
478759
fmt.Println("Opening browser to:", loginURL)
479760
fmt.Printf("Waiting for authentication on port %d...\n\n", port)
@@ -524,7 +805,7 @@ func (c *appContext) ensureCheckout(ctx context.Context, port int) error {
524805
return err
525806
}
526807
if !c.json {
527-
fmt.Println("\nInsufficient balance. Please complete payment to continue.\n")
808+
fmt.Println("\nInsufficient balance. Please complete payment to continue.")
528809
fmt.Println("Opening browser to:", checkoutURL)
529810
fmt.Printf("Waiting for checkout completion on port %d...\n\n", port)
530811
}

0 commit comments

Comments
 (0)