systemprompt_cli/runner/args/
assemble.rs1use super::{Cli, Commands};
18use crate::cli_settings::{CliConfig, ColorMode, OutputFormat, VerbosityLevel};
19use crate::env_overrides::EnvOverrides;
20
21pub fn build_cli_config(cli: &Cli, env: &EnvOverrides) -> CliConfig {
22 let mut cfg = CliConfig::resolve(env);
23
24 if cli.verbosity.debug {
25 cfg = cfg.with_verbosity(VerbosityLevel::Debug);
26 } else if cli.verbosity.verbose {
27 cfg = cfg.with_verbosity(VerbosityLevel::Verbose);
28 } else if cli.verbosity.quiet {
29 cfg = cfg.with_verbosity(VerbosityLevel::Quiet);
30 }
31
32 if cli.output.json {
33 cfg = cfg.with_output_format(OutputFormat::Json);
34 } else if cli.output.yaml {
35 cfg = cfg.with_output_format(OutputFormat::Yaml);
36 }
37
38 if cli.display.no_color {
39 cfg = cfg.with_color_mode(ColorMode::Never);
40 }
41
42 if cli.display.non_interactive {
43 cfg = cfg.with_interactive(false);
44 }
45
46 cfg = cfg.with_profile_override(cli.profile_opts.profile.clone());
47
48 cfg
49}
50
51pub fn reconstruct_args() -> Vec<String> {
52 let original: Vec<String> = std::env::args().skip(1).collect();
53 reconstruct_args_from(&original)
54}
55
56pub fn reconstruct_args_from(original_args: &[String]) -> Vec<String> {
57 let mut leading_globals = Vec::new();
58 let mut tokens = original_args.iter();
59 let mut subcommand = None;
60
61 while let Some(arg) = tokens.next() {
62 if is_local_only_flag(arg) {
63 if takes_separate_value(arg) {
64 tokens.next();
65 }
66 continue;
67 }
68 if arg.starts_with('-') {
69 leading_globals.push(arg.clone());
70 continue;
71 }
72 subcommand = Some(arg.clone());
73 break;
74 }
75
76 let Some(subcommand) = subcommand else {
77 return leading_globals;
78 };
79
80 let mut forwarded = vec![subcommand];
81 forwarded.extend(leading_globals);
82
83 let mut after_terminator = false;
84 while let Some(arg) = tokens.next() {
85 if after_terminator {
86 forwarded.push(arg.clone());
87 continue;
88 }
89 if arg == "--" {
90 after_terminator = true;
91 forwarded.push(arg.clone());
92 continue;
93 }
94 if is_local_only_flag(arg) {
95 if takes_separate_value(arg) {
96 tokens.next();
97 }
98 continue;
99 }
100 forwarded.push(arg.clone());
101 }
102
103 forwarded
104}
105
106const LOCAL_ONLY_FLAGS: [&str; 2] = ["--profile", "--database-url"];
107
108fn takes_separate_value(arg: &str) -> bool {
109 LOCAL_ONLY_FLAGS.contains(&arg)
110}
111
112fn is_local_only_flag(arg: &str) -> bool {
113 LOCAL_ONLY_FLAGS.iter().any(|flag| {
114 arg == *flag
115 || arg
116 .strip_prefix(flag)
117 .is_some_and(|rest| rest.starts_with('='))
118 })
119}
120
121pub fn has_local_export_flag(command: Option<&Commands>) -> bool {
122 let args: Vec<String> = std::env::args().collect();
123 has_local_export_flag_in(command, &args)
124}
125
126pub fn has_local_export_flag_in(command: Option<&Commands>, args: &[String]) -> bool {
127 if !matches!(command, Some(Commands::Analytics(_))) {
128 return false;
129 }
130 args.iter()
131 .any(|arg| arg == "--export" || arg.starts_with("--export="))
132}