summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-22 08:42:56 +0300
committerPaul Buetow <paul@buetow.org>2026-04-22 08:42:56 +0300
commitf9baad3a11e48a6d438d3e614e1ca1ee45c1547d (patch)
tree72db85faa6307b7b586d0ed982da977ad12c6e46 /cmd
parent15639ba3508ab92599bd1884ba07139c73b2dac0 (diff)
Fix manual prompt mode flags
Diffstat (limited to 'cmd')
-rw-r--r--cmd/comicforge/cli.go17
-rw-r--r--cmd/comicforge/cli_test.go50
2 files changed, 62 insertions, 5 deletions
diff --git a/cmd/comicforge/cli.go b/cmd/comicforge/cli.go
index 1a7f1ec..47ec2df 100644
--- a/cmd/comicforge/cli.go
+++ b/cmd/comicforge/cli.go
@@ -83,6 +83,9 @@ func newRootCommandWithDeps(deps commandDeps) *cobra.Command {
_, _ = fmt.Fprintln(cmd.OutOrStdout(), version.Version)
return nil
}
+ if err := validateUltraRealisticFlags(flags); err != nil {
+ return err
+ }
if cmd.Flags().Changed("prompt") && strings.TrimSpace(flags.prompt) == "" {
return fmt.Errorf("--prompt is required when set")
}
@@ -105,8 +108,8 @@ func newRootCommandWithDeps(deps commandDeps) *cobra.Command {
cmd.Flags().StringVar(&flags.configPath, "config", "", "config file (default: search ~/.config/comicforge, $HOME, and .)")
cmd.Flags().StringVar(&flags.promptsDir, "prompts-dir", "", "directory containing prompt templates")
cmd.Flags().StringVar(&flags.outputDir, "output", ".", "root output directory for generated comic data")
- cmd.Flags().StringVar(&flags.style, "style", "", "comic art style override")
- cmd.Flags().StringVar(&flags.theme, "theme", "", "story theme override")
+ cmd.Flags().StringVar(&flags.style, "style", "", "comic art style override for story and prompt mode")
+ cmd.Flags().StringVar(&flags.theme, "theme", "", "story theme override; used as prompt context in manual prompt mode")
cmd.Flags().BoolVar(&flags.ultraRealistic, "ultra-realistic", false, "force photorealistic rendering")
cmd.Flags().BoolVar(&flags.noUltraRealistic, "no-ultra-realistic", false, "disable photorealistic rendering")
cmd.Flags().BoolVar(&flags.narrateEnabled, "narrate", false, "generate narration after the comic")
@@ -127,9 +130,6 @@ func runCommand(ctx context.Context, cmd *cobra.Command, deps commandDeps, flags
if ctx == nil {
ctx = context.Background()
}
- if flags.noUltraRealistic && flags.ultraRealistic {
- return fmt.Errorf("only one of --ultra-realistic and --no-ultra-realistic may be set")
- }
cfg, err := deps.loadConfig(flags.configPath)
if err != nil {
@@ -224,6 +224,13 @@ func runPromptCommand(ctx context.Context, cmd *cobra.Command, deps commandDeps,
return runner.RunPrompt(ctx, flags.prompt)
}
+func validateUltraRealisticFlags(flags cliFlags) error {
+ if flags.noUltraRealistic && flags.ultraRealistic {
+ return fmt.Errorf("only one of --ultra-realistic and --no-ultra-realistic may be set")
+ }
+ return nil
+}
+
func applyConfigOverrides(cmd *cobra.Command, cfg *config.Config, flags cliFlags) {
if cfg == nil {
return
diff --git a/cmd/comicforge/cli_test.go b/cmd/comicforge/cli_test.go
index 048d22e..54c5ea8 100644
--- a/cmd/comicforge/cli_test.go
+++ b/cmd/comicforge/cli_test.go
@@ -300,6 +300,44 @@ func TestRootCommandRejectsConflictingUltraFlags(t *testing.T) {
}
}
+func TestRootCommandRejectsConflictingUltraFlagsInPromptMode(t *testing.T) {
+ cmd := newRootCommandWithDeps(commandDeps{
+ loadConfig: func(string) (*config.Config, error) {
+ t.Fatal("loadConfig should not be called when ultra-realistic flags conflict")
+ return nil, nil
+ },
+ newTextProvider: func(*config.Config) (provider.TextProvider, error) {
+ t.Fatal("newTextProvider should not be called when ultra-realistic flags conflict")
+ return noopProvider{}, nil
+ },
+ newImageProvider: func(*config.Config) (provider.ImageProvider, error) {
+ t.Fatal("newImageProvider should not be called when ultra-realistic flags conflict")
+ return noopProvider{}, nil
+ },
+ newTTSProvider: func(*config.Config, string) (provider.TTSProvider, error) {
+ t.Fatal("newTTSProvider should not be called when ultra-realistic flags conflict")
+ return noopProvider{}, nil
+ },
+ newRunner: func(*comic.RunnerConfig) comic.StoryRunner {
+ t.Fatal("newRunner should not be called when ultra-realistic flags conflict")
+ return &recordingRunner{}
+ },
+ })
+ cmd.SetArgs([]string{
+ "--prompt", "draw a robot",
+ "--ultra-realistic",
+ "--no-ultra-realistic",
+ })
+
+ err := cmd.ExecuteContext(context.Background())
+ if err == nil {
+ t.Fatal("ExecuteContext() error = nil, want conflict error")
+ }
+ if !strings.Contains(err.Error(), "only one of --ultra-realistic and --no-ultra-realistic may be set") {
+ t.Fatalf("ExecuteContext() error = %v, want conflict error", err)
+ }
+}
+
func TestRootCommandProviderFlagsDefaultToGemini(t *testing.T) {
cmd := newRootCommand()
for _, flagName := range []string{"text-provider", "image-provider", "tts-provider"} {
@@ -399,6 +437,9 @@ func TestRootCommandPromptModeSkipsVocabFlow(t *testing.T) {
"--prompt", "a robot reading a newspaper",
"--output", filepath.Join(tmpDir, "out"),
"--slug", "manual-robot",
+ "--style", "noir",
+ "--theme", "mystery",
+ "--ultra-realistic",
})
if err := cmd.ExecuteContext(context.Background()); err != nil {
@@ -425,6 +466,15 @@ func TestRootCommandPromptModeSkipsVocabFlow(t *testing.T) {
if got, want := gotRunnerCfg.Slug, "manual-robot"; got != want {
t.Fatalf("slug = %q, want %q", got, want)
}
+ if got, want := gotRunnerCfg.Style, "noir"; got != want {
+ t.Fatalf("style = %q, want %q", got, want)
+ }
+ if got, want := gotRunnerCfg.Theme, "mystery"; got != want {
+ t.Fatalf("theme = %q, want %q", got, want)
+ }
+ if gotRunnerCfg.UltraRealistic == nil || !*gotRunnerCfg.UltraRealistic {
+ t.Fatalf("ultra realistic = %#v, want true", gotRunnerCfg.UltraRealistic)
+ }
}
func TestRootCommandRejectsPromptAndVocabTogether(t *testing.T) {