forge/cmd/generate/
mod.rs1use clap::{Parser, Subcommand};
2use eyre::Result;
3use foundry_common::fs;
4use std::path::Path;
5use yansi::Paint;
6
7#[derive(Debug, Parser)]
9pub struct GenerateArgs {
10 #[command(subcommand)]
11 pub sub: GenerateSubcommands,
12}
13
14#[derive(Debug, Subcommand)]
15pub enum GenerateSubcommands {
16 Test(GenerateTestArgs),
18}
19
20#[derive(Debug, Parser)]
21pub struct GenerateTestArgs {
22 #[arg(long, short, value_name = "CONTRACT_NAME")]
24 pub contract_name: String,
25}
26
27impl GenerateTestArgs {
28 pub fn run(self) -> Result<()> {
29 sh_warn!("`forge generate` is deprecated and will be removed in a future version")?;
30
31 let contract_name = format_identifier(&self.contract_name, true);
32 let instance_name = format_identifier(&self.contract_name, false);
33
34 let test_content = include_str!("../../../assets/generated/TestTemplate.t.sol");
36 let test_content = test_content
37 .replace("{contract_name}", &contract_name)
38 .replace("{instance_name}", &instance_name);
39
40 fs::create_dir_all("test")?;
42
43 let test_file_path = Path::new("test").join(format!("{contract_name}.t.sol"));
45
46 fs::write(&test_file_path, test_content)?;
48
49 sh_println!("{} test file: {}", "Generated".green(), test_file_path.to_str().unwrap())?;
50 Ok(())
51 }
52}
53
54fn format_identifier(input: &str, is_pascal_case: bool) -> String {
56 let mut result = String::new();
57 let mut capitalize_next = is_pascal_case;
58
59 for word in input.split_whitespace() {
60 if !word.is_empty() {
61 let (first, rest) = word.split_at(1);
62 let formatted_word = if capitalize_next {
63 format!("{}{}", first.to_uppercase(), rest)
64 } else {
65 format!("{}{}", first.to_lowercase(), rest)
66 };
67 capitalize_next = true;
68 result.push_str(&formatted_word);
69 }
70 }
71 result
72}