use std::path::PathBuf;
use crate::config;
pub fn initialize(path: &str) {
let notebook_dir = if path == "." {
std::env::current_dir().unwrap_or_else(|e| {
eprintln!("Failed to get current directory: {e}");
std::process::exit(1);
})
} else {
let p = PathBuf::from(path);
if p.is_absolute() {
p
} else {
std::env::current_dir()
.unwrap_or_else(|_| PathBuf::from("."))
.join(p)
}
};
let notebook_dir = notebook_dir.canonicalize().unwrap_or(notebook_dir);
let global = config::GlobalConfig::load();
if let Some(existing) = global.notebook_path() {
crate::vprintln!("A notebook is already initialized at: {}", existing.display());
return;
}
crate::vprintln!("Initializing notebook at: {}", notebook_dir.display());
let smarana_dir = notebook_dir.join(".smarana");
if let Err(e) = std::fs::create_dir_all(&smarana_dir) {
eprintln!("Failed to create .smarana directory: {e}");
std::process::exit(1);
}
let notebook_config = smarana_dir.join("config.toml");
if notebook_config.exists() {
crate::vprintln!("Notebook config already exists: {}", notebook_config.display());
} else {
let template = include_str!("../res/default_config.toml");
if let Err(e) = std::fs::write(¬ebook_config, template) {
eprintln!("Failed to create notebook config: {e}");
std::process::exit(1);
}
crate::vprintln!("Created: {}", notebook_config.display());
}
let templates_dir = smarana_dir.join("templates");
if let Err(e) = std::fs::create_dir_all(&templates_dir) {
eprintln!("Failed to create templates dir: {e}");
std::process::exit(1);
}
let lib_dir = smarana_dir.join("lib");
if let Err(e) = std::fs::create_dir_all(&lib_dir) {
eprintln!("Failed to create lib dir: {e}");
std::process::exit(1);
}
deploy_file(
&templates_dir.join("atomic.typ"),
include_str!("../res/templates/atomic.typ"),
"atomic template",
);
deploy_file(
&templates_dir.join("fleeting.typ"),
include_str!("../res/templates/fleeting.typ"),
"fleeting template",
);
deploy_file(
&templates_dir.join("capture.typ"),
include_str!("../res/templates/capture.typ"),
"capture template",
);
deploy_file(
&lib_dir.join("library.typ"),
include_str!("../res/library.typ"),
"library.typ",
);
deploy_file(
&lib_dir.join("fleeting.typ"),
include_str!("../res/fleeting.typ"),
"fleeting.typ",
);
deploy_file(
&lib_dir.join("capture.typ"),
include_str!("../res/capture.typ"),
"capture.typ",
);
deploy_file(
&lib_dir.join("atomic.typ"),
include_str!("../res/atomic.typ"),
"atomic.typ",
);
deploy_file(
&lib_dir.join("theme.typ"),
include_str!("../res/theme.typ"),
"theme.typ",
);
deploy_file(
&lib_dir.join("dividers.typ"),
include_str!("../res/dividers.typ"),
"dividers.typ",
);
deploy_file(
&lib_dir.join("appendix.typ"),
include_str!("../res/appendix.typ"),
"appendix.typ",
);
let user_typ_path = smarana_dir.join("user.typ");
if !user_typ_path.exists() {
deploy_file(
&user_typ_path,
include_str!("../res/user.typ"),
"user.typ",
);
} else {
crate::vprintln!("User configuration wrapper already exists: {}", user_typ_path.display());
}
let global_config_path = config::global_config_path();
if let Some(parent) = global_config_path.parent() {
if let Err(e) = std::fs::create_dir_all(parent) {
eprintln!("Failed to create global config directory: {e}");
std::process::exit(1);
}
}
let portable_path = path_with_home_var(¬ebook_dir);
let global_content = format!(
"# Smarana Global Configuration\n# Path to the notebook directory\nnotebook = \"{portable_path}\"\n"
);
if let Err(e) = std::fs::write(&global_config_path, global_content) {
eprintln!("Failed to create global config: {e}");
std::process::exit(1);
}
crate::vprintln!("Created: {}", global_config_path.display());
if let Err(e) = crate::db::init_db(¬ebook_dir) {
eprintln!("Failed to initialize database: {e}");
std::process::exit(1);
}
crate::db::export_smarana_typ(¬ebook_dir);
crate::vprintln!("Initialized database at {}", notebook_dir.join(".smarana").join("index.db").display());
crate::vprintln!("Notebook initialized successfully!");
}
pub fn update_library(path: &str) {
let notebook_dir = PathBuf::from(path);
let smarana_dir = notebook_dir.join(".smarana");
let lib_dir = smarana_dir.join("lib");
if !smarana_dir.exists() {
eprintln!("Notebook not initialized at {}; cannot update library.", path);
std::process::exit(1);
}
if let Err(e) = std::fs::create_dir_all(&lib_dir) {
eprintln!("Failed to ensure lib dir exists: {e}");
std::process::exit(1);
}
deploy_file(
&lib_dir.join("library.typ"),
include_str!("../res/library.typ"),
"library.typ",
);
deploy_file(
&lib_dir.join("fleeting.typ"),
include_str!("../res/fleeting.typ"),
"fleeting.typ",
);
deploy_file(
&lib_dir.join("capture.typ"),
include_str!("../res/capture.typ"),
"capture.typ",
);
deploy_file(
&lib_dir.join("atomic.typ"),
include_str!("../res/atomic.typ"),
"atomic.typ",
);
deploy_file(
&lib_dir.join("theme.typ"),
include_str!("../res/theme.typ"),
"theme.typ",
);
deploy_file(
&lib_dir.join("dividers.typ"),
include_str!("../res/dividers.typ"),
"dividers.typ",
);
deploy_file(
&lib_dir.join("appendix.typ"),
include_str!("../res/appendix.typ"),
"appendix.typ",
);
crate::vprintln!("Library updated successfully!");
}
fn deploy_file(path: &std::path::Path, content: &str, label: &str) {
if let Err(e) = std::fs::write(path, content) {
eprintln!("Failed to create {}: {e}", label);
std::process::exit(1);
}
crate::vprintln!("Created: {}", path.display());
}
fn path_with_home_var(path: &std::path::Path) -> String {
if let Ok(home) = std::env::var("HOME") {
let home_path = PathBuf::from(&home);
if let Ok(relative) = path.strip_prefix(&home_path) {
return format!("$HOME/{}", relative.display());
}
}
path.display().to_string()
}