mirror of
https://github.com/crate-ci/typos.git
synced 2024-11-29 04:21:06 -05:00
Merge pull request #693 from epage/re
feat(dict): extend-ignore-identifiers-re support
This commit is contained in:
commit
7e0c4c4456
6 changed files with 62 additions and 5 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -1299,9 +1299,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.6.0"
|
version = "1.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
@ -1316,9 +1316,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.27"
|
version = "0.6.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
|
@ -1407,6 +1407,16 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_regex"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf"
|
||||||
|
dependencies = [
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -1674,8 +1684,10 @@ dependencies = [
|
||||||
"maplit",
|
"maplit",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-exit",
|
"proc-exit",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_regex",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
"toml",
|
"toml",
|
||||||
"trycmd",
|
"trycmd",
|
||||||
|
|
|
@ -72,6 +72,12 @@ Sometimes, what looks like a typo is intentional, like with people's names, acro
|
||||||
|
|
||||||
To mark a word or an identifier (grouping of words) as valid, add it your [`_typos.toml`](docs/reference.md) by declaring itself as the valid spelling:
|
To mark a word or an identifier (grouping of words) as valid, add it your [`_typos.toml`](docs/reference.md) by declaring itself as the valid spelling:
|
||||||
```toml
|
```toml
|
||||||
|
[default]
|
||||||
|
extend-ignore-identifiers-re = [
|
||||||
|
# *sigh* this just isn't worth the cost of fixing
|
||||||
|
"AttributeID.*Supress.*",
|
||||||
|
]
|
||||||
|
|
||||||
[default.extend-identifiers]
|
[default.extend-identifiers]
|
||||||
# *sigh* this just isn't worth the cost of fixing
|
# *sigh* this just isn't worth the cost of fixing
|
||||||
AttributeIDSupressMenu = "AttributeIDSupressMenu"
|
AttributeIDSupressMenu = "AttributeIDSupressMenu"
|
||||||
|
|
|
@ -80,6 +80,8 @@ thread_local = "1.1.7"
|
||||||
globset = "0.4.10"
|
globset = "0.4.10"
|
||||||
anstyle = "0.3.1"
|
anstyle = "0.3.1"
|
||||||
anstream = "0.2.0"
|
anstream = "0.2.0"
|
||||||
|
serde_regex = "1.1.0"
|
||||||
|
regex = "1.7.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_fs = "1.0"
|
assert_fs = "1.0"
|
||||||
|
|
|
@ -390,12 +390,14 @@ impl TokenizerConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct DictConfig {
|
pub struct DictConfig {
|
||||||
pub locale: Option<Locale>,
|
pub locale: Option<Locale>,
|
||||||
|
#[serde(with = "serde_regex")]
|
||||||
|
pub extend_ignore_identifiers_re: Vec<regex::Regex>,
|
||||||
pub extend_identifiers: HashMap<kstring::KString, kstring::KString>,
|
pub extend_identifiers: HashMap<kstring::KString, kstring::KString>,
|
||||||
pub extend_words: HashMap<kstring::KString, kstring::KString>,
|
pub extend_words: HashMap<kstring::KString, kstring::KString>,
|
||||||
}
|
}
|
||||||
|
@ -405,6 +407,7 @@ impl DictConfig {
|
||||||
let empty = Self::default();
|
let empty = Self::default();
|
||||||
Self {
|
Self {
|
||||||
locale: Some(empty.locale()),
|
locale: Some(empty.locale()),
|
||||||
|
extend_ignore_identifiers_re: Default::default(),
|
||||||
extend_identifiers: Default::default(),
|
extend_identifiers: Default::default(),
|
||||||
extend_words: Default::default(),
|
extend_words: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -414,6 +417,8 @@ impl DictConfig {
|
||||||
if let Some(source) = source.locale {
|
if let Some(source) = source.locale {
|
||||||
self.locale = Some(source);
|
self.locale = Some(source);
|
||||||
}
|
}
|
||||||
|
self.extend_ignore_identifiers_re
|
||||||
|
.extend(source.extend_ignore_identifiers_re.iter().cloned());
|
||||||
self.extend_identifiers.extend(
|
self.extend_identifiers.extend(
|
||||||
source
|
source
|
||||||
.extend_identifiers
|
.extend_identifiers
|
||||||
|
@ -432,6 +437,10 @@ impl DictConfig {
|
||||||
self.locale.unwrap_or_default()
|
self.locale.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn extend_ignore_identifiers_re(&self) -> Box<dyn Iterator<Item = ®ex::Regex> + '_> {
|
||||||
|
Box::new(self.extend_ignore_identifiers_re.iter())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn extend_identifiers(&self) -> Box<dyn Iterator<Item = (&str, &str)> + '_> {
|
pub fn extend_identifiers(&self) -> Box<dyn Iterator<Item = (&str, &str)> + '_> {
|
||||||
Box::new(
|
Box::new(
|
||||||
self.extend_identifiers
|
self.extend_identifiers
|
||||||
|
@ -460,6 +469,21 @@ fn find_project_file(dir: &std::path::Path, names: &[&str]) -> Option<std::path:
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DictConfig {
|
||||||
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
|
self.locale == rhs.locale
|
||||||
|
&& self
|
||||||
|
.extend_ignore_identifiers_re
|
||||||
|
.iter()
|
||||||
|
.map(|r| r.as_str())
|
||||||
|
.eq(rhs.extend_ignore_identifiers_re.iter().map(|r| r.as_str()))
|
||||||
|
&& self.extend_identifiers == rhs.extend_identifiers
|
||||||
|
&& self.extend_words == rhs.extend_words
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for DictConfig {}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum Locale {
|
pub enum Locale {
|
||||||
|
|
|
@ -199,6 +199,7 @@ fn case_correct(correction: &mut Cow<'_, str>, case: Case) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Override<'i, 'w, D> {
|
pub struct Override<'i, 'w, D> {
|
||||||
|
ignored_identifiers: Vec<regex::Regex>,
|
||||||
identifiers: HashMap<&'i str, Status<'i>, ahash::RandomState>,
|
identifiers: HashMap<&'i str, Status<'i>, ahash::RandomState>,
|
||||||
words: HashMap<unicase::UniCase<&'w str>, Status<'w>, ahash::RandomState>,
|
words: HashMap<unicase::UniCase<&'w str>, Status<'w>, ahash::RandomState>,
|
||||||
inner: D,
|
inner: D,
|
||||||
|
@ -207,12 +208,17 @@ pub struct Override<'i, 'w, D> {
|
||||||
impl<'i, 'w, D: typos::Dictionary> Override<'i, 'w, D> {
|
impl<'i, 'w, D: typos::Dictionary> Override<'i, 'w, D> {
|
||||||
pub fn new(inner: D) -> Self {
|
pub fn new(inner: D) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
ignored_identifiers: Default::default(),
|
||||||
identifiers: Default::default(),
|
identifiers: Default::default(),
|
||||||
words: Default::default(),
|
words: Default::default(),
|
||||||
inner,
|
inner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ignored_identifiers<'r>(&mut self, ignored: impl Iterator<Item = &'r regex::Regex>) {
|
||||||
|
self.ignored_identifiers.extend(ignored.cloned());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn identifiers<I: Iterator<Item = (&'i str, &'i str)>>(&mut self, identifiers: I) {
|
pub fn identifiers<I: Iterator<Item = (&'i str, &'i str)>>(&mut self, identifiers: I) {
|
||||||
self.identifiers = Self::interpret(identifiers).collect();
|
self.identifiers = Self::interpret(identifiers).collect();
|
||||||
}
|
}
|
||||||
|
@ -241,6 +247,12 @@ impl<'i, 'w, D: typos::Dictionary> Override<'i, 'w, D> {
|
||||||
|
|
||||||
impl<'i, 'w, D: typos::Dictionary> typos::Dictionary for Override<'i, 'w, D> {
|
impl<'i, 'w, D: typos::Dictionary> typos::Dictionary for Override<'i, 'w, D> {
|
||||||
fn correct_ident<'s, 't>(&'s self, ident: typos::tokens::Identifier<'t>) -> Option<Status<'s>> {
|
fn correct_ident<'s, 't>(&'s self, ident: typos::tokens::Identifier<'t>) -> Option<Status<'s>> {
|
||||||
|
for ignored in &self.ignored_identifiers {
|
||||||
|
if ignored.is_match(ident.token()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Skip hashing if we can
|
// Skip hashing if we can
|
||||||
if !self.identifiers.is_empty() {
|
if !self.identifiers.is_empty() {
|
||||||
self.identifiers
|
self.identifiers
|
||||||
|
|
|
@ -28,6 +28,7 @@ Configuration is read from the following (in precedence order)
|
||||||
| default.unicode | --unicode | bool | Allow unicode characters in identifiers (and not just ASCII) |
|
| default.unicode | --unicode | bool | Allow unicode characters in identifiers (and not just ASCII) |
|
||||||
| default.locale | --locale | en, en-us, en-gb, en-ca, en-au | English dialect to correct to. |
|
| default.locale | --locale | en, en-us, en-gb, en-ca, en-au | English dialect to correct to. |
|
||||||
| default.extend-identifiers | \- | table of strings | Corrections for [identifiers](./design.md#identifiers-and-words). When the correction is blank, the identifier is never valid. When the correction is the key, the identifier is always valid. |
|
| default.extend-identifiers | \- | table of strings | Corrections for [identifiers](./design.md#identifiers-and-words). When the correction is blank, the identifier is never valid. When the correction is the key, the identifier is always valid. |
|
||||||
|
| default.extend-ignore-identifiers-re | \- | list of [regexes](https://docs.rs/regex/latest/regex/index.html#syntax) | Pattern-match always-valid identifiers |
|
||||||
| default.extend-words | \- | table of strings | Corrections for [words](./design.md#identifiers-and-words). When the correction is blank, the word is never valid. When the correction is the key, the word is always valid. |
|
| default.extend-words | \- | table of strings | Corrections for [words](./design.md#identifiers-and-words). When the correction is blank, the word is never valid. When the correction is the key, the word is always valid. |
|
||||||
| type.\<name>.\<field> | \<varied> | \<varied> | See `default.` for child keys. Run with `--type-list` to see available `<name>`s |
|
| type.\<name>.\<field> | \<varied> | \<varied> | See `default.` for child keys. Run with `--type-list` to see available `<name>`s |
|
||||||
| type.\<name>.extend_globs | \- | list of strings | File globs for matching `<name>` |
|
| type.\<name>.extend_globs | \- | list of strings | File globs for matching `<name>` |
|
||||||
|
|
Loading…
Reference in a new issue