set_mode and launch command at same time

This allows to run custom commands when a mode is entered
pull/460/head
blob42 1 month ago
parent 3a693d26af
commit aece461db6

@ -262,6 +262,11 @@ keymap:
MOD1-KEY_XXX: { escape_next_key: true }
# Set mode to configure Vim-like modal remapping
MOD1-KEY_XXX: { set_mode: default }
# Set mode and launch command at same time
MOD1-KEY_XXX:
set_mode: test
launch: ["notify-send", "test mode"]
application: # Optional
not: [Application, ...]
# or

@ -5,7 +5,6 @@ use crate::config::remap::Remap;
use evdev::Key;
use serde::de;
use serde::{Deserialize, Deserializer};
use std::fmt::Debug;
use std::time::Duration;
use super::key::parse_key;
@ -22,7 +21,7 @@ pub enum KeymapAction {
#[serde(deserialize_with = "deserialize_launch")]
Launch(Vec<String>),
#[serde(deserialize_with = "deserialize_set_mode")]
SetMode(String),
SetMode(ModeAction),
#[serde(deserialize_with = "deserialize_set_mark")]
SetMark(bool),
#[serde(deserialize_with = "deserialize_with_mark")]
@ -67,17 +66,21 @@ where
Err(de::Error::custom("not a map with a single \"launch\" key"))
}
fn deserialize_set_mode<'de, D>(deserializer: D) -> Result<String, D::Error>
fn deserialize_set_mode<'de, D>(deserializer: D) -> Result<ModeAction, D::Error>
where
D: Deserializer<'de>,
{
let mut action = HashMap::<String, String>::deserialize(deserializer)?;
if let Some(set) = action.remove("set_mode") {
if action.is_empty() {
return Ok(set);
}
let action = ModeAction::deserialize(deserializer)?;
match &action {
ModeAction::Set(set_only) => {
if !set_only.contains_key("set_mode") {
return Err(de::Error::custom("not a map with a single \"set_mode\" key"));
}
Ok(action)
},
ModeAction::SetLaunch(_set_launch) => Ok(action)
}
Err(de::Error::custom("not a map with a single \"set_mode\" key"))
}
fn deserialize_set_mark<'de, D>(deserializer: D) -> Result<bool, D::Error>
@ -135,3 +138,21 @@ impl Actions {
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct Mode {
#[serde(rename = "set_mode")]
pub name: String,
#[serde(rename = "launch")]
pub command: Vec<String>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum ModeAction {
// set mode only
Set(HashMap<String, String>),
// set mode and launch command
SetLaunch(Mode)
}

@ -199,6 +199,25 @@ fn test_yaml_keymap_mode() {
"})
}
#[test]
fn test_yaml_keymap_mode_launch() {
yaml_assert_parse(indoc! {r#"
default_mode: insert
keymap:
- mode: insert
remap:
Esc: { set_mode: normal, launch: ["wmctrl", "-x", "-a", "code.Code"] }
- mode: normal
remap:
i: { set_mode: insert }
h: Left
j: Down
k: Up
l: Right
"#})
}
#[test]
fn test_yaml_keymap_mark() {
yaml_assert_parse(indoc! {"

@ -3,7 +3,7 @@ use crate::client::WMClient;
use crate::config::application::OnlyOrNot;
use crate::config::key_press::{KeyPress, Modifier};
use crate::config::keymap::{build_override_table, OverrideEntry};
use crate::config::keymap_action::KeymapAction;
use crate::config::keymap_action::{KeymapAction, ModeAction};
use crate::config::modmap_action::{Keys, ModmapAction, MultiPurposeKey, PressReleaseKey};
use crate::config::remap::Remap;
use crate::device::InputDeviceInfo;
@ -539,8 +539,16 @@ impl EventHandler {
}
KeymapAction::Launch(command) => self.run_command(command.clone()),
KeymapAction::SetMode(mode) => {
self.mode = mode.clone();
println!("mode: {}", mode);
match mode {
ModeAction::Set(set_only) => {
let mode = set_only.clone().remove("set_mode").unwrap_or_default();
self.mode = mode.clone();
},
ModeAction::SetLaunch(set) => {
self.run_command(set.command.clone());
self.mode = set.name.clone();
}
}
}
KeymapAction::SetMark(set) => self.mark_set = *set,
KeymapAction::WithMark(key_press) => self.send_key_press(&self.with_mark(key_press)),

Loading…
Cancel
Save