119 lines
3.7 KiB
Rust
119 lines
3.7 KiB
Rust
use {
|
|
crate::{
|
|
config::{
|
|
InputMode,
|
|
context::Context,
|
|
extractor::{Extractor, ExtractorError, opt, recover, str, val},
|
|
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
|
parsers::shortcuts::{ComplexShortcutsParser, ShortcutsParser, ShortcutsParserError},
|
|
spanned::SpannedErrorExt,
|
|
},
|
|
jay_toml::{
|
|
toml_span::{DespanExt, Span, Spanned},
|
|
toml_value::Value,
|
|
},
|
|
},
|
|
ahash::{AHashMap, AHashSet},
|
|
indexmap::IndexMap,
|
|
std::collections::HashSet,
|
|
thiserror::Error,
|
|
};
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum InputModeParserError {
|
|
#[error(transparent)]
|
|
Expected(#[from] UnexpectedDataType),
|
|
#[error(transparent)]
|
|
ExtractorError(#[from] ExtractorError),
|
|
#[error("Could not parse the shortcuts")]
|
|
ParseShortcuts(#[source] ShortcutsParserError),
|
|
}
|
|
|
|
pub struct InputModesParser<'a>(pub &'a Context<'a>);
|
|
|
|
impl Parser for InputModesParser<'_> {
|
|
type Value = AHashMap<String, InputMode>;
|
|
type Error = InputModeParserError;
|
|
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
|
|
|
fn parse_table(
|
|
&mut self,
|
|
_span: Span,
|
|
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
|
) -> ParseResult<Self> {
|
|
let mut modes = AHashMap::new();
|
|
let mut used = AHashSet::new();
|
|
for (key, value) in table.iter() {
|
|
let mode = match value.parse(&mut InputModeParser(self.0)) {
|
|
Ok(m) => m,
|
|
Err(e) => {
|
|
log::warn!(
|
|
"Could not parse input mode {}: {}",
|
|
key.value,
|
|
self.0.error(e)
|
|
);
|
|
continue;
|
|
}
|
|
};
|
|
log_used(self.0, &mut used, key);
|
|
modes.insert(key.value.to_string(), mode);
|
|
}
|
|
Ok(modes)
|
|
}
|
|
}
|
|
|
|
pub struct InputModeParser<'a>(pub &'a Context<'a>);
|
|
|
|
impl Parser for InputModeParser<'_> {
|
|
type Value = InputMode;
|
|
type Error = InputModeParserError;
|
|
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
|
|
|
fn parse_table(
|
|
&mut self,
|
|
span: Span,
|
|
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
|
) -> ParseResult<Self> {
|
|
let mut ext = Extractor::new(self.0, span, table);
|
|
let (parent, shortcuts_val, complex_shortcuts_val) = ext.extract((
|
|
recover(opt(str("parent"))),
|
|
opt(val("shortcuts")),
|
|
opt(val("complex-shortcuts")),
|
|
))?;
|
|
let mut used_keys = HashSet::new();
|
|
let mut shortcuts = vec![];
|
|
if let Some(value) = shortcuts_val {
|
|
value
|
|
.parse(&mut ShortcutsParser {
|
|
cx: self.0,
|
|
used_keys: &mut used_keys,
|
|
shortcuts: &mut shortcuts,
|
|
})
|
|
.map_spanned_err(InputModeParserError::ParseShortcuts)?;
|
|
}
|
|
if let Some(value) = complex_shortcuts_val {
|
|
value
|
|
.parse(&mut ComplexShortcutsParser {
|
|
cx: self.0,
|
|
used_keys: &mut used_keys,
|
|
shortcuts: &mut shortcuts,
|
|
})
|
|
.map_spanned_err(InputModeParserError::ParseShortcuts)?;
|
|
}
|
|
Ok(InputMode {
|
|
parent: parent.despan_into(),
|
|
shortcuts,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn log_used(cx: &Context<'_>, used: &mut AHashSet<Spanned<String>>, key: &Spanned<String>) {
|
|
if let Some(prev) = used.get(key) {
|
|
log::warn!(
|
|
"Duplicate input mode overrides previous definition: {}",
|
|
cx.error3(key.span)
|
|
);
|
|
log::info!("Previous definition here: {}", cx.error3(prev.span));
|
|
}
|
|
used.insert(key.clone());
|
|
}
|