From 45872ee48d216f443e4c97f02848d656ce8c36f8 Mon Sep 17 00:00:00 2001 From: "Peter A. Ramaldes" Date: Wed, 1 Nov 2023 17:03:19 -0300 Subject: [PATCH] Create `zet search` Command (#8) * Enable visit all the folders/file inside the zet repository * Enable `zet search` * Improve the documentation for zet::dir * Added example of environment needed by project * Added the zet current dir for testing on gitignore --- .envrc.example | 1 + .gitignore | 2 ++ src/create.rs | 33 ++++++--------------------------- src/lib.rs | 29 +++++++++++++++++++++++++++++ src/main.rs | 19 ++++++++++++++++++- src/search.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 .envrc.example create mode 100644 src/lib.rs create mode 100644 src/search.rs diff --git a/.envrc.example b/.envrc.example new file mode 100644 index 0000000..87d211a --- /dev/null +++ b/.envrc.example @@ -0,0 +1 @@ +ZET_PATH="./zet" diff --git a/.gitignore b/.gitignore index ea8c4bf..ec07be0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +/zet +.envrc diff --git a/src/create.rs b/src/create.rs index e2b874a..fdf0981 100644 --- a/src/create.rs +++ b/src/create.rs @@ -7,7 +7,7 @@ use std::{ }; pub fn run() -> io::Result<()> { - let path = get_path_from_files(); + let path = zet::dir(); // Create the path if doesn't exists, thrown an error if cannot fs::create_dir_all(&path)?; @@ -15,7 +15,11 @@ pub fn run() -> io::Result<()> { // Create dir if doesn´t exists let today = Utc::now(); let folder_name = today.date_naive().format("%Y%m%d"); - let folder_path = format!("{path}/{folder_name}"); + let folder_path = format!( + "{}/{}", + path.into_os_string().into_string().unwrap(), + folder_name + ); let _ = fs::create_dir(&folder_path); // Create the file @@ -29,28 +33,3 @@ pub fn run() -> io::Result<()> { Ok(()) } - -/// Get path with this precendece: -/// -/// 1. $ZET_PATH -/// 2. $HOME/.config/zet -/// -/// This function is not portable, the .config folder will not work on windows -fn get_path_from_files() -> String { - let mut path = match env::var("ZET_PATH") { - Ok(val) => String::from(val), - Err(_e) => "".to_string(), - }; - - if path.is_empty() { - let home = match env::var("HOME") { - Ok(val) => String::from(val), - Err(_e) => panic!("doesn't have $HOME env set"), // TODO: this should not be a problem - // for windows :( - }; - - path = format!("{home}/.config/zet"); - } - - path -} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..88b8af4 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,29 @@ +use std::{ + env, + path::{Path, PathBuf}, +}; + +/// Returns the directory for Zettelkasten repository +/// +/// The Zettelkasten repository take the below procedence: +/// 1. `${ZET_PATH}` +/// 2. `$HOME/.config/zet` +/// +pub fn dir() -> PathBuf { + let mut path = match env::var("ZET_PATH") { + Ok(val) => String::from(val), + Err(_e) => "".to_string(), + }; + + if path.is_empty() { + let home = match env::var("HOME") { + Ok(val) => String::from(val), + Err(_e) => panic!("doesn't have $HOME env set"), // TODO: this should not be a problem + // for windows :( + }; + + path = format!("{home}/.config/zet"); + } + + return Path::new(&path).to_path_buf(); +} diff --git a/src/main.rs b/src/main.rs index 67a5ef0..735423b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ pub mod create; +pub mod search; -use clap::Parser; +use clap::{Args, Parser}; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -16,6 +17,21 @@ enum Subcommand { /// the env isn´t set. #[clap(visible_alias = "c")] Create, + + /// Search specific words on the Zettelkasten repository + #[clap(visible_alias = "s")] + Search(SearchArgs), +} + +#[derive(Args, Debug)] +pub struct SearchArgs { + /// The word that you are trying to find on Zettelkasten repository + #[arg(short, long)] + target_word: Option, + + /// If this flag enable, means that the word search using the `target_word` will ignore case + #[arg(short, long)] + ignore_case: bool, } fn main() -> std::io::Result<()> { @@ -23,5 +39,6 @@ fn main() -> std::io::Result<()> { return match cli.subcommand { Subcommand::Create => create::run(), + Subcommand::Search(args) => search::run(args), }; } diff --git a/src/search.rs b/src/search.rs new file mode 100644 index 0000000..554849b --- /dev/null +++ b/src/search.rs @@ -0,0 +1,43 @@ +use std::{ + fs::{self}, + io::{self, Read}, + path::PathBuf, +}; + +use crate::SearchArgs; + +pub fn run(args: SearchArgs) -> io::Result<()> { + println!("Search for word: '{}'", args.target_word.as_ref().unwrap()); + search_target_word(&zet::dir(), &args) +} + +fn search_target_word(dir: &PathBuf, args: &SearchArgs) -> io::Result<()> { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + + if entry.file_type()?.is_file() { + // Check if contains the word that we are searching + let file_path = entry.path(); + + // Open the file + let mut file = fs::File::open(&file_path)?; + + // Read the file content into a String + let mut content = String::new(); + file.read_to_string(&mut content)?; + + // Search for the target word in the content + let target_word = args.target_word.as_ref().unwrap(); + if (args.ignore_case && content.to_lowercase().contains(&target_word.to_lowercase())) + || content.contains(target_word) + { + println!("* {:?}", file_path); + } + } else { + search_target_word(&path, args)?; + } + } + + Ok(()) +}