mirror of
https://github.com/crate-ci/typos.git
synced 2025-03-13 07:09:32 -04:00
parent
72f3776b6e
commit
d06a1dd728
4 changed files with 241 additions and 0 deletions
|
@ -77,10 +77,18 @@ pub(crate) struct Args {
|
||||||
#[arg(long, group = "mode", help_heading = "Mode")]
|
#[arg(long, group = "mode", help_heading = "Mode")]
|
||||||
pub(crate) file_types: bool,
|
pub(crate) file_types: bool,
|
||||||
|
|
||||||
|
/// Debug: Print back out files, stylizing identifiers that would be spellchecked.
|
||||||
|
#[arg(long, group = "mode", help_heading = "Mode")]
|
||||||
|
pub(crate) highlight_identifiers: bool,
|
||||||
|
|
||||||
/// Debug: Print each identifier that would be spellchecked.
|
/// Debug: Print each identifier that would be spellchecked.
|
||||||
#[arg(long, group = "mode", help_heading = "Mode")]
|
#[arg(long, group = "mode", help_heading = "Mode")]
|
||||||
pub(crate) identifiers: bool,
|
pub(crate) identifiers: bool,
|
||||||
|
|
||||||
|
/// Debug: Print back out files, stylizing words that would be spellchecked.
|
||||||
|
#[arg(long, group = "mode", help_heading = "Mode")]
|
||||||
|
pub(crate) highlight_words: bool,
|
||||||
|
|
||||||
/// Debug: Print each word that would be spellchecked.
|
/// Debug: Print each word that would be spellchecked.
|
||||||
#[arg(long, group = "mode", help_heading = "Mode")]
|
#[arg(long, group = "mode", help_heading = "Mode")]
|
||||||
pub(crate) words: bool,
|
pub(crate) words: bool,
|
||||||
|
|
|
@ -288,8 +288,12 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
||||||
&typos_cli::file::FoundFiles
|
&typos_cli::file::FoundFiles
|
||||||
} else if args.file_types {
|
} else if args.file_types {
|
||||||
&typos_cli::file::FileTypes
|
&typos_cli::file::FileTypes
|
||||||
|
} else if args.highlight_identifiers {
|
||||||
|
&typos_cli::file::HighlightIdentifiers
|
||||||
} else if args.identifiers {
|
} else if args.identifiers {
|
||||||
&typos_cli::file::Identifiers
|
&typos_cli::file::Identifiers
|
||||||
|
} else if args.highlight_words {
|
||||||
|
&typos_cli::file::HighlightWords
|
||||||
} else if args.words {
|
} else if args.words {
|
||||||
&typos_cli::file::Words
|
&typos_cli::file::Words
|
||||||
} else if args.write_changes {
|
} else if args.write_changes {
|
||||||
|
|
|
@ -245,6 +245,113 @@ impl FileChecker for DiffTypos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct HighlightIdentifiers;
|
||||||
|
|
||||||
|
impl FileChecker for HighlightIdentifiers {
|
||||||
|
fn check_file(
|
||||||
|
&self,
|
||||||
|
path: &std::path::Path,
|
||||||
|
explicit: bool,
|
||||||
|
policy: &crate::policy::Policy<'_, '_, '_>,
|
||||||
|
reporter: &dyn report::Report,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut handle = stdout.lock();
|
||||||
|
|
||||||
|
let mut ignores: Option<Ignores> = None;
|
||||||
|
if policy.check_filenames {
|
||||||
|
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||||
|
let mut styled = String::new();
|
||||||
|
let mut prev_end = 0;
|
||||||
|
for (word, highlight) in policy
|
||||||
|
.tokenizer
|
||||||
|
.parse_str(file_name)
|
||||||
|
.filter(|word| {
|
||||||
|
!ignores
|
||||||
|
.get_or_insert_with(|| {
|
||||||
|
Ignores::new(file_name.as_bytes(), policy.ignore)
|
||||||
|
})
|
||||||
|
.is_ignored(word.span())
|
||||||
|
})
|
||||||
|
.zip(HIGHLIGHTS.iter().cycle())
|
||||||
|
{
|
||||||
|
let start = word.offset();
|
||||||
|
let end = word.offset() + word.token().len();
|
||||||
|
if prev_end != start {
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&file_name[prev_end..start]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let _ = write!(&mut styled, "{highlight}{}{highlight:#}", word.token());
|
||||||
|
prev_end = end;
|
||||||
|
}
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&file_name[prev_end..file_name.len()]
|
||||||
|
);
|
||||||
|
|
||||||
|
let parent_dir = path.parent().unwrap();
|
||||||
|
if !parent_dir.as_os_str().is_empty() {
|
||||||
|
let parent_dir = parent_dir.display();
|
||||||
|
write!(handle, "{UNMATCHED}{parent_dir}/")?;
|
||||||
|
}
|
||||||
|
writeln!(handle, "{styled}{UNMATCHED}:{UNMATCHED:#}")?;
|
||||||
|
} else {
|
||||||
|
writeln!(handle, "{UNMATCHED}{}:{UNMATCHED:#}", path.display())?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writeln!(handle, "{UNMATCHED}{}:{UNMATCHED:#}", path.display())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if policy.check_files {
|
||||||
|
let (buffer, content_type) = read_file(path, reporter)?;
|
||||||
|
if !explicit && !policy.binary && content_type.is_binary() {
|
||||||
|
// nop
|
||||||
|
} else if let Ok(buffer) = buffer.to_str() {
|
||||||
|
let mut styled = String::new();
|
||||||
|
let mut prev_end = 0;
|
||||||
|
for (word, highlight) in policy
|
||||||
|
.tokenizer
|
||||||
|
.parse_bytes(buffer.as_bytes())
|
||||||
|
.filter(|word| {
|
||||||
|
!ignores
|
||||||
|
.get_or_insert_with(|| Ignores::new(buffer.as_bytes(), policy.ignore))
|
||||||
|
.is_ignored(word.span())
|
||||||
|
})
|
||||||
|
.zip(HIGHLIGHTS.iter().cycle())
|
||||||
|
{
|
||||||
|
let start = word.offset();
|
||||||
|
let end = word.offset() + word.token().len();
|
||||||
|
if prev_end != start {
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&buffer[prev_end..start]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let _ = write!(&mut styled, "{highlight}{}{highlight:#}", word.token());
|
||||||
|
prev_end = end;
|
||||||
|
}
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&buffer[prev_end..buffer.len()]
|
||||||
|
);
|
||||||
|
|
||||||
|
write!(handle, "{styled}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Identifiers;
|
pub struct Identifiers;
|
||||||
|
|
||||||
|
@ -307,6 +414,124 @@ impl FileChecker for Identifiers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct HighlightWords;
|
||||||
|
|
||||||
|
impl FileChecker for HighlightWords {
|
||||||
|
fn check_file(
|
||||||
|
&self,
|
||||||
|
path: &std::path::Path,
|
||||||
|
explicit: bool,
|
||||||
|
policy: &crate::policy::Policy<'_, '_, '_>,
|
||||||
|
reporter: &dyn report::Report,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut handle = stdout.lock();
|
||||||
|
|
||||||
|
let mut ignores: Option<Ignores> = None;
|
||||||
|
if policy.check_filenames {
|
||||||
|
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||||
|
let mut styled = String::new();
|
||||||
|
let mut prev_end = 0;
|
||||||
|
for (word, highlight) in policy
|
||||||
|
.tokenizer
|
||||||
|
.parse_str(file_name)
|
||||||
|
.flat_map(|i| i.split())
|
||||||
|
.filter(|word| {
|
||||||
|
!ignores
|
||||||
|
.get_or_insert_with(|| {
|
||||||
|
Ignores::new(file_name.as_bytes(), policy.ignore)
|
||||||
|
})
|
||||||
|
.is_ignored(word.span())
|
||||||
|
})
|
||||||
|
.zip(HIGHLIGHTS.iter().cycle())
|
||||||
|
{
|
||||||
|
let start = word.offset();
|
||||||
|
let end = word.offset() + word.token().len();
|
||||||
|
if prev_end != start {
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&file_name[prev_end..start]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let _ = write!(&mut styled, "{highlight}{}{highlight:#}", word.token());
|
||||||
|
prev_end = end;
|
||||||
|
}
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&file_name[prev_end..file_name.len()]
|
||||||
|
);
|
||||||
|
|
||||||
|
let parent_dir = path.parent().unwrap();
|
||||||
|
if !parent_dir.as_os_str().is_empty() {
|
||||||
|
let parent_dir = parent_dir.display();
|
||||||
|
write!(handle, "{UNMATCHED}{parent_dir}/")?;
|
||||||
|
}
|
||||||
|
writeln!(handle, "{styled}{UNMATCHED}:{UNMATCHED:#}")?;
|
||||||
|
} else {
|
||||||
|
writeln!(handle, "{UNMATCHED}{}:{UNMATCHED:#}", path.display())?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writeln!(handle, "{UNMATCHED}{}:{UNMATCHED:#}", path.display())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if policy.check_files {
|
||||||
|
let (buffer, content_type) = read_file(path, reporter)?;
|
||||||
|
if !explicit && !policy.binary && content_type.is_binary() {
|
||||||
|
// nop
|
||||||
|
} else if let Ok(buffer) = buffer.to_str() {
|
||||||
|
let mut styled = String::new();
|
||||||
|
let mut prev_end = 0;
|
||||||
|
for (word, highlight) in policy
|
||||||
|
.tokenizer
|
||||||
|
.parse_bytes(buffer.as_bytes())
|
||||||
|
.flat_map(|i| i.split())
|
||||||
|
.filter(|word| {
|
||||||
|
!ignores
|
||||||
|
.get_or_insert_with(|| Ignores::new(buffer.as_bytes(), policy.ignore))
|
||||||
|
.is_ignored(word.span())
|
||||||
|
})
|
||||||
|
.zip(HIGHLIGHTS.iter().cycle())
|
||||||
|
{
|
||||||
|
let start = word.offset();
|
||||||
|
let end = word.offset() + word.token().len();
|
||||||
|
if prev_end != start {
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&buffer[prev_end..start]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let _ = write!(&mut styled, "{highlight}{}{highlight:#}", word.token());
|
||||||
|
prev_end = end;
|
||||||
|
}
|
||||||
|
let _ = write!(
|
||||||
|
&mut styled,
|
||||||
|
"{UNMATCHED}{}{UNMATCHED:#}",
|
||||||
|
&buffer[prev_end..buffer.len()]
|
||||||
|
);
|
||||||
|
|
||||||
|
write!(handle, "{styled}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HIGHLIGHTS: &[anstyle::Style] = &[
|
||||||
|
anstyle::AnsiColor::Cyan.on_default(),
|
||||||
|
anstyle::AnsiColor::Cyan
|
||||||
|
.on_default()
|
||||||
|
.effects(anstyle::Effects::BOLD),
|
||||||
|
];
|
||||||
|
|
||||||
|
static UNMATCHED: anstyle::Style = anstyle::Style::new().effects(anstyle::Effects::DIMMED);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Words;
|
pub struct Words;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,11 @@ Mode:
|
||||||
-w, --write-changes Write fixes out
|
-w, --write-changes Write fixes out
|
||||||
--files Debug: Print each file that would be spellchecked
|
--files Debug: Print each file that would be spellchecked
|
||||||
--file-types Debug: Print each file's type
|
--file-types Debug: Print each file's type
|
||||||
|
--highlight-identifiers Debug: Print back out files, stylizing identifiers that would be
|
||||||
|
spellchecked
|
||||||
--identifiers Debug: Print each identifier that would be spellchecked
|
--identifiers Debug: Print each identifier that would be spellchecked
|
||||||
|
--highlight-words Debug: Print back out files, stylizing words that would be
|
||||||
|
spellchecked
|
||||||
--words Debug: Print each word that would be spellchecked
|
--words Debug: Print each word that would be spellchecked
|
||||||
--dump-config <DUMP_CONFIG> Write the current configuration to file with `-` for stdout
|
--dump-config <DUMP_CONFIG> Write the current configuration to file with `-` for stdout
|
||||||
--type-list Show all supported file types
|
--type-list Show all supported file types
|
||||||
|
|
Loading…
Add table
Reference in a new issue