Add support for running commands on key press (#566)
Based on option `command` in key binding section in config, e.g. - { key: N, mods: Control|Shift, command: alacritty } # or - { key: N, mods: Control|Shift, command: { program: "alacritty", args: ["-e", "vttest"], }} specified command will be run in the background on key press. Alacritty doesn't wait for its result nor block IO.
This commit is contained in:
parent
112abf385f
commit
5977776874
|
@ -378,6 +378,17 @@ impl de::Deserialize for ActionWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum CommandWrapper {
|
||||||
|
Just(String),
|
||||||
|
WithArgs {
|
||||||
|
program: String,
|
||||||
|
#[serde(default)]
|
||||||
|
args: Vec<String>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
use ::term::{mode, TermMode};
|
use ::term::{mode, TermMode};
|
||||||
|
|
||||||
struct ModeWrapper {
|
struct ModeWrapper {
|
||||||
|
@ -517,7 +528,8 @@ impl de::Deserialize for RawBinding {
|
||||||
Mode,
|
Mode,
|
||||||
Action,
|
Action,
|
||||||
Chars,
|
Chars,
|
||||||
Mouse
|
Mouse,
|
||||||
|
Command,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl de::Deserialize for Field {
|
impl de::Deserialize for Field {
|
||||||
|
@ -527,7 +539,7 @@ impl de::Deserialize for RawBinding {
|
||||||
struct FieldVisitor;
|
struct FieldVisitor;
|
||||||
|
|
||||||
static FIELDS: &'static [&'static str] = &[
|
static FIELDS: &'static [&'static str] = &[
|
||||||
"key", "mods", "mode", "action", "chars", "mouse"
|
"key", "mods", "mode", "action", "chars", "mouse", "command",
|
||||||
];
|
];
|
||||||
|
|
||||||
impl Visitor for FieldVisitor {
|
impl Visitor for FieldVisitor {
|
||||||
|
@ -547,6 +559,7 @@ impl de::Deserialize for RawBinding {
|
||||||
"action" => Ok(Field::Action),
|
"action" => Ok(Field::Action),
|
||||||
"chars" => Ok(Field::Chars),
|
"chars" => Ok(Field::Chars),
|
||||||
"mouse" => Ok(Field::Mouse),
|
"mouse" => Ok(Field::Mouse),
|
||||||
|
"command" => Ok(Field::Command),
|
||||||
_ => Err(E::unknown_field(value, FIELDS)),
|
_ => Err(E::unknown_field(value, FIELDS)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -577,6 +590,7 @@ impl de::Deserialize for RawBinding {
|
||||||
let mut mode: Option<TermMode> = None;
|
let mut mode: Option<TermMode> = None;
|
||||||
let mut not_mode: Option<TermMode> = None;
|
let mut not_mode: Option<TermMode> = None;
|
||||||
let mut mouse: Option<::glutin::MouseButton> = None;
|
let mut mouse: Option<::glutin::MouseButton> = None;
|
||||||
|
let mut command: Option<CommandWrapper> = None;
|
||||||
|
|
||||||
use ::serde::de::Error;
|
use ::serde::de::Error;
|
||||||
|
|
||||||
|
@ -626,17 +640,32 @@ impl de::Deserialize for RawBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse = Some(visitor.visit_value::<MouseButton>()?.into_inner());
|
mouse = Some(visitor.visit_value::<MouseButton>()?.into_inner());
|
||||||
}
|
},
|
||||||
|
Field::Command => {
|
||||||
|
if command.is_some() {
|
||||||
|
return Err(<V::Error as Error>::duplicate_field("command"));
|
||||||
|
}
|
||||||
|
|
||||||
|
command = Some(visitor.visit_value::<CommandWrapper>()?);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let action = match (action, chars) {
|
let action = match (action, chars, command) {
|
||||||
(Some(_), Some(_)) => {
|
(Some(action), None, None) => action,
|
||||||
return Err(V::Error::custom("must specify only chars or action"));
|
(None, Some(chars), None) => Action::Esc(chars),
|
||||||
|
(None, None, Some(cmd)) => {
|
||||||
|
match cmd {
|
||||||
|
CommandWrapper::Just(program) => {
|
||||||
|
Action::Command(program, vec![])
|
||||||
|
},
|
||||||
|
CommandWrapper::WithArgs { program, args } => {
|
||||||
|
Action::Command(program, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
(Some(action), _) => action,
|
(None, None, None) => return Err(V::Error::custom("must specify chars, action or command")),
|
||||||
(_, Some(chars)) => Action::Esc(chars),
|
_ => return Err(V::Error::custom("must specify only chars, action or command")),
|
||||||
_ => return Err(V::Error::custom("must specify chars or action"))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mode = mode.unwrap_or_else(TermMode::empty);
|
let mode = mode.unwrap_or_else(TermMode::empty);
|
||||||
|
@ -659,7 +688,7 @@ impl de::Deserialize for RawBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
const FIELDS: &'static [&'static str] = &[
|
const FIELDS: &'static [&'static str] = &[
|
||||||
"key", "mods", "mode", "action", "chars", "mouse"
|
"key", "mods", "mode", "action", "chars", "mouse", "command",
|
||||||
];
|
];
|
||||||
|
|
||||||
deserializer.deserialize_struct("RawBinding", FIELDS, RawBindingVisitor)
|
deserializer.deserialize_struct("RawBinding", FIELDS, RawBindingVisitor)
|
||||||
|
|
15
src/input.rs
15
src/input.rs
|
@ -20,6 +20,7 @@
|
||||||
//! determine what to do when a non-modifier key is pressed.
|
//! determine what to do when a non-modifier key is pressed.
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::process::Command;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use copypasta::{Clipboard, Load, Buffer};
|
use copypasta::{Clipboard, Load, Buffer};
|
||||||
|
@ -144,6 +145,9 @@ pub enum Action {
|
||||||
/// Paste contents of selection buffer
|
/// Paste contents of selection buffer
|
||||||
PasteSelection,
|
PasteSelection,
|
||||||
|
|
||||||
|
/// Run given command
|
||||||
|
Command(String, Vec<String>),
|
||||||
|
|
||||||
/// Quits Alacritty.
|
/// Quits Alacritty.
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
@ -174,6 +178,17 @@ impl Action {
|
||||||
warn!("Error loading data from clipboard. {}", Red(err));
|
warn!("Error loading data from clipboard. {}", Red(err));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
Action::Command(ref program, ref args) => {
|
||||||
|
trace!("running command: {} {:?}", program, args);
|
||||||
|
match Command::new(program).args(args).spawn() {
|
||||||
|
Ok(child) => {
|
||||||
|
debug!("spawned new proc with pid: {}", child.id());
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
warn!("couldn't run command: {}", err);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
Action::Quit => {
|
Action::Quit => {
|
||||||
// FIXME should do a more graceful shutdown
|
// FIXME should do a more graceful shutdown
|
||||||
::std::process::exit(0);
|
::std::process::exit(0);
|
||||||
|
|
Loading…
Reference in New Issue