Skip to content

Commit

Permalink
Merge pull request #169 from epage/refactor
Browse files Browse the repository at this point in the history
Further polish
  • Loading branch information
epage authored Nov 12, 2020
2 parents 36709b6 + ce16d38 commit 8a35a12
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 48 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
18 changes: 9 additions & 9 deletions crates/typos/src/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct ReportContext<'m, 'r> {

impl<'m, 'r> report::Report for ReportContext<'m, 'r> {
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)
}
}
Expand Down Expand Up @@ -188,7 +188,7 @@ impl Check for Typos {
Some(corrections) => {
let byte_offset = ident.offset();
let msg = report::Typo {
context: report::Context::None,
context: None,
buffer: std::borrow::Cow::Borrowed(buffer.as_bytes()),
byte_offset,
typo: ident.token(),
Expand All @@ -203,7 +203,7 @@ impl Check for Typos {
Some(corrections) => {
let byte_offset = word.offset();
let msg = report::Typo {
context: report::Context::None,
context: None,
buffer: std::borrow::Cow::Borrowed(buffer.as_bytes()),
byte_offset,
typo: word.token(),
Expand Down Expand Up @@ -236,7 +236,7 @@ impl Check for Typos {
Some(corrections) => {
let byte_offset = ident.offset();
let msg = report::Typo {
context: report::Context::None,
context: None,
buffer: std::borrow::Cow::Borrowed(buffer),
byte_offset,
typo: ident.token(),
Expand All @@ -251,7 +251,7 @@ impl Check for Typos {
Some(corrections) => {
let byte_offset = word.offset();
let msg = report::Typo {
context: report::Context::None,
context: None,
buffer: std::borrow::Cow::Borrowed(buffer),
byte_offset,
typo: word.token(),
Expand Down Expand Up @@ -300,7 +300,7 @@ impl Check for ParseIdentifiers {
let typos_found = false;

let msg = report::Parse {
context: report::Context::None,
context: None,
kind: report::ParseKind::Identifier,
data: parser.parse_str(buffer).map(|i| i.token()).collect(),
};
Expand All @@ -321,7 +321,7 @@ impl Check for ParseIdentifiers {
let typos_found = false;

let msg = report::Parse {
context: report::Context::None,
context: None,
kind: report::ParseKind::Identifier,
data: parser.parse_bytes(buffer).map(|i| i.token()).collect(),
};
Expand Down Expand Up @@ -363,7 +363,7 @@ impl Check for ParseWords {
let typos_found = false;

let msg = report::Parse {
context: report::Context::None,
context: None,
kind: report::ParseKind::Word,
data: parser
.parse_str(buffer)
Expand All @@ -387,7 +387,7 @@ impl Check for ParseWords {
let typos_found = false;

let msg = report::Parse {
context: report::Context::None,
context: None,
kind: report::ParseKind::Word,
data: parser
.parse_bytes(buffer)
Expand Down
47 changes: 28 additions & 19 deletions crates/typos/src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Message::Typo(typo) => {
let typo = typo.context(context);
Expand All @@ -65,7 +65,7 @@ pub struct BinaryFile<'m> {
#[non_exhaustive]
pub struct Typo<'m> {
#[serde(flatten)]
pub context: Context<'m>,
pub context: Option<Context<'m>>,
#[serde(skip)]
pub buffer: Cow<'m, [u8]>,
pub byte_offset: usize,
Expand All @@ -76,7 +76,7 @@ pub struct Typo<'m> {
impl<'m> Default for Typo<'m> {
fn default() -> Self {
Self {
context: Context::None,
context: None,
buffer: Cow::Borrowed(&[]),
byte_offset: 0,
typo: "",
Expand All @@ -91,21 +91,13 @@ impl<'m> Default for Typo<'m> {
pub enum Context<'m> {
File(FileContext<'m>),
Path(PathContext<'m>),
None,
}

impl<'m> Default for Context<'m> {
fn default() -> Self {
Context::None
}
}

impl<'m> std::fmt::Display for Context<'m> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self {
Context::File(c) => write!(f, "{}:{}", c.path.display(), c.line_num),
Context::Path(c) => write!(f, "{}", c.path.display()),
Context::None => Ok(()),
}
}
}
Expand Down Expand Up @@ -172,15 +164,15 @@ impl<'m> Default for File<'m> {
#[non_exhaustive]
pub struct Parse<'m> {
#[serde(flatten)]
pub context: Context<'m>,
pub context: Option<Context<'m>>,
pub kind: ParseKind,
pub data: Vec<&'m str>,
}

impl<'m> Default for Parse<'m> {
fn default() -> Self {
Self {
context: Context::None,
context: None,
kind: ParseKind::Identifier,
data: vec![],
}
Expand Down Expand Up @@ -294,13 +286,15 @@ fn print_brief_correction(msg: &Typo) {
crate::Status::Invalid => {
println!(
"{}:{}: {} is disallowed",
msg.context, msg.byte_offset, msg.typo,
context_display(&msg.context),
msg.byte_offset,
msg.typo,
);
}
crate::Status::Corrections(corrections) => {
println!(
"{}:{}: {} -> {}",
msg.context,
context_display(&msg.context),
msg.byte_offset,
msg.typo,
itertools::join(corrections.iter(), ", ")
Expand All @@ -318,7 +312,9 @@ fn print_long_correction(msg: &Typo) {
writeln!(
handle,
"{}:{}: {} is disallowed",
msg.context, msg.byte_offset, msg.typo,
context_display(&msg.context),
msg.byte_offset,
msg.typo,
)
.unwrap();
}
Expand All @@ -332,9 +328,15 @@ fn print_long_correction(msg: &Typo) {
.unwrap();
}
}
writeln!(handle, " --> {}:{}", msg.context, msg.byte_offset).unwrap();

if let Context::File(context) = &msg.context {
writeln!(
handle,
" --> {}:{}",
context_display(&msg.context),
msg.byte_offset
)
.unwrap();

if let Some(Context::File(context)) = &msg.context {
let line_num = context.line_num.to_string();
let line_indent: String = itertools::repeat_n(" ", line_num.len()).collect();

Expand All @@ -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)]
pub struct PrintJson;

Expand Down
4 changes: 4 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 12 additions & 6 deletions src/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ impl BuiltIn {
&'s self,
word_token: typos::tokens::Word<'w>,
) -> Option<Status<'s>> {
if word_token.case() == typos::tokens::Case::None {
return None;
}

let word = word_token.token();
let mut corrections = if let Some(correction) = self.correct_with_dict(word) {
self.correct_with_vars(word)
Expand Down Expand Up @@ -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>> {
if word.case() == typos::tokens::Case::None {
return None;
}

// Skip hashing if we can
if !self.words.is_empty() {
let custom = if !self.words.is_empty() {
let w = UniCase::new(word.token());
// HACK: couldn't figure out the lifetime issue with replacing `cloned` with `borrow`
self.words
.get(&w)
.cloned()
.or_else(|| self.inner.correct_word(word))
self.words.get(&w).cloned()
} else {
None
}
};
custom.or_else(|| self.inner.correct_word(word))
}
}

Expand Down
93 changes: 93 additions & 0 deletions src/diff.rs
Original file line number Diff line number Diff line change
@@ -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(),
}
}
}
Loading

0 comments on commit 8a35a12

Please sign in to comment.