feat(config): Per-file type settings

Fixes #14
This commit is contained in:
Ed Page 2021-04-05 21:03:41 -05:00
parent 3fd90b09f8
commit a101df95c2
4 changed files with 52 additions and 18 deletions

View file

@ -31,3 +31,4 @@ Configuration is read from the following (in precedence order)
| 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. When the correction is blank, the word is never valid. When the correction is the key, the word is always valid. | | default.extend-identifiers | \- | table of strings | Corrections for identifiers. 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 identifiers. 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 identifiers. When the correction is blank, the word is never valid. When the correction is the key, the word is always valid. |
| type.<name>.binary | <varied> | <varied> | See `default.` for child keys. |

View file

@ -182,7 +182,7 @@ impl ConfigArgs {
pub fn to_config(&self) -> config::Config { pub fn to_config(&self) -> config::Config {
config::Config { config::Config {
files: self.walk.to_config(), files: self.walk.to_config(),
overrides: Some(self.overrides.to_config()), overrides: self.overrides.to_config(),
..Default::default() ..Default::default()
} }
} }

View file

@ -6,8 +6,10 @@ use std::collections::HashMap;
pub struct Config { pub struct Config {
pub files: Walk, pub files: Walk,
pub default: EngineConfig, pub default: EngineConfig,
#[serde(rename = "type")]
pub type_: std::collections::HashMap<kstring::KString, EngineConfig>,
#[serde(skip)] #[serde(skip)]
pub overrides: Option<EngineConfig>, pub overrides: EngineConfig,
} }
impl Config { impl Config {
@ -36,7 +38,8 @@ impl Config {
Self { Self {
files: Walk::from_defaults(), files: Walk::from_defaults(),
default: EngineConfig::from_defaults(), default: EngineConfig::from_defaults(),
overrides: None, type_: Default::default(),
overrides: EngineConfig::default(),
} }
} }

View file

@ -77,12 +77,13 @@ impl<'s> ConfigEngine<'s> {
pub fn policy(&self, path: &std::path::Path) -> Policy<'_, '_> { pub fn policy(&self, path: &std::path::Path) -> Policy<'_, '_> {
let dir = self.get_dir(path).expect("`walk()` should be called first"); let dir = self.get_dir(path).expect("`walk()` should be called first");
let file_config = dir.get_file_config(path);
Policy { Policy {
check_filenames: dir.default.check_filenames, check_filenames: file_config.check_filenames,
check_files: dir.default.check_files, check_files: file_config.check_files,
binary: dir.default.binary, binary: file_config.binary,
tokenizer: self.get_tokenizer(&dir.default), tokenizer: self.get_tokenizer(&file_config),
dict: self.get_dict(&dir.default), dict: self.get_dict(&file_config),
} }
} }
@ -134,25 +135,37 @@ impl<'s> ConfigEngine<'s> {
let crate::config::Config { let crate::config::Config {
files, files,
mut default, mut default,
type_,
overrides, overrides,
} = config; } = config;
if let Some(overrides) = overrides {
default.update(&overrides);
}
let walk = self.walk.intern(files); let walk = self.walk.intern(files);
let default = self.init_file_config(default)?;
let dir = DirConfig { walk, default }; let types = type_
.into_iter()
.map(|(type_, type_engine)| {
let mut new_type_engine = default.clone();
new_type_engine.update(&type_engine);
new_type_engine.update(&overrides);
let type_config = self.init_file_config(new_type_engine);
(type_, type_config)
})
.collect();
default.update(&overrides);
let default = self.init_file_config(default);
let dir = DirConfig {
walk,
default,
types,
type_matcher: ignore::types::TypesBuilder::new().add_defaults().build()?,
};
self.configs.insert(cwd.to_owned(), dir); self.configs.insert(cwd.to_owned(), dir);
Ok(()) Ok(())
} }
fn init_file_config( fn init_file_config(&mut self, engine: crate::config::EngineConfig) -> FileConfig {
&mut self,
engine: crate::config::EngineConfig,
) -> Result<FileConfig, anyhow::Error> {
let binary = engine.binary(); let binary = engine.binary();
let check_filename = engine.check_filename(); let check_filename = engine.check_filename();
let check_file = engine.check_file(); let check_file = engine.check_file();
@ -194,7 +207,7 @@ impl<'s> ConfigEngine<'s> {
tokenizer, tokenizer,
dict, dict,
}; };
Ok(file) file
} }
} }
@ -226,11 +239,28 @@ impl<T> Default for Intern<T> {
} }
} }
#[derive(Clone, Debug)]
struct DirConfig { struct DirConfig {
walk: usize, walk: usize,
default: FileConfig, default: FileConfig,
types: std::collections::HashMap<kstring::KString, FileConfig>,
type_matcher: ignore::types::Types,
} }
impl DirConfig {
fn get_file_config(&self, path: &std::path::Path) -> FileConfig {
let match_ = self.type_matcher.matched(path, false);
let name = match_
.inner()
.and_then(|g| g.file_type_def())
.map(|f| f.name());
name.and_then(|name| self.types.get(name).copied())
.unwrap_or(self.default)
}
}
#[derive(Copy, Clone, Debug)]
struct FileConfig { struct FileConfig {
tokenizer: usize, tokenizer: usize,
dict: usize, dict: usize,