systemprompt_cli/commands/web/templates/
delete.rs1use anyhow::{Context, Result, anyhow};
2use clap::Args;
3use std::fs;
4use std::path::Path;
5
6use crate::CliConfig;
7use crate::interactive::{Prompter, require_confirmation, resolve_required};
8use crate::shared::CommandOutput;
9use systemprompt_logging::CliService;
10
11use super::super::paths::WebPaths;
12use super::super::types::{TemplateDeleteOutput, TemplatesConfig};
13use super::selection::prompt_template_selection;
14
15#[derive(Debug, Args)]
16pub struct DeleteArgs {
17 #[arg(help = "Template name")]
18 pub name: Option<String>,
19
20 #[arg(short = 'y', long, help = "Skip confirmation prompts")]
21 pub yes: bool,
22
23 #[arg(long, help = "Also delete the .html file")]
24 pub delete_file: bool,
25}
26
27pub(super) fn execute(
28 args: DeleteArgs,
29 prompter: &dyn Prompter,
30 config: &CliConfig,
31) -> Result<CommandOutput> {
32 execute_in_dir(args, prompter, config, &WebPaths::resolve()?.templates)
33}
34
35pub fn execute_in_dir(
36 args: DeleteArgs,
37 prompter: &dyn Prompter,
38 config: &CliConfig,
39 templates_dir: &Path,
40) -> Result<CommandOutput> {
41 let templates_yaml_path = templates_dir.join("templates.yaml");
42
43 let yaml_content = fs::read_to_string(&templates_yaml_path).with_context(|| {
44 format!(
45 "Failed to read templates config at {}",
46 templates_yaml_path.display()
47 )
48 })?;
49
50 let mut templates_config: TemplatesConfig =
51 serde_yaml::from_str(&yaml_content).with_context(|| {
52 format!(
53 "Failed to parse templates config at {}",
54 templates_yaml_path.display()
55 )
56 })?;
57
58 let name = resolve_required(args.name, "name", config, || {
59 prompt_template_selection(prompter, &templates_config, "Select template to delete")
60 })?;
61
62 if !templates_config.templates.contains_key(&name) {
63 return Err(anyhow!("Template '{}' not found", name));
64 }
65
66 let confirm_msg = if args.delete_file {
67 format!("Delete template '{}' and its HTML file?", name)
68 } else {
69 format!("Delete template '{}'?", name)
70 };
71
72 require_confirmation(prompter, &confirm_msg, args.yes, config)?;
73
74 templates_config.templates.remove(&name);
75
76 let html_file_path = templates_dir.join(format!("{}.html", name));
77 let file_deleted = if args.delete_file && html_file_path.exists() {
78 fs::remove_file(&html_file_path)
79 .with_context(|| format!("Failed to delete HTML file: {}", html_file_path.display()))?;
80 true
81 } else {
82 false
83 };
84
85 let yaml = serde_yaml::to_string(&templates_config).context("Failed to serialize config")?;
86 fs::write(&templates_yaml_path, yaml).with_context(|| {
87 format!(
88 "Failed to write templates config to {}",
89 templates_yaml_path.display()
90 )
91 })?;
92
93 let message = if file_deleted {
94 format!("Template '{}' deleted (including HTML file)", name)
95 } else if html_file_path.exists() {
96 format!(
97 "Template '{}' deleted. HTML file still exists at {}",
98 name,
99 html_file_path.display()
100 )
101 } else {
102 format!("Template '{}' deleted", name)
103 };
104
105 CliService::success(&message);
106
107 let output = TemplateDeleteOutput {
108 deleted: name,
109 file_deleted,
110 message,
111 };
112
113 Ok(CommandOutput::card_value("Template Deleted", &output))
114}