mirror of
https://github.com/crate-ci/typos.git
synced 2024-11-25 18:41:05 -05:00
commit
8a35a12096
9 changed files with 173 additions and 47 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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "difflib"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "doc-comment"
|
name = "doc-comment"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -1078,6 +1084,7 @@ dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"clap",
|
"clap",
|
||||||
"clap-verbosity-flag",
|
"clap-verbosity-flag",
|
||||||
|
"difflib",
|
||||||
"env_logger 0.8.1",
|
"env_logger 0.8.1",
|
||||||
"ignore",
|
"ignore",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
@ -47,6 +47,7 @@ log = "0.4"
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
bstr = "0.2"
|
bstr = "0.2"
|
||||||
ahash = "0.5.8"
|
ahash = "0.5.8"
|
||||||
|
difflib = "0.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_fs = "1.0"
|
assert_fs = "1.0"
|
||||||
|
|
|
@ -94,7 +94,7 @@ struct ReportContext<'m, 'r> {
|
||||||
|
|
||||||
impl<'m, 'r> report::Report for ReportContext<'m, 'r> {
|
impl<'m, 'r> report::Report for ReportContext<'m, 'r> {
|
||||||
fn report(&self, msg: report::Message) -> bool {
|
fn report(&self, msg: report::Message) -> bool {
|
||||||
let msg = msg.context(self.context.clone());
|
let msg = msg.context(Some(self.context.clone()));
|
||||||
self.reporter.report(msg)
|
self.reporter.report(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ impl Check for Typos {
|
||||||
Some(corrections) => {
|
Some(corrections) => {
|
||||||
let byte_offset = ident.offset();
|
let byte_offset = ident.offset();
|
||||||
let msg = report::Typo {
|
let msg = report::Typo {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
buffer: std::borrow::Cow::Borrowed(buffer.as_bytes()),
|
buffer: std::borrow::Cow::Borrowed(buffer.as_bytes()),
|
||||||
byte_offset,
|
byte_offset,
|
||||||
typo: ident.token(),
|
typo: ident.token(),
|
||||||
|
@ -203,7 +203,7 @@ impl Check for Typos {
|
||||||
Some(corrections) => {
|
Some(corrections) => {
|
||||||
let byte_offset = word.offset();
|
let byte_offset = word.offset();
|
||||||
let msg = report::Typo {
|
let msg = report::Typo {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
buffer: std::borrow::Cow::Borrowed(buffer.as_bytes()),
|
buffer: std::borrow::Cow::Borrowed(buffer.as_bytes()),
|
||||||
byte_offset,
|
byte_offset,
|
||||||
typo: word.token(),
|
typo: word.token(),
|
||||||
|
@ -236,7 +236,7 @@ impl Check for Typos {
|
||||||
Some(corrections) => {
|
Some(corrections) => {
|
||||||
let byte_offset = ident.offset();
|
let byte_offset = ident.offset();
|
||||||
let msg = report::Typo {
|
let msg = report::Typo {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
buffer: std::borrow::Cow::Borrowed(buffer),
|
buffer: std::borrow::Cow::Borrowed(buffer),
|
||||||
byte_offset,
|
byte_offset,
|
||||||
typo: ident.token(),
|
typo: ident.token(),
|
||||||
|
@ -251,7 +251,7 @@ impl Check for Typos {
|
||||||
Some(corrections) => {
|
Some(corrections) => {
|
||||||
let byte_offset = word.offset();
|
let byte_offset = word.offset();
|
||||||
let msg = report::Typo {
|
let msg = report::Typo {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
buffer: std::borrow::Cow::Borrowed(buffer),
|
buffer: std::borrow::Cow::Borrowed(buffer),
|
||||||
byte_offset,
|
byte_offset,
|
||||||
typo: word.token(),
|
typo: word.token(),
|
||||||
|
@ -300,7 +300,7 @@ impl Check for ParseIdentifiers {
|
||||||
let typos_found = false;
|
let typos_found = false;
|
||||||
|
|
||||||
let msg = report::Parse {
|
let msg = report::Parse {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
kind: report::ParseKind::Identifier,
|
kind: report::ParseKind::Identifier,
|
||||||
data: parser.parse_str(buffer).map(|i| i.token()).collect(),
|
data: parser.parse_str(buffer).map(|i| i.token()).collect(),
|
||||||
};
|
};
|
||||||
|
@ -321,7 +321,7 @@ impl Check for ParseIdentifiers {
|
||||||
let typos_found = false;
|
let typos_found = false;
|
||||||
|
|
||||||
let msg = report::Parse {
|
let msg = report::Parse {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
kind: report::ParseKind::Identifier,
|
kind: report::ParseKind::Identifier,
|
||||||
data: parser.parse_bytes(buffer).map(|i| i.token()).collect(),
|
data: parser.parse_bytes(buffer).map(|i| i.token()).collect(),
|
||||||
};
|
};
|
||||||
|
@ -363,7 +363,7 @@ impl Check for ParseWords {
|
||||||
let typos_found = false;
|
let typos_found = false;
|
||||||
|
|
||||||
let msg = report::Parse {
|
let msg = report::Parse {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
kind: report::ParseKind::Word,
|
kind: report::ParseKind::Word,
|
||||||
data: parser
|
data: parser
|
||||||
.parse_str(buffer)
|
.parse_str(buffer)
|
||||||
|
@ -387,7 +387,7 @@ impl Check for ParseWords {
|
||||||
let typos_found = false;
|
let typos_found = false;
|
||||||
|
|
||||||
let msg = report::Parse {
|
let msg = report::Parse {
|
||||||
context: report::Context::None,
|
context: None,
|
||||||
kind: report::ParseKind::Word,
|
kind: report::ParseKind::Word,
|
||||||
data: parser
|
data: parser
|
||||||
.parse_bytes(buffer)
|
.parse_bytes(buffer)
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl<'m> Message<'m> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context(self, context: Context<'m>) -> Self {
|
pub fn context(self, context: Option<Context<'m>>) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Message::Typo(typo) => {
|
Message::Typo(typo) => {
|
||||||
let typo = typo.context(context);
|
let typo = typo.context(context);
|
||||||
|
@ -65,7 +65,7 @@ pub struct BinaryFile<'m> {
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct Typo<'m> {
|
pub struct Typo<'m> {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub context: Context<'m>,
|
pub context: Option<Context<'m>>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub buffer: Cow<'m, [u8]>,
|
pub buffer: Cow<'m, [u8]>,
|
||||||
pub byte_offset: usize,
|
pub byte_offset: usize,
|
||||||
|
@ -76,7 +76,7 @@ pub struct Typo<'m> {
|
||||||
impl<'m> Default for Typo<'m> {
|
impl<'m> Default for Typo<'m> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
context: Context::None,
|
context: None,
|
||||||
buffer: Cow::Borrowed(&[]),
|
buffer: Cow::Borrowed(&[]),
|
||||||
byte_offset: 0,
|
byte_offset: 0,
|
||||||
typo: "",
|
typo: "",
|
||||||
|
@ -91,13 +91,6 @@ impl<'m> Default for Typo<'m> {
|
||||||
pub enum Context<'m> {
|
pub enum Context<'m> {
|
||||||
File(FileContext<'m>),
|
File(FileContext<'m>),
|
||||||
Path(PathContext<'m>),
|
Path(PathContext<'m>),
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'m> Default for Context<'m> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Context::None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'m> std::fmt::Display for Context<'m> {
|
impl<'m> std::fmt::Display for Context<'m> {
|
||||||
|
@ -105,7 +98,6 @@ impl<'m> std::fmt::Display for Context<'m> {
|
||||||
match self {
|
match self {
|
||||||
Context::File(c) => write!(f, "{}:{}", c.path.display(), c.line_num),
|
Context::File(c) => write!(f, "{}:{}", c.path.display(), c.line_num),
|
||||||
Context::Path(c) => write!(f, "{}", c.path.display()),
|
Context::Path(c) => write!(f, "{}", c.path.display()),
|
||||||
Context::None => Ok(()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +164,7 @@ impl<'m> Default for File<'m> {
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct Parse<'m> {
|
pub struct Parse<'m> {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub context: Context<'m>,
|
pub context: Option<Context<'m>>,
|
||||||
pub kind: ParseKind,
|
pub kind: ParseKind,
|
||||||
pub data: Vec<&'m str>,
|
pub data: Vec<&'m str>,
|
||||||
}
|
}
|
||||||
|
@ -180,7 +172,7 @@ pub struct Parse<'m> {
|
||||||
impl<'m> Default for Parse<'m> {
|
impl<'m> Default for Parse<'m> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
context: Context::None,
|
context: None,
|
||||||
kind: ParseKind::Identifier,
|
kind: ParseKind::Identifier,
|
||||||
data: vec![],
|
data: vec![],
|
||||||
}
|
}
|
||||||
|
@ -294,13 +286,15 @@ fn print_brief_correction(msg: &Typo) {
|
||||||
crate::Status::Invalid => {
|
crate::Status::Invalid => {
|
||||||
println!(
|
println!(
|
||||||
"{}:{}: {} is disallowed",
|
"{}:{}: {} is disallowed",
|
||||||
msg.context, msg.byte_offset, msg.typo,
|
context_display(&msg.context),
|
||||||
|
msg.byte_offset,
|
||||||
|
msg.typo,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
crate::Status::Corrections(corrections) => {
|
crate::Status::Corrections(corrections) => {
|
||||||
println!(
|
println!(
|
||||||
"{}:{}: {} -> {}",
|
"{}:{}: {} -> {}",
|
||||||
msg.context,
|
context_display(&msg.context),
|
||||||
msg.byte_offset,
|
msg.byte_offset,
|
||||||
msg.typo,
|
msg.typo,
|
||||||
itertools::join(corrections.iter(), ", ")
|
itertools::join(corrections.iter(), ", ")
|
||||||
|
@ -318,7 +312,9 @@ fn print_long_correction(msg: &Typo) {
|
||||||
writeln!(
|
writeln!(
|
||||||
handle,
|
handle,
|
||||||
"{}:{}: {} is disallowed",
|
"{}:{}: {} is disallowed",
|
||||||
msg.context, msg.byte_offset, msg.typo,
|
context_display(&msg.context),
|
||||||
|
msg.byte_offset,
|
||||||
|
msg.typo,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -332,9 +328,15 @@ fn print_long_correction(msg: &Typo) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeln!(handle, " --> {}:{}", msg.context, msg.byte_offset).unwrap();
|
writeln!(
|
||||||
|
handle,
|
||||||
|
" --> {}:{}",
|
||||||
|
context_display(&msg.context),
|
||||||
|
msg.byte_offset
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if let Context::File(context) = &msg.context {
|
if let Some(Context::File(context)) = &msg.context {
|
||||||
let line_num = context.line_num.to_string();
|
let line_num = context.line_num.to_string();
|
||||||
let line_indent: String = itertools::repeat_n(" ", line_num.len()).collect();
|
let line_indent: String = itertools::repeat_n(" ", line_num.len()).collect();
|
||||||
|
|
||||||
|
@ -350,6 +352,13 @@ fn print_long_correction(msg: &Typo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn context_display<'c>(context: &'c Option<Context<'c>>) -> &'c dyn std::fmt::Display {
|
||||||
|
context
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c as &dyn std::fmt::Display)
|
||||||
|
.unwrap_or(&"")
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct PrintJson;
|
pub struct PrintJson;
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,10 @@ pub(crate) struct Args {
|
||||||
/// Ignore implicit configuration files.
|
/// Ignore implicit configuration files.
|
||||||
pub(crate) isolated: bool,
|
pub(crate) isolated: bool,
|
||||||
|
|
||||||
|
#[structopt(long)]
|
||||||
|
/// Print a diff of what would change
|
||||||
|
pub(crate) diff: bool,
|
||||||
|
|
||||||
#[structopt(long, short = "w")]
|
#[structopt(long, short = "w")]
|
||||||
/// Write corrections out
|
/// Write corrections out
|
||||||
pub(crate) write_changes: bool,
|
pub(crate) write_changes: bool,
|
||||||
|
|
18
src/dict.rs
18
src/dict.rs
|
@ -29,6 +29,10 @@ impl BuiltIn {
|
||||||
&'s self,
|
&'s self,
|
||||||
word_token: typos::tokens::Word<'w>,
|
word_token: typos::tokens::Word<'w>,
|
||||||
) -> Option<Status<'s>> {
|
) -> Option<Status<'s>> {
|
||||||
|
if word_token.case() == typos::tokens::Case::None {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let word = word_token.token();
|
let word = word_token.token();
|
||||||
let mut corrections = if let Some(correction) = self.correct_with_dict(word) {
|
let mut corrections = if let Some(correction) = self.correct_with_dict(word) {
|
||||||
self.correct_with_vars(word)
|
self.correct_with_vars(word)
|
||||||
|
@ -211,17 +215,19 @@ impl<'i, 'w, D: typos::Dictionary> typos::Dictionary for Override<'i, 'w, D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn correct_word<'s, 't>(&'s self, word: typos::tokens::Word<'t>) -> Option<Status<'s>> {
|
fn correct_word<'s, 't>(&'s self, word: typos::tokens::Word<'t>) -> Option<Status<'s>> {
|
||||||
|
if word.case() == typos::tokens::Case::None {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// Skip hashing if we can
|
// Skip hashing if we can
|
||||||
if !self.words.is_empty() {
|
let custom = if !self.words.is_empty() {
|
||||||
let w = UniCase::new(word.token());
|
let w = UniCase::new(word.token());
|
||||||
// HACK: couldn't figure out the lifetime issue with replacing `cloned` with `borrow`
|
// HACK: couldn't figure out the lifetime issue with replacing `cloned` with `borrow`
|
||||||
self.words
|
self.words.get(&w).cloned()
|
||||||
.get(&w)
|
|
||||||
.cloned()
|
|
||||||
.or_else(|| self.inner.correct_word(word))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
};
|
||||||
|
custom.or_else(|| self.inner.correct_word(word))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
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 checks;
|
||||||
mod config;
|
mod config;
|
||||||
mod dict;
|
mod dict;
|
||||||
|
mod diff;
|
||||||
mod replace;
|
mod replace;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -86,7 +87,10 @@ fn run() -> Result<i32, anyhow::Error> {
|
||||||
|
|
||||||
let mut reporter = args.format.reporter();
|
let mut reporter = args.format.reporter();
|
||||||
let replace_reporter = replace::Replace::new(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;
|
reporter = &replace_reporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +133,9 @@ fn run() -> Result<i32, anyhow::Error> {
|
||||||
errors_found = true;
|
errors_found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.write_changes {
|
if args.diff {
|
||||||
|
diff_reporter.show()?;
|
||||||
|
} else if args.write_changes {
|
||||||
replace_reporter.write()?;
|
replace_reporter.write()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl<'r> typos::report::Report for Replace<'r> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match &typo.context {
|
match &typo.context {
|
||||||
typos::report::Context::File(file) => {
|
Some(typos::report::Context::File(file)) => {
|
||||||
let path = file.path.to_owned();
|
let path = file.path.to_owned();
|
||||||
let line_num = file.line_num;
|
let line_num = file.line_num;
|
||||||
let correction =
|
let correction =
|
||||||
|
@ -82,7 +82,7 @@ impl<'r> typos::report::Report for Replace<'r> {
|
||||||
content.push(correction);
|
content.push(correction);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
typos::report::Context::Path(path) => {
|
Some(typos::report::Context::Path(path)) => {
|
||||||
let path = path.path.to_owned();
|
let path = path.path.to_owned();
|
||||||
let correction =
|
let correction =
|
||||||
Correction::new(typo.byte_offset, typo.typo, corrections[0].as_ref());
|
Correction::new(typo.byte_offset, typo.typo, corrections[0].as_ref());
|
||||||
|
@ -97,20 +97,20 @@ impl<'r> typos::report::Report for Replace<'r> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct Deferred {
|
pub(crate) struct Deferred {
|
||||||
content: BTreeMap<path::PathBuf, BTreeMap<usize, Vec<Correction>>>,
|
pub(crate) content: BTreeMap<path::PathBuf, BTreeMap<usize, Vec<Correction>>>,
|
||||||
paths: BTreeMap<path::PathBuf, Vec<Correction>>,
|
pub(crate) paths: BTreeMap<path::PathBuf, Vec<Correction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
struct Correction {
|
pub(crate) struct Correction {
|
||||||
pub byte_offset: usize,
|
pub byte_offset: usize,
|
||||||
pub typo: Vec<u8>,
|
pub typo: Vec<u8>,
|
||||||
pub correction: Vec<u8>,
|
pub correction: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Correction {
|
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 {
|
Self {
|
||||||
byte_offset,
|
byte_offset,
|
||||||
typo: typo.as_bytes().to_vec(),
|
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();
|
let mut corrections: Vec<_> = corrections.iter().collect();
|
||||||
corrections.sort_unstable();
|
corrections.sort_unstable();
|
||||||
corrections.reverse();
|
corrections.reverse();
|
||||||
|
@ -209,12 +209,12 @@ mod test {
|
||||||
let replace = Replace::new(&primary);
|
let replace = Replace::new(&primary);
|
||||||
replace.report(
|
replace.report(
|
||||||
typos::report::Typo::default()
|
typos::report::Typo::default()
|
||||||
.context(
|
.context(Some(
|
||||||
typos::report::FileContext::default()
|
typos::report::FileContext::default()
|
||||||
.path(input_file.path())
|
.path(input_file.path())
|
||||||
.line_num(1)
|
.line_num(1)
|
||||||
.into(),
|
.into(),
|
||||||
)
|
))
|
||||||
.buffer(std::borrow::Cow::Borrowed(b"1 foo 2\n3 4 5"))
|
.buffer(std::borrow::Cow::Borrowed(b"1 foo 2\n3 4 5"))
|
||||||
.byte_offset(2)
|
.byte_offset(2)
|
||||||
.typo("foo")
|
.typo("foo")
|
||||||
|
@ -238,11 +238,11 @@ mod test {
|
||||||
let replace = Replace::new(&primary);
|
let replace = Replace::new(&primary);
|
||||||
replace.report(
|
replace.report(
|
||||||
typos::report::Typo::default()
|
typos::report::Typo::default()
|
||||||
.context(
|
.context(Some(
|
||||||
typos::report::PathContext::default()
|
typos::report::PathContext::default()
|
||||||
.path(input_file.path())
|
.path(input_file.path())
|
||||||
.into(),
|
.into(),
|
||||||
)
|
))
|
||||||
.buffer(std::borrow::Cow::Borrowed(b"foo.txt"))
|
.buffer(std::borrow::Cow::Borrowed(b"foo.txt"))
|
||||||
.byte_offset(0)
|
.byte_offset(0)
|
||||||
.typo("foo")
|
.typo("foo")
|
||||||
|
|
Loading…
Reference in a new issue