toml-config: add input modes
This commit is contained in:
parent
e160aa3406
commit
a57f0036a8
10 changed files with 797 additions and 46 deletions
|
|
@ -27,6 +27,7 @@ mod gfx_api;
|
|||
mod idle;
|
||||
mod input;
|
||||
mod input_match;
|
||||
pub mod input_mode;
|
||||
pub mod keymap;
|
||||
mod libei;
|
||||
mod log_level;
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ impl ActionParser<'_> {
|
|||
"focus-tiles" => FocusTiles,
|
||||
"create-mark" => CreateMark,
|
||||
"jump-to-mark" => JumpToMark,
|
||||
"clear-modes" => PopMode(false),
|
||||
"pop-mode" => PopMode(true),
|
||||
_ => {
|
||||
return Err(
|
||||
ActionParserError::UnknownSimpleAction(string.to_string()).spanned(span)
|
||||
|
|
@ -414,6 +416,22 @@ impl ActionParser<'_> {
|
|||
.map_spanned_err(ActionParserError::CopyMark)?;
|
||||
Ok(Action::CopyMark(src, dst))
|
||||
}
|
||||
|
||||
fn parse_push_mode(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||
let (name,) = ext.extract((str("name"),))?;
|
||||
Ok(Action::SetMode {
|
||||
name: name.value.to_string(),
|
||||
latch: false,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_latch_mode(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||
let (name,) = ext.extract((str("name"),))?;
|
||||
Ok(Action::SetMode {
|
||||
name: name.value.to_string(),
|
||||
latch: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parser for ActionParser<'_> {
|
||||
|
|
@ -471,6 +489,8 @@ impl Parser for ActionParser<'_> {
|
|||
"create-mark" => self.parse_create_mark(&mut ext),
|
||||
"jump-to-mark" => self.parse_jump_to_mark(&mut ext),
|
||||
"copy-mark" => self.parse_copy_mark(&mut ext),
|
||||
"push-mode" => self.parse_push_mode(&mut ext),
|
||||
"latch-mode" => self.parse_latch_mode(&mut ext),
|
||||
v => {
|
||||
ext.ignore_unused();
|
||||
return Err(ActionParserError::UnknownType(v.to_string()).spanned(ty.span));
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use {
|
|||
gfx_api::GfxApiParser,
|
||||
idle::IdleParser,
|
||||
input::InputsParser,
|
||||
input_mode::InputModesParser,
|
||||
keymap::KeymapParser,
|
||||
libei::LibeiParser,
|
||||
log_level::LogLevelParser,
|
||||
|
|
@ -44,6 +45,7 @@ use {
|
|||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
indexmap::IndexMap,
|
||||
std::collections::HashSet,
|
||||
thiserror::Error,
|
||||
|
|
@ -136,7 +138,7 @@ impl Parser for ConfigParser<'_> {
|
|||
show_bar,
|
||||
focus_history_val,
|
||||
),
|
||||
(middle_click_paste,),
|
||||
(middle_click_paste, input_modes_val),
|
||||
) = ext.extract((
|
||||
(
|
||||
opt(val("keymap")),
|
||||
|
|
@ -186,7 +188,7 @@ impl Parser for ConfigParser<'_> {
|
|||
recover(opt(bol("show-bar"))),
|
||||
opt(val("focus-history")),
|
||||
),
|
||||
(recover(opt(bol("middle-click-paste"))),),
|
||||
(recover(opt(bol("middle-click-paste"))), opt(val("modes"))),
|
||||
))?;
|
||||
let mut keymap = None;
|
||||
if let Some(value) = keymap_val {
|
||||
|
|
@ -475,6 +477,15 @@ impl Parser for ConfigParser<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
let mut input_modes = AHashMap::new();
|
||||
if let Some(value) = input_modes_val {
|
||||
match value.parse(&mut InputModesParser(self.0)) {
|
||||
Ok(v) => input_modes = v,
|
||||
Err(e) => {
|
||||
log::warn!("Could not parse the input modes: {}", self.0.error(e),);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Config {
|
||||
keymap,
|
||||
repeat_rate,
|
||||
|
|
@ -516,6 +527,7 @@ impl Parser for ConfigParser<'_> {
|
|||
show_bar: show_bar.despan(),
|
||||
focus_history,
|
||||
middle_click_paste: middle_click_paste.despan(),
|
||||
input_modes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
125
toml-config/src/config/parsers/input_mode.rs
Normal file
125
toml-config/src/config/parsers/input_mode.rs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
use {
|
||||
crate::{
|
||||
config::{
|
||||
Shortcut,
|
||||
context::Context,
|
||||
extractor::{Extractor, ExtractorError, opt, recover, str, val},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
parsers::shortcuts::{ComplexShortcutsParser, ShortcutsParser, ShortcutsParserError},
|
||||
spanned::SpannedErrorExt,
|
||||
},
|
||||
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),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct InputMode {
|
||||
pub parent: Option<String>,
|
||||
pub shortcuts: Vec<Shortcut>,
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue