use super::app_template::normalize_identifier;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectTemplateConfig {
pub project_name: String,
pub settings_module: String,
pub include_manage_rs: bool,
pub include_urls: bool,
}
impl Default for ProjectTemplateConfig {
fn default() -> Self {
Self::new("project")
}
}
impl ProjectTemplateConfig {
#[must_use]
pub fn new(project_name: impl Into<String>) -> Self {
let project_name = canonical_name(project_name.into(), "project");
Self {
project_name,
settings_module: String::from("settings"),
include_manage_rs: true,
include_urls: true,
}
}
#[must_use]
pub fn with_manage_rs(mut self, value: bool) -> Self {
self.include_manage_rs = value;
self
}
#[must_use]
pub fn with_urls(mut self, value: bool) -> Self {
self.include_urls = value;
self
}
#[must_use]
pub fn crate_name(&self) -> String {
normalize_identifier(&self.project_name, "project")
}
#[must_use]
pub fn settings_path(&self) -> String {
let module = normalize_identifier(&self.settings_module, "settings");
format!("src/{module}.rs")
}
#[must_use]
pub fn scaffold_files(&self) -> Vec<String> {
let mut files = Vec::new();
if self.include_manage_rs {
files.push(String::from("manage.rs"));
}
files.push(String::from("Cargo.toml"));
files.push(String::from("src/main.rs"));
files.push(self.settings_path());
if self.include_urls {
files.push(String::from("src/urls.rs"));
}
files
}
}
fn canonical_name(name: String, fallback: &str) -> String {
let trimmed = name.trim();
if trimmed.is_empty() {
String::from(fallback)
} else {
trimmed.to_owned()
}
}
#[cfg(test)]
mod tests {
use super::ProjectTemplateConfig;
#[test]
fn default_config_matches_current_project_layout() {
let config = ProjectTemplateConfig::default();
assert_eq!(config.project_name, "project");
assert_eq!(config.crate_name(), "project");
assert_eq!(
config.scaffold_files(),
vec![
String::from("manage.rs"),
String::from("Cargo.toml"),
String::from("src/main.rs"),
String::from("src/settings.rs"),
String::from("src/urls.rs"),
]
);
}
#[test]
fn crate_name_is_normalized_for_cargo_packages() {
let config = ProjectTemplateConfig::new("Customer Portal");
assert_eq!(config.crate_name(), "customer_portal");
}
#[test]
fn settings_path_uses_custom_module_name() {
let mut config = ProjectTemplateConfig::new("customer-portal");
config.settings_module = String::from("prod_settings");
assert_eq!(config.settings_path(), "src/prod_settings.rs");
}
#[test]
fn optional_files_can_be_disabled() {
let config = ProjectTemplateConfig::new("customer-portal")
.with_manage_rs(false)
.with_urls(false);
assert_eq!(
config.scaffold_files(),
vec![
String::from("Cargo.toml"),
String::from("src/main.rs"),
String::from("src/settings.rs"),
]
);
}
}