use std::path::PathBuf;
use clap::Args;
use console::style;
use topcoat_ui::manage::{self, InitOptions, Package};
use super::PackageArg;
#[derive(Args)]
pub(super) struct InitCommand {
#[arg(short, long)]
components_dir: Option<PathBuf>,
#[arg(short, long)]
theme: Option<String>,
#[command(flatten)]
package: PackageArg,
}
impl InitCommand {
pub(super) fn run(self) {
if let Err(error) = self.run_inner() {
eprintln!("{}", style(error).red());
std::process::exit(1);
}
}
fn run_inner(self) -> Result<(), String> {
let package = Package::locate(self.package.package)?;
let options = InitOptions {
components_dir: self.components_dir,
theme: self.theme,
};
let mut choose = choose_theme;
let initialized = manage::init(&package, options, &mut choose)?;
println!(
"{} initialized {} {}",
style("+").green(),
style(initialized.state_file.display()).bold(),
style(format!(
"(components under {})",
initialized.components_dir.display()
))
.dim(),
);
let theme_file = initialized.theme.file.display().to_string();
println!(
"{} installed theme {} {}",
style("+").green(),
style(initialized.theme.name).bold(),
style(format!("({theme_file})")).dim(),
);
println!();
println!(
"{} Load the theme by using it as your Tailwind {} in build.rs:",
style("!").yellow(),
style("input").bold(),
);
println!(
"{}",
style(format!(
" topcoat::tailwind::BuildConfig::new().input({theme_file:?}).render().unwrap();"
))
.dim(),
);
println!();
println!(
"{} This theme uses the {} font. Set it up with topcoat-font:",
style("!").yellow(),
style("Geist").bold(),
);
println!(
" {} enable topcoat's {} feature",
style("-").dim(),
style("font-fontsource").bold(),
);
println!(" {} load it in your page's <head>:", style("-").dim());
println!(
"{}",
style(" topcoat::font::link(font: fontsource_font!(GEIST))").dim(),
);
Ok(())
}
}
fn choose_theme(themes: &[String]) -> Result<String, String> {
use std::io::IsTerminal;
use dialoguer::{Select, theme::ColorfulTheme};
if !std::io::stdin().is_terminal() {
return Err(format!(
"no theme selected and no terminal to prompt on; pass --theme <name> (available: {})",
themes.join(", ")
));
}
let selection = Select::with_theme(&ColorfulTheme::default())
.with_prompt("Choose a theme")
.items(themes)
.default(0)
.interact_opt()
.map_err(|error| format!("failed to read input: {error}"))?;
match selection {
Some(index) => Ok(themes[index].clone()),
None => Err("no theme selected".to_string()),
}
}