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};
|
||||
|
||||
struct ModeWrapper {
|
||||
|
@ -517,7 +528,8 @@ impl de::Deserialize for RawBinding {
|
|||
Mode,
|
||||
Action,
|
||||
Chars,
|
||||
Mouse
|
||||
Mouse,
|
||||
Command,
|
||||
}
|
||||
|
||||
impl de::Deserialize for Field {
|
||||
|
@ -527,7 +539,7 @@ impl de::Deserialize for RawBinding {
|
|||
struct FieldVisitor;
|
||||
|
||||
static FIELDS: &'static [&'static str] = &[
|
||||
"key", "mods", "mode", "action", "chars", "mouse"
|
||||
"key", "mods", "mode", "action", "chars", "mouse", "command",
|
||||
];
|
||||
|
||||
impl Visitor for FieldVisitor {
|
||||
|
@ -547,6 +559,7 @@ impl de::Deserialize for RawBinding {
|
|||
"action" => Ok(Field::Action),
|
||||
"chars" => Ok(Field::Chars),
|
||||
"mouse" => Ok(Field::Mouse),
|
||||
"command" => Ok(Field::Command),
|
||||
_ => Err(E::unknown_field(value, FIELDS)),
|
||||
}
|
||||
}
|
||||
|
@ -577,6 +590,7 @@ impl de::Deserialize for RawBinding {
|
|||
let mut mode: Option<TermMode> = None;
|
||||
let mut not_mode: Option<TermMode> = None;
|
||||
let mut mouse: Option<::glutin::MouseButton> = None;
|
||||
let mut command: Option<CommandWrapper> = None;
|
||||
|
||||
use ::serde::de::Error;
|
||||
|
||||
|
@ -626,17 +640,32 @@ impl de::Deserialize for RawBinding {
|
|||
}
|
||||
|
||||
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) {
|
||||
(Some(_), Some(_)) => {
|
||||
return Err(V::Error::custom("must specify only chars or action"));
|
||||
let action = match (action, chars, command) {
|
||||
(Some(action), None, None) => 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,
|
||||
(_, Some(chars)) => Action::Esc(chars),
|
||||
_ => return Err(V::Error::custom("must specify chars or action"))
|
||||
(None, None, None) => return Err(V::Error::custom("must specify chars, action or command")),
|
||||
_ => return Err(V::Error::custom("must specify only chars, action or command")),
|
||||
};
|
||||
|
||||
let mode = mode.unwrap_or_else(TermMode::empty);
|
||||
|
@ -659,7 +688,7 @@ impl de::Deserialize for RawBinding {
|
|||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &[
|
||||
"key", "mods", "mode", "action", "chars", "mouse"
|
||||
"key", "mods", "mode", "action", "chars", "mouse", "command",
|
||||
];
|
||||
|
||||
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.
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
use std::process::Command;
|
||||
use std::time::Instant;
|
||||
|
||||
use copypasta::{Clipboard, Load, Buffer};
|
||||
|
@ -144,6 +145,9 @@ pub enum Action {
|
|||
/// Paste contents of selection buffer
|
||||
PasteSelection,
|
||||
|
||||
/// Run given command
|
||||
Command(String, Vec<String>),
|
||||
|
||||
/// Quits Alacritty.
|
||||
Quit,
|
||||
}
|
||||
|
@ -174,6 +178,17 @@ impl Action {
|
|||
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 => {
|
||||
// FIXME should do a more graceful shutdown
|
||||
::std::process::exit(0);
|
||||
|
|
Loading…
Reference in New Issue