mirror of
https://github.com/crate-ci/typos.git
synced 2024-11-25 02:20:58 -05:00
Merge pull request #197 from epage/args
Improve feature discoverability
This commit is contained in:
commit
1798081344
3 changed files with 105 additions and 22 deletions
25
src/args.rs
25
src/args.rs
|
@ -41,9 +41,10 @@ impl Default for Format {
|
||||||
setting = structopt::clap::AppSettings::DeriveDisplayOrder,
|
setting = structopt::clap::AppSettings::DeriveDisplayOrder,
|
||||||
setting = structopt::clap::AppSettings::DontCollapseArgsInUsage
|
setting = structopt::clap::AppSettings::DontCollapseArgsInUsage
|
||||||
)]
|
)]
|
||||||
|
#[structopt(group = structopt::clap::ArgGroup::with_name("mode").multiple(false))]
|
||||||
pub(crate) struct Args {
|
pub(crate) struct Args {
|
||||||
#[structopt(parse(from_os_str), default_value = ".")]
|
#[structopt(parse(from_os_str), default_value = ".")]
|
||||||
/// Paths to check
|
/// Paths to check with `-` for stdin
|
||||||
pub(crate) path: Vec<std::path::PathBuf>,
|
pub(crate) path: Vec<std::path::PathBuf>,
|
||||||
|
|
||||||
#[structopt(short = "c", long = "config")]
|
#[structopt(short = "c", long = "config")]
|
||||||
|
@ -54,26 +55,30 @@ pub(crate) struct Args {
|
||||||
/// Ignore implicit configuration files.
|
/// Ignore implicit configuration files.
|
||||||
pub(crate) isolated: bool,
|
pub(crate) isolated: bool,
|
||||||
|
|
||||||
#[structopt(long)]
|
#[structopt(long, group = "mode")]
|
||||||
/// Print a diff of what would change
|
/// Print a diff of what would change
|
||||||
pub(crate) diff: bool,
|
pub(crate) diff: bool,
|
||||||
|
|
||||||
#[structopt(long, short = "w")]
|
#[structopt(long, short = "w", group = "mode")]
|
||||||
/// Write corrections out
|
/// Write fixes out
|
||||||
pub(crate) write_changes: bool,
|
pub(crate) write_changes: bool,
|
||||||
|
|
||||||
#[structopt(long)]
|
#[structopt(long, group = "mode")]
|
||||||
/// Print each file that would be spellchecked.
|
/// Debug: Print each file that would be spellchecked.
|
||||||
pub(crate) files: bool,
|
pub(crate) files: bool,
|
||||||
|
|
||||||
#[structopt(long)]
|
#[structopt(long, group = "mode")]
|
||||||
/// Print each identifier that would be spellchecked.
|
/// Debug: Print each identifier that would be spellchecked.
|
||||||
pub(crate) identifiers: bool,
|
pub(crate) identifiers: bool,
|
||||||
|
|
||||||
#[structopt(long)]
|
#[structopt(long, group = "mode")]
|
||||||
/// Print each word that would be spellchecked.
|
/// Debug: Print each word that would be spellchecked.
|
||||||
pub(crate) words: bool,
|
pub(crate) words: bool,
|
||||||
|
|
||||||
|
#[structopt(long, group = "mode")]
|
||||||
|
/// Write the current configuration to file with `-` for stdout
|
||||||
|
pub(crate) dump_config: Option<std::path::PathBuf>,
|
||||||
|
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
pub(crate) overrides: FileArgs,
|
pub(crate) overrides: FileArgs,
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,13 @@ impl Config {
|
||||||
Ok(content)
|
Ok(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_defaults() -> Self {
|
||||||
|
Self {
|
||||||
|
files: Walk::from_defaults(),
|
||||||
|
default: FileConfig::from_defaults(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn derive(cwd: &std::path::Path) -> Result<Self, anyhow::Error> {
|
pub fn derive(cwd: &std::path::Path) -> Result<Self, anyhow::Error> {
|
||||||
if let Some(path) = find_project_file(cwd, &["typos.toml", "_typos.toml", ".typos.toml"]) {
|
if let Some(path) = find_project_file(cwd, &["typos.toml", "_typos.toml", ".typos.toml"]) {
|
||||||
Self::from_file(&path)
|
Self::from_file(&path)
|
||||||
|
@ -160,6 +167,19 @@ pub struct Walk {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Walk {
|
impl Walk {
|
||||||
|
pub fn from_defaults() -> Self {
|
||||||
|
let empty = Self::default();
|
||||||
|
Self {
|
||||||
|
binary: Some(empty.binary()),
|
||||||
|
ignore_hidden: Some(empty.ignore_hidden()),
|
||||||
|
ignore_files: Some(true),
|
||||||
|
ignore_dot: Some(empty.ignore_dot()),
|
||||||
|
ignore_vcs: Some(empty.ignore_vcs()),
|
||||||
|
ignore_global: Some(empty.ignore_global()),
|
||||||
|
ignore_parent: Some(empty.ignore_parent()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, source: &dyn WalkSource) {
|
pub fn update(&mut self, source: &dyn WalkSource) {
|
||||||
if let Some(source) = source.binary() {
|
if let Some(source) = source.binary() {
|
||||||
self.binary = Some(source);
|
self.binary = Some(source);
|
||||||
|
@ -264,6 +284,22 @@ pub struct FileConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileConfig {
|
impl FileConfig {
|
||||||
|
pub fn from_defaults() -> Self {
|
||||||
|
let empty = Self::default();
|
||||||
|
FileConfig {
|
||||||
|
check_filename: Some(empty.check_filename()),
|
||||||
|
check_file: Some(empty.check_file()),
|
||||||
|
ignore_hex: Some(empty.ignore_hex()),
|
||||||
|
identifier_leading_digits: Some(empty.identifier_leading_digits()),
|
||||||
|
identifier_leading_chars: Some(empty.identifier_leading_chars().to_owned()),
|
||||||
|
identifier_include_digits: Some(empty.identifier_include_digits()),
|
||||||
|
identifier_include_chars: Some(empty.identifier_include_chars().to_owned()),
|
||||||
|
locale: Some(empty.locale()),
|
||||||
|
extend_identifiers: Default::default(),
|
||||||
|
extend_words: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, source: &dyn FileSource) {
|
pub fn update(&mut self, source: &dyn FileSource) {
|
||||||
if let Some(source) = source.check_filename() {
|
if let Some(source) = source.check_filename() {
|
||||||
self.check_filename = Some(source);
|
self.check_filename = Some(source);
|
||||||
|
|
66
src/main.rs
66
src/main.rs
|
@ -34,13 +34,46 @@ fn run() -> proc_exit::ExitResult {
|
||||||
};
|
};
|
||||||
|
|
||||||
init_logging(args.verbose.log_level());
|
init_logging(args.verbose.log_level());
|
||||||
|
|
||||||
|
if let Some(output_path) = args.dump_config.as_ref() {
|
||||||
|
run_dump_config(&args, output_path)
|
||||||
|
} else {
|
||||||
|
run_checks(&args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_dump_config(args: &args::Args, output_path: &std::path::Path) -> proc_exit::ExitResult {
|
||||||
let global_cwd = std::env::current_dir()?;
|
let global_cwd = std::env::current_dir()?;
|
||||||
|
|
||||||
let config = if let Some(path) = args.custom_config.as_ref() {
|
let path = &args.path[0];
|
||||||
config::Config::from_file(path).with_code(proc_exit::Code::CONFIG_ERR)?
|
let path = if path == std::path::Path::new("-") {
|
||||||
|
path.to_owned()
|
||||||
} else {
|
} else {
|
||||||
config::Config::default()
|
path.canonicalize().with_code(proc_exit::Code::USAGE_ERR)?
|
||||||
};
|
};
|
||||||
|
let cwd = if path == std::path::Path::new("-") {
|
||||||
|
global_cwd.as_path()
|
||||||
|
} else if path.is_file() {
|
||||||
|
path.parent().unwrap()
|
||||||
|
} else {
|
||||||
|
path.as_path()
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = load_config(cwd, &args).with_code(proc_exit::Code::CONFIG_ERR)?;
|
||||||
|
let mut defaulted_config = config::Config::from_defaults();
|
||||||
|
defaulted_config.update(&config);
|
||||||
|
let output = toml::to_string_pretty(&defaulted_config).with_code(proc_exit::Code::FAILURE)?;
|
||||||
|
if output_path == std::path::Path::new("-") {
|
||||||
|
std::io::stdout().write_all(output.as_bytes())?;
|
||||||
|
} else {
|
||||||
|
std::fs::write(output_path, &output)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
||||||
|
let global_cwd = std::env::current_dir()?;
|
||||||
|
|
||||||
let mut typos_found = false;
|
let mut typos_found = false;
|
||||||
let mut errors_found = false;
|
let mut errors_found = false;
|
||||||
|
@ -57,15 +90,7 @@ fn run() -> proc_exit::ExitResult {
|
||||||
} else {
|
} else {
|
||||||
path.as_path()
|
path.as_path()
|
||||||
};
|
};
|
||||||
|
let config = load_config(cwd, &args).with_code(proc_exit::Code::CONFIG_ERR)?;
|
||||||
let mut config = config.clone();
|
|
||||||
if !args.isolated {
|
|
||||||
let derived = config::Config::derive(cwd).with_code(proc_exit::Code::CONFIG_ERR)?;
|
|
||||||
config.update(&derived);
|
|
||||||
}
|
|
||||||
config.update(&args.config);
|
|
||||||
config.default.update(&args.overrides);
|
|
||||||
let config = config;
|
|
||||||
|
|
||||||
let parser = typos::tokens::TokenizerBuilder::new()
|
let parser = typos::tokens::TokenizerBuilder::new()
|
||||||
.ignore_hex(config.default.ignore_hex())
|
.ignore_hex(config.default.ignore_hex())
|
||||||
|
@ -194,3 +219,20 @@ fn init_logging(level: Option<log::Level>) {
|
||||||
builder.init();
|
builder.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_config(cwd: &std::path::Path, args: &args::Args) -> Result<config::Config, anyhow::Error> {
|
||||||
|
let mut config = config::Config::default();
|
||||||
|
|
||||||
|
if !args.isolated {
|
||||||
|
let derived = config::Config::derive(cwd)?;
|
||||||
|
config.update(&derived);
|
||||||
|
}
|
||||||
|
if let Some(path) = args.custom_config.as_ref() {
|
||||||
|
config.update(&config::Config::from_file(path)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.update(&args.config);
|
||||||
|
config.default.update(&args.overrides);
|
||||||
|
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue