ralph_workflow/cli/init/smart_init.rs
1/// Handle the smart `--init` flag with a custom path resolver.
2///
3/// This function intelligently determines what the user wants to initialize:
4/// - If a value is provided and matches a known template name -> create PROMPT.md
5/// - If config doesn't exist and no template specified -> create config
6/// - If config exists but PROMPT.md doesn't -> prompt to create PROMPT.md
7/// - If both exist -> show helpful message about what's already set up
8///
9/// # Arguments
10///
11/// * `template_arg` - Optional template name from `--init=TEMPLATE`
12/// * `force` - If true, overwrite existing PROMPT.md without prompting
13/// * `colors` - Terminal color configuration for output
14/// * `env` - Path resolver for determining config file locations
15///
16/// # Returns
17///
18/// Returns `Ok(true)` if the flag was handled (program should exit after),
19/// or `Ok(false)` if not handled, or an error if initialization failed.
20pub fn handle_smart_init_with<R: ConfigEnvironment>(
21 template_arg: Option<&str>,
22 force: bool,
23 colors: Colors,
24 env: &R,
25) -> anyhow::Result<bool> {
26 let config_path = env
27 .unified_config_path()
28 .ok_or_else(|| anyhow::anyhow!("Cannot determine config directory (no home directory)"))?;
29 let prompt_path = env.prompt_path();
30 handle_smart_init_at_paths_with_env(
31 template_arg,
32 force,
33 colors,
34 &config_path,
35 &prompt_path,
36 env,
37 )
38}
39
40/// Handle the smart `--init` flag using the default path resolver.
41///
42/// This is a convenience wrapper that uses [`RealConfigEnvironment`] internally.
43pub fn handle_smart_init(
44 template_arg: Option<&str>,
45 force: bool,
46 colors: Colors,
47) -> anyhow::Result<bool> {
48 handle_smart_init_with(template_arg, force, colors, &RealConfigEnvironment)
49}
50
51fn handle_smart_init_at_paths_with_env<R: ConfigEnvironment>(
52 template_arg: Option<&str>,
53 force: bool,
54 colors: Colors,
55 config_path: &std::path::Path,
56 prompt_path: &Path,
57 env: &R,
58) -> anyhow::Result<bool> {
59 let config_exists = env.file_exists(config_path);
60 let prompt_exists = env.file_exists(prompt_path);
61
62 // If a template name is provided (non-empty), treat it as --init <template>
63 if let Some(template_name) = template_arg {
64 if !template_name.is_empty() {
65 return handle_init_template_arg_at_path_with_env(
66 template_name,
67 prompt_path,
68 force,
69 colors,
70 env,
71 );
72 }
73 // Empty string means --init was used without a value, fall through to smart inference
74 }
75
76 // No template provided - use smart inference based on current state
77 handle_init_state_inference_with_env(
78 config_path,
79 prompt_path,
80 config_exists,
81 prompt_exists,
82 force,
83 colors,
84 env,
85 )
86}