feat(plugins): API to temporarily bind keys to send a message to a specific plugin id (#3561)
This commit is contained in:
parent
905ce0a27d
commit
08b6072a69
5 changed files with 117 additions and 34 deletions
|
|
@ -134,6 +134,7 @@ pub enum PluginInstruction {
|
|||
cwd: Option<PathBuf>,
|
||||
skip_cache: bool,
|
||||
cli_client_id: ClientId,
|
||||
plugin_and_client_id: Option<(u32, ClientId)>,
|
||||
},
|
||||
CachePluginEvents {
|
||||
plugin_id: PluginId,
|
||||
|
|
@ -624,42 +625,52 @@ pub(crate) fn plugin_thread_main(
|
|||
cwd,
|
||||
skip_cache,
|
||||
cli_client_id,
|
||||
plugin_and_client_id,
|
||||
} => {
|
||||
let should_float = floating.unwrap_or(true);
|
||||
let mut pipe_messages = vec![];
|
||||
match plugin {
|
||||
Some(plugin_url) => {
|
||||
// send to specific plugin(s)
|
||||
pipe_to_specific_plugins(
|
||||
PipeSource::Keybind,
|
||||
&plugin_url,
|
||||
&configuration,
|
||||
&cwd,
|
||||
skip_cache,
|
||||
should_float,
|
||||
&pane_id_to_replace,
|
||||
&pane_title,
|
||||
Some(cli_client_id),
|
||||
&mut pipe_messages,
|
||||
&name,
|
||||
&payload,
|
||||
&args,
|
||||
&bus,
|
||||
&mut wasm_bridge,
|
||||
&plugin_aliases,
|
||||
);
|
||||
},
|
||||
None => {
|
||||
// no specific destination, send to all plugins
|
||||
pipe_to_all_plugins(
|
||||
PipeSource::Keybind,
|
||||
&name,
|
||||
&payload,
|
||||
&args,
|
||||
&mut wasm_bridge,
|
||||
&mut pipe_messages,
|
||||
);
|
||||
},
|
||||
if let Some((plugin_id, client_id)) = plugin_and_client_id {
|
||||
let is_private = true;
|
||||
pipe_messages.push((
|
||||
Some(plugin_id),
|
||||
Some(client_id),
|
||||
PipeMessage::new(PipeSource::Keybind, name, &payload, &args, is_private),
|
||||
));
|
||||
} else {
|
||||
match plugin {
|
||||
Some(plugin_url) => {
|
||||
// send to specific plugin(s)
|
||||
pipe_to_specific_plugins(
|
||||
PipeSource::Keybind,
|
||||
&plugin_url,
|
||||
&configuration,
|
||||
&cwd,
|
||||
skip_cache,
|
||||
should_float,
|
||||
&pane_id_to_replace,
|
||||
&pane_title,
|
||||
Some(cli_client_id),
|
||||
&mut pipe_messages,
|
||||
&name,
|
||||
&payload,
|
||||
&args,
|
||||
&bus,
|
||||
&mut wasm_bridge,
|
||||
&plugin_aliases,
|
||||
);
|
||||
},
|
||||
None => {
|
||||
// no specific destination, send to all plugins
|
||||
pipe_to_all_plugins(
|
||||
PipeSource::Keybind,
|
||||
&name,
|
||||
&payload,
|
||||
&args,
|
||||
&mut wasm_bridge,
|
||||
&mut pipe_messages,
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
wasm_bridge.pipe_messages(pipe_messages, shutdown_send.clone())?;
|
||||
},
|
||||
|
|
@ -768,6 +779,8 @@ pub(crate) fn plugin_thread_main(
|
|||
keybinds,
|
||||
default_mode,
|
||||
} => {
|
||||
// TODO: notify plugins that this happened so that they can eg. rebind temporary keys that
|
||||
// were lost
|
||||
wasm_bridge
|
||||
.reconfigure(client_id, keybinds, default_mode)
|
||||
.non_fatal();
|
||||
|
|
|
|||
|
|
@ -921,12 +921,13 @@ pub(crate) fn route_action(
|
|||
cwd,
|
||||
pane_title,
|
||||
launch_new,
|
||||
plugin_id,
|
||||
..
|
||||
} => {
|
||||
if let Some(name) = name.take() {
|
||||
let should_open_in_place = in_place.unwrap_or(false);
|
||||
let pane_id_to_replace = if should_open_in_place { pane_id } else { None };
|
||||
if launch_new {
|
||||
if launch_new && plugin_id.is_none() {
|
||||
// we do this to make sure the plugin is unique (has a unique configuration parameter)
|
||||
configuration
|
||||
.get_or_insert_with(BTreeMap::new)
|
||||
|
|
@ -945,6 +946,7 @@ pub(crate) fn route_action(
|
|||
pane_title,
|
||||
skip_cache,
|
||||
cli_client_id: client_id,
|
||||
plugin_and_client_id: plugin_id.map(|plugin_id| (plugin_id, client_id)),
|
||||
})
|
||||
.with_context(err_context)?;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -289,6 +289,7 @@ pub enum Action {
|
|||
payload: Option<String>,
|
||||
args: Option<BTreeMap<String, String>>,
|
||||
plugin: Option<String>,
|
||||
plugin_id: Option<u32>, // supercedes plugin if present
|
||||
configuration: Option<BTreeMap<String, String>>,
|
||||
launch_new: bool,
|
||||
skip_cache: bool,
|
||||
|
|
|
|||
|
|
@ -363,6 +363,27 @@ pub fn kdl_arguments_that_are_strings<'a>(
|
|||
Ok(args)
|
||||
}
|
||||
|
||||
pub fn kdl_arguments_that_are_digits<'a>(
|
||||
arguments: impl Iterator<Item = &'a KdlEntry>,
|
||||
) -> Result<Vec<i64>, ConfigError> {
|
||||
let mut args: Vec<i64> = vec![];
|
||||
for kdl_entry in arguments {
|
||||
match kdl_entry.value().as_i64() {
|
||||
Some(digit_value) => {
|
||||
args.push(digit_value);
|
||||
},
|
||||
None => {
|
||||
return Err(ConfigError::new_kdl_error(
|
||||
format!("Argument must be a digit"),
|
||||
kdl_entry.span().offset(),
|
||||
kdl_entry.span().len(),
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
pub fn kdl_child_string_value_for_entry<'a>(
|
||||
command_metadata: &'a KdlDocument,
|
||||
entry_name: &'a str,
|
||||
|
|
@ -1010,7 +1031,12 @@ impl Action {
|
|||
in_place,
|
||||
cwd,
|
||||
pane_title,
|
||||
plugin_id,
|
||||
} => {
|
||||
if plugin_id.is_some() {
|
||||
log::warn!("Not serializing temporary keybinding MessagePluginId");
|
||||
return None;
|
||||
}
|
||||
let mut node = KdlNode::new("MessagePlugin");
|
||||
let mut node_children = KdlDocument::new();
|
||||
if let Some(plugin) = plugin {
|
||||
|
|
@ -1678,6 +1704,46 @@ impl TryFrom<(&KdlNode, &Options)> for Action {
|
|||
in_place: None, // TODO: support this
|
||||
cwd,
|
||||
pane_title: title,
|
||||
plugin_id: None,
|
||||
})
|
||||
},
|
||||
"MessagePluginId" => {
|
||||
let arguments = action_arguments.iter().copied();
|
||||
let mut args = kdl_arguments_that_are_digits(arguments)?;
|
||||
let plugin_id = if args.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(args.remove(0) as u32)
|
||||
};
|
||||
|
||||
let command_metadata = action_children.iter().next();
|
||||
let launch_new = false;
|
||||
let skip_cache = false;
|
||||
let name = command_metadata
|
||||
.and_then(|c_m| kdl_child_string_value_for_entry(c_m, "name"))
|
||||
.map(|n| n.to_owned());
|
||||
let payload = command_metadata
|
||||
.and_then(|c_m| kdl_child_string_value_for_entry(c_m, "payload"))
|
||||
.map(|p| p.to_owned());
|
||||
let configuration = None;
|
||||
|
||||
let name = name
|
||||
// if no name is provided, we use a uuid to at least have some sort of identifier for this message
|
||||
.or_else(|| Some(Uuid::new_v4().to_string()));
|
||||
|
||||
Ok(Action::KeybindPipe {
|
||||
name,
|
||||
payload,
|
||||
args: None, // TODO: consider supporting this if there's a need
|
||||
plugin: None,
|
||||
configuration,
|
||||
launch_new,
|
||||
skip_cache,
|
||||
floating: None,
|
||||
in_place: None, // TODO: support this
|
||||
cwd: None,
|
||||
pane_title: None,
|
||||
plugin_id,
|
||||
})
|
||||
},
|
||||
_ => Err(ConfigError::new_kdl_error(
|
||||
|
|
|
|||
|
|
@ -703,6 +703,7 @@ impl TryFrom<ProtobufAction> for Action {
|
|||
in_place: None,
|
||||
cwd: None,
|
||||
pane_title: None,
|
||||
plugin_id: None,
|
||||
}),
|
||||
},
|
||||
_ => Err("Unknown Action"),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue