feat(plugins): allow opening command panes in the background (hidden) (#3530)
* start background pane * open command and edit panes in the background * some cleanups * style(fmt): rustfmt * more cleanups
This commit is contained in:
parent
a6fe5ff1d5
commit
355463383a
53 changed files with 3082 additions and 621 deletions
|
|
@ -166,10 +166,13 @@ impl ZellijPlugin for State {
|
||||||
start_or_reload_plugin(plugin_url)
|
start_or_reload_plugin(plugin_url)
|
||||||
},
|
},
|
||||||
BareKey::Char('g') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
BareKey::Char('g') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||||
open_file(FileToOpen {
|
open_file(
|
||||||
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
FileToOpen {
|
||||||
..Default::default()
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
});
|
..Default::default()
|
||||||
|
},
|
||||||
|
BTreeMap::new(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
BareKey::Char('h') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
BareKey::Char('h') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||||
open_file_floating(
|
open_file_floating(
|
||||||
|
|
@ -178,14 +181,18 @@ impl ZellijPlugin for State {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
|
BTreeMap::new(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
BareKey::Char('i') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
BareKey::Char('i') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||||
open_file(FileToOpen {
|
open_file(
|
||||||
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
FileToOpen {
|
||||||
line_number: Some(42),
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
..Default::default()
|
line_number: Some(42),
|
||||||
});
|
..Default::default()
|
||||||
|
},
|
||||||
|
BTreeMap::new(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
BareKey::Char('j') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
BareKey::Char('j') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||||
open_file_floating(
|
open_file_floating(
|
||||||
|
|
@ -195,6 +202,7 @@ impl ZellijPlugin for State {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
|
BTreeMap::new(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
BareKey::Char('k') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
BareKey::Char('k') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||||
|
|
@ -335,6 +343,22 @@ impl ZellijPlugin for State {
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
BareKey::Char('a') if key.has_modifiers(&[KeyModifier::Alt]) => {
|
||||||
|
hide_pane_with_id(PaneId::Terminal(1));
|
||||||
|
},
|
||||||
|
BareKey::Char('b') if key.has_modifiers(&[KeyModifier::Alt]) => {
|
||||||
|
show_pane_with_id(PaneId::Terminal(1), true);
|
||||||
|
},
|
||||||
|
BareKey::Char('c') if key.has_modifiers(&[KeyModifier::Alt]) => {
|
||||||
|
open_command_pane_background(
|
||||||
|
CommandToRun {
|
||||||
|
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||||
|
args: vec!["arg1".to_owned(), "arg2".to_owned()],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
BTreeMap::new(),
|
||||||
|
);
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
Event::CustomMessage(message, payload) => {
|
Event::CustomMessage(message, payload) => {
|
||||||
|
|
|
||||||
|
|
@ -677,7 +677,7 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
|
||||||
let mut secondary_info = LinePart::default();
|
let mut secondary_info = LinePart::default();
|
||||||
let binds = &help.get_mode_keybinds();
|
let binds = &help.get_mode_keybinds();
|
||||||
// New Pane
|
// New Pane
|
||||||
let new_pane_action_key = action_key(binds, &[Action::NewPane(None, None)]);
|
let new_pane_action_key = action_key(binds, &[Action::NewPane(None, None, false)]);
|
||||||
let mut new_pane_key_to_display = new_pane_action_key
|
let mut new_pane_key_to_display = new_pane_action_key
|
||||||
.iter()
|
.iter()
|
||||||
.find(|k| k.is_key_with_alt_modifier(BareKey::Char('n')))
|
.find(|k| k.is_key_with_alt_modifier(BareKey::Char('n')))
|
||||||
|
|
@ -1163,7 +1163,7 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<KeyWithModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
if mi.mode == IM::Pane { vec![
|
if mi.mode == IM::Pane { vec![
|
||||||
(s("New"), s("New"), single_action_key(&km, &[A::NewPane(None, None), TO_NORMAL])),
|
(s("New"), s("New"), single_action_key(&km, &[A::NewPane(None, None, false), TO_NORMAL])),
|
||||||
(s("Change Focus"), s("Move"),
|
(s("Change Focus"), s("Move"),
|
||||||
action_key_group(&km, &[&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
action_key_group(&km, &[&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||||
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
||||||
|
|
@ -1271,8 +1271,8 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<KeyWithModifier
|
||||||
(s("Move focus"), s("Move"), action_key_group(&km, &[
|
(s("Move focus"), s("Move"), action_key_group(&km, &[
|
||||||
&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||||
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
||||||
(s("Split down"), s("Down"), action_key(&km, &[A::NewPane(Some(Dir::Down), None), TO_NORMAL])),
|
(s("Split down"), s("Down"), action_key(&km, &[A::NewPane(Some(Dir::Down), None, false), TO_NORMAL])),
|
||||||
(s("Split right"), s("Right"), action_key(&km, &[A::NewPane(Some(Dir::Right), None), TO_NORMAL])),
|
(s("Split right"), s("Right"), action_key(&km, &[A::NewPane(Some(Dir::Right), None, false), TO_NORMAL])),
|
||||||
(s("Fullscreen"), s("Fullscreen"), action_key(&km, &[A::ToggleFocusFullscreen, TO_NORMAL])),
|
(s("Fullscreen"), s("Fullscreen"), action_key(&km, &[A::ToggleFocusFullscreen, TO_NORMAL])),
|
||||||
(s("New tab"), s("New"), action_key(&km, &[A::NewTab(None, vec![], None, None, None), TO_NORMAL])),
|
(s("New tab"), s("New"), action_key(&km, &[A::NewTab(None, vec![], None, None, None), TO_NORMAL])),
|
||||||
(s("Rename tab"), s("Rename"),
|
(s("Rename tab"), s("Rename"),
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<KeyWithModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
if mi.mode == IM::Pane { vec![
|
if mi.mode == IM::Pane { vec![
|
||||||
(s("New"), s("New"), action_key(&km, &[A::NewPane(None, None), TO_NORMAL])),
|
(s("New"), s("New"), action_key(&km, &[A::NewPane(None, None, false), TO_NORMAL])),
|
||||||
(s("Change Focus"), s("Move"),
|
(s("Change Focus"), s("Move"),
|
||||||
action_key_group(&km, &[&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
action_key_group(&km, &[&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||||
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
||||||
|
|
@ -256,8 +256,8 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<KeyWithModifier
|
||||||
(s("Move focus"), s("Move"), action_key_group(&km, &[
|
(s("Move focus"), s("Move"), action_key_group(&km, &[
|
||||||
&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||||
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
&[A::MoveFocus(Dir::Up)], &[A::MoveFocus(Dir::Right)]])),
|
||||||
(s("Split down"), s("Down"), action_key(&km, &[A::NewPane(Some(Dir::Down), None), TO_NORMAL])),
|
(s("Split down"), s("Down"), action_key(&km, &[A::NewPane(Some(Dir::Down), None, false), TO_NORMAL])),
|
||||||
(s("Split right"), s("Right"), action_key(&km, &[A::NewPane(Some(Dir::Right), None), TO_NORMAL])),
|
(s("Split right"), s("Right"), action_key(&km, &[A::NewPane(Some(Dir::Right), None, false), TO_NORMAL])),
|
||||||
(s("Fullscreen"), s("Fullscreen"), action_key(&km, &[A::ToggleFocusFullscreen, TO_NORMAL])),
|
(s("Fullscreen"), s("Fullscreen"), action_key(&km, &[A::ToggleFocusFullscreen, TO_NORMAL])),
|
||||||
(s("New tab"), s("New"), action_key(&km, &[A::NewTab(None, vec![], None, None, None), TO_NORMAL])),
|
(s("New tab"), s("New"), action_key(&km, &[A::NewTab(None, vec![], None, None, None), TO_NORMAL])),
|
||||||
(s("Rename tab"), s("Rename"),
|
(s("Rename tab"), s("Rename"),
|
||||||
|
|
@ -713,7 +713,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
KeyWithModifier::new(BareKey::Char('n')),
|
KeyWithModifier::new(BareKey::Char('n')),
|
||||||
vec![Action::NewPane(None, None), TO_NORMAL],
|
vec![Action::NewPane(None, None, false), TO_NORMAL],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
KeyWithModifier::new(BareKey::Char('x')),
|
KeyWithModifier::new(BareKey::Char('x')),
|
||||||
|
|
@ -763,7 +763,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
KeyWithModifier::new(BareKey::Char('n')),
|
KeyWithModifier::new(BareKey::Char('n')),
|
||||||
vec![Action::NewPane(None, None), TO_NORMAL],
|
vec![Action::NewPane(None, None, false), TO_NORMAL],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
KeyWithModifier::new(BareKey::Char('x')),
|
KeyWithModifier::new(BareKey::Char('x')),
|
||||||
|
|
@ -809,7 +809,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
KeyWithModifier::new(BareKey::Backspace),
|
KeyWithModifier::new(BareKey::Backspace),
|
||||||
vec![Action::NewPane(None, None), TO_NORMAL],
|
vec![Action::NewPane(None, None, false), TO_NORMAL],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
KeyWithModifier::new(BareKey::Esc),
|
KeyWithModifier::new(BareKey::Esc),
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ struct Keygroups<'a> {
|
||||||
|
|
||||||
fn add_keybinds(help: &ModeInfo) -> Keygroups {
|
fn add_keybinds(help: &ModeInfo) -> Keygroups {
|
||||||
let normal_keymap = help.get_mode_keybinds();
|
let normal_keymap = help.get_mode_keybinds();
|
||||||
let new_pane_keys = action_key(&normal_keymap, &[Action::NewPane(None, None)]);
|
let new_pane_keys = action_key(&normal_keymap, &[Action::NewPane(None, None, false)]);
|
||||||
let new_pane = if new_pane_keys.is_empty() {
|
let new_pane = if new_pane_keys.is_empty() {
|
||||||
vec![Style::new().bold().paint("UNBOUND")]
|
vec![Style::new().bold().paint("UNBOUND")]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -152,9 +152,10 @@ impl State {
|
||||||
if let Some(parent_folder) = self.file_list_view.path.parent() {
|
if let Some(parent_folder) = self.file_list_view.path.parent() {
|
||||||
open_file(
|
open_file(
|
||||||
FileToOpen::new(&self.file_list_view.path).with_cwd(parent_folder.into()),
|
FileToOpen::new(&self.file_list_view.path).with_cwd(parent_folder.into()),
|
||||||
|
BTreeMap::new(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
open_file(FileToOpen::new(&self.file_list_view.path));
|
open_file(FileToOpen::new(&self.file_list_view.path), BTreeMap::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.close_on_selection {
|
if self.close_on_selection {
|
||||||
|
|
|
||||||
|
|
@ -288,10 +288,10 @@ fn spawn_terminal(
|
||||||
// secondary fd
|
// secondary fd
|
||||||
let mut failover_cmd_args = None;
|
let mut failover_cmd_args = None;
|
||||||
let cmd = match terminal_action {
|
let cmd = match terminal_action {
|
||||||
TerminalAction::OpenFile(mut file_to_open, line_number, cwd) => {
|
TerminalAction::OpenFile(mut payload) => {
|
||||||
if file_to_open.is_relative() {
|
if payload.path.is_relative() {
|
||||||
if let Some(cwd) = cwd.as_ref() {
|
if let Some(cwd) = payload.cwd.as_ref() {
|
||||||
file_to_open = cwd.join(file_to_open);
|
payload.path = cwd.join(payload.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut command = default_editor.unwrap_or_else(|| {
|
let mut command = default_editor.unwrap_or_else(|| {
|
||||||
|
|
@ -306,11 +306,12 @@ fn spawn_terminal(
|
||||||
if !command.is_dir() {
|
if !command.is_dir() {
|
||||||
separate_command_arguments(&mut command, &mut args);
|
separate_command_arguments(&mut command, &mut args);
|
||||||
}
|
}
|
||||||
let file_to_open = file_to_open
|
let file_to_open = payload
|
||||||
|
.path
|
||||||
.into_os_string()
|
.into_os_string()
|
||||||
.into_string()
|
.into_string()
|
||||||
.expect("Not valid Utf8 Encoding");
|
.expect("Not valid Utf8 Encoding");
|
||||||
if let Some(line_number) = line_number {
|
if let Some(line_number) = payload.line_number {
|
||||||
if command.ends_with("vim")
|
if command.ends_with("vim")
|
||||||
|| command.ends_with("nvim")
|
|| command.ends_with("nvim")
|
||||||
|| command.ends_with("emacs")
|
|| command.ends_with("emacs")
|
||||||
|
|
@ -334,7 +335,7 @@ fn spawn_terminal(
|
||||||
RunCommand {
|
RunCommand {
|
||||||
command,
|
command,
|
||||||
args,
|
args,
|
||||||
cwd,
|
cwd: payload.cwd,
|
||||||
hold_on_close: false,
|
hold_on_close: false,
|
||||||
hold_on_start: false,
|
hold_on_start: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -854,7 +854,7 @@ impl<'a> FloatingPaneGrid<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn half_size_middle_geom(space: &Viewport, offset: usize) -> PaneGeom {
|
pub fn half_size_middle_geom(space: &Viewport, offset: usize) -> PaneGeom {
|
||||||
let mut geom = PaneGeom {
|
let mut geom = PaneGeom {
|
||||||
x: space.x + (space.cols as f64 / 4.0).round() as usize + offset,
|
x: space.x + (space.cols as f64 / 4.0).round() as usize + offset,
|
||||||
y: space.y + (space.rows as f64 / 4.0).round() as usize + offset,
|
y: space.y + (space.rows as f64 / 4.0).round() as usize + offset,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
mod floating_pane_grid;
|
pub mod floating_pane_grid;
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
data::{Direction, PaneInfo, ResizeStrategy},
|
data::{Direction, PaneInfo, ResizeStrategy},
|
||||||
position::Position,
|
position::Position,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub mod sixel;
|
||||||
pub mod terminal_character;
|
pub mod terminal_character;
|
||||||
|
|
||||||
mod active_panes;
|
mod active_panes;
|
||||||
mod floating_panes;
|
pub mod floating_panes;
|
||||||
mod plugin_pane;
|
mod plugin_pane;
|
||||||
mod search;
|
mod search;
|
||||||
mod terminal_pane;
|
mod terminal_pane;
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,15 @@ impl From<ZellijUtilsPaneId> for PaneId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<ZellijUtilsPaneId> for PaneId {
|
||||||
|
fn into(self) -> ZellijUtilsPaneId {
|
||||||
|
match self {
|
||||||
|
PaneId::Terminal(id) => ZellijUtilsPaneId::Terminal(id),
|
||||||
|
PaneId::Plugin(id) => ZellijUtilsPaneId::Plugin(id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type IsFirstRun = bool;
|
type IsFirstRun = bool;
|
||||||
|
|
||||||
// FIXME: This should hold an os_api handle so that terminal panes can set their own size via FD in
|
// FIXME: This should hold an os_api handle so that terminal panes can set their own size via FD in
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases);
|
run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases);
|
||||||
let cwd = run_plugin_or_alias.get_initial_cwd().or(cwd);
|
let cwd = run_plugin_or_alias.get_initial_cwd().or(cwd);
|
||||||
let run_plugin = run_plugin_or_alias.get_run_plugin();
|
let run_plugin = run_plugin_or_alias.get_run_plugin();
|
||||||
|
let start_suppressed = false;
|
||||||
match wasm_bridge.load_plugin(
|
match wasm_bridge.load_plugin(
|
||||||
&run_plugin,
|
&run_plugin,
|
||||||
Some(tab_index),
|
Some(tab_index),
|
||||||
|
|
@ -268,6 +269,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
plugin_id,
|
plugin_id,
|
||||||
pane_id_to_replace,
|
pane_id_to_replace,
|
||||||
cwd,
|
cwd,
|
||||||
|
start_suppressed,
|
||||||
Some(client_id),
|
Some(client_id),
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
|
|
@ -307,6 +309,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
// we intentionally do not provide the client_id here because it belongs to
|
// we intentionally do not provide the client_id here because it belongs to
|
||||||
// the cli who spawned the command and is not an existing client_id
|
// the cli who spawned the command and is not an existing client_id
|
||||||
let skip_cache = true; // when reloading we always skip cache
|
let skip_cache = true; // when reloading we always skip cache
|
||||||
|
let start_suppressed = false;
|
||||||
match wasm_bridge.load_plugin(
|
match wasm_bridge.load_plugin(
|
||||||
&Some(run_plugin),
|
&Some(run_plugin),
|
||||||
Some(tab_index),
|
Some(tab_index),
|
||||||
|
|
@ -328,6 +331,7 @@ pub(crate) fn plugin_thread_main(
|
||||||
plugin_id,
|
plugin_id,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
start_suppressed,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
@ -365,6 +369,16 @@ pub(crate) fn plugin_thread_main(
|
||||||
tab_index,
|
tab_index,
|
||||||
client_id,
|
client_id,
|
||||||
) => {
|
) => {
|
||||||
|
// prefer connected clients so as to avoid opening plugins in the background for
|
||||||
|
// CLI clients unless no-one else is connected
|
||||||
|
let client_id = if wasm_bridge.client_is_connected(&client_id) {
|
||||||
|
client_id
|
||||||
|
} else if let Some(first_client_id) = wasm_bridge.get_first_client_id() {
|
||||||
|
first_client_id
|
||||||
|
} else {
|
||||||
|
client_id
|
||||||
|
};
|
||||||
|
|
||||||
let mut plugin_ids: HashMap<RunPluginOrAlias, Vec<PluginId>> = HashMap::new();
|
let mut plugin_ids: HashMap<RunPluginOrAlias, Vec<PluginId>> = HashMap::new();
|
||||||
tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0));
|
tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0));
|
||||||
tab_layout
|
tab_layout
|
||||||
|
|
|
||||||
|
|
@ -6655,3 +6655,223 @@ pub fn run_plugin_in_specific_cwd() {
|
||||||
"File written into plugin initial cwd"
|
"File written into plugin initial cwd"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
pub fn hide_pane_with_id_plugin_command() {
|
||||||
|
let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its
|
||||||
|
// destructor removes the directory
|
||||||
|
let plugin_host_folder = PathBuf::from(temp_folder.path());
|
||||||
|
let cache_path = plugin_host_folder.join("permissions_test.kdl");
|
||||||
|
let (plugin_thread_sender, screen_receiver, teardown) =
|
||||||
|
create_plugin_thread(Some(plugin_host_folder));
|
||||||
|
let plugin_should_float = Some(false);
|
||||||
|
let plugin_title = Some("test_plugin".to_owned());
|
||||||
|
let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
|
||||||
|
configuration: Default::default(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
let tab_index = 1;
|
||||||
|
let client_id = 1;
|
||||||
|
let size = Size {
|
||||||
|
cols: 121,
|
||||||
|
rows: 20,
|
||||||
|
};
|
||||||
|
let received_screen_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let screen_thread = grant_permissions_and_log_actions_in_thread!(
|
||||||
|
received_screen_instructions,
|
||||||
|
ScreenInstruction::SuppressPane,
|
||||||
|
screen_receiver,
|
||||||
|
1,
|
||||||
|
&PermissionType::ChangeApplicationState,
|
||||||
|
cache_path,
|
||||||
|
plugin_thread_sender,
|
||||||
|
client_id
|
||||||
|
);
|
||||||
|
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::Load(
|
||||||
|
plugin_should_float,
|
||||||
|
false,
|
||||||
|
plugin_title,
|
||||||
|
run_plugin,
|
||||||
|
tab_index,
|
||||||
|
None,
|
||||||
|
client_id,
|
||||||
|
size,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
|
||||||
|
None,
|
||||||
|
Some(client_id),
|
||||||
|
Event::Key(KeyWithModifier::new(BareKey::Char('a')).with_alt_modifier()), // this triggers the enent in the fixture plugin
|
||||||
|
)]));
|
||||||
|
screen_thread.join().unwrap(); // this might take a while if the cache is cold
|
||||||
|
teardown();
|
||||||
|
let suppress_pane_event = received_screen_instructions
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.find_map(|i| {
|
||||||
|
if let ScreenInstruction::SuppressPane(..) = i {
|
||||||
|
Some(i.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.clone();
|
||||||
|
assert_snapshot!(format!("{:#?}", suppress_pane_event));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
pub fn show_pane_with_id_plugin_command() {
|
||||||
|
let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its
|
||||||
|
// destructor removes the directory
|
||||||
|
let plugin_host_folder = PathBuf::from(temp_folder.path());
|
||||||
|
let cache_path = plugin_host_folder.join("permissions_test.kdl");
|
||||||
|
let (plugin_thread_sender, screen_receiver, teardown) =
|
||||||
|
create_plugin_thread(Some(plugin_host_folder));
|
||||||
|
let plugin_should_float = Some(false);
|
||||||
|
let plugin_title = Some("test_plugin".to_owned());
|
||||||
|
let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
|
||||||
|
configuration: Default::default(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
let tab_index = 1;
|
||||||
|
let client_id = 1;
|
||||||
|
let size = Size {
|
||||||
|
cols: 121,
|
||||||
|
rows: 20,
|
||||||
|
};
|
||||||
|
let received_screen_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let screen_thread = grant_permissions_and_log_actions_in_thread!(
|
||||||
|
received_screen_instructions,
|
||||||
|
ScreenInstruction::FocusPaneWithId,
|
||||||
|
screen_receiver,
|
||||||
|
1,
|
||||||
|
&PermissionType::ChangeApplicationState,
|
||||||
|
cache_path,
|
||||||
|
plugin_thread_sender,
|
||||||
|
client_id
|
||||||
|
);
|
||||||
|
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::Load(
|
||||||
|
plugin_should_float,
|
||||||
|
false,
|
||||||
|
plugin_title,
|
||||||
|
run_plugin,
|
||||||
|
tab_index,
|
||||||
|
None,
|
||||||
|
client_id,
|
||||||
|
size,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
|
||||||
|
None,
|
||||||
|
Some(client_id),
|
||||||
|
Event::Key(KeyWithModifier::new(BareKey::Char('b')).with_alt_modifier()), // this triggers the enent in the fixture plugin
|
||||||
|
)]));
|
||||||
|
screen_thread.join().unwrap(); // this might take a while if the cache is cold
|
||||||
|
teardown();
|
||||||
|
let focus_pane_event = received_screen_instructions
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.find_map(|i| {
|
||||||
|
if let ScreenInstruction::FocusPaneWithId(..) = i {
|
||||||
|
Some(i.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.clone();
|
||||||
|
assert_snapshot!(format!("{:#?}", focus_pane_event));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
pub fn open_command_pane_background_plugin_command() {
|
||||||
|
let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its
|
||||||
|
// destructor removes the directory
|
||||||
|
let plugin_host_folder = PathBuf::from(temp_folder.path());
|
||||||
|
let cache_path = plugin_host_folder.join("permissions_test.kdl");
|
||||||
|
let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) =
|
||||||
|
create_plugin_thread_with_pty_receiver(Some(plugin_host_folder));
|
||||||
|
let plugin_should_float = Some(false);
|
||||||
|
let plugin_title = Some("test_plugin".to_owned());
|
||||||
|
let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin {
|
||||||
|
_allow_exec_host_cmd: false,
|
||||||
|
location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
|
||||||
|
configuration: Default::default(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
let tab_index = 1;
|
||||||
|
let client_id = 1;
|
||||||
|
let size = Size {
|
||||||
|
cols: 121,
|
||||||
|
rows: 20,
|
||||||
|
};
|
||||||
|
let received_pty_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let pty_thread = log_actions_in_thread!(
|
||||||
|
received_pty_instructions,
|
||||||
|
PtyInstruction::SpawnTerminal,
|
||||||
|
pty_receiver,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
let received_screen_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!(
|
||||||
|
received_screen_instructions,
|
||||||
|
ScreenInstruction::Exit,
|
||||||
|
screen_receiver,
|
||||||
|
1,
|
||||||
|
&PermissionType::ChangeApplicationState,
|
||||||
|
cache_path,
|
||||||
|
plugin_thread_sender,
|
||||||
|
client_id
|
||||||
|
);
|
||||||
|
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::Load(
|
||||||
|
plugin_should_float,
|
||||||
|
false,
|
||||||
|
plugin_title,
|
||||||
|
run_plugin,
|
||||||
|
tab_index,
|
||||||
|
None,
|
||||||
|
client_id,
|
||||||
|
size,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||||
|
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
|
||||||
|
None,
|
||||||
|
Some(client_id),
|
||||||
|
Event::Key(KeyWithModifier::new(BareKey::Char('c')).with_alt_modifier()), // this triggers the enent in the fixture plugin
|
||||||
|
)]));
|
||||||
|
pty_thread.join().unwrap(); // this might take a while if the cache is cold
|
||||||
|
teardown();
|
||||||
|
let new_tab_event = received_pty_instructions
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.find_map(|i| {
|
||||||
|
if let PtyInstruction::SpawnTerminal(..) = i {
|
||||||
|
Some(i.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.clone();
|
||||||
|
assert_snapshot!(format!("{:#?}", new_tab_event));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
|
assertion_line: 6727
|
||||||
|
expression: "format!(\"{:#?}\", suppress_pane_event)"
|
||||||
|
---
|
||||||
|
Some(
|
||||||
|
SuppressPane(
|
||||||
|
Terminal(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
|
assertion_line: 6876
|
||||||
|
expression: "format!(\"{:#?}\", new_tab_event)"
|
||||||
|
---
|
||||||
|
Some(
|
||||||
|
SpawnTerminal(
|
||||||
|
Some(
|
||||||
|
RunCommand(
|
||||||
|
RunCommand {
|
||||||
|
command: "/path/to/my/file.rs",
|
||||||
|
args: [
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
],
|
||||||
|
cwd: None,
|
||||||
|
hold_on_close: true,
|
||||||
|
hold_on_start: false,
|
||||||
|
originating_plugin: Some(
|
||||||
|
OriginatingPlugin {
|
||||||
|
plugin_id: 0,
|
||||||
|
client_id: 1,
|
||||||
|
context: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
ClientId(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -31,6 +31,7 @@ Some(
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ Some(
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,26 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 3846
|
assertion_line: 3996
|
||||||
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
SpawnTerminal(
|
SpawnTerminal(
|
||||||
Some(
|
Some(
|
||||||
OpenFile(
|
OpenFile(
|
||||||
"/path/to/my/file.rs",
|
OpenFilePayload {
|
||||||
None,
|
path: "/path/to/my/file.rs",
|
||||||
Some(
|
line_number: None,
|
||||||
"CWD",
|
cwd: Some(
|
||||||
),
|
"CWD",
|
||||||
|
),
|
||||||
|
originating_plugin: Some(
|
||||||
|
OriginatingPlugin {
|
||||||
|
plugin_id: 0,
|
||||||
|
client_id: 1,
|
||||||
|
context: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -21,6 +30,7 @@ Some(
|
||||||
"Editing: /path/to/my/file.rs",
|
"Editing: /path/to/my/file.rs",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,26 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 3927
|
assertion_line: 4078
|
||||||
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
SpawnTerminal(
|
SpawnTerminal(
|
||||||
Some(
|
Some(
|
||||||
OpenFile(
|
OpenFile(
|
||||||
"/path/to/my/file.rs",
|
OpenFilePayload {
|
||||||
None,
|
path: "/path/to/my/file.rs",
|
||||||
Some(
|
line_number: None,
|
||||||
"CWD",
|
cwd: Some(
|
||||||
),
|
"CWD",
|
||||||
|
),
|
||||||
|
originating_plugin: Some(
|
||||||
|
OriginatingPlugin {
|
||||||
|
plugin_id: 0,
|
||||||
|
client_id: 1,
|
||||||
|
context: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -21,6 +30,7 @@ Some(
|
||||||
"Editing: /path/to/my/file.rs",
|
"Editing: /path/to/my/file.rs",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,28 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 4090
|
assertion_line: 4243
|
||||||
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
SpawnTerminal(
|
SpawnTerminal(
|
||||||
Some(
|
Some(
|
||||||
OpenFile(
|
OpenFile(
|
||||||
"/path/to/my/file.rs",
|
OpenFilePayload {
|
||||||
Some(
|
path: "/path/to/my/file.rs",
|
||||||
42,
|
line_number: Some(
|
||||||
),
|
42,
|
||||||
Some(
|
),
|
||||||
"CWD",
|
cwd: Some(
|
||||||
),
|
"CWD",
|
||||||
|
),
|
||||||
|
originating_plugin: Some(
|
||||||
|
OriginatingPlugin {
|
||||||
|
plugin_id: 0,
|
||||||
|
client_id: 1,
|
||||||
|
context: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -23,6 +32,7 @@ Some(
|
||||||
"Editing: /path/to/my/file.rs",
|
"Editing: /path/to/my/file.rs",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,28 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
assertion_line: 4009
|
assertion_line: 4161
|
||||||
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")"
|
||||||
---
|
---
|
||||||
Some(
|
Some(
|
||||||
SpawnTerminal(
|
SpawnTerminal(
|
||||||
Some(
|
Some(
|
||||||
OpenFile(
|
OpenFile(
|
||||||
"/path/to/my/file.rs",
|
OpenFilePayload {
|
||||||
Some(
|
path: "/path/to/my/file.rs",
|
||||||
42,
|
line_number: Some(
|
||||||
),
|
42,
|
||||||
Some(
|
),
|
||||||
"CWD",
|
cwd: Some(
|
||||||
),
|
"CWD",
|
||||||
|
),
|
||||||
|
originating_plugin: Some(
|
||||||
|
OriginatingPlugin {
|
||||||
|
plugin_id: 0,
|
||||||
|
client_id: 1,
|
||||||
|
context: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -23,6 +32,7 @@ Some(
|
||||||
"Editing: /path/to/my/file.rs",
|
"Editing: /path/to/my/file.rs",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ Some(
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ Some(
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientId(
|
ClientId(
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||||
|
assertion_line: 6798
|
||||||
|
expression: "format!(\"{:#?}\", focus_pane_event)"
|
||||||
|
---
|
||||||
|
Some(
|
||||||
|
FocusPaneWithId(
|
||||||
|
Terminal(
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -1193,6 +1193,7 @@ impl WasmBridge {
|
||||||
cli_client_id,
|
cli_client_id,
|
||||||
) {
|
) {
|
||||||
Ok((plugin_id, client_id)) => {
|
Ok((plugin_id, client_id)) => {
|
||||||
|
let start_suppressed = false;
|
||||||
drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
||||||
Some(should_float),
|
Some(should_float),
|
||||||
should_be_open_in_place,
|
should_be_open_in_place,
|
||||||
|
|
@ -1202,6 +1203,7 @@ impl WasmBridge {
|
||||||
plugin_id,
|
plugin_id,
|
||||||
pane_id_to_replace,
|
pane_id_to_replace,
|
||||||
cwd,
|
cwd,
|
||||||
|
start_suppressed,
|
||||||
Some(client_id),
|
Some(client_id),
|
||||||
)));
|
)));
|
||||||
vec![(plugin_id, Some(client_id))]
|
vec![(plugin_id, Some(client_id))]
|
||||||
|
|
@ -1268,6 +1270,17 @@ impl WasmBridge {
|
||||||
|| (message_cid.is_none() && message_pid == Some(*plugin_id))
|
|| (message_cid.is_none() && message_pid == Some(*plugin_id))
|
||||||
|| (message_cid == Some(*client_id) && message_pid == Some(*plugin_id))
|
|| (message_cid == Some(*client_id) && message_pid == Some(*plugin_id))
|
||||||
}
|
}
|
||||||
|
pub fn client_is_connected(&self, client_id: &ClientId) -> bool {
|
||||||
|
self.connected_clients.lock().unwrap().contains(client_id)
|
||||||
|
}
|
||||||
|
pub fn get_first_client_id(&self) -> Option<ClientId> {
|
||||||
|
self.connected_clients
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_plugin_successful_loading(senders: &ThreadSenders, plugin_id: PluginId) {
|
fn handle_plugin_successful_loading(senders: &ThreadSenders, plugin_id: PluginId) {
|
||||||
|
|
@ -1316,6 +1329,9 @@ fn check_event_permission(
|
||||||
| Event::SystemClipboardFailure
|
| Event::SystemClipboardFailure
|
||||||
| Event::CommandPaneOpened(..)
|
| Event::CommandPaneOpened(..)
|
||||||
| Event::CommandPaneExited(..)
|
| Event::CommandPaneExited(..)
|
||||||
|
| Event::PaneClosed(..)
|
||||||
|
| Event::EditPaneOpened(..)
|
||||||
|
| Event::EditPaneExited(..)
|
||||||
| Event::InputReceived => PermissionType::ReadApplicationState,
|
| Event::InputReceived => PermissionType::ReadApplicationState,
|
||||||
_ => return (PermissionStatus::Granted, None),
|
_ => return (PermissionStatus::Granted, None),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use super::PluginInstruction;
|
||||||
use crate::background_jobs::BackgroundJob;
|
use crate::background_jobs::BackgroundJob;
|
||||||
use crate::plugins::plugin_map::PluginEnv;
|
use crate::plugins::plugin_map::PluginEnv;
|
||||||
use crate::plugins::wasm_bridge::handle_plugin_crash;
|
use crate::plugins::wasm_bridge::handle_plugin_crash;
|
||||||
|
use crate::pty::{ClientTabIndexOrPaneId, PtyInstruction};
|
||||||
use crate::route::route_action;
|
use crate::route::route_action;
|
||||||
use crate::ServerInstruction;
|
use crate::ServerInstruction;
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
|
|
@ -22,6 +23,7 @@ use zellij_utils::data::{
|
||||||
};
|
};
|
||||||
use zellij_utils::input::permission::PermissionCache;
|
use zellij_utils::input::permission::PermissionCache;
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
|
async_std::task,
|
||||||
interprocess::local_socket::LocalSocketStream,
|
interprocess::local_socket::LocalSocketStream,
|
||||||
ipc::{ClientToServerMsg, IpcSenderWithContext},
|
ipc::{ClientToServerMsg, IpcSenderWithContext},
|
||||||
};
|
};
|
||||||
|
|
@ -37,7 +39,7 @@ use zellij_utils::{
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
input::{
|
input::{
|
||||||
actions::Action,
|
actions::Action,
|
||||||
command::{RunCommand, RunCommandAction, TerminalAction},
|
command::{OpenFilePayload, RunCommand, RunCommandAction, TerminalAction},
|
||||||
layout::{Layout, RunPluginOrAlias},
|
layout::{Layout, RunPluginOrAlias},
|
||||||
plugins::PluginType,
|
plugins::PluginType,
|
||||||
},
|
},
|
||||||
|
|
@ -91,10 +93,14 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
|
||||||
PluginCommand::SetSelectable(selectable) => set_selectable(env, selectable),
|
PluginCommand::SetSelectable(selectable) => set_selectable(env, selectable),
|
||||||
PluginCommand::GetPluginIds => get_plugin_ids(env),
|
PluginCommand::GetPluginIds => get_plugin_ids(env),
|
||||||
PluginCommand::GetZellijVersion => get_zellij_version(env),
|
PluginCommand::GetZellijVersion => get_zellij_version(env),
|
||||||
PluginCommand::OpenFile(file_to_open) => open_file(env, file_to_open),
|
PluginCommand::OpenFile(file_to_open, context) => {
|
||||||
PluginCommand::OpenFileFloating(file_to_open, floating_pane_coordinates) => {
|
open_file(env, file_to_open, context)
|
||||||
open_file_floating(env, file_to_open, floating_pane_coordinates)
|
|
||||||
},
|
},
|
||||||
|
PluginCommand::OpenFileFloating(
|
||||||
|
file_to_open,
|
||||||
|
floating_pane_coordinates,
|
||||||
|
context,
|
||||||
|
) => open_file_floating(env, file_to_open, floating_pane_coordinates, context),
|
||||||
PluginCommand::OpenTerminal(cwd) => open_terminal(env, cwd.path.try_into()?),
|
PluginCommand::OpenTerminal(cwd) => open_terminal(env, cwd.path.try_into()?),
|
||||||
PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => {
|
PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => {
|
||||||
open_terminal_floating(env, cwd.path.try_into()?, floating_pane_coordinates)
|
open_terminal_floating(env, cwd.path.try_into()?, floating_pane_coordinates)
|
||||||
|
|
@ -221,8 +227,8 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
|
||||||
delete_dead_session(session_name)?
|
delete_dead_session(session_name)?
|
||||||
},
|
},
|
||||||
PluginCommand::DeleteAllDeadSessions => delete_all_dead_sessions()?,
|
PluginCommand::DeleteAllDeadSessions => delete_all_dead_sessions()?,
|
||||||
PluginCommand::OpenFileInPlace(file_to_open) => {
|
PluginCommand::OpenFileInPlace(file_to_open, context) => {
|
||||||
open_file_in_place(env, file_to_open)
|
open_file_in_place(env, file_to_open, context)
|
||||||
},
|
},
|
||||||
PluginCommand::OpenTerminalInPlace(cwd) => {
|
PluginCommand::OpenTerminalInPlace(cwd) => {
|
||||||
open_terminal_in_place(env, cwd.path.try_into()?)
|
open_terminal_in_place(env, cwd.path.try_into()?)
|
||||||
|
|
@ -258,6 +264,9 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
|
||||||
PluginCommand::ShowPaneWithId(pane_id, should_float_if_hidden) => {
|
PluginCommand::ShowPaneWithId(pane_id, should_float_if_hidden) => {
|
||||||
show_pane_with_id(env, pane_id.into(), should_float_if_hidden)
|
show_pane_with_id(env, pane_id.into(), should_float_if_hidden)
|
||||||
},
|
},
|
||||||
|
PluginCommand::OpenCommandPaneBackground(command_to_run, context) => {
|
||||||
|
open_command_pane_background(env, command_to_run, context)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
(PermissionStatus::Denied, permission) => {
|
(PermissionStatus::Denied, permission) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|
@ -355,6 +364,7 @@ fn request_permission(env: &PluginEnv, permissions: Vec<PermissionType>) -> Resu
|
||||||
if PermissionCache::from_path_or_default(None)
|
if PermissionCache::from_path_or_default(None)
|
||||||
.check_permissions(env.plugin.location.to_string(), &permissions)
|
.check_permissions(env.plugin.location.to_string(), &permissions)
|
||||||
{
|
{
|
||||||
|
log::info!("PermissionRequestResult 1");
|
||||||
return env
|
return env
|
||||||
.senders
|
.senders
|
||||||
.send_to_plugin(PluginInstruction::PermissionRequestResult(
|
.send_to_plugin(PluginInstruction::PermissionRequestResult(
|
||||||
|
|
@ -416,22 +426,24 @@ fn get_zellij_version(env: &PluginEnv) {
|
||||||
.non_fatal();
|
.non_fatal();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_file(env: &PluginEnv, file_to_open: FileToOpen) {
|
fn open_file(env: &PluginEnv, file_to_open: FileToOpen, context: BTreeMap<String, String>) {
|
||||||
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
||||||
let floating = false;
|
let floating = false;
|
||||||
let in_place = false;
|
let in_place = false;
|
||||||
|
let start_suppressed = false;
|
||||||
let path = env.plugin_cwd.join(file_to_open.path);
|
let path = env.plugin_cwd.join(file_to_open.path);
|
||||||
let cwd = file_to_open
|
let cwd = file_to_open
|
||||||
.cwd
|
.cwd
|
||||||
.map(|cwd| env.plugin_cwd.join(cwd))
|
.map(|cwd| env.plugin_cwd.join(cwd))
|
||||||
.or_else(|| Some(env.plugin_cwd.clone()));
|
.or_else(|| Some(env.plugin_cwd.clone()));
|
||||||
let action = Action::EditFile(
|
let action = Action::EditFile(
|
||||||
path,
|
OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin(
|
||||||
file_to_open.line_number,
|
OriginatingPlugin::new(env.plugin_id, env.client_id, context),
|
||||||
cwd,
|
),
|
||||||
None,
|
None,
|
||||||
floating,
|
floating,
|
||||||
in_place,
|
in_place,
|
||||||
|
start_suppressed,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
apply_action!(action, error_msg, env);
|
apply_action!(action, error_msg, env);
|
||||||
|
|
@ -441,31 +453,39 @@ fn open_file_floating(
|
||||||
env: &PluginEnv,
|
env: &PluginEnv,
|
||||||
file_to_open: FileToOpen,
|
file_to_open: FileToOpen,
|
||||||
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
|
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
|
||||||
|
context: BTreeMap<String, String>,
|
||||||
) {
|
) {
|
||||||
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
||||||
let floating = true;
|
let floating = true;
|
||||||
let in_place = false;
|
let in_place = false;
|
||||||
|
let start_suppressed = false;
|
||||||
let path = env.plugin_cwd.join(file_to_open.path);
|
let path = env.plugin_cwd.join(file_to_open.path);
|
||||||
let cwd = file_to_open
|
let cwd = file_to_open
|
||||||
.cwd
|
.cwd
|
||||||
.map(|cwd| env.plugin_cwd.join(cwd))
|
.map(|cwd| env.plugin_cwd.join(cwd))
|
||||||
.or_else(|| Some(env.plugin_cwd.clone()));
|
.or_else(|| Some(env.plugin_cwd.clone()));
|
||||||
let action = Action::EditFile(
|
let action = Action::EditFile(
|
||||||
path,
|
OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin(
|
||||||
file_to_open.line_number,
|
OriginatingPlugin::new(env.plugin_id, env.client_id, context),
|
||||||
cwd,
|
),
|
||||||
None,
|
None,
|
||||||
floating,
|
floating,
|
||||||
in_place,
|
in_place,
|
||||||
|
start_suppressed,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
);
|
);
|
||||||
apply_action!(action, error_msg, env);
|
apply_action!(action, error_msg, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_file_in_place(env: &PluginEnv, file_to_open: FileToOpen) {
|
fn open_file_in_place(
|
||||||
|
env: &PluginEnv,
|
||||||
|
file_to_open: FileToOpen,
|
||||||
|
context: BTreeMap<String, String>,
|
||||||
|
) {
|
||||||
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
||||||
let floating = false;
|
let floating = false;
|
||||||
let in_place = true;
|
let in_place = true;
|
||||||
|
let start_suppressed = false;
|
||||||
let path = env.plugin_cwd.join(file_to_open.path);
|
let path = env.plugin_cwd.join(file_to_open.path);
|
||||||
let cwd = file_to_open
|
let cwd = file_to_open
|
||||||
.cwd
|
.cwd
|
||||||
|
|
@ -473,12 +493,13 @@ fn open_file_in_place(env: &PluginEnv, file_to_open: FileToOpen) {
|
||||||
.or_else(|| Some(env.plugin_cwd.clone()));
|
.or_else(|| Some(env.plugin_cwd.clone()));
|
||||||
|
|
||||||
let action = Action::EditFile(
|
let action = Action::EditFile(
|
||||||
path,
|
OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin(
|
||||||
file_to_open.line_number,
|
OriginatingPlugin::new(env.plugin_id, env.client_id, context),
|
||||||
cwd,
|
),
|
||||||
None,
|
None,
|
||||||
floating,
|
floating,
|
||||||
in_place,
|
in_place,
|
||||||
|
start_suppressed,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
apply_action!(action, error_msg, env);
|
apply_action!(action, error_msg, env);
|
||||||
|
|
@ -633,6 +654,43 @@ fn open_command_pane_in_place(
|
||||||
apply_action!(action, error_msg, env);
|
apply_action!(action, error_msg, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open_command_pane_background(
|
||||||
|
env: &PluginEnv,
|
||||||
|
command_to_run: CommandToRun,
|
||||||
|
context: BTreeMap<String, String>,
|
||||||
|
) {
|
||||||
|
let command = command_to_run.path;
|
||||||
|
let cwd = command_to_run.cwd.map(|cwd| env.plugin_cwd.join(cwd));
|
||||||
|
let args = command_to_run.args;
|
||||||
|
let direction = None;
|
||||||
|
let hold_on_close = true;
|
||||||
|
let hold_on_start = false;
|
||||||
|
let start_suppressed = true;
|
||||||
|
let name = None;
|
||||||
|
let run_command_action = RunCommandAction {
|
||||||
|
command,
|
||||||
|
args,
|
||||||
|
cwd,
|
||||||
|
direction,
|
||||||
|
hold_on_close,
|
||||||
|
hold_on_start,
|
||||||
|
originating_plugin: Some(OriginatingPlugin::new(
|
||||||
|
env.plugin_id,
|
||||||
|
env.client_id,
|
||||||
|
context,
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
let run_cmd = TerminalAction::RunCommand(run_command_action.into());
|
||||||
|
let _ = env.senders.send_to_pty(PtyInstruction::SpawnTerminal(
|
||||||
|
Some(run_cmd),
|
||||||
|
None,
|
||||||
|
name,
|
||||||
|
None,
|
||||||
|
start_suppressed,
|
||||||
|
ClientTabIndexOrPaneId::ClientId(env.client_id),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
fn switch_tab_to(env: &PluginEnv, tab_idx: u32) {
|
fn switch_tab_to(env: &PluginEnv, tab_idx: u32) {
|
||||||
env.senders
|
env.senders
|
||||||
.send_to_screen(ScreenInstruction::GoToTab(tab_idx, Some(env.client_id)))
|
.send_to_screen(ScreenInstruction::GoToTab(tab_idx, Some(env.client_id)))
|
||||||
|
|
@ -646,23 +704,13 @@ fn switch_tab_to(env: &PluginEnv, tab_idx: u32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_timeout(env: &PluginEnv, secs: f64) {
|
fn set_timeout(env: &PluginEnv, secs: f64) {
|
||||||
// There is a fancy, high-performance way to do this with zero additional threads:
|
|
||||||
// If the plugin thread keeps a BinaryHeap of timer structs, it can manage multiple and easily `.peek()` at the
|
|
||||||
// next time to trigger in O(1) time. Once the wake-up time is known, the `wasm` thread can use `recv_timeout()`
|
|
||||||
// to wait for an event with the timeout set to be the time of the next wake up. If events come in in the meantime,
|
|
||||||
// they are handled, but if the timeout triggers, we replace the event from `recv()` with an
|
|
||||||
// `Update(pid, TimerEvent)` and pop the timer from the Heap (or reschedule it). No additional threads for as many
|
|
||||||
// timers as we'd like.
|
|
||||||
//
|
|
||||||
// But that's a lot of code, and this is a few lines:
|
|
||||||
let send_plugin_instructions = env.senders.to_plugin.clone();
|
let send_plugin_instructions = env.senders.to_plugin.clone();
|
||||||
let update_target = Some(env.plugin_id);
|
let update_target = Some(env.plugin_id);
|
||||||
let client_id = env.client_id;
|
let client_id = env.client_id;
|
||||||
let plugin_name = env.name();
|
let plugin_name = env.name();
|
||||||
// TODO: we should really use an async task for this
|
task::spawn(async move {
|
||||||
thread::spawn(move || {
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
thread::sleep(Duration::from_secs_f64(secs));
|
task::sleep(Duration::from_secs_f64(secs)).await;
|
||||||
// FIXME: The way that elapsed time is being calculated here is not exact; it doesn't take into account the
|
// FIXME: The way that elapsed time is being calculated here is not exact; it doesn't take into account the
|
||||||
// time it takes an event to actually reach the plugin after it's sent to the `wasm` thread.
|
// time it takes an event to actually reach the plugin after it's sent to the `wasm` thread.
|
||||||
let elapsed_time = Instant::now().duration_since(start_time).as_secs_f64();
|
let elapsed_time = Instant::now().duration_since(start_time).as_secs_f64();
|
||||||
|
|
@ -1446,6 +1494,7 @@ fn check_command_permission(
|
||||||
PluginCommand::OpenCommandPane(..)
|
PluginCommand::OpenCommandPane(..)
|
||||||
| PluginCommand::OpenCommandPaneFloating(..)
|
| PluginCommand::OpenCommandPaneFloating(..)
|
||||||
| PluginCommand::OpenCommandPaneInPlace(..)
|
| PluginCommand::OpenCommandPaneInPlace(..)
|
||||||
|
| PluginCommand::OpenCommandPaneBackground(..)
|
||||||
| PluginCommand::RunCommand(..)
|
| PluginCommand::RunCommand(..)
|
||||||
| PluginCommand::ExecCmd(..) => PermissionType::RunCommands,
|
| PluginCommand::ExecCmd(..) => PermissionType::RunCommands,
|
||||||
PluginCommand::WebRequest(..) => PermissionType::WebAccess,
|
PluginCommand::WebRequest(..) => PermissionType::WebAccess,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use zellij_utils::{
|
||||||
errors::prelude::*,
|
errors::prelude::*,
|
||||||
errors::{ContextType, PtyContext},
|
errors::{ContextType, PtyContext},
|
||||||
input::{
|
input::{
|
||||||
command::{RunCommand, TerminalAction},
|
command::{OpenFilePayload, RunCommand, TerminalAction},
|
||||||
layout::{FloatingPaneLayout, Layout, Run, RunPluginOrAlias, TiledPaneLayout},
|
layout::{FloatingPaneLayout, Layout, Run, RunPluginOrAlias, TiledPaneLayout},
|
||||||
},
|
},
|
||||||
pane_size::Size,
|
pane_size::Size,
|
||||||
|
|
@ -43,6 +43,7 @@ pub enum PtyInstruction {
|
||||||
Option<bool>,
|
Option<bool>,
|
||||||
Option<String>,
|
Option<String>,
|
||||||
Option<FloatingPaneCoordinates>,
|
Option<FloatingPaneCoordinates>,
|
||||||
|
bool, // start suppressed
|
||||||
ClientTabIndexOrPaneId,
|
ClientTabIndexOrPaneId,
|
||||||
), // bool (if Some) is
|
), // bool (if Some) is
|
||||||
// should_float, String is an optional pane name
|
// should_float, String is an optional pane name
|
||||||
|
|
@ -50,6 +51,7 @@ pub enum PtyInstruction {
|
||||||
SpawnTerminalVertically(Option<TerminalAction>, Option<String>, ClientId), // String is an
|
SpawnTerminalVertically(Option<TerminalAction>, Option<String>, ClientId), // String is an
|
||||||
// optional pane
|
// optional pane
|
||||||
// name
|
// name
|
||||||
|
// bool is start_suppressed
|
||||||
SpawnTerminalHorizontally(Option<TerminalAction>, Option<String>, ClientId), // String is an
|
SpawnTerminalHorizontally(Option<TerminalAction>, Option<String>, ClientId), // String is an
|
||||||
// optional pane
|
// optional pane
|
||||||
// name
|
// name
|
||||||
|
|
@ -141,29 +143,36 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
should_float,
|
should_float,
|
||||||
name,
|
name,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
client_or_tab_index,
|
client_or_tab_index,
|
||||||
) => {
|
) => {
|
||||||
let err_context =
|
let err_context =
|
||||||
|| format!("failed to spawn terminal for {:?}", client_or_tab_index);
|
|| format!("failed to spawn terminal for {:?}", client_or_tab_index);
|
||||||
|
|
||||||
let (hold_on_close, run_command, pane_title) = match &terminal_action {
|
let (hold_on_close, run_command, pane_title, open_file_payload) =
|
||||||
Some(TerminalAction::RunCommand(run_command)) => (
|
|
||||||
run_command.hold_on_close,
|
|
||||||
Some(run_command.clone()),
|
|
||||||
Some(name.unwrap_or_else(|| run_command.to_string())),
|
|
||||||
),
|
|
||||||
_ => (false, None, name),
|
|
||||||
};
|
|
||||||
let invoked_with =
|
|
||||||
match &terminal_action {
|
match &terminal_action {
|
||||||
Some(TerminalAction::RunCommand(run_command)) => {
|
Some(TerminalAction::RunCommand(run_command)) => (
|
||||||
Some(Run::Command(run_command.clone()))
|
run_command.hold_on_close,
|
||||||
},
|
Some(run_command.clone()),
|
||||||
Some(TerminalAction::OpenFile(file, line_number, cwd)) => Some(
|
Some(name.unwrap_or_else(|| run_command.to_string())),
|
||||||
Run::EditFile(file.clone(), line_number.clone(), cwd.clone()),
|
None,
|
||||||
),
|
),
|
||||||
_ => None,
|
Some(TerminalAction::OpenFile(open_file_payload)) => {
|
||||||
|
(false, None, name, Some(open_file_payload.clone()))
|
||||||
|
},
|
||||||
|
_ => (false, None, name, None),
|
||||||
};
|
};
|
||||||
|
let invoked_with = match &terminal_action {
|
||||||
|
Some(TerminalAction::RunCommand(run_command)) => {
|
||||||
|
Some(Run::Command(run_command.clone()))
|
||||||
|
},
|
||||||
|
Some(TerminalAction::OpenFile(payload)) => Some(Run::EditFile(
|
||||||
|
payload.path.clone(),
|
||||||
|
payload.line_number.clone(),
|
||||||
|
payload.cwd.clone(),
|
||||||
|
)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
match pty
|
match pty
|
||||||
.spawn_terminal(terminal_action, client_or_tab_index)
|
.spawn_terminal(terminal_action, client_or_tab_index)
|
||||||
.with_context(err_context)
|
.with_context(err_context)
|
||||||
|
|
@ -191,6 +200,20 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
)]))
|
)]))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
}
|
}
|
||||||
|
if let Some(originating_plugin) =
|
||||||
|
open_file_payload.and_then(|o| o.originating_plugin)
|
||||||
|
{
|
||||||
|
let update_event =
|
||||||
|
Event::EditPaneOpened(pid, originating_plugin.context.clone());
|
||||||
|
pty.bus
|
||||||
|
.senders
|
||||||
|
.send_to_plugin(PluginInstruction::Update(vec![(
|
||||||
|
Some(originating_plugin.plugin_id),
|
||||||
|
Some(originating_plugin.client_id),
|
||||||
|
update_event,
|
||||||
|
)]))
|
||||||
|
.with_context(err_context)?;
|
||||||
|
}
|
||||||
|
|
||||||
pty.bus
|
pty.bus
|
||||||
.senders
|
.senders
|
||||||
|
|
@ -201,6 +224,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
hold_for_command,
|
hold_for_command,
|
||||||
invoked_with,
|
invoked_with,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
client_or_tab_index,
|
client_or_tab_index,
|
||||||
))
|
))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
|
|
@ -218,6 +242,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
hold_for_command,
|
hold_for_command,
|
||||||
invoked_with,
|
invoked_with,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
client_or_tab_index,
|
client_or_tab_index,
|
||||||
))
|
))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
|
|
@ -259,16 +284,17 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
),
|
),
|
||||||
_ => (false, None, name),
|
_ => (false, None, name),
|
||||||
};
|
};
|
||||||
let invoked_with =
|
let invoked_with = match &terminal_action {
|
||||||
match &terminal_action {
|
Some(TerminalAction::RunCommand(run_command)) => {
|
||||||
Some(TerminalAction::RunCommand(run_command)) => {
|
Some(Run::Command(run_command.clone()))
|
||||||
Some(Run::Command(run_command.clone()))
|
},
|
||||||
},
|
Some(TerminalAction::OpenFile(payload)) => Some(Run::EditFile(
|
||||||
Some(TerminalAction::OpenFile(file, line_number, cwd)) => Some(
|
payload.path.clone(),
|
||||||
Run::EditFile(file.clone(), line_number.clone(), cwd.clone()),
|
payload.line_number.clone(),
|
||||||
),
|
payload.cwd.clone(),
|
||||||
_ => None,
|
)),
|
||||||
};
|
_ => None,
|
||||||
|
};
|
||||||
match pty
|
match pty
|
||||||
.spawn_terminal(terminal_action, client_id_tab_index_or_pane_id)
|
.spawn_terminal(terminal_action, client_id_tab_index_or_pane_id)
|
||||||
.with_context(err_context)
|
.with_context(err_context)
|
||||||
|
|
@ -324,7 +350,11 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
|| format!("failed to open in-place editor for client {}", client_id);
|
|| format!("failed to open in-place editor for client {}", client_id);
|
||||||
|
|
||||||
match pty.spawn_terminal(
|
match pty.spawn_terminal(
|
||||||
Some(TerminalAction::OpenFile(temp_file, line_number, None)),
|
Some(TerminalAction::OpenFile(OpenFilePayload::new(
|
||||||
|
temp_file,
|
||||||
|
line_number,
|
||||||
|
None,
|
||||||
|
))),
|
||||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
) {
|
) {
|
||||||
Ok((pid, _starts_held)) => {
|
Ok((pid, _starts_held)) => {
|
||||||
|
|
@ -761,13 +791,13 @@ impl Pty {
|
||||||
TerminalAction::RunCommand(ref mut command) => {
|
TerminalAction::RunCommand(ref mut command) => {
|
||||||
command.cwd = Some(cwd);
|
command.cwd = Some(cwd);
|
||||||
},
|
},
|
||||||
TerminalAction::OpenFile(ref _file, _line_number, ref mut edit_cwd) => {
|
TerminalAction::OpenFile(ref mut payload) => {
|
||||||
match edit_cwd.as_mut() {
|
match payload.cwd.as_mut() {
|
||||||
Some(edit_cwd) => {
|
Some(edit_cwd) => {
|
||||||
*edit_cwd = cwd.join(&edit_cwd);
|
*edit_cwd = cwd.join(&edit_cwd);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let _ = edit_cwd.insert(cwd.clone());
|
let _ = payload.cwd.insert(cwd.clone());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -847,14 +877,24 @@ impl Pty {
|
||||||
terminal_action
|
terminal_action
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let (hold_on_start, hold_on_close, originating_plugin) = match &terminal_action {
|
let (hold_on_start, hold_on_close, originating_command_plugin, originating_edit_plugin) =
|
||||||
TerminalAction::RunCommand(run_command) => (
|
match &terminal_action {
|
||||||
run_command.hold_on_start,
|
TerminalAction::RunCommand(run_command) => (
|
||||||
run_command.hold_on_close,
|
run_command.hold_on_start,
|
||||||
run_command.originating_plugin.clone(),
|
run_command.hold_on_close,
|
||||||
),
|
run_command.originating_plugin.clone(),
|
||||||
_ => (false, false, None),
|
None,
|
||||||
};
|
),
|
||||||
|
TerminalAction::OpenFile(open_file_payload) => (
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
open_file_payload.originating_plugin.clone(),
|
||||||
|
),
|
||||||
|
_ => (false, false, None, None),
|
||||||
|
};
|
||||||
|
// TODO: CONTINUE HERE - get originating_plugin also from TerminalAction::OpenFile and do
|
||||||
|
// the right thing in the quit_cb below
|
||||||
|
|
||||||
if hold_on_start {
|
if hold_on_start {
|
||||||
// we don't actually open a terminal in this case, just wait for the user to run it
|
// we don't actually open a terminal in this case, just wait for the user to run it
|
||||||
|
|
@ -869,22 +909,35 @@ impl Pty {
|
||||||
return Ok((terminal_id, starts_held));
|
return Ok((terminal_id, starts_held));
|
||||||
}
|
}
|
||||||
|
|
||||||
let originating_plugin = Arc::new(originating_plugin.clone());
|
let originating_command_plugin = Arc::new(originating_command_plugin.clone());
|
||||||
|
let originating_edit_plugin = Arc::new(originating_edit_plugin.clone());
|
||||||
let quit_cb = Box::new({
|
let quit_cb = Box::new({
|
||||||
let senders = self.bus.senders.clone();
|
let senders = self.bus.senders.clone();
|
||||||
move |pane_id, exit_status, command| {
|
move |pane_id, exit_status, command| {
|
||||||
// if this command originated in a plugin, we send the plugin an event letting it
|
// if this command originated in a plugin, we send the plugin an event letting it
|
||||||
// know the command exited and some other useful information
|
// know the command exited and some other useful information
|
||||||
if let PaneId::Terminal(pane_id) = pane_id {
|
if let PaneId::Terminal(pane_id) = pane_id {
|
||||||
if let Some(originating_plugin) = originating_plugin.as_ref() {
|
if let Some(originating_command_plugin) = originating_command_plugin.as_ref() {
|
||||||
let update_event = Event::CommandPaneExited(
|
let update_event = Event::CommandPaneExited(
|
||||||
pane_id,
|
pane_id,
|
||||||
exit_status,
|
exit_status,
|
||||||
originating_plugin.context.clone(),
|
originating_command_plugin.context.clone(),
|
||||||
);
|
);
|
||||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||||
Some(originating_plugin.plugin_id),
|
Some(originating_command_plugin.plugin_id),
|
||||||
Some(originating_plugin.client_id),
|
Some(originating_command_plugin.client_id),
|
||||||
|
update_event,
|
||||||
|
)]));
|
||||||
|
}
|
||||||
|
if let Some(originating_edit_plugin) = originating_edit_plugin.as_ref() {
|
||||||
|
let update_event = Event::EditPaneExited(
|
||||||
|
pane_id,
|
||||||
|
exit_status,
|
||||||
|
originating_edit_plugin.context.clone(),
|
||||||
|
);
|
||||||
|
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||||
|
Some(originating_edit_plugin.plugin_id),
|
||||||
|
Some(originating_edit_plugin.client_id),
|
||||||
update_event,
|
update_event,
|
||||||
)]));
|
)]));
|
||||||
}
|
}
|
||||||
|
|
@ -1200,7 +1253,11 @@ impl Pty {
|
||||||
.context("no OS I/O interface found")
|
.context("no OS I/O interface found")
|
||||||
.with_context(err_context)?
|
.with_context(err_context)?
|
||||||
.spawn_terminal(
|
.spawn_terminal(
|
||||||
TerminalAction::OpenFile(path_to_file, line_number, cwd),
|
TerminalAction::OpenFile(OpenFilePayload::new(
|
||||||
|
path_to_file,
|
||||||
|
line_number,
|
||||||
|
cwd,
|
||||||
|
)),
|
||||||
quit_cb,
|
quit_cb,
|
||||||
self.default_editor.clone(),
|
self.default_editor.clone(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ pub(crate) fn route_action(
|
||||||
.send_to_screen(ScreenInstruction::TogglePaneFrames)
|
.send_to_screen(ScreenInstruction::TogglePaneFrames)
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
},
|
},
|
||||||
Action::NewPane(direction, name) => {
|
Action::NewPane(direction, name, start_suppressed) => {
|
||||||
let shell = default_shell.clone();
|
let shell = default_shell.clone();
|
||||||
let pty_instr = match direction {
|
let pty_instr = match direction {
|
||||||
Some(Direction::Left) => {
|
Some(Direction::Left) => {
|
||||||
|
|
@ -295,22 +295,22 @@ pub(crate) fn route_action(
|
||||||
None,
|
None,
|
||||||
name,
|
name,
|
||||||
None,
|
None,
|
||||||
|
start_suppressed,
|
||||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
senders.send_to_pty(pty_instr).with_context(err_context)?;
|
senders.send_to_pty(pty_instr).with_context(err_context)?;
|
||||||
},
|
},
|
||||||
Action::EditFile(
|
Action::EditFile(
|
||||||
path_to_file,
|
open_file_payload,
|
||||||
line_number,
|
|
||||||
cwd,
|
|
||||||
split_direction,
|
split_direction,
|
||||||
should_float,
|
should_float,
|
||||||
should_open_in_place,
|
should_open_in_place,
|
||||||
|
start_suppressed,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
) => {
|
) => {
|
||||||
let title = format!("Editing: {}", path_to_file.display());
|
let title = format!("Editing: {}", open_file_payload.path.display());
|
||||||
let open_file = TerminalAction::OpenFile(path_to_file, line_number, cwd);
|
let open_file = TerminalAction::OpenFile(open_file_payload);
|
||||||
let pty_instr = match (split_direction, should_float, should_open_in_place) {
|
let pty_instr = match (split_direction, should_float, should_open_in_place) {
|
||||||
(Some(Direction::Left), false, false) => {
|
(Some(Direction::Left), false, false) => {
|
||||||
PtyInstruction::SpawnTerminalVertically(Some(open_file), Some(title), client_id)
|
PtyInstruction::SpawnTerminalVertically(Some(open_file), Some(title), client_id)
|
||||||
|
|
@ -348,6 +348,7 @@ pub(crate) fn route_action(
|
||||||
Some(should_float),
|
Some(should_float),
|
||||||
Some(title),
|
Some(title),
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
@ -394,6 +395,7 @@ pub(crate) fn route_action(
|
||||||
Some(should_float),
|
Some(should_float),
|
||||||
name,
|
name,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
false,
|
||||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
))
|
))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
|
|
@ -447,6 +449,7 @@ pub(crate) fn route_action(
|
||||||
Some(should_float),
|
Some(should_float),
|
||||||
name,
|
name,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
@ -496,6 +499,7 @@ pub(crate) fn route_action(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ pub enum ScreenInstruction {
|
||||||
HoldForCommand,
|
HoldForCommand,
|
||||||
Option<Run>, // invoked with
|
Option<Run>, // invoked with
|
||||||
Option<FloatingPaneCoordinates>,
|
Option<FloatingPaneCoordinates>,
|
||||||
|
bool, // start suppressed
|
||||||
ClientTabIndexOrPaneId,
|
ClientTabIndexOrPaneId,
|
||||||
),
|
),
|
||||||
OpenInPlaceEditor(PaneId, ClientId),
|
OpenInPlaceEditor(PaneId, ClientId),
|
||||||
|
|
@ -312,6 +313,7 @@ pub enum ScreenInstruction {
|
||||||
u32, // plugin id
|
u32, // plugin id
|
||||||
Option<PaneId>,
|
Option<PaneId>,
|
||||||
Option<PathBuf>, // cwd
|
Option<PathBuf>, // cwd
|
||||||
|
bool, // start suppressed
|
||||||
Option<ClientId>,
|
Option<ClientId>,
|
||||||
),
|
),
|
||||||
UpdatePluginLoadingStage(u32, LoadingIndication), // u32 - plugin_id
|
UpdatePluginLoadingStage(u32, LoadingIndication), // u32 - plugin_id
|
||||||
|
|
@ -1905,7 +1907,7 @@ impl Screen {
|
||||||
tab_index_and_plugin_pane_id = Some((*tab_index, plugin_pane_id));
|
tab_index_and_plugin_pane_id = Some((*tab_index, plugin_pane_id));
|
||||||
if move_to_focused_tab && focused_tab_index != *tab_index {
|
if move_to_focused_tab && focused_tab_index != *tab_index {
|
||||||
plugin_pane_to_move_to_active_tab =
|
plugin_pane_to_move_to_active_tab =
|
||||||
tab.extract_pane(plugin_pane_id, Some(client_id));
|
tab.extract_pane(plugin_pane_id, false, Some(client_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -1992,7 +1994,7 @@ impl Screen {
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let pane_to_break_is_floating = active_tab.are_floating_panes_visible();
|
let pane_to_break_is_floating = active_tab.are_floating_panes_visible();
|
||||||
let active_pane = active_tab
|
let active_pane = active_tab
|
||||||
.close_pane(active_pane_id, false, Some(client_id))
|
.extract_pane(active_pane_id, false, Some(client_id))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let active_pane_run_instruction = active_pane.invoked_with().clone();
|
let active_pane_run_instruction = active_pane.invoked_with().clone();
|
||||||
let tab_index = self.get_new_tab_index();
|
let tab_index = self.get_new_tab_index();
|
||||||
|
|
@ -2053,7 +2055,7 @@ impl Screen {
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let pane_to_break_is_floating = active_tab.are_floating_panes_visible();
|
let pane_to_break_is_floating = active_tab.are_floating_panes_visible();
|
||||||
let active_pane = active_tab
|
let active_pane = active_tab
|
||||||
.close_pane(active_pane_id, false, Some(client_id))
|
.extract_pane(active_pane_id, false, Some(client_id))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
(active_pane_id, active_pane, pane_to_break_is_floating)
|
(active_pane_id, active_pane, pane_to_break_is_floating)
|
||||||
};
|
};
|
||||||
|
|
@ -2456,6 +2458,7 @@ pub(crate) fn screen_thread_main(
|
||||||
hold_for_command,
|
hold_for_command,
|
||||||
invoked_with,
|
invoked_with,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
client_or_tab_index,
|
client_or_tab_index,
|
||||||
) => {
|
) => {
|
||||||
match client_or_tab_index {
|
match client_or_tab_index {
|
||||||
|
|
@ -2466,6 +2469,7 @@ pub(crate) fn screen_thread_main(
|
||||||
should_float,
|
should_float,
|
||||||
invoked_with,
|
invoked_with,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
Some(client_id)
|
Some(client_id)
|
||||||
)
|
)
|
||||||
}, ?);
|
}, ?);
|
||||||
|
|
@ -2491,6 +2495,7 @@ pub(crate) fn screen_thread_main(
|
||||||
should_float,
|
should_float,
|
||||||
invoked_with,
|
invoked_with,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
start_suppressed,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
if let Some(hold_for_command) = hold_for_command {
|
if let Some(hold_for_command) = hold_for_command {
|
||||||
|
|
@ -2999,6 +3004,7 @@ pub(crate) fn screen_thread_main(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.unblock_input()?;
|
screen.unblock_input()?;
|
||||||
screen.log_and_report_session_state()?;
|
screen.log_and_report_session_state()?;
|
||||||
},
|
},
|
||||||
|
|
@ -3632,6 +3638,7 @@ pub(crate) fn screen_thread_main(
|
||||||
plugin_id,
|
plugin_id,
|
||||||
pane_id_to_replace,
|
pane_id_to_replace,
|
||||||
cwd,
|
cwd,
|
||||||
|
start_suppressed,
|
||||||
client_id,
|
client_id,
|
||||||
) => {
|
) => {
|
||||||
let pane_title = pane_title.unwrap_or_else(|| {
|
let pane_title = pane_title.unwrap_or_else(|| {
|
||||||
|
|
@ -3676,6 +3683,7 @@ pub(crate) fn screen_thread_main(
|
||||||
should_float,
|
should_float,
|
||||||
Some(run_plugin),
|
Some(run_plugin),
|
||||||
None,
|
None,
|
||||||
|
start_suppressed,
|
||||||
Some(client_id),
|
Some(client_id),
|
||||||
)
|
)
|
||||||
}, ?);
|
}, ?);
|
||||||
|
|
@ -3688,6 +3696,7 @@ pub(crate) fn screen_thread_main(
|
||||||
should_float,
|
should_float,
|
||||||
Some(run_plugin),
|
Some(run_plugin),
|
||||||
None,
|
None,
|
||||||
|
start_suppressed,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ use self::clipboard::ClipboardProvider;
|
||||||
use crate::{
|
use crate::{
|
||||||
os_input_output::ServerOsApi,
|
os_input_output::ServerOsApi,
|
||||||
output::{CharacterChunk, Output, SixelImageChunk},
|
output::{CharacterChunk, Output, SixelImageChunk},
|
||||||
|
panes::floating_panes::floating_pane_grid::half_size_middle_geom,
|
||||||
panes::sixel::SixelImageStore,
|
panes::sixel::SixelImageStore,
|
||||||
panes::{FloatingPanes, TiledPanes},
|
panes::{FloatingPanes, TiledPanes},
|
||||||
panes::{LinkHandler, PaneId, PluginPane, TerminalPane},
|
panes::{LinkHandler, PaneId, PluginPane, TerminalPane},
|
||||||
|
|
@ -985,7 +986,7 @@ impl Tab {
|
||||||
if let Some(focused_floating_pane_id) = self.floating_panes.active_pane_id(client_id) {
|
if let Some(focused_floating_pane_id) = self.floating_panes.active_pane_id(client_id) {
|
||||||
if self.tiled_panes.has_room_for_new_pane() {
|
if self.tiled_panes.has_room_for_new_pane() {
|
||||||
let floating_pane_to_embed = self
|
let floating_pane_to_embed = self
|
||||||
.close_pane(focused_floating_pane_id, true, Some(client_id))
|
.extract_pane(focused_floating_pane_id, true, Some(client_id))
|
||||||
.with_context(|| format!(
|
.with_context(|| format!(
|
||||||
"failed to find floating pane (ID: {focused_floating_pane_id:?}) to embed for client {client_id}",
|
"failed to find floating pane (ID: {focused_floating_pane_id:?}) to embed for client {client_id}",
|
||||||
))
|
))
|
||||||
|
|
@ -1004,7 +1005,7 @@ impl Tab {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Some(embedded_pane_to_float) =
|
if let Some(embedded_pane_to_float) =
|
||||||
self.close_pane(focused_pane_id, true, Some(client_id))
|
self.extract_pane(focused_pane_id, true, Some(client_id))
|
||||||
{
|
{
|
||||||
self.show_floating_panes();
|
self.show_floating_panes();
|
||||||
self.add_floating_pane(
|
self.add_floating_pane(
|
||||||
|
|
@ -1047,11 +1048,13 @@ impl Tab {
|
||||||
Some(client_id) => ClientTabIndexOrPaneId::ClientId(client_id),
|
Some(client_id) => ClientTabIndexOrPaneId::ClientId(client_id),
|
||||||
None => ClientTabIndexOrPaneId::TabIndex(self.index),
|
None => ClientTabIndexOrPaneId::TabIndex(self.index),
|
||||||
};
|
};
|
||||||
|
let should_start_suppressed = false;
|
||||||
let instruction = PtyInstruction::SpawnTerminal(
|
let instruction = PtyInstruction::SpawnTerminal(
|
||||||
default_shell,
|
default_shell,
|
||||||
Some(should_float),
|
Some(should_float),
|
||||||
name,
|
name,
|
||||||
None,
|
None,
|
||||||
|
should_start_suppressed,
|
||||||
client_id_or_tab_index,
|
client_id_or_tab_index,
|
||||||
);
|
);
|
||||||
self.senders
|
self.senders
|
||||||
|
|
@ -1071,6 +1074,7 @@ impl Tab {
|
||||||
should_float: Option<bool>,
|
should_float: Option<bool>,
|
||||||
invoked_with: Option<Run>,
|
invoked_with: Option<Run>,
|
||||||
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
|
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
|
||||||
|
start_suppressed: bool,
|
||||||
client_id: Option<ClientId>,
|
client_id: Option<ClientId>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let err_context = || format!("failed to create new pane with id {pid:?}");
|
let err_context = || format!("failed to create new pane with id {pid:?}");
|
||||||
|
|
@ -1081,7 +1085,7 @@ impl Tab {
|
||||||
};
|
};
|
||||||
self.close_down_to_max_terminals()
|
self.close_down_to_max_terminals()
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
let new_pane = match pid {
|
let mut new_pane = match pid {
|
||||||
PaneId::Terminal(term_pid) => {
|
PaneId::Terminal(term_pid) => {
|
||||||
let next_terminal_position = self.get_next_terminal_position();
|
let next_terminal_position = self.get_next_terminal_position();
|
||||||
Box::new(TerminalPane::new(
|
Box::new(TerminalPane::new(
|
||||||
|
|
@ -1128,7 +1132,32 @@ impl Tab {
|
||||||
)) as Box<dyn Pane>
|
)) as Box<dyn Pane>
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if self.floating_panes.panes_are_visible() {
|
|
||||||
|
if start_suppressed {
|
||||||
|
// this pane needs to start in the background (suppressed), only accessible if a plugin takes it out
|
||||||
|
// of there in one way or another
|
||||||
|
// we need to do some bookkeeping for this pane, namely setting its geom and
|
||||||
|
// content_offset so that things will appear properly in the terminal - we set it to
|
||||||
|
// the default geom of the first floating pane - this is just in order to give it some
|
||||||
|
// reasonable size, when it is shown - if needed - it will be given the proper geom as if it were
|
||||||
|
// resized
|
||||||
|
let viewport = { self.viewport.borrow().clone() };
|
||||||
|
let new_pane_geom = half_size_middle_geom(&viewport, 0);
|
||||||
|
new_pane.set_active_at(Instant::now());
|
||||||
|
new_pane.set_geom(new_pane_geom);
|
||||||
|
new_pane.set_content_offset(Offset::frame(1));
|
||||||
|
resize_pty!(
|
||||||
|
new_pane,
|
||||||
|
self.os_api,
|
||||||
|
self.senders,
|
||||||
|
self.character_cell_size
|
||||||
|
)
|
||||||
|
.with_context(err_context)?;
|
||||||
|
let is_scrollback_editor = false;
|
||||||
|
self.suppressed_panes
|
||||||
|
.insert(pid, (is_scrollback_editor, new_pane));
|
||||||
|
Ok(())
|
||||||
|
} else if self.floating_panes.panes_are_visible() {
|
||||||
self.add_floating_pane(new_pane, pid, floating_pane_coordinates, client_id)
|
self.add_floating_pane(new_pane, pid, floating_pane_coordinates, client_id)
|
||||||
} else {
|
} else {
|
||||||
self.add_tiled_pane(new_pane, pid, client_id)
|
self.add_tiled_pane(new_pane, pid, client_id)
|
||||||
|
|
@ -2448,8 +2477,14 @@ impl Tab {
|
||||||
self.get_tiled_panes().map(|(&pid, _)| pid).collect()
|
self.get_tiled_panes().map(|(&pid, _)| pid).collect()
|
||||||
}
|
}
|
||||||
pub fn get_all_pane_ids(&self) -> Vec<PaneId> {
|
pub fn get_all_pane_ids(&self) -> Vec<PaneId> {
|
||||||
// this is here just as a naming thing to make things more explicit
|
let mut static_and_floating_pane_ids = self.get_static_and_floating_pane_ids();
|
||||||
self.get_static_and_floating_pane_ids()
|
let mut suppressed_pane_ids = self
|
||||||
|
.suppressed_panes
|
||||||
|
.values()
|
||||||
|
.map(|(_key, pane)| pane.pid())
|
||||||
|
.collect();
|
||||||
|
static_and_floating_pane_ids.append(&mut suppressed_pane_ids);
|
||||||
|
static_and_floating_pane_ids
|
||||||
}
|
}
|
||||||
pub fn get_static_and_floating_pane_ids(&self) -> Vec<PaneId> {
|
pub fn get_static_and_floating_pane_ids(&self) -> Vec<PaneId> {
|
||||||
self.tiled_panes
|
self.tiled_panes
|
||||||
|
|
@ -2494,26 +2529,22 @@ impl Tab {
|
||||||
id: PaneId,
|
id: PaneId,
|
||||||
ignore_suppressed_panes: bool,
|
ignore_suppressed_panes: bool,
|
||||||
client_id: Option<ClientId>,
|
client_id: Option<ClientId>,
|
||||||
) -> Option<Box<dyn Pane>> {
|
) {
|
||||||
// we need to ignore suppressed panes when we toggle a pane to be floating/embedded(tiled)
|
// we need to ignore suppressed panes when we toggle a pane to be floating/embedded(tiled)
|
||||||
// this is because in that case, while we do use this logic, we're not actually closing the
|
// this is because in that case, while we do use this logic, we're not actually closing the
|
||||||
// pane, we're moving it
|
// pane, we're moving it
|
||||||
//
|
|
||||||
// TODO: separate the "close_pane" logic and the "move_pane_somewhere_else" logic, they're
|
|
||||||
// overloaded here and that's not great
|
|
||||||
if !ignore_suppressed_panes && self.suppressed_panes.contains_key(&id) {
|
if !ignore_suppressed_panes && self.suppressed_panes.contains_key(&id) {
|
||||||
return match self.replace_pane_with_suppressed_pane(id) {
|
return match self.replace_pane_with_suppressed_pane(id) {
|
||||||
Ok(pane) => pane,
|
Ok(_pane) => {},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
Err::<(), _>(e)
|
Err::<(), _>(e)
|
||||||
.with_context(|| format!("failed to close pane {:?}", id))
|
.with_context(|| format!("failed to close pane {:?}", id))
|
||||||
.non_fatal();
|
.non_fatal();
|
||||||
None
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if self.floating_panes.panes_contain(&id) {
|
if self.floating_panes.panes_contain(&id) {
|
||||||
let closed_pane = self.floating_panes.remove_pane(id);
|
let _closed_pane = self.floating_panes.remove_pane(id);
|
||||||
self.floating_panes.move_clients_out_of_pane(id);
|
self.floating_panes.move_clients_out_of_pane(id);
|
||||||
if !self.floating_panes.has_panes() {
|
if !self.floating_panes.has_panes() {
|
||||||
self.hide_floating_panes();
|
self.hide_floating_panes();
|
||||||
|
|
@ -2529,12 +2560,11 @@ impl Tab {
|
||||||
// confusing
|
// confusing
|
||||||
let _ = self.next_swap_layout(client_id, false);
|
let _ = self.next_swap_layout(client_id, false);
|
||||||
}
|
}
|
||||||
closed_pane
|
|
||||||
} else {
|
} else {
|
||||||
if self.tiled_panes.fullscreen_is_active() {
|
if self.tiled_panes.fullscreen_is_active() {
|
||||||
self.tiled_panes.unset_fullscreen();
|
self.tiled_panes.unset_fullscreen();
|
||||||
}
|
}
|
||||||
let closed_pane = self.tiled_panes.remove_pane(id);
|
let _closed_pane = self.tiled_panes.remove_pane(id);
|
||||||
self.set_force_render();
|
self.set_force_render();
|
||||||
self.tiled_panes.set_force_render();
|
self.tiled_panes.set_force_render();
|
||||||
if self.auto_layout && !self.swap_layouts.is_tiled_damaged() {
|
if self.auto_layout && !self.swap_layouts.is_tiled_damaged() {
|
||||||
|
|
@ -2543,14 +2573,30 @@ impl Tab {
|
||||||
// confusing
|
// confusing
|
||||||
let _ = self.next_swap_layout(client_id, false);
|
let _ = self.next_swap_layout(client_id, false);
|
||||||
}
|
}
|
||||||
closed_pane
|
};
|
||||||
}
|
let _ = self.senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Event::PaneClosed(id.into()),
|
||||||
|
)]));
|
||||||
}
|
}
|
||||||
pub fn extract_pane(
|
pub fn extract_pane(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: PaneId,
|
id: PaneId,
|
||||||
|
ignore_suppressed_panes: bool,
|
||||||
client_id: Option<ClientId>,
|
client_id: Option<ClientId>,
|
||||||
) -> Option<Box<dyn Pane>> {
|
) -> Option<Box<dyn Pane>> {
|
||||||
|
if !ignore_suppressed_panes && self.suppressed_panes.contains_key(&id) {
|
||||||
|
return match self.replace_pane_with_suppressed_pane(id) {
|
||||||
|
Ok(pane) => pane,
|
||||||
|
Err(e) => {
|
||||||
|
Err::<(), _>(e)
|
||||||
|
.with_context(|| format!("failed to close pane {:?}", id))
|
||||||
|
.non_fatal();
|
||||||
|
None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
if self.floating_panes.panes_contain(&id) {
|
if self.floating_panes.panes_contain(&id) {
|
||||||
let closed_pane = self.floating_panes.remove_pane(id);
|
let closed_pane = self.floating_panes.remove_pane(id);
|
||||||
self.floating_panes.move_clients_out_of_pane(id);
|
self.floating_panes.move_clients_out_of_pane(id);
|
||||||
|
|
@ -2609,9 +2655,11 @@ impl Tab {
|
||||||
if self.floating_panes.panes_contain(&id) {
|
if self.floating_panes.panes_contain(&id) {
|
||||||
self.floating_panes
|
self.floating_panes
|
||||||
.hold_pane(id, exit_status, is_first_run, run_command);
|
.hold_pane(id, exit_status, is_first_run, run_command);
|
||||||
} else {
|
} else if self.tiled_panes.panes_contain(&id) {
|
||||||
self.tiled_panes
|
self.tiled_panes
|
||||||
.hold_pane(id, exit_status, is_first_run, run_command);
|
.hold_pane(id, exit_status, is_first_run, run_command);
|
||||||
|
} else if let Some(pane) = self.suppressed_panes.values_mut().find(|p| p.1.pid() == id) {
|
||||||
|
pane.1.hold(exit_status, is_first_run, run_command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn replace_pane_with_suppressed_pane(
|
pub fn replace_pane_with_suppressed_pane(
|
||||||
|
|
@ -3772,7 +3820,7 @@ impl Tab {
|
||||||
// not take it out of there when another pane is closed (eg. like happens with the
|
// not take it out of there when another pane is closed (eg. like happens with the
|
||||||
// scrollback editor), but it has to take itself out on its own (eg. a plugin using the
|
// scrollback editor), but it has to take itself out on its own (eg. a plugin using the
|
||||||
// show_self() method)
|
// show_self() method)
|
||||||
if let Some(pane) = self.close_pane(pane_id, true, Some(client_id)) {
|
if let Some(pane) = self.extract_pane(pane_id, true, Some(client_id)) {
|
||||||
let is_scrollback_editor = false;
|
let is_scrollback_editor = false;
|
||||||
self.suppressed_panes
|
self.suppressed_panes
|
||||||
.insert(pane_id, (is_scrollback_editor, pane));
|
.insert(pane_id, (is_scrollback_editor, pane));
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -571,7 +571,7 @@ fn split_largest_pane() {
|
||||||
let mut tab = create_new_tab(size);
|
let mut tab = create_new_tab(size);
|
||||||
for i in 2..5 {
|
for i in 2..5 {
|
||||||
let new_pane_id = PaneId::Terminal(i);
|
let new_pane_id = PaneId::Terminal(i);
|
||||||
tab.new_pane(new_pane_id, None, None, None, None, Some(1))
|
tab.new_pane(new_pane_id, None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
assert_eq!(tab.tiled_panes.panes.len(), 4, "The tab has four panes");
|
assert_eq!(tab.tiled_panes.panes.len(), 4, "The tab has four panes");
|
||||||
|
|
@ -777,7 +777,7 @@ pub fn cannot_split_panes_horizontally_when_active_pane_is_too_small() {
|
||||||
pub fn cannot_split_largest_pane_when_there_is_no_room() {
|
pub fn cannot_split_largest_pane_when_there_is_no_room() {
|
||||||
let size = Size { cols: 8, rows: 4 };
|
let size = Size { cols: 8, rows: 4 };
|
||||||
let mut tab = create_new_tab(size);
|
let mut tab = create_new_tab(size);
|
||||||
tab.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1))
|
tab.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tab.tiled_panes.panes.len(),
|
tab.tiled_panes.panes.len(),
|
||||||
|
|
@ -821,7 +821,7 @@ pub fn toggle_focused_pane_fullscreen() {
|
||||||
let mut tab = create_new_tab(size);
|
let mut tab = create_new_tab(size);
|
||||||
for i in 2..5 {
|
for i in 2..5 {
|
||||||
let new_pane_id = PaneId::Terminal(i);
|
let new_pane_id = PaneId::Terminal(i);
|
||||||
tab.new_pane(new_pane_id, None, None, None, None, Some(1))
|
tab.new_pane(new_pane_id, None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
tab.toggle_active_pane_fullscreen(1);
|
tab.toggle_active_pane_fullscreen(1);
|
||||||
|
|
@ -896,16 +896,16 @@ fn switch_to_next_pane_fullscreen() {
|
||||||
let mut active_tab = create_new_tab(size);
|
let mut active_tab = create_new_tab(size);
|
||||||
|
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(1), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(1), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(3), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(3), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(4), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(4), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab.toggle_active_pane_fullscreen(1);
|
active_tab.toggle_active_pane_fullscreen(1);
|
||||||
|
|
||||||
|
|
@ -936,16 +936,16 @@ fn switch_to_prev_pane_fullscreen() {
|
||||||
//testing four consecutive switches in fullscreen mode
|
//testing four consecutive switches in fullscreen mode
|
||||||
|
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(1), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(1), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(3), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(3), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(4), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(4), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab.toggle_active_pane_fullscreen(1);
|
active_tab.toggle_active_pane_fullscreen(1);
|
||||||
// order is now 1 2 3 4
|
// order is now 1 2 3 4
|
||||||
|
|
@ -14427,7 +14427,7 @@ fn correctly_resize_frameless_panes_on_pane_close() {
|
||||||
let content_size = (pane.get_content_columns(), pane.get_content_rows());
|
let content_size = (pane.get_content_columns(), pane.get_content_rows());
|
||||||
assert_eq!(content_size, (cols, rows));
|
assert_eq!(content_size, (cols, rows));
|
||||||
|
|
||||||
tab.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1))
|
tab.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.close_pane(PaneId::Terminal(2), true, None);
|
tab.close_pane(PaneId::Terminal(2), true, None);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1166,7 +1166,7 @@ fn switch_to_tab_with_fullscreen() {
|
||||||
{
|
{
|
||||||
let active_tab = screen.get_active_tab_mut(1).unwrap();
|
let active_tab = screen.get_active_tab_mut(1).unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab.toggle_active_pane_fullscreen(1);
|
active_tab.toggle_active_pane_fullscreen(1);
|
||||||
}
|
}
|
||||||
|
|
@ -1281,7 +1281,7 @@ fn attach_after_first_tab_closed() {
|
||||||
{
|
{
|
||||||
let active_tab = screen.get_active_tab_mut(1).unwrap();
|
let active_tab = screen.get_active_tab_mut(1).unwrap();
|
||||||
active_tab
|
active_tab
|
||||||
.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1))
|
.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
active_tab.toggle_active_pane_fullscreen(1);
|
active_tab.toggle_active_pane_fullscreen(1);
|
||||||
}
|
}
|
||||||
|
|
@ -1315,6 +1315,7 @@ fn open_new_floating_pane_with_custom_coordinates() {
|
||||||
width: Some(SplitSize::Percent(1)),
|
width: Some(SplitSize::Percent(1)),
|
||||||
height: Some(SplitSize::Fixed(2)),
|
height: Some(SplitSize::Fixed(2)),
|
||||||
}),
|
}),
|
||||||
|
false,
|
||||||
Some(1),
|
Some(1),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -1348,6 +1349,7 @@ fn open_new_floating_pane_with_custom_coordinates_exceeding_viewport() {
|
||||||
width: Some(SplitSize::Fixed(10)),
|
width: Some(SplitSize::Fixed(10)),
|
||||||
height: Some(SplitSize::Fixed(10)),
|
height: Some(SplitSize::Fixed(10)),
|
||||||
}),
|
}),
|
||||||
|
false,
|
||||||
Some(1),
|
Some(1),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2031
|
assertion_line: 2389
|
||||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||||
---
|
---
|
||||||
[SpawnTerminal(Some(OpenFile("/file/to/edit", None, Some("."))), Some(false), Some("Editing: /file/to/edit"), None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
[SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some(false), Some("Editing: /file/to/edit"), None, false, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2065
|
assertion_line: 2427
|
||||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||||
---
|
---
|
||||||
[SpawnTerminal(Some(OpenFile("/file/to/edit", Some(100), Some("."))), Some(false), Some("Editing: /file/to/edit"), None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
[SpawnTerminal(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: Some(100), cwd: Some("."), originating_plugin: None })), Some(false), Some("Editing: /file/to/edit"), None, false, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2178
|
assertion_line: 2465
|
||||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||||
---
|
---
|
||||||
[SpawnTerminalHorizontally(Some(OpenFile("/file/to/edit", None, Some("."))), Some("Editing: /file/to/edit"), 10), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
[SpawnTerminalHorizontally(Some(OpenFile(OpenFilePayload { path: "/file/to/edit", line_number: None, cwd: Some("."), originating_plugin: None })), Some("Editing: /file/to/edit"), 10), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 1911
|
assertion_line: 2222
|
||||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||||
---
|
---
|
||||||
[SpawnTerminal(None, Some(false), None, None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
[SpawnTerminal(None, Some(false), None, None, false, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: zellij-server/src/./unit/screen_tests.rs
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
assertion_line: 2349
|
assertion_line: 2351
|
||||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||||
---
|
---
|
||||||
[SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), Some(true), None, Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None }), ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
[SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false, originating_plugin: None })), Some(true), None, Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None }), false, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit]
|
||||||
|
|
|
||||||
|
|
@ -76,24 +76,28 @@ pub fn get_zellij_version() -> String {
|
||||||
// Host Functions
|
// Host Functions
|
||||||
|
|
||||||
/// Open a file in the user's default `$EDITOR` in a new pane
|
/// Open a file in the user's default `$EDITOR` in a new pane
|
||||||
pub fn open_file(file_to_open: FileToOpen) {
|
pub fn open_file(file_to_open: FileToOpen, context: BTreeMap<String, String>) {
|
||||||
let plugin_command = PluginCommand::OpenFile(file_to_open);
|
let plugin_command = PluginCommand::OpenFile(file_to_open, context);
|
||||||
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
unsafe { host_run_plugin_command() };
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a file in the user's default `$EDITOR` in a new floating pane
|
/// Open a file in the user's default `$EDITOR` in a new floating pane
|
||||||
pub fn open_file_floating(file_to_open: FileToOpen, coordinates: Option<FloatingPaneCoordinates>) {
|
pub fn open_file_floating(
|
||||||
let plugin_command = PluginCommand::OpenFileFloating(file_to_open, coordinates);
|
file_to_open: FileToOpen,
|
||||||
|
coordinates: Option<FloatingPaneCoordinates>,
|
||||||
|
context: BTreeMap<String, String>,
|
||||||
|
) {
|
||||||
|
let plugin_command = PluginCommand::OpenFileFloating(file_to_open, coordinates, context);
|
||||||
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
unsafe { host_run_plugin_command() };
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a file in the user's default `$EDITOR`, replacing the focused pane
|
/// Open a file in the user's default `$EDITOR`, replacing the focused pane
|
||||||
pub fn open_file_in_place(file_to_open: FileToOpen) {
|
pub fn open_file_in_place(file_to_open: FileToOpen, context: BTreeMap<String, String>) {
|
||||||
let plugin_command = PluginCommand::OpenFileInPlace(file_to_open);
|
let plugin_command = PluginCommand::OpenFileInPlace(file_to_open, context);
|
||||||
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
unsafe { host_run_plugin_command() };
|
unsafe { host_run_plugin_command() };
|
||||||
|
|
@ -159,6 +163,17 @@ pub fn open_command_pane_in_place(command_to_run: CommandToRun, context: BTreeMa
|
||||||
unsafe { host_run_plugin_command() };
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Open a new hidden (background) command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI).
|
||||||
|
pub fn open_command_pane_background(
|
||||||
|
command_to_run: CommandToRun,
|
||||||
|
context: BTreeMap<String, String>,
|
||||||
|
) {
|
||||||
|
let plugin_command = PluginCommand::OpenCommandPaneBackground(command_to_run, context);
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
|
}
|
||||||
|
|
||||||
/// Change the focused tab to the specified index (corresponding with the default tab names, to starting at `1`, `0` will be considered as `1`).
|
/// Change the focused tab to the specified index (corresponding with the default tab names, to starting at `1`, `0` will be considered as `1`).
|
||||||
pub fn switch_tab_to(tab_idx: u32) {
|
pub fn switch_tab_to(tab_idx: u32) {
|
||||||
let plugin_command = PluginCommand::SwitchTabTo(tab_idx);
|
let plugin_command = PluginCommand::SwitchTabTo(tab_idx);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ pub struct Event {
|
||||||
pub name: i32,
|
pub name: i32,
|
||||||
#[prost(
|
#[prost(
|
||||||
oneof = "event::Payload",
|
oneof = "event::Payload",
|
||||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17"
|
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20"
|
||||||
)]
|
)]
|
||||||
pub payload: ::core::option::Option<event::Payload>,
|
pub payload: ::core::option::Option<event::Payload>,
|
||||||
}
|
}
|
||||||
|
|
@ -52,10 +52,31 @@ pub mod event {
|
||||||
CommandPaneOpenedPayload(super::CommandPaneOpenedPayload),
|
CommandPaneOpenedPayload(super::CommandPaneOpenedPayload),
|
||||||
#[prost(message, tag = "17")]
|
#[prost(message, tag = "17")]
|
||||||
CommandPaneExitedPayload(super::CommandPaneExitedPayload),
|
CommandPaneExitedPayload(super::CommandPaneExitedPayload),
|
||||||
|
#[prost(message, tag = "18")]
|
||||||
|
PaneClosedPayload(super::PaneClosedPayload),
|
||||||
|
#[prost(message, tag = "19")]
|
||||||
|
EditPaneOpenedPayload(super::EditPaneOpenedPayload),
|
||||||
|
#[prost(message, tag = "20")]
|
||||||
|
EditPaneExitedPayload(super::EditPaneExitedPayload),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct PaneClosedPayload {
|
||||||
|
#[prost(message, optional, tag = "1")]
|
||||||
|
pub pane_id: ::core::option::Option<PaneId>,
|
||||||
|
}
|
||||||
|
/// duplicate of plugin_command.PaneId because protobuffs don't like recursive imports
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct PaneId {
|
||||||
|
#[prost(enumeration = "PaneType", tag = "1")]
|
||||||
|
pub pane_type: i32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub id: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct CommandPaneOpenedPayload {
|
pub struct CommandPaneOpenedPayload {
|
||||||
#[prost(uint32, tag = "1")]
|
#[prost(uint32, tag = "1")]
|
||||||
pub terminal_pane_id: u32,
|
pub terminal_pane_id: u32,
|
||||||
|
|
@ -64,6 +85,14 @@ pub struct CommandPaneOpenedPayload {
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct EditPaneOpenedPayload {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub terminal_pane_id: u32,
|
||||||
|
#[prost(message, repeated, tag = "2")]
|
||||||
|
pub context: ::prost::alloc::vec::Vec<ContextItem>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct CommandPaneExitedPayload {
|
pub struct CommandPaneExitedPayload {
|
||||||
#[prost(uint32, tag = "1")]
|
#[prost(uint32, tag = "1")]
|
||||||
pub terminal_pane_id: u32,
|
pub terminal_pane_id: u32,
|
||||||
|
|
@ -74,6 +103,16 @@ pub struct CommandPaneExitedPayload {
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct EditPaneExitedPayload {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub terminal_pane_id: u32,
|
||||||
|
#[prost(int32, optional, tag = "2")]
|
||||||
|
pub exit_code: ::core::option::Option<i32>,
|
||||||
|
#[prost(message, repeated, tag = "3")]
|
||||||
|
pub context: ::prost::alloc::vec::Vec<ContextItem>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct SessionUpdatePayload {
|
pub struct SessionUpdatePayload {
|
||||||
#[prost(message, repeated, tag = "1")]
|
#[prost(message, repeated, tag = "1")]
|
||||||
pub session_manifests: ::prost::alloc::vec::Vec<SessionManifest>,
|
pub session_manifests: ::prost::alloc::vec::Vec<SessionManifest>,
|
||||||
|
|
@ -373,6 +412,9 @@ pub enum EventType {
|
||||||
WebRequestResult = 18,
|
WebRequestResult = 18,
|
||||||
CommandPaneOpened = 19,
|
CommandPaneOpened = 19,
|
||||||
CommandPaneExited = 20,
|
CommandPaneExited = 20,
|
||||||
|
PaneClosed = 21,
|
||||||
|
EditPaneOpened = 22,
|
||||||
|
EditPaneExited = 23,
|
||||||
}
|
}
|
||||||
impl EventType {
|
impl EventType {
|
||||||
/// String value of the enum field names used in the ProtoBuf definition.
|
/// String value of the enum field names used in the ProtoBuf definition.
|
||||||
|
|
@ -402,6 +444,9 @@ impl EventType {
|
||||||
EventType::WebRequestResult => "WebRequestResult",
|
EventType::WebRequestResult => "WebRequestResult",
|
||||||
EventType::CommandPaneOpened => "CommandPaneOpened",
|
EventType::CommandPaneOpened => "CommandPaneOpened",
|
||||||
EventType::CommandPaneExited => "CommandPaneExited",
|
EventType::CommandPaneExited => "CommandPaneExited",
|
||||||
|
EventType::PaneClosed => "PaneClosed",
|
||||||
|
EventType::EditPaneOpened => "EditPaneOpened",
|
||||||
|
EventType::EditPaneExited => "EditPaneExited",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
|
|
@ -428,6 +473,36 @@ impl EventType {
|
||||||
"WebRequestResult" => Some(Self::WebRequestResult),
|
"WebRequestResult" => Some(Self::WebRequestResult),
|
||||||
"CommandPaneOpened" => Some(Self::CommandPaneOpened),
|
"CommandPaneOpened" => Some(Self::CommandPaneOpened),
|
||||||
"CommandPaneExited" => Some(Self::CommandPaneExited),
|
"CommandPaneExited" => Some(Self::CommandPaneExited),
|
||||||
|
"PaneClosed" => Some(Self::PaneClosed),
|
||||||
|
"EditPaneOpened" => Some(Self::EditPaneOpened),
|
||||||
|
"EditPaneExited" => Some(Self::EditPaneExited),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// duplicate of plugin_command.PaneType because protobuffs don't like recursive imports
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum PaneType {
|
||||||
|
Terminal = 0,
|
||||||
|
Plugin = 1,
|
||||||
|
}
|
||||||
|
impl PaneType {
|
||||||
|
/// String value of the enum field names used in the ProtoBuf definition.
|
||||||
|
///
|
||||||
|
/// The values are not transformed in any way and thus are considered stable
|
||||||
|
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||||
|
pub fn as_str_name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
PaneType::Terminal => "Terminal",
|
||||||
|
PaneType::Plugin => "Plugin",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
|
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||||
|
match value {
|
||||||
|
"Terminal" => Some(Self::Terminal),
|
||||||
|
"Plugin" => Some(Self::Plugin),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ pub struct PluginCommand {
|
||||||
pub name: i32,
|
pub name: i32,
|
||||||
#[prost(
|
#[prost(
|
||||||
oneof = "plugin_command::Payload",
|
oneof = "plugin_command::Payload",
|
||||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65"
|
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66"
|
||||||
)]
|
)]
|
||||||
pub payload: ::core::option::Option<plugin_command::Payload>,
|
pub payload: ::core::option::Option<plugin_command::Payload>,
|
||||||
}
|
}
|
||||||
|
|
@ -124,6 +124,8 @@ pub mod plugin_command {
|
||||||
HidePaneWithIdPayload(super::HidePaneWithIdPayload),
|
HidePaneWithIdPayload(super::HidePaneWithIdPayload),
|
||||||
#[prost(message, tag = "65")]
|
#[prost(message, tag = "65")]
|
||||||
ShowPaneWithIdPayload(super::ShowPaneWithIdPayload),
|
ShowPaneWithIdPayload(super::ShowPaneWithIdPayload),
|
||||||
|
#[prost(message, tag = "66")]
|
||||||
|
OpenCommandPaneBackgroundPayload(super::OpenCommandPanePayload),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
|
@ -245,6 +247,8 @@ pub struct OpenFilePayload {
|
||||||
pub file_to_open: ::core::option::Option<super::file::File>,
|
pub file_to_open: ::core::option::Option<super::file::File>,
|
||||||
#[prost(message, optional, tag = "2")]
|
#[prost(message, optional, tag = "2")]
|
||||||
pub floating_pane_coordinates: ::core::option::Option<FloatingPaneCoordinates>,
|
pub floating_pane_coordinates: ::core::option::Option<FloatingPaneCoordinates>,
|
||||||
|
#[prost(message, repeated, tag = "3")]
|
||||||
|
pub context: ::prost::alloc::vec::Vec<ContextItem>,
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
|
@ -456,6 +460,7 @@ pub enum CommandName {
|
||||||
Reconfigure = 87,
|
Reconfigure = 87,
|
||||||
HidePaneWithId = 88,
|
HidePaneWithId = 88,
|
||||||
ShowPaneWithId = 89,
|
ShowPaneWithId = 89,
|
||||||
|
OpenCommandPaneBackground = 90,
|
||||||
}
|
}
|
||||||
impl CommandName {
|
impl CommandName {
|
||||||
/// String value of the enum field names used in the ProtoBuf definition.
|
/// String value of the enum field names used in the ProtoBuf definition.
|
||||||
|
|
@ -554,6 +559,7 @@ impl CommandName {
|
||||||
CommandName::Reconfigure => "Reconfigure",
|
CommandName::Reconfigure => "Reconfigure",
|
||||||
CommandName::HidePaneWithId => "HidePaneWithId",
|
CommandName::HidePaneWithId => "HidePaneWithId",
|
||||||
CommandName::ShowPaneWithId => "ShowPaneWithId",
|
CommandName::ShowPaneWithId => "ShowPaneWithId",
|
||||||
|
CommandName::OpenCommandPaneBackground => "OpenCommandPaneBackground",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
|
|
@ -649,6 +655,7 @@ impl CommandName {
|
||||||
"Reconfigure" => Some(Self::Reconfigure),
|
"Reconfigure" => Some(Self::Reconfigure),
|
||||||
"HidePaneWithId" => Some(Self::HidePaneWithId),
|
"HidePaneWithId" => Some(Self::HidePaneWithId),
|
||||||
"ShowPaneWithId" => Some(Self::ShowPaneWithId),
|
"ShowPaneWithId" => Some(Self::ShowPaneWithId),
|
||||||
|
"OpenCommandPaneBackground" => Some(Self::OpenCommandPaneBackground),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -915,7 +915,10 @@ pub enum Event {
|
||||||
// context
|
// context
|
||||||
CommandPaneOpened(u32, Context), // u32 - terminal_pane_id
|
CommandPaneOpened(u32, Context), // u32 - terminal_pane_id
|
||||||
CommandPaneExited(u32, Option<i32>, Context), // u32 - terminal_pane_id, Option<i32> -
|
CommandPaneExited(u32, Option<i32>, Context), // u32 - terminal_pane_id, Option<i32> -
|
||||||
// exit_code
|
// exit_code
|
||||||
|
PaneClosed(PaneId),
|
||||||
|
EditPaneOpened(u32, Context), // u32 - terminal_pane_id
|
||||||
|
EditPaneExited(u32, Option<i32>, Context), // u32 - terminal_pane_id, Option<i32> - exit code
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
@ -1446,7 +1449,7 @@ pub struct NewPluginArgs {
|
||||||
pub skip_cache: bool,
|
pub skip_cache: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum PaneId {
|
pub enum PaneId {
|
||||||
Terminal(u32),
|
Terminal(u32),
|
||||||
Plugin(u32),
|
Plugin(u32),
|
||||||
|
|
@ -1702,8 +1705,8 @@ pub enum PluginCommand {
|
||||||
SetSelectable(bool),
|
SetSelectable(bool),
|
||||||
GetPluginIds,
|
GetPluginIds,
|
||||||
GetZellijVersion,
|
GetZellijVersion,
|
||||||
OpenFile(FileToOpen),
|
OpenFile(FileToOpen, Context),
|
||||||
OpenFileFloating(FileToOpen, Option<FloatingPaneCoordinates>),
|
OpenFileFloating(FileToOpen, Option<FloatingPaneCoordinates>, Context),
|
||||||
OpenTerminal(FileToOpen), // only used for the path as cwd
|
OpenTerminal(FileToOpen), // only used for the path as cwd
|
||||||
OpenTerminalFloating(FileToOpen, Option<FloatingPaneCoordinates>), // only used for the path as cwd
|
OpenTerminalFloating(FileToOpen, Option<FloatingPaneCoordinates>), // only used for the path as cwd
|
||||||
OpenCommandPane(CommandToRun, Context),
|
OpenCommandPane(CommandToRun, Context),
|
||||||
|
|
@ -1768,7 +1771,7 @@ pub enum PluginCommand {
|
||||||
DeleteDeadSession(String), // String -> session name
|
DeleteDeadSession(String), // String -> session name
|
||||||
DeleteAllDeadSessions, // String -> session name
|
DeleteAllDeadSessions, // String -> session name
|
||||||
OpenTerminalInPlace(FileToOpen), // only used for the path as cwd
|
OpenTerminalInPlace(FileToOpen), // only used for the path as cwd
|
||||||
OpenFileInPlace(FileToOpen),
|
OpenFileInPlace(FileToOpen, Context),
|
||||||
OpenCommandPaneInPlace(CommandToRun, Context),
|
OpenCommandPaneInPlace(CommandToRun, Context),
|
||||||
RunCommand(
|
RunCommand(
|
||||||
Vec<String>, // command
|
Vec<String>, // command
|
||||||
|
|
@ -1798,4 +1801,5 @@ pub enum PluginCommand {
|
||||||
Reconfigure(String), // String -> stringified configuration
|
Reconfigure(String), // String -> stringified configuration
|
||||||
HidePaneWithId(PaneId),
|
HidePaneWithId(PaneId),
|
||||||
ShowPaneWithId(PaneId, bool), // bool -> should_float_if_hidden
|
ShowPaneWithId(PaneId, bool), // bool -> should_float_if_hidden
|
||||||
|
OpenCommandPaneBackground(CommandToRun, Context),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Definition of the actions that can be bound to keys.
|
//! Definition of the actions that can be bound to keys.
|
||||||
|
|
||||||
use super::command::RunCommandAction;
|
use super::command::{OpenFilePayload, RunCommandAction};
|
||||||
use super::layout::{
|
use super::layout::{
|
||||||
FloatingPaneLayout, Layout, PluginAlias, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
FloatingPaneLayout, Layout, PluginAlias, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||||
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||||
|
|
@ -157,17 +157,17 @@ pub enum Action {
|
||||||
ToggleActiveSyncTab,
|
ToggleActiveSyncTab,
|
||||||
/// Open a new pane in the specified direction (relative to focus).
|
/// Open a new pane in the specified direction (relative to focus).
|
||||||
/// If no direction is specified, will try to use the biggest available space.
|
/// If no direction is specified, will try to use the biggest available space.
|
||||||
NewPane(Option<Direction>, Option<String>), // String is an optional pane name
|
NewPane(Option<Direction>, Option<String>, bool), // String is an optional pane name
|
||||||
/// Open the file in a new pane using the default editor
|
/// Open the file in a new pane using the default editor, bool -> start suppressed
|
||||||
EditFile(
|
EditFile(
|
||||||
PathBuf,
|
OpenFilePayload,
|
||||||
Option<usize>,
|
|
||||||
Option<PathBuf>,
|
|
||||||
Option<Direction>,
|
Option<Direction>,
|
||||||
bool,
|
bool,
|
||||||
bool,
|
bool,
|
||||||
|
bool,
|
||||||
Option<FloatingPaneCoordinates>,
|
Option<FloatingPaneCoordinates>,
|
||||||
), // usize is an optional line number, Option<PathBuf> is an optional cwd, bool is floating true/false, second bool is in_place
|
), // bool is floating true/false, second bool is in_place
|
||||||
|
// third bool is start_suppressed
|
||||||
/// Open a new floating pane
|
/// Open a new floating pane
|
||||||
NewFloatingPane(
|
NewFloatingPane(
|
||||||
Option<RunCommandAction>,
|
Option<RunCommandAction>,
|
||||||
|
|
@ -485,13 +485,13 @@ impl Action {
|
||||||
file = cwd.join(file);
|
file = cwd.join(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let start_suppressed = false;
|
||||||
Ok(vec![Action::EditFile(
|
Ok(vec![Action::EditFile(
|
||||||
file,
|
OpenFilePayload::new(file, line_number, cwd),
|
||||||
line_number,
|
|
||||||
cwd,
|
|
||||||
direction,
|
direction,
|
||||||
floating,
|
floating,
|
||||||
in_place,
|
in_place,
|
||||||
|
start_suppressed,
|
||||||
FloatingPaneCoordinates::new(x, y, width, height),
|
FloatingPaneCoordinates::new(x, y, width, height),
|
||||||
)])
|
)])
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,15 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TerminalAction {
|
pub enum TerminalAction {
|
||||||
OpenFile(PathBuf, Option<usize>, Option<PathBuf>), // path to file (should be absolute), optional line_number and an
|
OpenFile(OpenFilePayload),
|
||||||
// optional cwd
|
|
||||||
RunCommand(RunCommand),
|
RunCommand(RunCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalAction {
|
impl TerminalAction {
|
||||||
pub fn change_cwd(&mut self, new_cwd: PathBuf) {
|
pub fn change_cwd(&mut self, new_cwd: PathBuf) {
|
||||||
match self {
|
match self {
|
||||||
TerminalAction::OpenFile(_, _, cwd) => {
|
TerminalAction::OpenFile(open_file_payload) => {
|
||||||
*cwd = Some(new_cwd);
|
open_file_payload.cwd = Some(new_cwd);
|
||||||
},
|
},
|
||||||
TerminalAction::RunCommand(run_command) => {
|
TerminalAction::RunCommand(run_command) => {
|
||||||
run_command.cwd = Some(new_cwd);
|
run_command.cwd = Some(new_cwd);
|
||||||
|
|
@ -23,6 +22,29 @@ impl TerminalAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct OpenFilePayload {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub line_number: Option<usize>,
|
||||||
|
pub cwd: Option<PathBuf>,
|
||||||
|
pub originating_plugin: Option<OriginatingPlugin>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpenFilePayload {
|
||||||
|
pub fn new(path: PathBuf, line_number: Option<usize>, cwd: Option<PathBuf>) -> Self {
|
||||||
|
OpenFilePayload {
|
||||||
|
path,
|
||||||
|
line_number,
|
||||||
|
cwd,
|
||||||
|
originating_plugin: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn with_originating_plugin(mut self, originating_plugin: OriginatingPlugin) -> Self {
|
||||||
|
self.originating_plugin = Some(originating_plugin);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Default, Serialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Deserialize, Default, Serialize, PartialEq, Eq)]
|
||||||
pub struct RunCommand {
|
pub struct RunCommand {
|
||||||
#[serde(alias = "cmd")]
|
#[serde(alias = "cmd")]
|
||||||
|
|
|
||||||
|
|
@ -507,7 +507,7 @@ impl Action {
|
||||||
"DumpLayout" => Ok(Action::DumpLayout),
|
"DumpLayout" => Ok(Action::DumpLayout),
|
||||||
"NewPane" => {
|
"NewPane" => {
|
||||||
if string.is_empty() {
|
if string.is_empty() {
|
||||||
return Ok(Action::NewPane(None, None));
|
return Ok(Action::NewPane(None, None, false));
|
||||||
} else {
|
} else {
|
||||||
let direction = Direction::from_str(string.as_str()).map_err(|_| {
|
let direction = Direction::from_str(string.as_str()).map_err(|_| {
|
||||||
ConfigError::new_kdl_error(
|
ConfigError::new_kdl_error(
|
||||||
|
|
@ -516,7 +516,7 @@ impl Action {
|
||||||
action_node.span().len(),
|
action_node.span().len(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(Action::NewPane(Some(direction), None))
|
Ok(Action::NewPane(Some(direction), None, false))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SearchToggleOption" => {
|
"SearchToggleOption" => {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use crate::data::{Direction, InputMode, ResizeStrategy};
|
||||||
use crate::errors::prelude::*;
|
use crate::errors::prelude::*;
|
||||||
use crate::input::actions::Action;
|
use crate::input::actions::Action;
|
||||||
use crate::input::actions::{SearchDirection, SearchOption};
|
use crate::input::actions::{SearchDirection, SearchOption};
|
||||||
use crate::input::command::RunCommandAction;
|
use crate::input::command::{OpenFilePayload, RunCommandAction};
|
||||||
use crate::input::layout::{
|
use crate::input::layout::{
|
||||||
PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||||
};
|
};
|
||||||
|
|
@ -220,7 +220,7 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
.and_then(|d| ProtobufResizeDirection::from_i32(d))
|
.and_then(|d| ProtobufResizeDirection::from_i32(d))
|
||||||
.and_then(|d| d.try_into().ok());
|
.and_then(|d| d.try_into().ok());
|
||||||
let pane_name = payload.pane_name;
|
let pane_name = payload.pane_name;
|
||||||
Ok(Action::NewPane(direction, pane_name))
|
Ok(Action::NewPane(direction, pane_name, false))
|
||||||
},
|
},
|
||||||
_ => Err("Wrong payload for Action::NewPane"),
|
_ => Err("Wrong payload for Action::NewPane"),
|
||||||
},
|
},
|
||||||
|
|
@ -236,12 +236,11 @@ impl TryFrom<ProtobufAction> for Action {
|
||||||
let should_float = payload.should_float;
|
let should_float = payload.should_float;
|
||||||
let should_be_in_place = false;
|
let should_be_in_place = false;
|
||||||
Ok(Action::EditFile(
|
Ok(Action::EditFile(
|
||||||
file_to_edit,
|
OpenFilePayload::new(file_to_edit, line_number, cwd),
|
||||||
line_number,
|
|
||||||
cwd,
|
|
||||||
direction,
|
direction,
|
||||||
should_float,
|
should_float,
|
||||||
should_be_in_place,
|
should_be_in_place,
|
||||||
|
false,
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
|
|
@ -885,7 +884,7 @@ impl TryFrom<Action> for ProtobufAction {
|
||||||
name: ProtobufActionName::ToggleActiveSyncTab as i32,
|
name: ProtobufActionName::ToggleActiveSyncTab as i32,
|
||||||
optional_payload: None,
|
optional_payload: None,
|
||||||
}),
|
}),
|
||||||
Action::NewPane(direction, new_pane_name) => {
|
Action::NewPane(direction, new_pane_name, _start_suppressed) => {
|
||||||
let direction = direction.and_then(|direction| {
|
let direction = direction.and_then(|direction| {
|
||||||
let protobuf_direction: ProtobufResizeDirection = direction.try_into().ok()?;
|
let protobuf_direction: ProtobufResizeDirection = direction.try_into().ok()?;
|
||||||
Some(protobuf_direction as i32)
|
Some(protobuf_direction as i32)
|
||||||
|
|
@ -899,20 +898,19 @@ impl TryFrom<Action> for ProtobufAction {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Action::EditFile(
|
Action::EditFile(
|
||||||
path_to_file,
|
open_file_payload,
|
||||||
line_number,
|
|
||||||
cwd,
|
|
||||||
direction,
|
direction,
|
||||||
should_float,
|
should_float,
|
||||||
_should_be_in_place,
|
_should_be_in_place,
|
||||||
_floating_pane_coordinates,
|
_floating_pane_coordinates,
|
||||||
|
_start_suppressed,
|
||||||
) => {
|
) => {
|
||||||
let file_to_edit = path_to_file.display().to_string();
|
let file_to_edit = open_file_payload.path.display().to_string();
|
||||||
let cwd = cwd.map(|cwd| cwd.display().to_string());
|
let cwd = open_file_payload.cwd.map(|cwd| cwd.display().to_string());
|
||||||
let direction: Option<i32> = direction
|
let direction: Option<i32> = direction
|
||||||
.and_then(|d| ProtobufResizeDirection::try_from(d).ok())
|
.and_then(|d| ProtobufResizeDirection::try_from(d).ok())
|
||||||
.map(|d| d as i32);
|
.map(|d| d as i32);
|
||||||
let line_number = line_number.map(|l| l as u32);
|
let line_number = open_file_payload.line_number.map(|l| l as u32);
|
||||||
Ok(ProtobufAction {
|
Ok(ProtobufAction {
|
||||||
name: ProtobufActionName::EditFile as i32,
|
name: ProtobufActionName::EditFile as i32,
|
||||||
optional_payload: Some(OptionalPayload::EditFilePayload(EditFilePayload {
|
optional_payload: Some(OptionalPayload::EditFilePayload(EditFilePayload {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@ enum EventType {
|
||||||
WebRequestResult = 18;
|
WebRequestResult = 18;
|
||||||
CommandPaneOpened = 19;
|
CommandPaneOpened = 19;
|
||||||
CommandPaneExited = 20;
|
CommandPaneExited = 20;
|
||||||
|
PaneClosed = 21;
|
||||||
|
EditPaneOpened = 22;
|
||||||
|
EditPaneExited = 23;
|
||||||
}
|
}
|
||||||
|
|
||||||
message EventNameList {
|
message EventNameList {
|
||||||
|
|
@ -69,20 +72,50 @@ message Event {
|
||||||
WebRequestResultPayload web_request_result_payload = 15;
|
WebRequestResultPayload web_request_result_payload = 15;
|
||||||
CommandPaneOpenedPayload command_pane_opened_payload = 16;
|
CommandPaneOpenedPayload command_pane_opened_payload = 16;
|
||||||
CommandPaneExitedPayload command_pane_exited_payload = 17;
|
CommandPaneExitedPayload command_pane_exited_payload = 17;
|
||||||
|
PaneClosedPayload pane_closed_payload = 18;
|
||||||
|
EditPaneOpenedPayload edit_pane_opened_payload = 19;
|
||||||
|
EditPaneExitedPayload edit_pane_exited_payload = 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message PaneClosedPayload {
|
||||||
|
PaneId pane_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// duplicate of plugin_command.PaneId because protobuffs don't like recursive imports
|
||||||
|
message PaneId {
|
||||||
|
PaneType pane_type = 1;
|
||||||
|
uint32 id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// duplicate of plugin_command.PaneType because protobuffs don't like recursive imports
|
||||||
|
enum PaneType {
|
||||||
|
Terminal = 0;
|
||||||
|
Plugin = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message CommandPaneOpenedPayload {
|
message CommandPaneOpenedPayload {
|
||||||
uint32 terminal_pane_id = 1;
|
uint32 terminal_pane_id = 1;
|
||||||
repeated ContextItem context = 2;
|
repeated ContextItem context = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message EditPaneOpenedPayload {
|
||||||
|
uint32 terminal_pane_id = 1;
|
||||||
|
repeated ContextItem context = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message CommandPaneExitedPayload {
|
message CommandPaneExitedPayload {
|
||||||
uint32 terminal_pane_id = 1;
|
uint32 terminal_pane_id = 1;
|
||||||
optional int32 exit_code = 2;
|
optional int32 exit_code = 2;
|
||||||
repeated ContextItem context = 3;
|
repeated ContextItem context = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message EditPaneExitedPayload {
|
||||||
|
uint32 terminal_pane_id = 1;
|
||||||
|
optional int32 exit_code = 2;
|
||||||
|
repeated ContextItem context = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message SessionUpdatePayload {
|
message SessionUpdatePayload {
|
||||||
repeated SessionManifest session_manifests = 1;
|
repeated SessionManifest session_manifests = 1;
|
||||||
repeated ResurrectableSession resurrectable_sessions = 2;
|
repeated ResurrectableSession resurrectable_sessions = 2;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ pub use super::generated_api::api::{
|
||||||
EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
|
EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
|
||||||
InputModeKeybinds as ProtobufInputModeKeybinds, KeyBind as ProtobufKeyBind,
|
InputModeKeybinds as ProtobufInputModeKeybinds, KeyBind as ProtobufKeyBind,
|
||||||
LayoutInfo as ProtobufLayoutInfo, ModeUpdatePayload as ProtobufModeUpdatePayload,
|
LayoutInfo as ProtobufLayoutInfo, ModeUpdatePayload as ProtobufModeUpdatePayload,
|
||||||
PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest,
|
PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo,
|
||||||
|
PaneManifest as ProtobufPaneManifest, PaneType as ProtobufPaneType,
|
||||||
ResurrectableSession as ProtobufResurrectableSession,
|
ResurrectableSession as ProtobufResurrectableSession,
|
||||||
SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *,
|
SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *,
|
||||||
},
|
},
|
||||||
|
|
@ -17,8 +18,8 @@ pub use super::generated_api::api::{
|
||||||
#[allow(hidden_glob_reexports)]
|
#[allow(hidden_glob_reexports)]
|
||||||
use crate::data::{
|
use crate::data::{
|
||||||
CopyDestination, Event, EventType, FileMetadata, InputMode, KeyWithModifier, LayoutInfo,
|
CopyDestination, Event, EventType, FileMetadata, InputMode, KeyWithModifier, LayoutInfo,
|
||||||
ModeInfo, Mouse, PaneInfo, PaneManifest, PermissionStatus, PluginCapabilities, SessionInfo,
|
ModeInfo, Mouse, PaneId, PaneInfo, PaneManifest, PermissionStatus, PluginCapabilities,
|
||||||
Style, TabInfo,
|
SessionInfo, Style, TabInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::errors::prelude::*;
|
use crate::errors::prelude::*;
|
||||||
|
|
@ -262,6 +263,42 @@ impl TryFrom<ProtobufEvent> for Event {
|
||||||
)),
|
)),
|
||||||
_ => Err("Malformed payload for the CommandPaneExited Event"),
|
_ => Err("Malformed payload for the CommandPaneExited Event"),
|
||||||
},
|
},
|
||||||
|
Some(ProtobufEventType::PaneClosed) => match protobuf_event.payload {
|
||||||
|
Some(ProtobufEventPayload::PaneClosedPayload(pane_closed_payload)) => {
|
||||||
|
let pane_id = pane_closed_payload
|
||||||
|
.pane_id
|
||||||
|
.ok_or("Malformed payload for the PaneClosed Event")?;
|
||||||
|
Ok(Event::PaneClosed(PaneId::try_from(pane_id)?))
|
||||||
|
},
|
||||||
|
_ => Err("Malformed payload for the PaneClosed Event"),
|
||||||
|
},
|
||||||
|
Some(ProtobufEventType::EditPaneOpened) => match protobuf_event.payload {
|
||||||
|
Some(ProtobufEventPayload::EditPaneOpenedPayload(command_pane_opened_payload)) => {
|
||||||
|
Ok(Event::EditPaneOpened(
|
||||||
|
command_pane_opened_payload.terminal_pane_id,
|
||||||
|
command_pane_opened_payload
|
||||||
|
.context
|
||||||
|
.into_iter()
|
||||||
|
.map(|c_i| (c_i.name, c_i.value))
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
_ => Err("Malformed payload for the EditPaneOpened Event"),
|
||||||
|
},
|
||||||
|
Some(ProtobufEventType::EditPaneExited) => match protobuf_event.payload {
|
||||||
|
Some(ProtobufEventPayload::EditPaneExitedPayload(command_pane_exited_payload)) => {
|
||||||
|
Ok(Event::EditPaneExited(
|
||||||
|
command_pane_exited_payload.terminal_pane_id,
|
||||||
|
command_pane_exited_payload.exit_code,
|
||||||
|
command_pane_exited_payload
|
||||||
|
.context
|
||||||
|
.into_iter()
|
||||||
|
.map(|c_i| (c_i.name, c_i.value))
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
_ => Err("Malformed payload for the EditPaneExited Event"),
|
||||||
|
},
|
||||||
None => Err("Unknown Protobuf Event"),
|
None => Err("Unknown Protobuf Event"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -518,6 +555,43 @@ impl TryFrom<Event> for ProtobufEvent {
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
Event::PaneClosed(pane_id) => Ok(ProtobufEvent {
|
||||||
|
name: ProtobufEventType::PaneClosed as i32,
|
||||||
|
payload: Some(event::Payload::PaneClosedPayload(PaneClosedPayload {
|
||||||
|
pane_id: Some(pane_id.try_into()?),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
Event::EditPaneOpened(terminal_pane_id, context) => {
|
||||||
|
let command_pane_opened_payload = EditPaneOpenedPayload {
|
||||||
|
terminal_pane_id,
|
||||||
|
context: context
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| ContextItem { name, value })
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
Ok(ProtobufEvent {
|
||||||
|
name: ProtobufEventType::EditPaneOpened as i32,
|
||||||
|
payload: Some(event::Payload::EditPaneOpenedPayload(
|
||||||
|
command_pane_opened_payload,
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Event::EditPaneExited(terminal_pane_id, exit_code, context) => {
|
||||||
|
let command_pane_exited_payload = EditPaneExitedPayload {
|
||||||
|
terminal_pane_id,
|
||||||
|
exit_code,
|
||||||
|
context: context
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| ContextItem { name, value })
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
Ok(ProtobufEvent {
|
||||||
|
name: ProtobufEventType::EditPaneExited as i32,
|
||||||
|
payload: Some(event::Payload::EditPaneExitedPayload(
|
||||||
|
command_pane_exited_payload,
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1023,6 +1097,9 @@ impl TryFrom<ProtobufEventType> for EventType {
|
||||||
ProtobufEventType::WebRequestResult => EventType::WebRequestResult,
|
ProtobufEventType::WebRequestResult => EventType::WebRequestResult,
|
||||||
ProtobufEventType::CommandPaneOpened => EventType::CommandPaneOpened,
|
ProtobufEventType::CommandPaneOpened => EventType::CommandPaneOpened,
|
||||||
ProtobufEventType::CommandPaneExited => EventType::CommandPaneExited,
|
ProtobufEventType::CommandPaneExited => EventType::CommandPaneExited,
|
||||||
|
ProtobufEventType::PaneClosed => EventType::PaneClosed,
|
||||||
|
ProtobufEventType::EditPaneOpened => EventType::EditPaneOpened,
|
||||||
|
ProtobufEventType::EditPaneExited => EventType::EditPaneExited,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1052,6 +1129,9 @@ impl TryFrom<EventType> for ProtobufEventType {
|
||||||
EventType::WebRequestResult => ProtobufEventType::WebRequestResult,
|
EventType::WebRequestResult => ProtobufEventType::WebRequestResult,
|
||||||
EventType::CommandPaneOpened => ProtobufEventType::CommandPaneOpened,
|
EventType::CommandPaneOpened => ProtobufEventType::CommandPaneOpened,
|
||||||
EventType::CommandPaneExited => ProtobufEventType::CommandPaneExited,
|
EventType::CommandPaneExited => ProtobufEventType::CommandPaneExited,
|
||||||
|
EventType::PaneClosed => ProtobufEventType::PaneClosed,
|
||||||
|
EventType::EditPaneOpened => ProtobufEventType::EditPaneOpened,
|
||||||
|
EventType::EditPaneExited => ProtobufEventType::EditPaneExited,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1616,3 +1696,36 @@ fn serialize_session_update_event_with_non_default_values() {
|
||||||
"Event properly serialized/deserialized without change"
|
"Event properly serialized/deserialized without change"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: ProtobufPaneId and ProtobufPaneType are not the same as the ones defined in plugin_command.rs
|
||||||
|
// this is a duplicate type - we are forced to do this because protobuffs do not support recursive
|
||||||
|
// imports
|
||||||
|
impl TryFrom<ProtobufPaneId> for PaneId {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(protobuf_pane_id: ProtobufPaneId) -> Result<Self, &'static str> {
|
||||||
|
match ProtobufPaneType::from_i32(protobuf_pane_id.pane_type) {
|
||||||
|
Some(ProtobufPaneType::Terminal) => Ok(PaneId::Terminal(protobuf_pane_id.id)),
|
||||||
|
Some(ProtobufPaneType::Plugin) => Ok(PaneId::Plugin(protobuf_pane_id.id)),
|
||||||
|
None => Err("Failed to convert PaneId"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: ProtobufPaneId and ProtobufPaneType are not the same as the ones defined in plugin_command.rs
|
||||||
|
// this is a duplicate type - we are forced to do this because protobuffs do not support recursive
|
||||||
|
// imports
|
||||||
|
impl TryFrom<PaneId> for ProtobufPaneId {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(pane_id: PaneId) -> Result<Self, &'static str> {
|
||||||
|
match pane_id {
|
||||||
|
PaneId::Terminal(id) => Ok(ProtobufPaneId {
|
||||||
|
pane_type: ProtobufPaneType::Terminal as i32,
|
||||||
|
id,
|
||||||
|
}),
|
||||||
|
PaneId::Plugin(id) => Ok(ProtobufPaneId {
|
||||||
|
pane_type: ProtobufPaneType::Plugin as i32,
|
||||||
|
id,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ enum CommandName {
|
||||||
Reconfigure = 87;
|
Reconfigure = 87;
|
||||||
HidePaneWithId = 88;
|
HidePaneWithId = 88;
|
||||||
ShowPaneWithId = 89;
|
ShowPaneWithId = 89;
|
||||||
|
OpenCommandPaneBackground = 90;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PluginCommand {
|
message PluginCommand {
|
||||||
|
|
@ -161,6 +162,7 @@ message PluginCommand {
|
||||||
string reconfigure_payload = 63;
|
string reconfigure_payload = 63;
|
||||||
HidePaneWithIdPayload hide_pane_with_id_payload = 64;
|
HidePaneWithIdPayload hide_pane_with_id_payload = 64;
|
||||||
ShowPaneWithIdPayload show_pane_with_id_payload = 65;
|
ShowPaneWithIdPayload show_pane_with_id_payload = 65;
|
||||||
|
OpenCommandPanePayload open_command_pane_background_payload = 66;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,6 +240,7 @@ message UnsubscribePayload {
|
||||||
message OpenFilePayload {
|
message OpenFilePayload {
|
||||||
file.File file_to_open = 1;
|
file.File file_to_open = 1;
|
||||||
optional FloatingPaneCoordinates floating_pane_coordinates = 2;
|
optional FloatingPaneCoordinates floating_pane_coordinates = 2;
|
||||||
|
repeated ContextItem context = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message OpenCommandPanePayload {
|
message OpenCommandPanePayload {
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,14 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||||
Some(CommandName::OpenFile) => match protobuf_plugin_command.payload {
|
Some(CommandName::OpenFile) => match protobuf_plugin_command.payload {
|
||||||
Some(Payload::OpenFilePayload(file_to_open_payload)) => {
|
Some(Payload::OpenFilePayload(file_to_open_payload)) => {
|
||||||
match file_to_open_payload.file_to_open {
|
match file_to_open_payload.file_to_open {
|
||||||
Some(file_to_open) => Ok(PluginCommand::OpenFile(file_to_open.try_into()?)),
|
Some(file_to_open) => {
|
||||||
|
let context: BTreeMap<String, String> = file_to_open_payload
|
||||||
|
.context
|
||||||
|
.into_iter()
|
||||||
|
.map(|e| (e.name, e.value))
|
||||||
|
.collect();
|
||||||
|
Ok(PluginCommand::OpenFile(file_to_open.try_into()?, context))
|
||||||
|
},
|
||||||
None => Err("Malformed open file payload"),
|
None => Err("Malformed open file payload"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -238,10 +245,16 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||||
let floating_pane_coordinates = file_to_open_payload
|
let floating_pane_coordinates = file_to_open_payload
|
||||||
.floating_pane_coordinates
|
.floating_pane_coordinates
|
||||||
.map(|f| f.into());
|
.map(|f| f.into());
|
||||||
|
let context: BTreeMap<String, String> = file_to_open_payload
|
||||||
|
.context
|
||||||
|
.into_iter()
|
||||||
|
.map(|e| (e.name, e.value))
|
||||||
|
.collect();
|
||||||
match file_to_open_payload.file_to_open {
|
match file_to_open_payload.file_to_open {
|
||||||
Some(file_to_open) => Ok(PluginCommand::OpenFileFloating(
|
Some(file_to_open) => Ok(PluginCommand::OpenFileFloating(
|
||||||
file_to_open.try_into()?,
|
file_to_open.try_into()?,
|
||||||
floating_pane_coordinates,
|
floating_pane_coordinates,
|
||||||
|
context,
|
||||||
)),
|
)),
|
||||||
None => Err("Malformed open file payload"),
|
None => Err("Malformed open file payload"),
|
||||||
}
|
}
|
||||||
|
|
@ -725,7 +738,15 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||||
Some(Payload::OpenFileInPlacePayload(file_to_open_payload)) => {
|
Some(Payload::OpenFileInPlacePayload(file_to_open_payload)) => {
|
||||||
match file_to_open_payload.file_to_open {
|
match file_to_open_payload.file_to_open {
|
||||||
Some(file_to_open) => {
|
Some(file_to_open) => {
|
||||||
Ok(PluginCommand::OpenFileInPlace(file_to_open.try_into()?))
|
let context: BTreeMap<String, String> = file_to_open_payload
|
||||||
|
.context
|
||||||
|
.into_iter()
|
||||||
|
.map(|e| (e.name, e.value))
|
||||||
|
.collect();
|
||||||
|
Ok(PluginCommand::OpenFileInPlace(
|
||||||
|
file_to_open.try_into()?,
|
||||||
|
context,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
None => Err("Malformed open file in place payload"),
|
None => Err("Malformed open file in place payload"),
|
||||||
}
|
}
|
||||||
|
|
@ -942,6 +963,25 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||||
},
|
},
|
||||||
_ => Err("Mismatched payload for ShowPaneWithId"),
|
_ => Err("Mismatched payload for ShowPaneWithId"),
|
||||||
},
|
},
|
||||||
|
Some(CommandName::OpenCommandPaneBackground) => match protobuf_plugin_command.payload {
|
||||||
|
Some(Payload::OpenCommandPaneBackgroundPayload(command_to_run_payload)) => {
|
||||||
|
match command_to_run_payload.command_to_run {
|
||||||
|
Some(command_to_run) => {
|
||||||
|
let context: BTreeMap<String, String> = command_to_run_payload
|
||||||
|
.context
|
||||||
|
.into_iter()
|
||||||
|
.map(|e| (e.name, e.value))
|
||||||
|
.collect();
|
||||||
|
Ok(PluginCommand::OpenCommandPaneBackground(
|
||||||
|
command_to_run.try_into()?,
|
||||||
|
context,
|
||||||
|
))
|
||||||
|
},
|
||||||
|
None => Err("Malformed open command pane background payload"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err("Mismatched payload for OpenCommandPaneBackground"),
|
||||||
|
},
|
||||||
None => Err("Unrecognized plugin command"),
|
None => Err("Unrecognized plugin command"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -981,19 +1021,27 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
name: CommandName::GetZellijVersion as i32,
|
name: CommandName::GetZellijVersion as i32,
|
||||||
payload: None,
|
payload: None,
|
||||||
}),
|
}),
|
||||||
PluginCommand::OpenFile(file_to_open) => Ok(ProtobufPluginCommand {
|
PluginCommand::OpenFile(file_to_open, context) => Ok(ProtobufPluginCommand {
|
||||||
name: CommandName::OpenFile as i32,
|
name: CommandName::OpenFile as i32,
|
||||||
payload: Some(Payload::OpenFilePayload(OpenFilePayload {
|
payload: Some(Payload::OpenFilePayload(OpenFilePayload {
|
||||||
file_to_open: Some(file_to_open.try_into()?),
|
file_to_open: Some(file_to_open.try_into()?),
|
||||||
floating_pane_coordinates: None,
|
floating_pane_coordinates: None,
|
||||||
|
context: context
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| ContextItem { name, value })
|
||||||
|
.collect(),
|
||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
PluginCommand::OpenFileFloating(file_to_open, floating_pane_coordinates) => {
|
PluginCommand::OpenFileFloating(file_to_open, floating_pane_coordinates, context) => {
|
||||||
Ok(ProtobufPluginCommand {
|
Ok(ProtobufPluginCommand {
|
||||||
name: CommandName::OpenFileFloating as i32,
|
name: CommandName::OpenFileFloating as i32,
|
||||||
payload: Some(Payload::OpenFileFloatingPayload(OpenFilePayload {
|
payload: Some(Payload::OpenFileFloatingPayload(OpenFilePayload {
|
||||||
file_to_open: Some(file_to_open.try_into()?),
|
file_to_open: Some(file_to_open.try_into()?),
|
||||||
floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()),
|
floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()),
|
||||||
|
context: context
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| ContextItem { name, value })
|
||||||
|
.collect(),
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
@ -1002,6 +1050,7 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
payload: Some(Payload::OpenTerminalPayload(OpenFilePayload {
|
payload: Some(Payload::OpenTerminalPayload(OpenFilePayload {
|
||||||
file_to_open: Some(cwd.try_into()?),
|
file_to_open: Some(cwd.try_into()?),
|
||||||
floating_pane_coordinates: None,
|
floating_pane_coordinates: None,
|
||||||
|
context: vec![], // will be added in the future
|
||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => {
|
PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => {
|
||||||
|
|
@ -1010,6 +1059,7 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
payload: Some(Payload::OpenTerminalFloatingPayload(OpenFilePayload {
|
payload: Some(Payload::OpenTerminalFloatingPayload(OpenFilePayload {
|
||||||
file_to_open: Some(cwd.try_into()?),
|
file_to_open: Some(cwd.try_into()?),
|
||||||
floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()),
|
floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()),
|
||||||
|
context: vec![], // will be added in the future
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
@ -1332,13 +1382,18 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
payload: Some(Payload::OpenTerminalInPlacePayload(OpenFilePayload {
|
payload: Some(Payload::OpenTerminalInPlacePayload(OpenFilePayload {
|
||||||
file_to_open: Some(cwd.try_into()?),
|
file_to_open: Some(cwd.try_into()?),
|
||||||
floating_pane_coordinates: None,
|
floating_pane_coordinates: None,
|
||||||
|
context: vec![], // will be added in the future
|
||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
PluginCommand::OpenFileInPlace(file_to_open) => Ok(ProtobufPluginCommand {
|
PluginCommand::OpenFileInPlace(file_to_open, context) => Ok(ProtobufPluginCommand {
|
||||||
name: CommandName::OpenFileInPlace as i32,
|
name: CommandName::OpenFileInPlace as i32,
|
||||||
payload: Some(Payload::OpenFileInPlacePayload(OpenFilePayload {
|
payload: Some(Payload::OpenFileInPlacePayload(OpenFilePayload {
|
||||||
file_to_open: Some(file_to_open.try_into()?),
|
file_to_open: Some(file_to_open.try_into()?),
|
||||||
floating_pane_coordinates: None,
|
floating_pane_coordinates: None,
|
||||||
|
context: context
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| ContextItem { name, value })
|
||||||
|
.collect(),
|
||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
PluginCommand::OpenCommandPaneInPlace(command_to_run, context) => {
|
PluginCommand::OpenCommandPaneInPlace(command_to_run, context) => {
|
||||||
|
|
@ -1516,6 +1571,22 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
PluginCommand::OpenCommandPaneBackground(command_to_run, context) => {
|
||||||
|
let context: Vec<_> = context
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| ContextItem { name, value })
|
||||||
|
.collect();
|
||||||
|
Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::OpenCommandPaneBackground as i32,
|
||||||
|
payload: Some(Payload::OpenCommandPaneBackgroundPayload(
|
||||||
|
OpenCommandPanePayload {
|
||||||
|
command_to_run: Some(command_to_run.try_into()?),
|
||||||
|
floating_pane_coordinates: None,
|
||||||
|
context,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -731,6 +732,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -990,6 +992,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1160,6 +1163,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1188,6 +1192,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -1255,6 +1260,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1786,6 +1792,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2255,6 +2262,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2608,6 +2616,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3043,6 +3052,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3411,6 +3421,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3742,6 +3753,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4097,6 +4109,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4541,6 +4554,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4875,6 +4889,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -5068,6 +5083,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5084,6 +5100,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5392,6 +5409,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -731,6 +732,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -990,6 +992,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1160,6 +1163,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1188,6 +1192,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -1255,6 +1260,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1786,6 +1792,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2255,6 +2262,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2608,6 +2616,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3043,6 +3052,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3411,6 +3421,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3742,6 +3753,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4097,6 +4109,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4541,6 +4554,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4875,6 +4889,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -5068,6 +5083,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5084,6 +5100,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5392,6 +5409,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -731,6 +732,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -990,6 +992,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1160,6 +1163,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1188,6 +1192,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -1255,6 +1260,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1786,6 +1792,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2255,6 +2262,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2608,6 +2616,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3043,6 +3052,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3411,6 +3421,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3742,6 +3753,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4097,6 +4109,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4541,6 +4554,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4875,6 +4889,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -5068,6 +5083,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5084,6 +5100,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5392,6 +5409,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -731,6 +732,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -990,6 +992,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1160,6 +1163,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1188,6 +1192,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -1255,6 +1260,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -1786,6 +1792,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2255,6 +2262,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -2608,6 +2616,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3043,6 +3052,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3411,6 +3421,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -3742,6 +3753,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4097,6 +4109,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4541,6 +4554,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -4875,6 +4889,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
@ -5068,6 +5083,7 @@ Config {
|
||||||
Down,
|
Down,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5084,6 +5100,7 @@ Config {
|
||||||
Right,
|
Right,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
SwitchToMode(
|
SwitchToMode(
|
||||||
Normal,
|
Normal,
|
||||||
|
|
@ -5392,6 +5409,7 @@ Config {
|
||||||
NewPane(
|
NewPane(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
KeyWithModifier {
|
KeyWithModifier {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue