1use super::handle_run_command;
3use crate::settings::Settings;
4use anyhow::{Context, Result, ensure};
5use clap::Subcommand;
6use include_dir::{Dir, DirEntry, include_dir};
7use std::fs;
8use std::path::{Path, PathBuf};
9use tempfile::TempDir;
10
11const EXAMPLES_DIR: Dir = include_dir!("examples");
13
14#[derive(Subcommand)]
16pub enum ExampleSubcommands {
17 List,
19 Info {
21 name: String,
23 },
24 Extract {
26 name: String,
28 new_path: Option<PathBuf>,
30 },
31 Run {
33 name: String,
35 #[arg(short, long)]
37 output_dir: Option<PathBuf>,
38 #[arg(long)]
40 debug_model: bool,
41 },
42}
43
44impl ExampleSubcommands {
45 pub fn execute(self) -> Result<()> {
47 match self {
48 Self::List => handle_example_list_command(),
49 Self::Info { name } => handle_example_info_command(&name)?,
50 Self::Extract {
51 name,
52 new_path: dest,
53 } => handle_example_extract_command(&name, dest.as_deref())?,
54 Self::Run {
55 name,
56 output_dir,
57 debug_model,
58 } => handle_example_run_command(&name, output_dir.as_deref(), debug_model, None)?,
59 }
60
61 Ok(())
62 }
63}
64
65fn handle_example_list_command() {
67 for entry in EXAMPLES_DIR.dirs() {
68 println!("{}", entry.path().display());
69 }
70}
71
72fn handle_example_info_command(name: &str) -> Result<()> {
74 let path: PathBuf = [name, "README.txt"].iter().collect();
75 let readme = EXAMPLES_DIR
76 .get_file(path)
77 .context("Example not found.")?
78 .contents_utf8()
79 .expect("README.txt is not UTF-8 encoded");
80
81 println!("{}", readme);
82
83 Ok(())
84}
85
86fn handle_example_extract_command(name: &str, dest: Option<&Path>) -> Result<()> {
88 let dest = dest.unwrap_or(Path::new(name));
89 extract_example(name, dest)
90}
91
92fn extract_example(name: &str, new_path: &Path) -> Result<()> {
94 let sub_dir = EXAMPLES_DIR.get_dir(name).context("Example not found.")?;
96
97 ensure!(
98 !new_path.exists(),
99 "Destination directory {} already exists",
100 new_path.display()
101 );
102
103 fs::create_dir(new_path)?;
105 for entry in sub_dir.entries() {
106 match entry {
107 DirEntry::Dir(_) => panic!("Subdirectories in examples not supported"),
108 DirEntry::File(f) => {
109 let file_name = f.path().file_name().unwrap();
110 let file_path = new_path.join(file_name);
111 fs::write(&file_path, f.contents())?;
112 }
113 }
114 }
115
116 Ok(())
117}
118
119pub fn handle_example_run_command(
121 name: &str,
122 output_path: Option<&Path>,
123 debug_model: bool,
124 settings: Option<Settings>,
125) -> Result<()> {
126 let temp_dir = TempDir::new().context("Failed to create temporary directory.")?;
127 let model_path = temp_dir.path().join(name);
128 extract_example(name, &model_path)?;
129 handle_run_command(&model_path, output_path, debug_model, settings)
130}