1use std::fs;
2
3use anyhow::Result;
4use schemaui::SchemaUI;
5use schemaui::precompile::tui as pre_tui;
6
7use crate::cli::{CommonArgs, TuiSnapshotCommand};
8use crate::session::diagnostics::DiagnosticCollector;
9use crate::session::format::resolve_format_hint;
10use crate::session::schema_source::{load_optional_document, resolve_session_inputs};
11use crate::session::{SessionBundle, prepare_session};
12
13pub fn run_cli(args: &CommonArgs) -> Result<()> {
14 let session = prepare_session(args)?;
15 execute_session(session)
16}
17
18pub(crate) fn execute_session(session: SessionBundle) -> Result<()> {
19 let SessionBundle {
20 schema,
21 defaults,
22 title,
23 description,
24 output,
25 } = session;
26 let mut ui = if let Some(defaults) = defaults {
27 SchemaUI::new(defaults).with_schema(schema)
28 } else {
29 SchemaUI::from_schema(schema)
30 };
31 if let Some(title) = title {
32 ui = ui.with_title(title);
33 }
34 if let Some(description) = description {
35 ui = ui.with_description(description);
36 }
37 let value = ui.run_tui()?;
38 if let Some(options) = output {
39 options.write(&value)?;
40 }
41 Ok(())
42}
43
44pub fn run_snapshot_cli(cmd: TuiSnapshotCommand) -> Result<()> {
45 let schema_spec = cmd.common.schema.as_deref();
46 let config_spec = cmd.common.config.as_deref();
47 let mut diagnostics = DiagnosticCollector::default();
48 let schema_stdin = schema_spec == Some("-");
49 let config_stdin = config_spec == Some("-");
50 if schema_stdin && config_stdin {
51 diagnostics.push_input(
52 "schema/config",
53 "cannot read schema and config from stdin simultaneously; provide inline content, files, or a remote schema",
54 );
55 }
56 let schema_hint = resolve_format_hint(schema_spec, "schema", &mut diagnostics);
57 let config_hint = resolve_format_hint(config_spec, "config", &mut diagnostics);
58 let schema_document = load_optional_document(
59 schema_spec,
60 schema_hint.hint.format,
61 "schema",
62 schema_hint.blocked || (schema_stdin && config_stdin),
63 &mut diagnostics,
64 );
65 let config_document = load_optional_document(
66 config_spec,
67 config_hint.hint.format,
68 "config",
69 config_hint.blocked || (schema_stdin && config_stdin),
70 &mut diagnostics,
71 );
72 diagnostics.into_result()?;
73 let resolved = resolve_session_inputs(schema_document, config_document)?;
74
75 fs::create_dir_all(&cmd.out_dir)?;
76 let tui_module = cmd.out_dir.join("tui_artifacts.rs");
77 let form_module = cmd.out_dir.join("tui_form_schema.rs");
78 let layout_module = cmd.out_dir.join("tui_layout_nav.rs");
79
80 pre_tui::generate_tui_artifacts_module_from_value(
81 &resolved.schema,
82 resolved.defaults.as_ref(),
83 &tui_module,
84 &cmd.tui_fn,
85 )?;
86 pre_tui::generate_tui_form_schema_module_from_value(
87 &resolved.schema,
88 resolved.defaults.as_ref(),
89 &form_module,
90 &cmd.form_fn,
91 )?;
92 pre_tui::generate_tui_layout_nav_module_from_value(
93 &resolved.schema,
94 resolved.defaults.as_ref(),
95 &layout_module,
96 &cmd.layout_fn,
97 )?;
98
99 eprintln!("Generated TUI artifact modules:");
100 eprintln!(" TuiArtifacts module: {:?}", tui_module);
101 eprintln!(" FormSchema module: {:?}", form_module);
102 eprintln!(" LayoutNavModel module: {:?}", layout_module);
103
104 Ok(())
105}