use std::path::{Path, PathBuf};
use tracing::{error, info};
mod cli;
mod error;
pub(crate) use error::Error;
fn get_working_directory() -> Result<PathBuf, Error> {
std::env::current_dir().map_err(|_| Error::new("failed to get the working directory"))
}
fn get_project_dir(always_use_cwd: bool) -> Result<PathBuf, Error> {
if always_use_cwd {
return get_working_directory();
}
match std::process::Command::new("git")
.arg("rev-parse")
.arg("--show-toplevel")
.output()
{
Ok(output) if output.stderr.is_empty() => {
Ok(Path::new(String::from_utf8(output.stdout).unwrap().trim()).to_owned())
}
Ok(_) => get_working_directory(),
_ => Err(Error::new("failed to get project root")),
}
}
fn get_data_dir() -> Result<PathBuf, Error> {
let app_name = env!("CARGO_PKG_NAME");
let xdg_dirs = xdg::BaseDirectories::with_prefix(app_name)
.map_err(|_| Error::new("failed to get data directory for program"))?;
Ok(xdg_dirs.get_data_home())
}
pub fn run() -> Result<(), Error> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::builder()
.with_default_directive(tracing_subscriber::filter::LevelFilter::OFF.into())
.from_env_lossy(),
)
.init();
let matches = cli::get_cli().get_matches();
let data_dir = get_data_dir()?;
info!("data dir: {:?}", data_dir);
let project_dir = if matches.contains_id("directory") {
Path::new(
matches
.get_one::<String>("directory")
.expect("guarded behind matches.contains_id(..)"),
)
.to_owned()
} else {
let always_use_cwd = matches
.get_one::<bool>("cwd")
.expect("should be false if it's not given");
get_project_dir(*always_use_cwd)?
};
let project_dir = project_dir.strip_prefix("/").unwrap();
info!("project dir: {:?}", project_dir);
let notes_dir_path = data_dir.join(project_dir);
info!("notes dir: {:?}", notes_dir_path);
std::fs::create_dir_all(¬es_dir_path)
.map_err(|_| Error::new(format!("failed to create the directory {:?}", project_dir)))?;
let note_file_path = notes_dir_path.join("notes.md");
info!("note file path: {:?}", note_file_path);
if !std::path::Path::exists(¬e_file_path) {
match std::fs::File::create(¬e_file_path) {
Ok(_) => {}
Err(e) => {
error!("std::fs::File::create failed with '{}'", e);
return Err(Error::new("failed to create the note file"));
}
}
}
let editor_command = std::env::var("EDITOR").unwrap_or("xdg-open".to_string());
info!("editor command: {:?}", editor_command);
let _ = std::process::Command::new(editor_command)
.arg(note_file_path)
.status()
.map_err(|e| Error::new(format!("failed to start editor: {}", e)))?;
Ok(())
}