diff --git a/Cargo.lock b/Cargo.lock index d622ee3..a2210cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,222 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "todo-system" version = "0.1.0" +dependencies = [ + "clap", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index cd4af3e..d1430b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,10 @@ name = "todo-system" version = "0.1.0" edition = "2021" +authors = ["Samuel Ć tancl "] +description = "An intuitive system for organizing TODOs in code" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4.4.8", features = ["derive"] } diff --git a/README.md b/README.md index 2fa7455..90316cc 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ That said, this repo includes a simple CLI tool written in Rust for getting an e Usage: ``` -todos src/ +todos --exclude node_modules src/ ``` Output: @@ -131,3 +131,8 @@ Output: ``` (without the HTML comments). + +Notes: +- `node_modules/` (for npm) and `vendor/` (for composer) are ignored by default +- paths starting with `.` are **always** ignored +- `--exclude`s are relative to the current working directory, not passed paths (including default excludes mentioned above). If you're running the script for another folder and want to exclude folders there, type out the path in `--exclude` diff --git a/src/main.rs b/src/main.rs index 00d4f6d..66b7fb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::{io, fs}; use std::path::{Path, PathBuf}; +use clap::Parser; #[derive(Debug, PartialEq, Clone)] struct Location { @@ -32,6 +33,25 @@ impl Entry { } } +struct Stats { + visited_folders: usize, + visited_files: usize, +} + +impl Stats { + fn new() -> Stats { + Stats { + visited_folders: 0, + visited_files: 0, + } + } + + fn print(&self) { + eprintln!("[INFO] Visited folders: {}", self.visited_folders); + eprintln!("[INFO] Visited files: {}", self.visited_files); + } +} + fn scan_string(str: String, filename: PathBuf, entries: &mut Vec) { for (line_num, line) in str.lines().enumerate() { if ! line.to_lowercase().contains("todo") { @@ -44,7 +64,7 @@ fn scan_string(str: String, filename: PathBuf, entries: &mut Vec) { } // Handles: `todo`, `TODO`, `todo:`, `TODO:` - // todo `replace` isnt ideal, it should only replace *after* the todo, to avoid merging eg `to:do` + // todo@real `replace` isnt ideal, it should only replace *after* the todo, to avoid merging eg `to:do` if word.to_lowercase().replace(':', "") == "todo" { let text_dirty = line.split_once(word).unwrap().1.replace("*/", ""); let text = text_dirty.trim(); @@ -113,7 +133,6 @@ fn scan_string(str: String, filename: PathBuf, entries: &mut Vec) { } } -// todo test this using sample.ts fn scan_file(path: &Path, entries: &mut Vec) -> io::Result<()> { match std::fs::read_to_string(path) { Ok(str) => scan_string(str, path.to_path_buf(), entries), @@ -123,27 +142,27 @@ fn scan_file(path: &Path, entries: &mut Vec) -> io::Result<()> { Ok(()) } -fn scan_dir(path: &Path, entries: &mut Vec) -> io::Result<()> { - for entry in fs::read_dir(path)? { +fn scan_dir(path: &Path, entries: &mut Vec, excludes: &Vec, stats: &mut Stats) -> io::Result<()> { + stats.visited_folders += 1; + + 'entry: for entry in fs::read_dir(path)? { let entry = entry?; let path = entry.path(); + if path.components().last().unwrap().as_os_str().to_string_lossy().starts_with('.') { + continue; + } + if path.is_dir() { - // todo make these configurable - if path.ends_with("node_modules") { - continue; + for exclude in excludes { + if path == *exclude { + continue 'entry; + } } - if path.ends_with("vendor") { - continue; - } - - if path.ends_with(".git") { - continue; - } - - scan_dir(path.as_path(), entries)? + scan_dir(path.as_path(), entries, excludes, stats)? } else { + stats.visited_files += 1; scan_file(path.as_path(), entries)? } } @@ -233,21 +252,66 @@ fn render(entries: Vec) { } -fn main() { - let args = std::env::args(); - let mut root_dir: PathBuf = std::env::current_dir().unwrap(); +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Path to your README.md file + #[arg(short, long, default_value = "")] + readme: String, - if args.len() > 1 { - for arg in args.skip(1) { - root_dir.push(arg); - } + // Path to your todo.md file + #[arg(short, long, default_value = "")] + todos: String, + + // Paths to search + #[arg(default_values_t = Vec::from([".".to_string()]))] + paths: Vec, + + // Paths to exclude + #[arg(short, long, default_values_t = Vec::from([ + "node_modules".to_string(), + "vendor".to_string(), + ]))] + exclude: Vec, + + #[arg(short, long, default_value_t = false)] + verbose: bool, +} + +fn main() { + let args = Args::parse(); + + let root_dir: PathBuf = std::env::current_dir().unwrap(); + let mut paths: Vec = vec![]; + let mut excludes: Vec = vec![]; + + for p in args.paths { + let mut path = root_dir.clone(); + path.push(p); + + paths.push(path); } - let mut entries: Vec = vec![]; + for exclude in args.exclude { + let mut path = root_dir.clone(); + path.push(exclude); - scan_dir(root_dir.as_path(), &mut entries).unwrap(); + excludes.push(path); + } + + // todo@real logic for readme.md and todos.md + + let mut entries: Vec = vec![]; + let mut stats = Stats::new(); + + scan_dir(root_dir.as_path(), &mut entries, &excludes, &mut stats).unwrap(); render(entries); + + if args.verbose { + eprint!("\n\n"); + stats.print(); + } } #[test] @@ -515,7 +579,10 @@ fn sample_test_ts() { let mut filepath = path.clone(); filepath.push("1.ts"); - scan_dir(path.as_path(), &mut entries).unwrap(); + let excludes: Vec = vec![]; + let mut stats = Stats::new(); + + scan_dir(path.as_path(), &mut entries, &excludes, &mut stats).unwrap(); assert_eq!(10, entries.len());