#![deny(dead_code)]
#![deny(missing_docs)]
#![deny(clippy::dbg_macro)]
#![warn(clippy::pedantic)]
#![allow(clippy::non_ascii_literal)]
#![allow(clippy::identity_op)]
#![allow(clippy::wildcard_imports)]
pub use doc_chunks as documentation;
#[cfg(test)]
pub(crate) use doc_chunks::{chyrp_up, fluff_up};
pub mod action;
mod checker;
mod config;
pub mod errors;
mod reflow;
mod suggestion;
mod tinhat;
mod traverse;
pub use self::action::*;
pub use self::config::args::*;
pub use self::config::{Config, HunspellConfig, LanguageToolConfig};
pub use self::documentation::span::*;
pub use self::documentation::util::*;
pub use self::documentation::*;
pub use self::suggestion::*;
pub use self::tinhat::*;
use self::errors::{bail, Result};
use std::io::Write;
#[cfg(target_os = "windows")]
use signal_hook as _;
use checker::Checker;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ExitCode {
Success,
Signal,
Custom(u8),
}
impl ExitCode {
pub fn as_u8(&self) -> u8 {
match *self {
Self::Success => 0u8,
Self::Signal => 130u8,
Self::Custom(code) => code,
}
}
}
pub fn run(args: Args) -> Result<ExitCode> {
let _ = ::rayon::ThreadPoolBuilder::new()
.num_threads(args.job_count())
.build_global();
env_logger::Builder::from_env(env_logger::Env::new().filter_or("CARGO_SPELLCHECK", "warn"))
.filter_level(args.verbosity())
.filter_module("nlprule", log::LevelFilter::Error)
.filter_module("mio", log::LevelFilter::Error)
.init();
#[cfg(not(target_os = "windows"))]
signal_handler(move || {
if let Err(e) = action::interactive::ScopedRaw::restore_terminal() {
log::warn!("Failed to restore terminal: {}", e);
}
});
let (unified, config) = match &args.command {
Some(Sub::Completions { shell }) => {
let sink = &mut std::io::stdout();
generate_completions(*shell, sink);
let _ = sink.flush();
return Ok(ExitCode::Success);
}
_ => args.unified()?,
};
match unified {
UnifiedArgs::Config {
dest_config,
checker_filter_set,
} => {
log::trace!("Configuration chore");
let mut config = Config::full();
Args::checker_selection_override(
checker_filter_set.as_ref().map(AsRef::as_ref),
&mut config,
)?;
match dest_config {
ConfigWriteDestination::Stdout => {
println!("{}", config.to_toml()?);
return Ok(ExitCode::Success);
}
ConfigWriteDestination::File { overwrite, path } => {
if path.exists() && !overwrite {
bail!(
"Attempting to overwrite {} requires `--force`.",
path.display()
);
}
log::info!("Writing configuration file to {}", path.display());
config.write_values_to_path(path)?;
}
}
return Ok(ExitCode::Success);
}
UnifiedArgs::Operate {
action,
paths,
recursive,
skip_readme,
config_path,
dev_comments,
exit_code_override,
} => {
log::debug!(
"Executing: {:?} with {:?} from {:?}",
action,
&config,
config_path
);
let documents =
traverse::extract(paths, recursive, skip_readme, dev_comments, &config)?;
let rt = tokio::runtime::Runtime::new()?;
let finish = rt.block_on(async move { action.run(documents, config).await })?;
match finish {
Finish::Success | Finish::MistakeCount(0) => Ok(ExitCode::Success),
Finish::MistakeCount(_n) => Ok(ExitCode::Custom(exit_code_override)),
Finish::Abort => Ok(ExitCode::Signal),
}
}
}
}
#[cfg(test)]
mod tests;