mirror of
https://github.com/crate-ci/typos.git
synced 2024-12-25 00:52:08 -05:00
feat(report): Diff output mode
This commit is contained in:
parent
7a1fac7fab
commit
d258e62f43
6 changed files with 119 additions and 8 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -291,6 +291,12 @@ version = "2.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
|
@ -1078,6 +1084,7 @@ dependencies = [
|
|||
"bstr",
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
"difflib",
|
||||
"env_logger 0.8.1",
|
||||
"ignore",
|
||||
"log",
|
||||
|
|
|
@ -47,6 +47,7 @@ log = "0.4"
|
|||
env_logger = "0.8"
|
||||
bstr = "0.2"
|
||||
ahash = "0.5.8"
|
||||
difflib = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_fs = "1.0"
|
||||
|
|
|
@ -54,6 +54,10 @@ pub(crate) struct Args {
|
|||
/// Ignore implicit configuration files.
|
||||
pub(crate) isolated: bool,
|
||||
|
||||
#[structopt(long)]
|
||||
/// Print a diff of what would change
|
||||
pub(crate) diff: bool,
|
||||
|
||||
#[structopt(long, short = "w")]
|
||||
/// Write corrections out
|
||||
pub(crate) write_changes: bool,
|
||||
|
|
93
src/diff.rs
Normal file
93
src/diff.rs
Normal file
|
@ -0,0 +1,93 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::sync;
|
||||
|
||||
use bstr::ByteSlice;
|
||||
|
||||
pub struct Diff<'r> {
|
||||
reporter: &'r dyn typos::report::Report,
|
||||
deferred: sync::Mutex<crate::replace::Deferred>,
|
||||
}
|
||||
|
||||
impl<'r> Diff<'r> {
|
||||
pub(crate) fn new(reporter: &'r dyn typos::report::Report) -> Self {
|
||||
Self {
|
||||
reporter,
|
||||
deferred: sync::Mutex::new(crate::replace::Deferred::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&self) -> Result<(), std::io::Error> {
|
||||
let deferred = self.deferred.lock().unwrap();
|
||||
|
||||
for (path, corrections) in deferred.content.iter() {
|
||||
let buffer = std::fs::read(path)?;
|
||||
|
||||
let mut original = Vec::new();
|
||||
let mut corrected = Vec::new();
|
||||
for (line_idx, line) in buffer.lines_with_terminator().enumerate() {
|
||||
original.push(String::from_utf8_lossy(line).into_owned());
|
||||
|
||||
let line_num = line_idx + 1;
|
||||
let line = if let Some(corrections) = corrections.get(&line_num) {
|
||||
let line = line.to_vec();
|
||||
crate::replace::correct(line, &corrections)
|
||||
} else {
|
||||
line.to_owned()
|
||||
};
|
||||
corrected.push(String::from_utf8_lossy(&line).into_owned())
|
||||
}
|
||||
|
||||
let display_path = path.display().to_string();
|
||||
let diff = difflib::unified_diff(
|
||||
&original,
|
||||
&corrected,
|
||||
display_path.as_str(),
|
||||
display_path.as_str(),
|
||||
"original",
|
||||
"corrected",
|
||||
0,
|
||||
);
|
||||
for line in diff {
|
||||
print!("{}", line);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> typos::report::Report for Diff<'r> {
|
||||
fn report(&self, msg: typos::report::Message<'_>) -> bool {
|
||||
let typo = match &msg {
|
||||
typos::report::Message::Typo(typo) => typo,
|
||||
_ => return self.reporter.report(msg),
|
||||
};
|
||||
|
||||
let corrections = match &typo.corrections {
|
||||
typos::Status::Corrections(corrections) if corrections.len() == 1 => corrections,
|
||||
_ => return self.reporter.report(msg),
|
||||
};
|
||||
|
||||
match &typo.context {
|
||||
Some(typos::report::Context::File(file)) => {
|
||||
let path = file.path.to_owned();
|
||||
let line_num = file.line_num;
|
||||
let correction = crate::replace::Correction::new(
|
||||
typo.byte_offset,
|
||||
typo.typo,
|
||||
corrections[0].as_ref(),
|
||||
);
|
||||
let mut deferred = self.deferred.lock().unwrap();
|
||||
let content = deferred
|
||||
.content
|
||||
.entry(path)
|
||||
.or_insert_with(BTreeMap::new)
|
||||
.entry(line_num)
|
||||
.or_insert_with(Vec::new);
|
||||
content.push(correction);
|
||||
false
|
||||
}
|
||||
_ => msg.is_correction(),
|
||||
}
|
||||
}
|
||||
}
|
10
src/main.rs
10
src/main.rs
|
@ -10,6 +10,7 @@ mod args;
|
|||
mod checks;
|
||||
mod config;
|
||||
mod dict;
|
||||
mod diff;
|
||||
mod replace;
|
||||
|
||||
fn main() {
|
||||
|
@ -86,7 +87,10 @@ fn run() -> Result<i32, anyhow::Error> {
|
|||
|
||||
let mut reporter = args.format.reporter();
|
||||
let replace_reporter = replace::Replace::new(reporter);
|
||||
if args.write_changes {
|
||||
let diff_reporter = diff::Diff::new(reporter);
|
||||
if args.diff {
|
||||
reporter = &diff_reporter;
|
||||
} else if args.write_changes {
|
||||
reporter = &replace_reporter;
|
||||
}
|
||||
|
||||
|
@ -129,7 +133,9 @@ fn run() -> Result<i32, anyhow::Error> {
|
|||
errors_found = true;
|
||||
}
|
||||
|
||||
if args.write_changes {
|
||||
if args.diff {
|
||||
diff_reporter.show()?;
|
||||
} else if args.write_changes {
|
||||
replace_reporter.write()?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,20 +97,20 @@ impl<'r> typos::report::Report for Replace<'r> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct Deferred {
|
||||
content: BTreeMap<path::PathBuf, BTreeMap<usize, Vec<Correction>>>,
|
||||
paths: BTreeMap<path::PathBuf, Vec<Correction>>,
|
||||
pub(crate) struct Deferred {
|
||||
pub(crate) content: BTreeMap<path::PathBuf, BTreeMap<usize, Vec<Correction>>>,
|
||||
pub(crate) paths: BTreeMap<path::PathBuf, Vec<Correction>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
struct Correction {
|
||||
pub(crate) struct Correction {
|
||||
pub byte_offset: usize,
|
||||
pub typo: Vec<u8>,
|
||||
pub correction: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Correction {
|
||||
fn new(byte_offset: usize, typo: &str, correction: &str) -> Self {
|
||||
pub(crate) fn new(byte_offset: usize, typo: &str, correction: &str) -> Self {
|
||||
Self {
|
||||
byte_offset,
|
||||
typo: typo.as_bytes().to_vec(),
|
||||
|
@ -119,7 +119,7 @@ impl Correction {
|
|||
}
|
||||
}
|
||||
|
||||
fn correct(mut line: Vec<u8>, corrections: &[Correction]) -> Vec<u8> {
|
||||
pub(crate) fn correct(mut line: Vec<u8>, corrections: &[Correction]) -> Vec<u8> {
|
||||
let mut corrections: Vec<_> = corrections.iter().collect();
|
||||
corrections.sort_unstable();
|
||||
corrections.reverse();
|
||||
|
|
Loading…
Reference in a new issue