Enhance CLI arguments with new options, validation, and detailed help messages
This commit is contained in:
@@ -10,6 +10,8 @@ clap = { version = "^4", features = ["derive"] }
|
|||||||
|
|
||||||
rayon = "^1"
|
rayon = "^1"
|
||||||
|
|
||||||
|
once_cell = "^1"
|
||||||
|
|
||||||
mago-syntax = "^1.13"
|
mago-syntax = "^1.13"
|
||||||
mago-interner = "^1.0.0-alpha"
|
mago-interner = "^1.0.0-alpha"
|
||||||
mago-source = "^1.0.0-alpha"
|
mago-source = "^1.0.0-alpha"
|
||||||
@@ -18,4 +20,5 @@ mago-names = "^1.13"
|
|||||||
mago-project = "^0.26"
|
mago-project = "^0.26"
|
||||||
mago-semantics = "^1.13"
|
mago-semantics = "^1.13"
|
||||||
|
|
||||||
|
regex = "^1"
|
||||||
walkdir = "^2"
|
walkdir = "^2"
|
||||||
|
|||||||
@@ -12,20 +12,35 @@ use crate::util::fs;
|
|||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(name = "pmp", about, version)]
|
#[command(name = "pmp", about, version)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
#[arg(long, value_hint = FilePath, value_parser = fs::path_exists)]
|
#[arg(long, value_hint = FilePath, value_parser = fs::path_exists, help = "Path to PHP binary")]
|
||||||
php: Option<PathBuf>,
|
php: Option<PathBuf>,
|
||||||
|
|
||||||
#[arg(long, short = 'd', hide = true)]
|
#[arg(long, short = 'd', hide = true)]
|
||||||
debug: bool,
|
debug: bool,
|
||||||
#[arg(long, short = 'v')]
|
#[arg(long, short = 'v', help = "Verbose output")]
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
#[arg(long, short = 'n', help = "Dry run, does not modify files or cache")]
|
||||||
|
dry_run: bool,
|
||||||
|
|
||||||
#[arg(default_value_os = OsStr::new("."), value_hint = FilePath, value_parser = fs::path_exists)]
|
#[arg(long, short = 'e', value_hint = FilePath, value_parser = fs::path_exists, default_values_os = [OsStr::new(".gitignore"), OsStr::new("vendor/")], help = "Exclude files from pre-processing, e.g. vendor/")]
|
||||||
|
exclude: Vec<PathBuf>,
|
||||||
|
#[arg(long, short = 'c', value_hint = FilePath, value_parser = fs::valid_possible_path, default_value_os = OsStr::new(".cache"), help = "Cache directory location")]
|
||||||
|
cache_dir: Option<PathBuf>,
|
||||||
|
#[arg(long, short = 'o', value_hint = FilePath, value_parser = fs::valid_possible_path, default_value_os = OsStr::new("."), help = "Output directory location")]
|
||||||
|
output_dir: Option<PathBuf>,
|
||||||
|
#[arg(long, short = 'i', conflicts_with = "dry_run", help = "Invalidate cache and re-process all files")]
|
||||||
|
invalidate_cache: bool,
|
||||||
|
|
||||||
|
#[arg(value_hint = FilePath, value_parser = fs::path_exists, default_value_os = OsStr::new("."), help = "Directory to recursively scan and pre-process")]
|
||||||
directory: Option<PathBuf>,
|
directory: Option<PathBuf>,
|
||||||
#[arg(last = true)]
|
#[arg(last = true)]
|
||||||
passthrough: Vec<String>,
|
passthrough: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: ignore .gitignore marked content per default
|
||||||
|
// todo: diff output with verbose and ofc trace for warnings/errors
|
||||||
|
// todo: cache with file hashes and system last edited timestamp
|
||||||
|
|
||||||
impl Args
|
impl Args
|
||||||
{
|
{
|
||||||
pub fn parse() -> Self {
|
pub fn parse() -> Self {
|
||||||
|
|||||||
@@ -1,6 +1,27 @@
|
|||||||
|
use regex::Regex;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
static PATH_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||||
|
Regex::new(r"^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$").unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
pub fn path_exists(s: &str) -> Result<PathBuf, String> {
|
pub fn path_exists(s: &str) -> Result<PathBuf, String> {
|
||||||
let p = PathBuf::from(s);
|
let p = PathBuf::from(s);
|
||||||
p.exists().then_some(p).ok_or("path does not exist".to_string())
|
p.exists().then_some(p).ok_or("path does not exist".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn valid_possible_path(s: &str) -> Result<PathBuf, String>
|
||||||
|
{
|
||||||
|
let lower = s.to_ascii_lowercase();
|
||||||
|
|
||||||
|
if lower == "true" || lower == "false" {
|
||||||
|
return Err("boolean literal is not allowed".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if PATH_REGEX.is_match(s) {
|
||||||
|
return Err("numeric literal is not allowed".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(PathBuf::from(s))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user