mirror of
https://github.com/k0kubun/xremap
synced 2024-11-02 03:40:25 +00:00
Parse remap action
This commit is contained in:
parent
689ad59163
commit
db1c9f5600
@ -33,6 +33,10 @@ keymap:
|
||||
# SKK hack for Chrome
|
||||
C-j: C-m
|
||||
|
||||
C-m:
|
||||
remap:
|
||||
C-j: a
|
||||
|
||||
- name: Default (Nocturn, etc.)
|
||||
wm_class:
|
||||
not: [Google-chrome, Slack, Gnome-terminal, jetbrains-idea]
|
||||
|
@ -1,18 +1,78 @@
|
||||
use crate::config::keypress::KeyPress;
|
||||
use crate::config::keypress::{parse_keypress, KeyPress};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::Deserialize;
|
||||
use crate::config::actions::Actions;
|
||||
use serde::de;
|
||||
use serde::de::{MapAccess, Visitor};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug)]
|
||||
pub enum Action {
|
||||
KeyPress(KeyPress),
|
||||
Remap(HashMap<KeyPress, Vec<Action>>),
|
||||
}
|
||||
|
||||
impl Debug for Action {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Action::KeyPress(key_press) => key_press.fmt(f),
|
||||
impl<'de> Deserialize<'de> for Action {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ActionVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ActionVisitor {
|
||||
type Value = Action;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("string or map")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let keypress = parse_keypress(value).map_err(de::Error::custom)?;
|
||||
Ok(Action::KeyPress(keypress))
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let key = map.next_key::<String>()?;
|
||||
let action = match key.as_deref() {
|
||||
Some("remap") => {
|
||||
let mut action: HashMap<KeyPress, Vec<Action>> = HashMap::new();
|
||||
let remap = map.next_value::<HashMap<KeyPress, Actions>>()?;
|
||||
for (keypress, actions) in remap.into_iter() {
|
||||
let actions = match actions {
|
||||
Actions::Action(action) => vec![action],
|
||||
Actions::Actions(actions) => actions,
|
||||
};
|
||||
action.insert(keypress, actions);
|
||||
}
|
||||
Action::Remap(action)
|
||||
}
|
||||
Some(action) => {
|
||||
return serde_error::<Self::Value, M>(&format!(
|
||||
"unexpected action '{}'",
|
||||
action
|
||||
))
|
||||
}
|
||||
None => return serde_error::<Self::Value, M>("missing action"),
|
||||
};
|
||||
Ok(action)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(ActionVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
fn serde_error<'de, V, M>(message: &str) -> Result<V, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let error: Box<dyn std::error::Error> = message.into();
|
||||
Err(error).map_err(de::Error::custom)
|
||||
}
|
||||
|
57
src/config/actions.rs
Normal file
57
src/config/actions.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use crate::config::action::Action;
|
||||
use crate::config::keypress::parse_keypress;
|
||||
use serde::de;
|
||||
use serde::de::{value, MapAccess, SeqAccess, Visitor};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::fmt::Formatter;
|
||||
|
||||
// Used only for deserializing Vec<Action>
|
||||
pub enum Actions {
|
||||
Action(Action),
|
||||
Actions(Vec<Action>),
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Actions {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ActionsVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ActionsVisitor {
|
||||
type Value = Actions;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("strings or maps")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let keypress = parse_keypress(value).map_err(de::Error::custom)?;
|
||||
Ok(Actions::Action(Action::KeyPress(keypress)))
|
||||
}
|
||||
|
||||
fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
|
||||
where
|
||||
S: SeqAccess<'de>,
|
||||
{
|
||||
let actions: Vec<Action> =
|
||||
Deserialize::deserialize(value::SeqAccessDeserializer::new(seq))?;
|
||||
Ok(Actions::Actions(actions))
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let action: Action =
|
||||
Deserialize::deserialize(value::MapAccessDeserializer::new(map))?;
|
||||
Ok(Actions::Action(action))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(ActionsVisitor)
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
use crate::config::action::Action;
|
||||
use crate::config::actions::Actions;
|
||||
use crate::config::keypress::KeyPress;
|
||||
use crate::config::wm_class::WMClass;
|
||||
use serde::de::{MapAccess, Visitor};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@ -21,17 +23,10 @@ where
|
||||
{
|
||||
struct KeymapRemap;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Actions {
|
||||
Action(Action),
|
||||
Actions(Vec<Action>),
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for KeymapRemap {
|
||||
type Value = HashMap<KeyPress, Vec<Action>>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter.write_str("map from string to strings or maps")
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,10 @@ impl<'de> Deserialize<'de> for KeyPress {
|
||||
type Value = KeyPress;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("string or map")
|
||||
formatter.write_str("string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<KeyPress, E>
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
@ -48,7 +48,7 @@ impl<'de> Deserialize<'de> for KeyPress {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_keypress(input: &str) -> Result<KeyPress, Box<dyn error::Error>> {
|
||||
pub fn parse_keypress(input: &str) -> Result<KeyPress, Box<dyn error::Error>> {
|
||||
let keys: Vec<&str> = input.split("-").collect();
|
||||
if let Some((key, modifiers)) = keys.split_last() {
|
||||
let mut shift = false;
|
||||
|
@ -1,4 +1,5 @@
|
||||
mod action;
|
||||
mod actions;
|
||||
mod key;
|
||||
mod keymap;
|
||||
mod keypress;
|
||||
|
Loading…
Reference in New Issue
Block a user