Compare commits
4 Commits
2471312f05
...
43279810a5
| Author | SHA1 | Date | |
|---|---|---|---|
| 43279810a5 | |||
| c61a7b605a | |||
| 3392b7e4d3 | |||
| 341202f87c |
@@ -171,7 +171,7 @@ impl App {
|
||||
// that asks for more width than there is would otherwise push it
|
||||
// wider every frame.
|
||||
.width_range(160.0..=460.0)
|
||||
.show_animated(ctx, show_files, |ui| {
|
||||
.show(ctx, show_files, |ui| {
|
||||
// The default theme renders unselected list rows fairly dim; bump
|
||||
// the widget text colours so file names stay legible (especially in
|
||||
// dark mode) without affecting the rest of the app.
|
||||
|
||||
+3
-3
@@ -61,7 +61,7 @@ impl App {
|
||||
self.np_status = format!("{} already exists.", parent.join(&name).display());
|
||||
return;
|
||||
}
|
||||
let template = self.config.project_template.clone();
|
||||
let template = self.config.effective_project_template();
|
||||
|
||||
// Check that the template directory exists
|
||||
if !template.is_dir() {
|
||||
@@ -600,8 +600,8 @@ impl App {
|
||||
|
||||
if browse_template {
|
||||
let mut dialog = rfd::FileDialog::new().set_title("Choose a cookiecutter template");
|
||||
if self.config.project_template.is_dir() {
|
||||
dialog = dialog.set_directory(&self.config.project_template);
|
||||
if self.config.effective_project_template().is_dir() {
|
||||
dialog = dialog.set_directory(&self.config.effective_project_template());
|
||||
}
|
||||
if let Some(path) = dialog.pick_folder() {
|
||||
self.config.project_template = path;
|
||||
|
||||
+53
-16
@@ -189,29 +189,34 @@ pub fn default_show_toolbar() -> bool {
|
||||
pub fn default_project_template() -> PathBuf {
|
||||
// Find the bundled template relative to the executable's location
|
||||
if let Ok(exe_path) = std::env::current_exe() {
|
||||
// The templates are at the project root level, same as Cargo.toml
|
||||
// binary is typically at target/release/md-manuscript or target/debug/md-manuscript
|
||||
// So we need to go up from target/release (or target/debug) to the project root
|
||||
// Then look for templates/snowflake there
|
||||
let candidates = [
|
||||
// Binary in target/release/ -> project root -> templates/snowflake
|
||||
exe_path.parent().and_then(|p| p.parent()).and_then(|p| p.parent()).map(|p| p.join("templates/snowflake")),
|
||||
// Binary in target/debug/ -> project root -> templates/snowflake
|
||||
exe_path.parent().and_then(|p| p.parent()).map(|p| p.join("templates/snowflake")),
|
||||
// Binary in project root (dev) -> templates/snowflake
|
||||
exe_path.parent().map(|p| p.join("templates/snowflake")),
|
||||
// Fallback: relative to current working directory
|
||||
std::env::current_dir().ok().map(|p| p.join("templates/snowflake")),
|
||||
];
|
||||
for candidate in candidates.into_iter().flatten() {
|
||||
// Walk up from the executable's directory looking for templates/snowflake/cookiecutter.json
|
||||
// This handles various build configurations (release, debug, cargo run, installed binary)
|
||||
let mut current = exe_path.parent().unwrap_or_else(|| exe_path.as_path());
|
||||
loop {
|
||||
// Check if current/templates/snowflake/cookiecutter.json exists
|
||||
let candidate = current.join("templates/snowflake");
|
||||
if candidate.join("cookiecutter.json").is_file() {
|
||||
return candidate;
|
||||
}
|
||||
// Try going up one level
|
||||
match current.parent() {
|
||||
Some(parent) => current = parent,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
// Also try relative to current working directory
|
||||
if let Ok(cwd) = std::env::current_dir() {
|
||||
let candidate = cwd.join("templates/snowflake");
|
||||
if candidate.join("cookiecutter.json").is_file() {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't find the bundled template, panic with a clear error
|
||||
// The bundled template should always be present in a properly built release
|
||||
panic!("Bundled template not found. Please ensure templates/snowflake/ exists relative to the executable.");
|
||||
panic!("Bundled template not found. Please ensure templates/snowflake/cookiecutter.json exists relative to the executable.");
|
||||
}
|
||||
|
||||
/// Default subfolder opened after generating a project: the snowflake
|
||||
@@ -422,6 +427,17 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
/// The project template path to use, falling back to the bundled template
|
||||
/// if the saved path doesn't exist.
|
||||
pub fn effective_project_template(&self) -> PathBuf {
|
||||
// If the saved template path exists and has cookiecutter.json, use it
|
||||
if self.project_template.join("cookiecutter.json").is_file() {
|
||||
return self.project_template.clone();
|
||||
}
|
||||
// Otherwise fall back to the bundled template
|
||||
default_project_template()
|
||||
}
|
||||
|
||||
pub fn load() -> Config {
|
||||
let path = config_path();
|
||||
match std::fs::read_to_string(&path) {
|
||||
@@ -595,5 +611,26 @@ mod tests {
|
||||
// Verify it returns a valid path that contains cookiecutter.json
|
||||
assert!(path.join("cookiecutter.json").is_file(),
|
||||
"Template path {} should contain cookiecutter.json", path.display());
|
||||
|
||||
// Also verify it's using the bundled template (contains "templates/snowflake")
|
||||
let path_str = path.to_string_lossy();
|
||||
assert!(path_str.contains("templates/snowflake"),
|
||||
"Template path {} should be the bundled template", path.display());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundled_template_contains_05_first_draft() {
|
||||
let path = default_project_template();
|
||||
let template_dir = path.join("{{ cookiecutter.project_name }}");
|
||||
|
||||
// Verify the template has the merged 05-First Draft folder
|
||||
assert!(template_dir.join("05-First Draft").is_dir(),
|
||||
"Bundled template should contain 05-First Draft directory");
|
||||
|
||||
// Verify it does NOT have the old separate directories
|
||||
assert!(!template_dir.join("05-Plot").is_dir(),
|
||||
"Bundled template should NOT contain old 05-Plot directory");
|
||||
assert!(!template_dir.join("06-First Draft").is_dir(),
|
||||
"Bundled template should NOT contain old 06-First Draft directory");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user