1use anyhow::Result;
3use clap::Parser;
4use hugr::Extension;
5use hugr::extension::ExtensionRegistry;
6use std::{io::Write, path::PathBuf};
7
8#[derive(Parser, Debug)]
10#[clap(version = "1.0", long_about = None)]
11#[clap(about = "Write standard extensions.")]
12#[group(id = "hugr")]
13#[non_exhaustive]
14pub struct ExtArgs {
15 #[arg(
17 default_value = ".",
18 short,
19 long,
20 value_name = "OUTPUT",
21 help = "Output directory."
22 )]
23 pub outdir: PathBuf,
24 #[arg(
30 long,
31 help = "Do not add the extension version to the output filename.",
32 default_value_t = false
33 )]
34 pub unversioned: bool,
35}
36
37impl ExtArgs {
38 pub fn run_dump(&self, registry: &ExtensionRegistry) -> Result<()> {
45 if !self.unversioned {
46 registry
47 .iter_all()
48 .try_for_each(|ext| self.dump_extension(ext))?;
49 } else {
50 registry
52 .iter()
53 .map(|ext| ext.latest())
54 .try_for_each(|ext| self.dump_extension(ext))?;
55 }
56
57 Ok(())
58 }
59
60 fn dump_extension(&self, ext: &Extension) -> Result<()> {
61 let mut path = self.outdir.clone();
62 let mut parts = ext.name().split('.').peekable();
63 while let Some(part) = parts.next() {
64 if parts.peek().is_some() {
65 path.push(part);
66 continue;
67 }
68
69 if self.unversioned {
72 path.push(format!("{part}.json"));
73 } else {
74 path.push(format!("{part}-{}.json", ext.version()));
75 }
76 }
77
78 std::fs::create_dir_all(path.clone().parent().unwrap())?;
79 let mut file = std::fs::File::create(&path)?;
81
82 serde_json::to_writer_pretty(&mut file, &ext)?;
83
84 file.write_all(b"\n")?;
87
88 Ok(())
89 }
90}