mirror of
https://github.com/archtechx/todo-system.git
synced 2025-12-12 09:04:03 +00:00
CLI arg parsing
This commit is contained in:
parent
15c2c7d3f0
commit
574cee8895
4 changed files with 318 additions and 27 deletions
216
Cargo.lock
generated
216
Cargo.lock
generated
|
|
@ -2,6 +2,222 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
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]]
|
[[package]]
|
||||||
name = "todo-system"
|
name = "todo-system"
|
||||||
version = "0.1.0"
|
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"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
name = "todo-system"
|
name = "todo-system"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
authors = ["Samuel Štancl <samuel@archte.ch>"]
|
||||||
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
clap = { version = "4.4.8", features = ["derive"] }
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ That said, this repo includes a simple CLI tool written in Rust for getting an e
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
```
|
```
|
||||||
todos src/
|
todos --exclude node_modules src/
|
||||||
```
|
```
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
|
|
@ -131,3 +131,8 @@ Output:
|
||||||
```
|
```
|
||||||
|
|
||||||
(without the HTML comments).
|
(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`
|
||||||
|
|
|
||||||
115
src/main.rs
115
src/main.rs
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{io, fs};
|
use std::{io, fs};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
struct Location {
|
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<Entry>) {
|
fn scan_string(str: String, filename: PathBuf, entries: &mut Vec<Entry>) {
|
||||||
for (line_num, line) in str.lines().enumerate() {
|
for (line_num, line) in str.lines().enumerate() {
|
||||||
if ! line.to_lowercase().contains("todo") {
|
if ! line.to_lowercase().contains("todo") {
|
||||||
|
|
@ -44,7 +64,7 @@ fn scan_string(str: String, filename: PathBuf, entries: &mut Vec<Entry>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles: `todo`, `TODO`, `todo:`, `TODO:`
|
// 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" {
|
if word.to_lowercase().replace(':', "") == "todo" {
|
||||||
let text_dirty = line.split_once(word).unwrap().1.replace("*/", "");
|
let text_dirty = line.split_once(word).unwrap().1.replace("*/", "");
|
||||||
let text = text_dirty.trim();
|
let text = text_dirty.trim();
|
||||||
|
|
@ -113,7 +133,6 @@ fn scan_string(str: String, filename: PathBuf, entries: &mut Vec<Entry>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo test this using sample.ts
|
|
||||||
fn scan_file(path: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {
|
fn scan_file(path: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {
|
||||||
match std::fs::read_to_string(path) {
|
match std::fs::read_to_string(path) {
|
||||||
Ok(str) => scan_string(str, path.to_path_buf(), entries),
|
Ok(str) => scan_string(str, path.to_path_buf(), entries),
|
||||||
|
|
@ -123,27 +142,27 @@ fn scan_file(path: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_dir(path: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {
|
fn scan_dir(path: &Path, entries: &mut Vec<Entry>, excludes: &Vec<PathBuf>, stats: &mut Stats) -> io::Result<()> {
|
||||||
for entry in fs::read_dir(path)? {
|
stats.visited_folders += 1;
|
||||||
|
|
||||||
|
'entry: for entry in fs::read_dir(path)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
|
|
||||||
|
if path.components().last().unwrap().as_os_str().to_string_lossy().starts_with('.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
// todo make these configurable
|
for exclude in excludes {
|
||||||
if path.ends_with("node_modules") {
|
if path == *exclude {
|
||||||
continue;
|
continue 'entry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.ends_with("vendor") {
|
scan_dir(path.as_path(), entries, excludes, stats)?
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if path.ends_with(".git") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
scan_dir(path.as_path(), entries)?
|
|
||||||
} else {
|
} else {
|
||||||
|
stats.visited_files += 1;
|
||||||
scan_file(path.as_path(), entries)?
|
scan_file(path.as_path(), entries)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -233,21 +252,66 @@ fn render(entries: Vec<Entry>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[derive(Parser, Debug)]
|
||||||
let args = std::env::args();
|
#[command(author, version, about, long_about = None)]
|
||||||
let mut root_dir: PathBuf = std::env::current_dir().unwrap();
|
struct Args {
|
||||||
|
/// Path to your README.md file
|
||||||
|
#[arg(short, long, default_value = "")]
|
||||||
|
readme: String,
|
||||||
|
|
||||||
if args.len() > 1 {
|
// Path to your todo.md file
|
||||||
for arg in args.skip(1) {
|
#[arg(short, long, default_value = "")]
|
||||||
root_dir.push(arg);
|
todos: String,
|
||||||
|
|
||||||
|
// Paths to search
|
||||||
|
#[arg(default_values_t = Vec::from([".".to_string()]))]
|
||||||
|
paths: Vec<String>,
|
||||||
|
|
||||||
|
// Paths to exclude
|
||||||
|
#[arg(short, long, default_values_t = Vec::from([
|
||||||
|
"node_modules".to_string(),
|
||||||
|
"vendor".to_string(),
|
||||||
|
]))]
|
||||||
|
exclude: Vec<String>,
|
||||||
|
|
||||||
|
#[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<PathBuf> = vec![];
|
||||||
|
let mut excludes: Vec<PathBuf> = vec![];
|
||||||
|
|
||||||
|
for p in args.paths {
|
||||||
|
let mut path = root_dir.clone();
|
||||||
|
path.push(p);
|
||||||
|
|
||||||
|
paths.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for exclude in args.exclude {
|
||||||
|
let mut path = root_dir.clone();
|
||||||
|
path.push(exclude);
|
||||||
|
|
||||||
|
excludes.push(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo@real logic for readme.md and todos.md
|
||||||
|
|
||||||
let mut entries: Vec<Entry> = vec![];
|
let mut entries: Vec<Entry> = vec![];
|
||||||
|
let mut stats = Stats::new();
|
||||||
|
|
||||||
scan_dir(root_dir.as_path(), &mut entries).unwrap();
|
scan_dir(root_dir.as_path(), &mut entries, &excludes, &mut stats).unwrap();
|
||||||
|
|
||||||
render(entries);
|
render(entries);
|
||||||
|
|
||||||
|
if args.verbose {
|
||||||
|
eprint!("\n\n");
|
||||||
|
stats.print();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -515,7 +579,10 @@ fn sample_test_ts() {
|
||||||
let mut filepath = path.clone();
|
let mut filepath = path.clone();
|
||||||
filepath.push("1.ts");
|
filepath.push("1.ts");
|
||||||
|
|
||||||
scan_dir(path.as_path(), &mut entries).unwrap();
|
let excludes: Vec<PathBuf> = vec![];
|
||||||
|
let mut stats = Stats::new();
|
||||||
|
|
||||||
|
scan_dir(path.as_path(), &mut entries, &excludes, &mut stats).unwrap();
|
||||||
|
|
||||||
assert_eq!(10, entries.len());
|
assert_eq!(10, entries.len());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue