mirror of
https://github.com/k0kubun/xremap
synced 2024-11-02 03:40:25 +00:00
Parse the basic config structure
This commit is contained in:
parent
2f8029a200
commit
d9127e8a90
92
Cargo.lock
generated
92
Cargo.lock
generated
@ -55,6 +55,22 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.111"
|
||||
@ -89,18 +105,91 @@ dependencies = [
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.4.0"
|
||||
@ -116,7 +205,8 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"evdev",
|
||||
"nix",
|
||||
"yaml-rust",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -8,4 +8,5 @@ edition = "2021"
|
||||
[dependencies]
|
||||
evdev = "0.11.3"
|
||||
nix = "0.23.1"
|
||||
yaml-rust = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.8"
|
||||
|
@ -10,12 +10,12 @@ modmap:
|
||||
Muhenkan: Ctrl_L
|
||||
Henkan: Shift_L
|
||||
|
||||
- name: Kana -> Windows
|
||||
- name: Kana -> Alt
|
||||
wm_class:
|
||||
not: jetbrains-idea
|
||||
only: jetbrains-idea
|
||||
remap:
|
||||
# Use Windows since Alt is annoying in Electron apps (Slack, Nocturn)
|
||||
KanaHira: Windows
|
||||
# Use Alt since Windows is annoying in IDEA
|
||||
KanaHira: Alt_L
|
||||
|
||||
keymap:
|
||||
- name: Global
|
||||
|
@ -1,36 +1,76 @@
|
||||
extern crate serde_yaml;
|
||||
|
||||
use serde::de::{value, SeqAccess, Visitor};
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
use yaml_rust::{Yaml, YamlLoader};
|
||||
use std::{fmt, fs};
|
||||
|
||||
pub fn load_config(filename: &str) -> Result<Config, Box<dyn Error>> {
|
||||
let yaml = YamlLoader::load_from_str(&fs::read_to_string(&filename)?)?;
|
||||
// println!("{:#?}", yaml);
|
||||
match &yaml[..] {
|
||||
[yaml] => {
|
||||
Ok(parse_config(yaml))
|
||||
},
|
||||
arr => {
|
||||
Err(format!("The number of top-level elements must be 1, but got: {}", arr.len()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_config(_yaml: &Yaml) -> Config {
|
||||
Config { modmap: vec![], keymap: vec![] }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
pub modmap: Vec<Modmap>,
|
||||
pub keymap: Vec<Keymap>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Modmap {
|
||||
// TODO
|
||||
pub name: String,
|
||||
pub remap: HashMap<String, String>,
|
||||
pub wm_class: Option<WMClass>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Keymap {
|
||||
// TODO
|
||||
pub name: String,
|
||||
pub remap: HashMap<String, String>,
|
||||
pub wm_class: Option<WMClass>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct WMClass {
|
||||
// TODO: validate only either `only` or `not` is set
|
||||
#[serde(default, deserialize_with = "string_or_vec")]
|
||||
pub only: Option<Vec<String>>,
|
||||
#[serde(default, deserialize_with = "string_or_vec")]
|
||||
pub not: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub fn load_config(filename: &str) -> Result<Config, Box<dyn Error>> {
|
||||
let yaml = fs::read_to_string(&filename)?;
|
||||
let config: Config = serde_yaml::from_str(&yaml)?;
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
fn string_or_vec<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct StringOrVec;
|
||||
|
||||
impl<'de> Visitor<'de> for StringOrVec {
|
||||
type Value = Option<Vec<String>>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("string or list of strings")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Some(vec![s.to_owned()]))
|
||||
}
|
||||
|
||||
fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
|
||||
where
|
||||
S: SeqAccess<'de>,
|
||||
{
|
||||
let result: Vec<String> =
|
||||
Deserialize::deserialize(value::SeqAccessDeserializer::new(seq))?;
|
||||
Ok(Some(result))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(StringOrVec)
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ extern crate evdev;
|
||||
extern crate nix;
|
||||
|
||||
use evdev::Device;
|
||||
use std::error::Error;
|
||||
use nix::sys::select::FdSet;
|
||||
use nix::sys::select::select;
|
||||
use std::os::unix::io::{AsRawFd};
|
||||
use nix::sys::select::FdSet;
|
||||
use std::error::Error;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
pub fn select_device() -> Result<Device, Box<dyn Error>> {
|
||||
// TODO: stop hard-coding the device
|
||||
|
23
src/main.rs
23
src/main.rs
@ -1,19 +1,20 @@
|
||||
use evdev::{EventType};
|
||||
use std::error::Error;
|
||||
use evdev::EventType;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::process::exit;
|
||||
|
||||
mod config;
|
||||
mod input;
|
||||
mod output;
|
||||
mod transform;
|
||||
mod config;
|
||||
|
||||
fn event_loop() -> Result<(), Box<dyn Error>> {
|
||||
let mut input_device = input::select_device()
|
||||
.map_err(|e| format!("Failed to open an input device: {}", e))?;
|
||||
let mut input_device =
|
||||
input::select_device().map_err(|e| format!("Failed to open an input device: {}", e))?;
|
||||
let mut output_device = output::build_device(&input_device)
|
||||
.map_err(|e| format!("Failed to build an output device: {}", e))?;
|
||||
input_device.grab()
|
||||
input_device
|
||||
.grab()
|
||||
.map_err(|e| format!("Failed to grab an input device: {}", e))?;
|
||||
|
||||
loop {
|
||||
@ -37,22 +38,22 @@ fn main() {
|
||||
None => {
|
||||
println!("Usage: xremap <file>");
|
||||
exit(1);
|
||||
},
|
||||
}
|
||||
};
|
||||
let config = match config::load_config(&filename) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
println!("Failed to load config '{}': {}", filename, e);
|
||||
exit(1);
|
||||
},
|
||||
}
|
||||
};
|
||||
println!("{:?}", config);
|
||||
println!("{:#?}", config);
|
||||
|
||||
match event_loop() {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
println!("Error: {}", e);
|
||||
exit(1);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use evdev::uinput::{VirtualDevice, VirtualDeviceBuilder};
|
||||
use evdev::{Device};
|
||||
use evdev::Device;
|
||||
use std::error::Error;
|
||||
|
||||
pub fn build_device(base_device: &Device) -> Result<VirtualDevice, Box<dyn Error>> {
|
||||
@ -7,6 +7,7 @@ pub fn build_device(base_device: &Device) -> Result<VirtualDevice, Box<dyn Error
|
||||
let device = match base_device.supported_keys() {
|
||||
Some(keys) => builder.with_keys(keys)?,
|
||||
None => builder,
|
||||
}.build()?;
|
||||
}
|
||||
.build()?;
|
||||
Ok(device)
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
use std::error::Error;
|
||||
use evdev::{EventType, InputEvent, InputEventKind};
|
||||
use evdev::uinput::VirtualDevice;
|
||||
use evdev::{EventType, InputEvent, InputEventKind};
|
||||
use std::error::Error;
|
||||
|
||||
pub fn on_event(event: InputEvent, device: &mut VirtualDevice) -> Result<(), Box<dyn Error>> {
|
||||
println!("event: {:?}", event);
|
||||
if event.kind() == InputEventKind::Key(evdev::Key::KEY_A) {
|
||||
device.emit(&[
|
||||
InputEvent::new(EventType::KEY, evdev::Key::KEY_B.code(), event.value())
|
||||
])?;
|
||||
device.emit(&[InputEvent::new(
|
||||
EventType::KEY,
|
||||
evdev::Key::KEY_B.code(),
|
||||
event.value(),
|
||||
)])?;
|
||||
} else {
|
||||
device.emit(&[event])?;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user