mirror of
https://github.com/zellij-org/zellij.git
synced 2024-11-22 04:33:22 +03:00
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
@ -166,10 +166,13 @@ impl ZellijPlugin for State {
|
||||
start_or_reload_plugin(plugin_url)
|
||||
},
|
||||
BareKey::Char('g') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||
open_file(FileToOpen {
|
||||
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||
..Default::default()
|
||||
});
|
||||
open_file(
|
||||
FileToOpen {
|
||||
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||
..Default::default()
|
||||
},
|
||||
BTreeMap::new(),
|
||||
);
|
||||
},
|
||||
BareKey::Char('h') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||
open_file_floating(
|
||||
@ -178,14 +181,18 @@ impl ZellijPlugin for State {
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
BTreeMap::new(),
|
||||
);
|
||||
},
|
||||
BareKey::Char('i') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||
open_file(FileToOpen {
|
||||
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||
line_number: Some(42),
|
||||
..Default::default()
|
||||
});
|
||||
open_file(
|
||||
FileToOpen {
|
||||
path: std::path::PathBuf::from("/path/to/my/file.rs"),
|
||||
line_number: Some(42),
|
||||
..Default::default()
|
||||
},
|
||||
BTreeMap::new(),
|
||||
);
|
||||
},
|
||||
BareKey::Char('j') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||
open_file_floating(
|
||||
@ -195,6 +202,7 @@ impl ZellijPlugin for State {
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
BTreeMap::new(),
|
||||
);
|
||||
},
|
||||
BareKey::Char('k') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
|
||||
@ -335,6 +343,22 @@ impl ZellijPlugin for State {
|
||||
.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) => {
|
||||
|
@ -677,7 +677,7 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz
|
||||
let mut secondary_info = LinePart::default();
|
||||
let binds = &help.get_mode_keybinds();
|
||||
// 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
|
||||
.iter()
|
||||
.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![
|
||||
(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"),
|
||||
action_key_group(&km, &[&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||
&[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, &[
|
||||
&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||
&[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 right"), s("Right"), action_key(&km, &[A::NewPane(Some(Dir::Right), 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, false), 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("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![
|
||||
(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"),
|
||||
action_key_group(&km, &[&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||
&[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, &[
|
||||
&[A::MoveFocus(Dir::Left)], &[A::MoveFocus(Dir::Down)],
|
||||
&[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 right"), s("Right"), action_key(&km, &[A::NewPane(Some(Dir::Right), 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, false), 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("Rename tab"), s("Rename"),
|
||||
@ -713,7 +713,7 @@ mod tests {
|
||||
),
|
||||
(
|
||||
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')),
|
||||
@ -763,7 +763,7 @@ mod tests {
|
||||
),
|
||||
(
|
||||
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')),
|
||||
@ -809,7 +809,7 @@ mod tests {
|
||||
),
|
||||
(
|
||||
KeyWithModifier::new(BareKey::Backspace),
|
||||
vec![Action::NewPane(None, None), TO_NORMAL],
|
||||
vec![Action::NewPane(None, None, false), TO_NORMAL],
|
||||
),
|
||||
(
|
||||
KeyWithModifier::new(BareKey::Esc),
|
||||
|
@ -62,7 +62,7 @@ struct Keygroups<'a> {
|
||||
|
||||
fn add_keybinds(help: &ModeInfo) -> Keygroups {
|
||||
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() {
|
||||
vec![Style::new().bold().paint("UNBOUND")]
|
||||
} else {
|
||||
|
@ -152,9 +152,10 @@ impl State {
|
||||
if let Some(parent_folder) = self.file_list_view.path.parent() {
|
||||
open_file(
|
||||
FileToOpen::new(&self.file_list_view.path).with_cwd(parent_folder.into()),
|
||||
BTreeMap::new(),
|
||||
);
|
||||
} 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 {
|
||||
|
@ -288,10 +288,10 @@ fn spawn_terminal(
|
||||
// secondary fd
|
||||
let mut failover_cmd_args = None;
|
||||
let cmd = match terminal_action {
|
||||
TerminalAction::OpenFile(mut file_to_open, line_number, cwd) => {
|
||||
if file_to_open.is_relative() {
|
||||
if let Some(cwd) = cwd.as_ref() {
|
||||
file_to_open = cwd.join(file_to_open);
|
||||
TerminalAction::OpenFile(mut payload) => {
|
||||
if payload.path.is_relative() {
|
||||
if let Some(cwd) = payload.cwd.as_ref() {
|
||||
payload.path = cwd.join(payload.path);
|
||||
}
|
||||
}
|
||||
let mut command = default_editor.unwrap_or_else(|| {
|
||||
@ -306,11 +306,12 @@ fn spawn_terminal(
|
||||
if !command.is_dir() {
|
||||
separate_command_arguments(&mut command, &mut args);
|
||||
}
|
||||
let file_to_open = file_to_open
|
||||
let file_to_open = payload
|
||||
.path
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.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")
|
||||
|| command.ends_with("nvim")
|
||||
|| command.ends_with("emacs")
|
||||
@ -334,7 +335,7 @@ fn spawn_terminal(
|
||||
RunCommand {
|
||||
command,
|
||||
args,
|
||||
cwd,
|
||||
cwd: payload.cwd,
|
||||
hold_on_close: false,
|
||||
hold_on_start: false,
|
||||
..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 {
|
||||
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,
|
||||
|
@ -1,4 +1,4 @@
|
||||
mod floating_pane_grid;
|
||||
pub mod floating_pane_grid;
|
||||
use zellij_utils::{
|
||||
data::{Direction, PaneInfo, ResizeStrategy},
|
||||
position::Position,
|
||||
|
@ -6,7 +6,7 @@ pub mod sixel;
|
||||
pub mod terminal_character;
|
||||
|
||||
mod active_panes;
|
||||
mod floating_panes;
|
||||
pub mod floating_panes;
|
||||
mod plugin_pane;
|
||||
mod search;
|
||||
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;
|
||||
|
||||
// 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);
|
||||
let cwd = run_plugin_or_alias.get_initial_cwd().or(cwd);
|
||||
let run_plugin = run_plugin_or_alias.get_run_plugin();
|
||||
let start_suppressed = false;
|
||||
match wasm_bridge.load_plugin(
|
||||
&run_plugin,
|
||||
Some(tab_index),
|
||||
@ -268,6 +269,7 @@ pub(crate) fn plugin_thread_main(
|
||||
plugin_id,
|
||||
pane_id_to_replace,
|
||||
cwd,
|
||||
start_suppressed,
|
||||
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
|
||||
// the cli who spawned the command and is not an existing client_id
|
||||
let skip_cache = true; // when reloading we always skip cache
|
||||
let start_suppressed = false;
|
||||
match wasm_bridge.load_plugin(
|
||||
&Some(run_plugin),
|
||||
Some(tab_index),
|
||||
@ -328,6 +331,7 @@ pub(crate) fn plugin_thread_main(
|
||||
plugin_id,
|
||||
None,
|
||||
None,
|
||||
start_suppressed,
|
||||
None,
|
||||
),
|
||||
));
|
||||
@ -365,6 +369,16 @@ pub(crate) fn plugin_thread_main(
|
||||
tab_index,
|
||||
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();
|
||||
tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0));
|
||||
tab_layout
|
||||
|
@ -6655,3 +6655,223 @@ pub fn run_plugin_in_specific_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,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -31,6 +31,7 @@ Some(
|
||||
),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -1,17 +1,26 @@
|
||||
---
|
||||
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\\\"\")"
|
||||
---
|
||||
Some(
|
||||
SpawnTerminal(
|
||||
Some(
|
||||
OpenFile(
|
||||
"/path/to/my/file.rs",
|
||||
None,
|
||||
Some(
|
||||
"CWD",
|
||||
),
|
||||
OpenFilePayload {
|
||||
path: "/path/to/my/file.rs",
|
||||
line_number: None,
|
||||
cwd: Some(
|
||||
"CWD",
|
||||
),
|
||||
originating_plugin: Some(
|
||||
OriginatingPlugin {
|
||||
plugin_id: 0,
|
||||
client_id: 1,
|
||||
context: {},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
Some(
|
||||
@ -21,6 +30,7 @@ Some(
|
||||
"Editing: /path/to/my/file.rs",
|
||||
),
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -1,17 +1,26 @@
|
||||
---
|
||||
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\\\"\")"
|
||||
---
|
||||
Some(
|
||||
SpawnTerminal(
|
||||
Some(
|
||||
OpenFile(
|
||||
"/path/to/my/file.rs",
|
||||
None,
|
||||
Some(
|
||||
"CWD",
|
||||
),
|
||||
OpenFilePayload {
|
||||
path: "/path/to/my/file.rs",
|
||||
line_number: None,
|
||||
cwd: Some(
|
||||
"CWD",
|
||||
),
|
||||
originating_plugin: Some(
|
||||
OriginatingPlugin {
|
||||
plugin_id: 0,
|
||||
client_id: 1,
|
||||
context: {},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
Some(
|
||||
@ -21,6 +30,7 @@ Some(
|
||||
"Editing: /path/to/my/file.rs",
|
||||
),
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -1,19 +1,28 @@
|
||||
---
|
||||
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\\\"\")"
|
||||
---
|
||||
Some(
|
||||
SpawnTerminal(
|
||||
Some(
|
||||
OpenFile(
|
||||
"/path/to/my/file.rs",
|
||||
Some(
|
||||
42,
|
||||
),
|
||||
Some(
|
||||
"CWD",
|
||||
),
|
||||
OpenFilePayload {
|
||||
path: "/path/to/my/file.rs",
|
||||
line_number: Some(
|
||||
42,
|
||||
),
|
||||
cwd: Some(
|
||||
"CWD",
|
||||
),
|
||||
originating_plugin: Some(
|
||||
OriginatingPlugin {
|
||||
plugin_id: 0,
|
||||
client_id: 1,
|
||||
context: {},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
Some(
|
||||
@ -23,6 +32,7 @@ Some(
|
||||
"Editing: /path/to/my/file.rs",
|
||||
),
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -1,19 +1,28 @@
|
||||
---
|
||||
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\\\"\")"
|
||||
---
|
||||
Some(
|
||||
SpawnTerminal(
|
||||
Some(
|
||||
OpenFile(
|
||||
"/path/to/my/file.rs",
|
||||
Some(
|
||||
42,
|
||||
),
|
||||
Some(
|
||||
"CWD",
|
||||
),
|
||||
OpenFilePayload {
|
||||
path: "/path/to/my/file.rs",
|
||||
line_number: Some(
|
||||
42,
|
||||
),
|
||||
cwd: Some(
|
||||
"CWD",
|
||||
),
|
||||
originating_plugin: Some(
|
||||
OriginatingPlugin {
|
||||
plugin_id: 0,
|
||||
client_id: 1,
|
||||
context: {},
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
Some(
|
||||
@ -23,6 +32,7 @@ Some(
|
||||
"Editing: /path/to/my/file.rs",
|
||||
),
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -24,6 +24,7 @@ Some(
|
||||
),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
1,
|
||||
),
|
||||
|
@ -24,6 +24,7 @@ Some(
|
||||
),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
ClientId(
|
||||
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,
|
||||
) {
|
||||
Ok((plugin_id, client_id)) => {
|
||||
let start_suppressed = false;
|
||||
drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin(
|
||||
Some(should_float),
|
||||
should_be_open_in_place,
|
||||
@ -1202,6 +1203,7 @@ impl WasmBridge {
|
||||
plugin_id,
|
||||
pane_id_to_replace,
|
||||
cwd,
|
||||
start_suppressed,
|
||||
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 == 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) {
|
||||
@ -1316,6 +1329,9 @@ fn check_event_permission(
|
||||
| Event::SystemClipboardFailure
|
||||
| Event::CommandPaneOpened(..)
|
||||
| Event::CommandPaneExited(..)
|
||||
| Event::PaneClosed(..)
|
||||
| Event::EditPaneOpened(..)
|
||||
| Event::EditPaneExited(..)
|
||||
| Event::InputReceived => PermissionType::ReadApplicationState,
|
||||
_ => return (PermissionStatus::Granted, None),
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ use super::PluginInstruction;
|
||||
use crate::background_jobs::BackgroundJob;
|
||||
use crate::plugins::plugin_map::PluginEnv;
|
||||
use crate::plugins::wasm_bridge::handle_plugin_crash;
|
||||
use crate::pty::{ClientTabIndexOrPaneId, PtyInstruction};
|
||||
use crate::route::route_action;
|
||||
use crate::ServerInstruction;
|
||||
use log::{debug, warn};
|
||||
@ -22,6 +23,7 @@ use zellij_utils::data::{
|
||||
};
|
||||
use zellij_utils::input::permission::PermissionCache;
|
||||
use zellij_utils::{
|
||||
async_std::task,
|
||||
interprocess::local_socket::LocalSocketStream,
|
||||
ipc::{ClientToServerMsg, IpcSenderWithContext},
|
||||
};
|
||||
@ -37,7 +39,7 @@ use zellij_utils::{
|
||||
errors::prelude::*,
|
||||
input::{
|
||||
actions::Action,
|
||||
command::{RunCommand, RunCommandAction, TerminalAction},
|
||||
command::{OpenFilePayload, RunCommand, RunCommandAction, TerminalAction},
|
||||
layout::{Layout, RunPluginOrAlias},
|
||||
plugins::PluginType,
|
||||
},
|
||||
@ -91,10 +93,14 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
|
||||
PluginCommand::SetSelectable(selectable) => set_selectable(env, selectable),
|
||||
PluginCommand::GetPluginIds => get_plugin_ids(env),
|
||||
PluginCommand::GetZellijVersion => get_zellij_version(env),
|
||||
PluginCommand::OpenFile(file_to_open) => open_file(env, file_to_open),
|
||||
PluginCommand::OpenFileFloating(file_to_open, floating_pane_coordinates) => {
|
||||
open_file_floating(env, file_to_open, floating_pane_coordinates)
|
||||
PluginCommand::OpenFile(file_to_open, context) => {
|
||||
open_file(env, file_to_open, context)
|
||||
},
|
||||
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::OpenTerminalFloating(cwd, 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)?
|
||||
},
|
||||
PluginCommand::DeleteAllDeadSessions => delete_all_dead_sessions()?,
|
||||
PluginCommand::OpenFileInPlace(file_to_open) => {
|
||||
open_file_in_place(env, file_to_open)
|
||||
PluginCommand::OpenFileInPlace(file_to_open, context) => {
|
||||
open_file_in_place(env, file_to_open, context)
|
||||
},
|
||||
PluginCommand::OpenTerminalInPlace(cwd) => {
|
||||
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) => {
|
||||
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) => {
|
||||
log::error!(
|
||||
@ -355,6 +364,7 @@ fn request_permission(env: &PluginEnv, permissions: Vec<PermissionType>) -> Resu
|
||||
if PermissionCache::from_path_or_default(None)
|
||||
.check_permissions(env.plugin.location.to_string(), &permissions)
|
||||
{
|
||||
log::info!("PermissionRequestResult 1");
|
||||
return env
|
||||
.senders
|
||||
.send_to_plugin(PluginInstruction::PermissionRequestResult(
|
||||
@ -416,22 +426,24 @@ fn get_zellij_version(env: &PluginEnv) {
|
||||
.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 floating = false;
|
||||
let in_place = false;
|
||||
let start_suppressed = false;
|
||||
let path = env.plugin_cwd.join(file_to_open.path);
|
||||
let cwd = file_to_open
|
||||
.cwd
|
||||
.map(|cwd| env.plugin_cwd.join(cwd))
|
||||
.or_else(|| Some(env.plugin_cwd.clone()));
|
||||
let action = Action::EditFile(
|
||||
path,
|
||||
file_to_open.line_number,
|
||||
cwd,
|
||||
OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin(
|
||||
OriginatingPlugin::new(env.plugin_id, env.client_id, context),
|
||||
),
|
||||
None,
|
||||
floating,
|
||||
in_place,
|
||||
start_suppressed,
|
||||
None,
|
||||
);
|
||||
apply_action!(action, error_msg, env);
|
||||
@ -441,31 +453,39 @@ fn open_file_floating(
|
||||
env: &PluginEnv,
|
||||
file_to_open: FileToOpen,
|
||||
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
|
||||
context: BTreeMap<String, String>,
|
||||
) {
|
||||
let error_msg = || format!("failed to open file in plugin {}", env.name());
|
||||
let floating = true;
|
||||
let in_place = false;
|
||||
let start_suppressed = false;
|
||||
let path = env.plugin_cwd.join(file_to_open.path);
|
||||
let cwd = file_to_open
|
||||
.cwd
|
||||
.map(|cwd| env.plugin_cwd.join(cwd))
|
||||
.or_else(|| Some(env.plugin_cwd.clone()));
|
||||
let action = Action::EditFile(
|
||||
path,
|
||||
file_to_open.line_number,
|
||||
cwd,
|
||||
OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin(
|
||||
OriginatingPlugin::new(env.plugin_id, env.client_id, context),
|
||||
),
|
||||
None,
|
||||
floating,
|
||||
in_place,
|
||||
start_suppressed,
|
||||
floating_pane_coordinates,
|
||||
);
|
||||
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 floating = false;
|
||||
let in_place = true;
|
||||
let start_suppressed = false;
|
||||
let path = env.plugin_cwd.join(file_to_open.path);
|
||||
let cwd = file_to_open
|
||||
.cwd
|
||||
@ -473,12 +493,13 @@ fn open_file_in_place(env: &PluginEnv, file_to_open: FileToOpen) {
|
||||
.or_else(|| Some(env.plugin_cwd.clone()));
|
||||
|
||||
let action = Action::EditFile(
|
||||
path,
|
||||
file_to_open.line_number,
|
||||
cwd,
|
||||
OpenFilePayload::new(path, file_to_open.line_number, cwd).with_originating_plugin(
|
||||
OriginatingPlugin::new(env.plugin_id, env.client_id, context),
|
||||
),
|
||||
None,
|
||||
floating,
|
||||
in_place,
|
||||
start_suppressed,
|
||||
None,
|
||||
);
|
||||
apply_action!(action, error_msg, env);
|
||||
@ -633,6 +654,43 @@ fn open_command_pane_in_place(
|
||||
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) {
|
||||
env.senders
|
||||
.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) {
|
||||
// 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 update_target = Some(env.plugin_id);
|
||||
let client_id = env.client_id;
|
||||
let plugin_name = env.name();
|
||||
// TODO: we should really use an async task for this
|
||||
thread::spawn(move || {
|
||||
task::spawn(async move {
|
||||
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
|
||||
// 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();
|
||||
@ -1446,6 +1494,7 @@ fn check_command_permission(
|
||||
PluginCommand::OpenCommandPane(..)
|
||||
| PluginCommand::OpenCommandPaneFloating(..)
|
||||
| PluginCommand::OpenCommandPaneInPlace(..)
|
||||
| PluginCommand::OpenCommandPaneBackground(..)
|
||||
| PluginCommand::RunCommand(..)
|
||||
| PluginCommand::ExecCmd(..) => PermissionType::RunCommands,
|
||||
PluginCommand::WebRequest(..) => PermissionType::WebAccess,
|
||||
|
@ -18,7 +18,7 @@ use zellij_utils::{
|
||||
errors::prelude::*,
|
||||
errors::{ContextType, PtyContext},
|
||||
input::{
|
||||
command::{RunCommand, TerminalAction},
|
||||
command::{OpenFilePayload, RunCommand, TerminalAction},
|
||||
layout::{FloatingPaneLayout, Layout, Run, RunPluginOrAlias, TiledPaneLayout},
|
||||
},
|
||||
pane_size::Size,
|
||||
@ -43,6 +43,7 @@ pub enum PtyInstruction {
|
||||
Option<bool>,
|
||||
Option<String>,
|
||||
Option<FloatingPaneCoordinates>,
|
||||
bool, // start suppressed
|
||||
ClientTabIndexOrPaneId,
|
||||
), // bool (if Some) is
|
||||
// should_float, String is an optional pane name
|
||||
@ -50,6 +51,7 @@ pub enum PtyInstruction {
|
||||
SpawnTerminalVertically(Option<TerminalAction>, Option<String>, ClientId), // String is an
|
||||
// optional pane
|
||||
// name
|
||||
// bool is start_suppressed
|
||||
SpawnTerminalHorizontally(Option<TerminalAction>, Option<String>, ClientId), // String is an
|
||||
// optional pane
|
||||
// name
|
||||
@ -141,29 +143,36 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||
should_float,
|
||||
name,
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
client_or_tab_index,
|
||||
) => {
|
||||
let err_context =
|
||||
|| format!("failed to spawn terminal for {:?}", client_or_tab_index);
|
||||
|
||||
let (hold_on_close, run_command, pane_title) = match &terminal_action {
|
||||
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 =
|
||||
let (hold_on_close, run_command, pane_title, open_file_payload) =
|
||||
match &terminal_action {
|
||||
Some(TerminalAction::RunCommand(run_command)) => {
|
||||
Some(Run::Command(run_command.clone()))
|
||||
},
|
||||
Some(TerminalAction::OpenFile(file, line_number, cwd)) => Some(
|
||||
Run::EditFile(file.clone(), line_number.clone(), cwd.clone()),
|
||||
Some(TerminalAction::RunCommand(run_command)) => (
|
||||
run_command.hold_on_close,
|
||||
Some(run_command.clone()),
|
||||
Some(name.unwrap_or_else(|| run_command.to_string())),
|
||||
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
|
||||
.spawn_terminal(terminal_action, client_or_tab_index)
|
||||
.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)?;
|
||||
}
|
||||
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
|
||||
.senders
|
||||
@ -201,6 +224,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||
hold_for_command,
|
||||
invoked_with,
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
client_or_tab_index,
|
||||
))
|
||||
.with_context(err_context)?;
|
||||
@ -218,6 +242,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||
hold_for_command,
|
||||
invoked_with,
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
client_or_tab_index,
|
||||
))
|
||||
.with_context(err_context)?;
|
||||
@ -259,16 +284,17 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||
),
|
||||
_ => (false, None, name),
|
||||
};
|
||||
let invoked_with =
|
||||
match &terminal_action {
|
||||
Some(TerminalAction::RunCommand(run_command)) => {
|
||||
Some(Run::Command(run_command.clone()))
|
||||
},
|
||||
Some(TerminalAction::OpenFile(file, line_number, cwd)) => Some(
|
||||
Run::EditFile(file.clone(), line_number.clone(), cwd.clone()),
|
||||
),
|
||||
_ => 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
|
||||
.spawn_terminal(terminal_action, client_id_tab_index_or_pane_id)
|
||||
.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);
|
||||
|
||||
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),
|
||||
) {
|
||||
Ok((pid, _starts_held)) => {
|
||||
@ -761,13 +791,13 @@ impl Pty {
|
||||
TerminalAction::RunCommand(ref mut command) => {
|
||||
command.cwd = Some(cwd);
|
||||
},
|
||||
TerminalAction::OpenFile(ref _file, _line_number, ref mut edit_cwd) => {
|
||||
match edit_cwd.as_mut() {
|
||||
TerminalAction::OpenFile(ref mut payload) => {
|
||||
match payload.cwd.as_mut() {
|
||||
Some(edit_cwd) => {
|
||||
*edit_cwd = cwd.join(&edit_cwd);
|
||||
},
|
||||
None => {
|
||||
let _ = edit_cwd.insert(cwd.clone());
|
||||
let _ = payload.cwd.insert(cwd.clone());
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -847,14 +877,24 @@ impl Pty {
|
||||
terminal_action
|
||||
},
|
||||
};
|
||||
let (hold_on_start, hold_on_close, originating_plugin) = match &terminal_action {
|
||||
TerminalAction::RunCommand(run_command) => (
|
||||
run_command.hold_on_start,
|
||||
run_command.hold_on_close,
|
||||
run_command.originating_plugin.clone(),
|
||||
),
|
||||
_ => (false, false, None),
|
||||
};
|
||||
let (hold_on_start, hold_on_close, originating_command_plugin, originating_edit_plugin) =
|
||||
match &terminal_action {
|
||||
TerminalAction::RunCommand(run_command) => (
|
||||
run_command.hold_on_start,
|
||||
run_command.hold_on_close,
|
||||
run_command.originating_plugin.clone(),
|
||||
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 {
|
||||
// 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));
|
||||
}
|
||||
|
||||
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 senders = self.bus.senders.clone();
|
||||
move |pane_id, exit_status, command| {
|
||||
// if this command originated in a plugin, we send the plugin an event letting it
|
||||
// know the command exited and some other useful information
|
||||
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(
|
||||
pane_id,
|
||||
exit_status,
|
||||
originating_plugin.context.clone(),
|
||||
originating_command_plugin.context.clone(),
|
||||
);
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
Some(originating_plugin.plugin_id),
|
||||
Some(originating_plugin.client_id),
|
||||
Some(originating_command_plugin.plugin_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,
|
||||
)]));
|
||||
}
|
||||
@ -1200,7 +1253,11 @@ impl Pty {
|
||||
.context("no OS I/O interface found")
|
||||
.with_context(err_context)?
|
||||
.spawn_terminal(
|
||||
TerminalAction::OpenFile(path_to_file, line_number, cwd),
|
||||
TerminalAction::OpenFile(OpenFilePayload::new(
|
||||
path_to_file,
|
||||
line_number,
|
||||
cwd,
|
||||
)),
|
||||
quit_cb,
|
||||
self.default_editor.clone(),
|
||||
)
|
||||
|
@ -274,7 +274,7 @@ pub(crate) fn route_action(
|
||||
.send_to_screen(ScreenInstruction::TogglePaneFrames)
|
||||
.with_context(err_context)?;
|
||||
},
|
||||
Action::NewPane(direction, name) => {
|
||||
Action::NewPane(direction, name, start_suppressed) => {
|
||||
let shell = default_shell.clone();
|
||||
let pty_instr = match direction {
|
||||
Some(Direction::Left) => {
|
||||
@ -295,22 +295,22 @@ pub(crate) fn route_action(
|
||||
None,
|
||||
name,
|
||||
None,
|
||||
start_suppressed,
|
||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||
),
|
||||
};
|
||||
senders.send_to_pty(pty_instr).with_context(err_context)?;
|
||||
},
|
||||
Action::EditFile(
|
||||
path_to_file,
|
||||
line_number,
|
||||
cwd,
|
||||
open_file_payload,
|
||||
split_direction,
|
||||
should_float,
|
||||
should_open_in_place,
|
||||
start_suppressed,
|
||||
floating_pane_coordinates,
|
||||
) => {
|
||||
let title = format!("Editing: {}", path_to_file.display());
|
||||
let open_file = TerminalAction::OpenFile(path_to_file, line_number, cwd);
|
||||
let title = format!("Editing: {}", open_file_payload.path.display());
|
||||
let open_file = TerminalAction::OpenFile(open_file_payload);
|
||||
let pty_instr = match (split_direction, should_float, should_open_in_place) {
|
||||
(Some(Direction::Left), false, false) => {
|
||||
PtyInstruction::SpawnTerminalVertically(Some(open_file), Some(title), client_id)
|
||||
@ -348,6 +348,7 @@ pub(crate) fn route_action(
|
||||
Some(should_float),
|
||||
Some(title),
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||
),
|
||||
};
|
||||
@ -394,6 +395,7 @@ pub(crate) fn route_action(
|
||||
Some(should_float),
|
||||
name,
|
||||
floating_pane_coordinates,
|
||||
false,
|
||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||
))
|
||||
.with_context(err_context)?;
|
||||
@ -447,6 +449,7 @@ pub(crate) fn route_action(
|
||||
Some(should_float),
|
||||
name,
|
||||
None,
|
||||
false,
|
||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||
),
|
||||
};
|
||||
@ -496,6 +499,7 @@ pub(crate) fn route_action(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
ClientTabIndexOrPaneId::ClientId(client_id),
|
||||
),
|
||||
};
|
||||
|
@ -152,6 +152,7 @@ pub enum ScreenInstruction {
|
||||
HoldForCommand,
|
||||
Option<Run>, // invoked with
|
||||
Option<FloatingPaneCoordinates>,
|
||||
bool, // start suppressed
|
||||
ClientTabIndexOrPaneId,
|
||||
),
|
||||
OpenInPlaceEditor(PaneId, ClientId),
|
||||
@ -312,6 +313,7 @@ pub enum ScreenInstruction {
|
||||
u32, // plugin id
|
||||
Option<PaneId>,
|
||||
Option<PathBuf>, // cwd
|
||||
bool, // start suppressed
|
||||
Option<ClientId>,
|
||||
),
|
||||
UpdatePluginLoadingStage(u32, LoadingIndication), // u32 - plugin_id
|
||||
@ -1905,7 +1907,7 @@ impl Screen {
|
||||
tab_index_and_plugin_pane_id = Some((*tab_index, plugin_pane_id));
|
||||
if move_to_focused_tab && focused_tab_index != *tab_index {
|
||||
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;
|
||||
@ -1992,7 +1994,7 @@ impl Screen {
|
||||
.with_context(err_context)?;
|
||||
let pane_to_break_is_floating = active_tab.are_floating_panes_visible();
|
||||
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)?;
|
||||
let active_pane_run_instruction = active_pane.invoked_with().clone();
|
||||
let tab_index = self.get_new_tab_index();
|
||||
@ -2053,7 +2055,7 @@ impl Screen {
|
||||
.with_context(err_context)?;
|
||||
let pane_to_break_is_floating = active_tab.are_floating_panes_visible();
|
||||
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)?;
|
||||
(active_pane_id, active_pane, pane_to_break_is_floating)
|
||||
};
|
||||
@ -2456,6 +2458,7 @@ pub(crate) fn screen_thread_main(
|
||||
hold_for_command,
|
||||
invoked_with,
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
client_or_tab_index,
|
||||
) => {
|
||||
match client_or_tab_index {
|
||||
@ -2466,6 +2469,7 @@ pub(crate) fn screen_thread_main(
|
||||
should_float,
|
||||
invoked_with,
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
Some(client_id)
|
||||
)
|
||||
}, ?);
|
||||
@ -2491,6 +2495,7 @@ pub(crate) fn screen_thread_main(
|
||||
should_float,
|
||||
invoked_with,
|
||||
floating_pane_coordinates,
|
||||
start_suppressed,
|
||||
None,
|
||||
)?;
|
||||
if let Some(hold_for_command) = hold_for_command {
|
||||
@ -2999,6 +3004,7 @@ pub(crate) fn screen_thread_main(
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
screen.unblock_input()?;
|
||||
screen.log_and_report_session_state()?;
|
||||
},
|
||||
@ -3632,6 +3638,7 @@ pub(crate) fn screen_thread_main(
|
||||
plugin_id,
|
||||
pane_id_to_replace,
|
||||
cwd,
|
||||
start_suppressed,
|
||||
client_id,
|
||||
) => {
|
||||
let pane_title = pane_title.unwrap_or_else(|| {
|
||||
@ -3676,6 +3683,7 @@ pub(crate) fn screen_thread_main(
|
||||
should_float,
|
||||
Some(run_plugin),
|
||||
None,
|
||||
start_suppressed,
|
||||
Some(client_id),
|
||||
)
|
||||
}, ?);
|
||||
@ -3688,6 +3696,7 @@ pub(crate) fn screen_thread_main(
|
||||
should_float,
|
||||
Some(run_plugin),
|
||||
None,
|
||||
start_suppressed,
|
||||
None,
|
||||
)?;
|
||||
} else {
|
||||
|
@ -30,6 +30,7 @@ use self::clipboard::ClipboardProvider;
|
||||
use crate::{
|
||||
os_input_output::ServerOsApi,
|
||||
output::{CharacterChunk, Output, SixelImageChunk},
|
||||
panes::floating_panes::floating_pane_grid::half_size_middle_geom,
|
||||
panes::sixel::SixelImageStore,
|
||||
panes::{FloatingPanes, TiledPanes},
|
||||
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 self.tiled_panes.has_room_for_new_pane() {
|
||||
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!(
|
||||
"failed to find floating pane (ID: {focused_floating_pane_id:?}) to embed for client {client_id}",
|
||||
))
|
||||
@ -1004,7 +1005,7 @@ impl Tab {
|
||||
return Ok(());
|
||||
}
|
||||
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.add_floating_pane(
|
||||
@ -1047,11 +1048,13 @@ impl Tab {
|
||||
Some(client_id) => ClientTabIndexOrPaneId::ClientId(client_id),
|
||||
None => ClientTabIndexOrPaneId::TabIndex(self.index),
|
||||
};
|
||||
let should_start_suppressed = false;
|
||||
let instruction = PtyInstruction::SpawnTerminal(
|
||||
default_shell,
|
||||
Some(should_float),
|
||||
name,
|
||||
None,
|
||||
should_start_suppressed,
|
||||
client_id_or_tab_index,
|
||||
);
|
||||
self.senders
|
||||
@ -1071,6 +1074,7 @@ impl Tab {
|
||||
should_float: Option<bool>,
|
||||
invoked_with: Option<Run>,
|
||||
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
|
||||
start_suppressed: bool,
|
||||
client_id: Option<ClientId>,
|
||||
) -> Result<()> {
|
||||
let err_context = || format!("failed to create new pane with id {pid:?}");
|
||||
@ -1081,7 +1085,7 @@ impl Tab {
|
||||
};
|
||||
self.close_down_to_max_terminals()
|
||||
.with_context(err_context)?;
|
||||
let new_pane = match pid {
|
||||
let mut new_pane = match pid {
|
||||
PaneId::Terminal(term_pid) => {
|
||||
let next_terminal_position = self.get_next_terminal_position();
|
||||
Box::new(TerminalPane::new(
|
||||
@ -1128,7 +1132,32 @@ impl Tab {
|
||||
)) 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)
|
||||
} else {
|
||||
self.add_tiled_pane(new_pane, pid, client_id)
|
||||
@ -2448,8 +2477,14 @@ impl Tab {
|
||||
self.get_tiled_panes().map(|(&pid, _)| pid).collect()
|
||||
}
|
||||
pub fn get_all_pane_ids(&self) -> Vec<PaneId> {
|
||||
// this is here just as a naming thing to make things more explicit
|
||||
self.get_static_and_floating_pane_ids()
|
||||
let mut 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> {
|
||||
self.tiled_panes
|
||||
@ -2494,26 +2529,22 @@ impl Tab {
|
||||
id: PaneId,
|
||||
ignore_suppressed_panes: bool,
|
||||
client_id: Option<ClientId>,
|
||||
) -> Option<Box<dyn Pane>> {
|
||||
) {
|
||||
// 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
|
||||
// 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) {
|
||||
return match self.replace_pane_with_suppressed_pane(id) {
|
||||
Ok(pane) => pane,
|
||||
Ok(_pane) => {},
|
||||
Err(e) => {
|
||||
Err::<(), _>(e)
|
||||
.with_context(|| format!("failed to close pane {:?}", id))
|
||||
.non_fatal();
|
||||
None
|
||||
},
|
||||
};
|
||||
}
|
||||
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);
|
||||
if !self.floating_panes.has_panes() {
|
||||
self.hide_floating_panes();
|
||||
@ -2529,12 +2560,11 @@ impl Tab {
|
||||
// confusing
|
||||
let _ = self.next_swap_layout(client_id, false);
|
||||
}
|
||||
closed_pane
|
||||
} else {
|
||||
if self.tiled_panes.fullscreen_is_active() {
|
||||
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.tiled_panes.set_force_render();
|
||||
if self.auto_layout && !self.swap_layouts.is_tiled_damaged() {
|
||||
@ -2543,14 +2573,30 @@ impl Tab {
|
||||
// confusing
|
||||
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(
|
||||
&mut self,
|
||||
id: PaneId,
|
||||
ignore_suppressed_panes: bool,
|
||||
client_id: Option<ClientId>,
|
||||
) -> 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) {
|
||||
let closed_pane = self.floating_panes.remove_pane(id);
|
||||
self.floating_panes.move_clients_out_of_pane(id);
|
||||
@ -2609,9 +2655,11 @@ impl Tab {
|
||||
if self.floating_panes.panes_contain(&id) {
|
||||
self.floating_panes
|
||||
.hold_pane(id, exit_status, is_first_run, run_command);
|
||||
} else {
|
||||
} else if self.tiled_panes.panes_contain(&id) {
|
||||
self.tiled_panes
|
||||
.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(
|
||||
@ -3772,7 +3820,7 @@ impl Tab {
|
||||
// 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
|
||||
// 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;
|
||||
self.suppressed_panes
|
||||
.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);
|
||||
for i in 2..5 {
|
||||
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();
|
||||
}
|
||||
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() {
|
||||
let size = Size { cols: 8, rows: 4 };
|
||||
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();
|
||||
assert_eq!(
|
||||
tab.tiled_panes.panes.len(),
|
||||
@ -821,7 +821,7 @@ pub fn toggle_focused_pane_fullscreen() {
|
||||
let mut tab = create_new_tab(size);
|
||||
for i in 2..5 {
|
||||
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();
|
||||
}
|
||||
tab.toggle_active_pane_fullscreen(1);
|
||||
@ -896,16 +896,16 @@ fn switch_to_next_pane_fullscreen() {
|
||||
let mut active_tab = create_new_tab(size);
|
||||
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
active_tab.toggle_active_pane_fullscreen(1);
|
||||
|
||||
@ -936,16 +936,16 @@ fn switch_to_prev_pane_fullscreen() {
|
||||
//testing four consecutive switches in fullscreen mode
|
||||
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
active_tab.toggle_active_pane_fullscreen(1);
|
||||
// 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());
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
active_tab.toggle_active_pane_fullscreen(1);
|
||||
}
|
||||
@ -1315,6 +1315,7 @@ fn open_new_floating_pane_with_custom_coordinates() {
|
||||
width: Some(SplitSize::Percent(1)),
|
||||
height: Some(SplitSize::Fixed(2)),
|
||||
}),
|
||||
false,
|
||||
Some(1),
|
||||
)
|
||||
.unwrap();
|
||||
@ -1348,6 +1349,7 @@ fn open_new_floating_pane_with_custom_coordinates_exceeding_viewport() {
|
||||
width: Some(SplitSize::Fixed(10)),
|
||||
height: Some(SplitSize::Fixed(10)),
|
||||
}),
|
||||
false,
|
||||
Some(1),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 2031
|
||||
assertion_line: 2389
|
||||
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
|
||||
assertion_line: 2065
|
||||
assertion_line: 2427
|
||||
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
|
||||
assertion_line: 2178
|
||||
assertion_line: 2465
|
||||
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
|
||||
assertion_line: 1911
|
||||
assertion_line: 2222
|
||||
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
|
||||
assertion_line: 2349
|
||||
assertion_line: 2351
|
||||
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
|
||||
|
||||
/// Open a file in the user's default `$EDITOR` in a new pane
|
||||
pub fn open_file(file_to_open: FileToOpen) {
|
||||
let plugin_command = PluginCommand::OpenFile(file_to_open);
|
||||
pub fn open_file(file_to_open: FileToOpen, context: BTreeMap<String, String>) {
|
||||
let plugin_command = PluginCommand::OpenFile(file_to_open, 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() };
|
||||
}
|
||||
|
||||
/// 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>) {
|
||||
let plugin_command = PluginCommand::OpenFileFloating(file_to_open, coordinates);
|
||||
pub fn open_file_floating(
|
||||
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();
|
||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||
unsafe { host_run_plugin_command() };
|
||||
}
|
||||
|
||||
/// Open a file in the user's default `$EDITOR`, replacing the focused pane
|
||||
pub fn open_file_in_place(file_to_open: FileToOpen) {
|
||||
let plugin_command = PluginCommand::OpenFileInPlace(file_to_open);
|
||||
pub fn open_file_in_place(file_to_open: FileToOpen, context: BTreeMap<String, String>) {
|
||||
let plugin_command = PluginCommand::OpenFileInPlace(file_to_open, 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() };
|
||||
@ -159,6 +163,17 @@ pub fn open_command_pane_in_place(command_to_run: CommandToRun, context: BTreeMa
|
||||
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`).
|
||||
pub fn switch_tab_to(tab_idx: u32) {
|
||||
let plugin_command = PluginCommand::SwitchTabTo(tab_idx);
|
||||
|
@ -11,7 +11,7 @@ pub struct Event {
|
||||
pub name: i32,
|
||||
#[prost(
|
||||
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>,
|
||||
}
|
||||
@ -52,10 +52,31 @@ pub mod event {
|
||||
CommandPaneOpenedPayload(super::CommandPaneOpenedPayload),
|
||||
#[prost(message, tag = "17")]
|
||||
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)]
|
||||
#[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 {
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub terminal_pane_id: u32,
|
||||
@ -64,6 +85,14 @@ pub struct CommandPaneOpenedPayload {
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[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 {
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub terminal_pane_id: u32,
|
||||
@ -74,6 +103,16 @@ pub struct CommandPaneExitedPayload {
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[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 {
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub session_manifests: ::prost::alloc::vec::Vec<SessionManifest>,
|
||||
@ -373,6 +412,9 @@ pub enum EventType {
|
||||
WebRequestResult = 18,
|
||||
CommandPaneOpened = 19,
|
||||
CommandPaneExited = 20,
|
||||
PaneClosed = 21,
|
||||
EditPaneOpened = 22,
|
||||
EditPaneExited = 23,
|
||||
}
|
||||
impl EventType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
@ -402,6 +444,9 @@ impl EventType {
|
||||
EventType::WebRequestResult => "WebRequestResult",
|
||||
EventType::CommandPaneOpened => "CommandPaneOpened",
|
||||
EventType::CommandPaneExited => "CommandPaneExited",
|
||||
EventType::PaneClosed => "PaneClosed",
|
||||
EventType::EditPaneOpened => "EditPaneOpened",
|
||||
EventType::EditPaneExited => "EditPaneExited",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
@ -428,6 +473,36 @@ impl EventType {
|
||||
"WebRequestResult" => Some(Self::WebRequestResult),
|
||||
"CommandPaneOpened" => Some(Self::CommandPaneOpened),
|
||||
"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,
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ pub struct PluginCommand {
|
||||
pub name: i32,
|
||||
#[prost(
|
||||
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>,
|
||||
}
|
||||
@ -124,6 +124,8 @@ pub mod plugin_command {
|
||||
HidePaneWithIdPayload(super::HidePaneWithIdPayload),
|
||||
#[prost(message, tag = "65")]
|
||||
ShowPaneWithIdPayload(super::ShowPaneWithIdPayload),
|
||||
#[prost(message, tag = "66")]
|
||||
OpenCommandPaneBackgroundPayload(super::OpenCommandPanePayload),
|
||||
}
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
@ -245,6 +247,8 @@ pub struct OpenFilePayload {
|
||||
pub file_to_open: ::core::option::Option<super::file::File>,
|
||||
#[prost(message, optional, tag = "2")]
|
||||
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)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
@ -456,6 +460,7 @@ pub enum CommandName {
|
||||
Reconfigure = 87,
|
||||
HidePaneWithId = 88,
|
||||
ShowPaneWithId = 89,
|
||||
OpenCommandPaneBackground = 90,
|
||||
}
|
||||
impl CommandName {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
@ -554,6 +559,7 @@ impl CommandName {
|
||||
CommandName::Reconfigure => "Reconfigure",
|
||||
CommandName::HidePaneWithId => "HidePaneWithId",
|
||||
CommandName::ShowPaneWithId => "ShowPaneWithId",
|
||||
CommandName::OpenCommandPaneBackground => "OpenCommandPaneBackground",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
@ -649,6 +655,7 @@ impl CommandName {
|
||||
"Reconfigure" => Some(Self::Reconfigure),
|
||||
"HidePaneWithId" => Some(Self::HidePaneWithId),
|
||||
"ShowPaneWithId" => Some(Self::ShowPaneWithId),
|
||||
"OpenCommandPaneBackground" => Some(Self::OpenCommandPaneBackground),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -915,7 +915,10 @@ pub enum Event {
|
||||
// context
|
||||
CommandPaneOpened(u32, Context), // u32 - terminal_pane_id
|
||||
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(
|
||||
@ -1446,7 +1449,7 @@ pub struct NewPluginArgs {
|
||||
pub skip_cache: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum PaneId {
|
||||
Terminal(u32),
|
||||
Plugin(u32),
|
||||
@ -1702,8 +1705,8 @@ pub enum PluginCommand {
|
||||
SetSelectable(bool),
|
||||
GetPluginIds,
|
||||
GetZellijVersion,
|
||||
OpenFile(FileToOpen),
|
||||
OpenFileFloating(FileToOpen, Option<FloatingPaneCoordinates>),
|
||||
OpenFile(FileToOpen, Context),
|
||||
OpenFileFloating(FileToOpen, Option<FloatingPaneCoordinates>, Context),
|
||||
OpenTerminal(FileToOpen), // only used for the path as cwd
|
||||
OpenTerminalFloating(FileToOpen, Option<FloatingPaneCoordinates>), // only used for the path as cwd
|
||||
OpenCommandPane(CommandToRun, Context),
|
||||
@ -1768,7 +1771,7 @@ pub enum PluginCommand {
|
||||
DeleteDeadSession(String), // String -> session name
|
||||
DeleteAllDeadSessions, // String -> session name
|
||||
OpenTerminalInPlace(FileToOpen), // only used for the path as cwd
|
||||
OpenFileInPlace(FileToOpen),
|
||||
OpenFileInPlace(FileToOpen, Context),
|
||||
OpenCommandPaneInPlace(CommandToRun, Context),
|
||||
RunCommand(
|
||||
Vec<String>, // command
|
||||
@ -1798,4 +1801,5 @@ pub enum PluginCommand {
|
||||
Reconfigure(String), // String -> stringified configuration
|
||||
HidePaneWithId(PaneId),
|
||||
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.
|
||||
|
||||
use super::command::RunCommandAction;
|
||||
use super::command::{OpenFilePayload, RunCommandAction};
|
||||
use super::layout::{
|
||||
FloatingPaneLayout, Layout, PluginAlias, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||
SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout,
|
||||
@ -157,17 +157,17 @@ pub enum Action {
|
||||
ToggleActiveSyncTab,
|
||||
/// Open a new pane in the specified direction (relative to focus).
|
||||
/// If no direction is specified, will try to use the biggest available space.
|
||||
NewPane(Option<Direction>, Option<String>), // String is an optional pane name
|
||||
/// Open the file in a new pane using the default editor
|
||||
NewPane(Option<Direction>, Option<String>, bool), // String is an optional pane name
|
||||
/// Open the file in a new pane using the default editor, bool -> start suppressed
|
||||
EditFile(
|
||||
PathBuf,
|
||||
Option<usize>,
|
||||
Option<PathBuf>,
|
||||
OpenFilePayload,
|
||||
Option<Direction>,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
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
|
||||
NewFloatingPane(
|
||||
Option<RunCommandAction>,
|
||||
@ -485,13 +485,13 @@ impl Action {
|
||||
file = cwd.join(file);
|
||||
}
|
||||
}
|
||||
let start_suppressed = false;
|
||||
Ok(vec![Action::EditFile(
|
||||
file,
|
||||
line_number,
|
||||
cwd,
|
||||
OpenFilePayload::new(file, line_number, cwd),
|
||||
direction,
|
||||
floating,
|
||||
in_place,
|
||||
start_suppressed,
|
||||
FloatingPaneCoordinates::new(x, y, width, height),
|
||||
)])
|
||||
},
|
||||
|
@ -5,16 +5,15 @@ use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TerminalAction {
|
||||
OpenFile(PathBuf, Option<usize>, Option<PathBuf>), // path to file (should be absolute), optional line_number and an
|
||||
// optional cwd
|
||||
OpenFile(OpenFilePayload),
|
||||
RunCommand(RunCommand),
|
||||
}
|
||||
|
||||
impl TerminalAction {
|
||||
pub fn change_cwd(&mut self, new_cwd: PathBuf) {
|
||||
match self {
|
||||
TerminalAction::OpenFile(_, _, cwd) => {
|
||||
*cwd = Some(new_cwd);
|
||||
TerminalAction::OpenFile(open_file_payload) => {
|
||||
open_file_payload.cwd = Some(new_cwd);
|
||||
},
|
||||
TerminalAction::RunCommand(run_command) => {
|
||||
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)]
|
||||
pub struct RunCommand {
|
||||
#[serde(alias = "cmd")]
|
||||
|
@ -507,7 +507,7 @@ impl Action {
|
||||
"DumpLayout" => Ok(Action::DumpLayout),
|
||||
"NewPane" => {
|
||||
if string.is_empty() {
|
||||
return Ok(Action::NewPane(None, None));
|
||||
return Ok(Action::NewPane(None, None, false));
|
||||
} else {
|
||||
let direction = Direction::from_str(string.as_str()).map_err(|_| {
|
||||
ConfigError::new_kdl_error(
|
||||
@ -516,7 +516,7 @@ impl Action {
|
||||
action_node.span().len(),
|
||||
)
|
||||
})?;
|
||||
Ok(Action::NewPane(Some(direction), None))
|
||||
Ok(Action::NewPane(Some(direction), None, false))
|
||||
}
|
||||
},
|
||||
"SearchToggleOption" => {
|
||||
|
@ -17,7 +17,7 @@ use crate::data::{Direction, InputMode, ResizeStrategy};
|
||||
use crate::errors::prelude::*;
|
||||
use crate::input::actions::Action;
|
||||
use crate::input::actions::{SearchDirection, SearchOption};
|
||||
use crate::input::command::RunCommandAction;
|
||||
use crate::input::command::{OpenFilePayload, RunCommandAction};
|
||||
use crate::input::layout::{
|
||||
PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias,
|
||||
};
|
||||
@ -220,7 +220,7 @@ impl TryFrom<ProtobufAction> for Action {
|
||||
.and_then(|d| ProtobufResizeDirection::from_i32(d))
|
||||
.and_then(|d| d.try_into().ok());
|
||||
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"),
|
||||
},
|
||||
@ -236,12 +236,11 @@ impl TryFrom<ProtobufAction> for Action {
|
||||
let should_float = payload.should_float;
|
||||
let should_be_in_place = false;
|
||||
Ok(Action::EditFile(
|
||||
file_to_edit,
|
||||
line_number,
|
||||
cwd,
|
||||
OpenFilePayload::new(file_to_edit, line_number, cwd),
|
||||
direction,
|
||||
should_float,
|
||||
should_be_in_place,
|
||||
false,
|
||||
None,
|
||||
))
|
||||
},
|
||||
@ -885,7 +884,7 @@ impl TryFrom<Action> for ProtobufAction {
|
||||
name: ProtobufActionName::ToggleActiveSyncTab as i32,
|
||||
optional_payload: None,
|
||||
}),
|
||||
Action::NewPane(direction, new_pane_name) => {
|
||||
Action::NewPane(direction, new_pane_name, _start_suppressed) => {
|
||||
let direction = direction.and_then(|direction| {
|
||||
let protobuf_direction: ProtobufResizeDirection = direction.try_into().ok()?;
|
||||
Some(protobuf_direction as i32)
|
||||
@ -899,20 +898,19 @@ impl TryFrom<Action> for ProtobufAction {
|
||||
})
|
||||
},
|
||||
Action::EditFile(
|
||||
path_to_file,
|
||||
line_number,
|
||||
cwd,
|
||||
open_file_payload,
|
||||
direction,
|
||||
should_float,
|
||||
_should_be_in_place,
|
||||
_floating_pane_coordinates,
|
||||
_start_suppressed,
|
||||
) => {
|
||||
let file_to_edit = path_to_file.display().to_string();
|
||||
let cwd = cwd.map(|cwd| cwd.display().to_string());
|
||||
let file_to_edit = open_file_payload.path.display().to_string();
|
||||
let cwd = open_file_payload.cwd.map(|cwd| cwd.display().to_string());
|
||||
let direction: Option<i32> = direction
|
||||
.and_then(|d| ProtobufResizeDirection::try_from(d).ok())
|
||||
.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 {
|
||||
name: ProtobufActionName::EditFile as i32,
|
||||
optional_payload: Some(OptionalPayload::EditFilePayload(EditFilePayload {
|
||||
|
@ -44,6 +44,9 @@ enum EventType {
|
||||
WebRequestResult = 18;
|
||||
CommandPaneOpened = 19;
|
||||
CommandPaneExited = 20;
|
||||
PaneClosed = 21;
|
||||
EditPaneOpened = 22;
|
||||
EditPaneExited = 23;
|
||||
}
|
||||
|
||||
message EventNameList {
|
||||
@ -69,20 +72,50 @@ message Event {
|
||||
WebRequestResultPayload web_request_result_payload = 15;
|
||||
CommandPaneOpenedPayload command_pane_opened_payload = 16;
|
||||
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 {
|
||||
uint32 terminal_pane_id = 1;
|
||||
repeated ContextItem context = 2;
|
||||
}
|
||||
|
||||
message EditPaneOpenedPayload {
|
||||
uint32 terminal_pane_id = 1;
|
||||
repeated ContextItem context = 2;
|
||||
}
|
||||
|
||||
message CommandPaneExitedPayload {
|
||||
uint32 terminal_pane_id = 1;
|
||||
optional int32 exit_code = 2;
|
||||
repeated ContextItem context = 3;
|
||||
}
|
||||
|
||||
message EditPaneExitedPayload {
|
||||
uint32 terminal_pane_id = 1;
|
||||
optional int32 exit_code = 2;
|
||||
repeated ContextItem context = 3;
|
||||
}
|
||||
|
||||
message SessionUpdatePayload {
|
||||
repeated SessionManifest session_manifests = 1;
|
||||
repeated ResurrectableSession resurrectable_sessions = 2;
|
||||
|
@ -6,7 +6,8 @@ pub use super::generated_api::api::{
|
||||
EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
|
||||
InputModeKeybinds as ProtobufInputModeKeybinds, KeyBind as ProtobufKeyBind,
|
||||
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,
|
||||
SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *,
|
||||
},
|
||||
@ -17,8 +18,8 @@ pub use super::generated_api::api::{
|
||||
#[allow(hidden_glob_reexports)]
|
||||
use crate::data::{
|
||||
CopyDestination, Event, EventType, FileMetadata, InputMode, KeyWithModifier, LayoutInfo,
|
||||
ModeInfo, Mouse, PaneInfo, PaneManifest, PermissionStatus, PluginCapabilities, SessionInfo,
|
||||
Style, TabInfo,
|
||||
ModeInfo, Mouse, PaneId, PaneInfo, PaneManifest, PermissionStatus, PluginCapabilities,
|
||||
SessionInfo, Style, TabInfo,
|
||||
};
|
||||
|
||||
use crate::errors::prelude::*;
|
||||
@ -262,6 +263,42 @@ impl TryFrom<ProtobufEvent> for 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"),
|
||||
}
|
||||
}
|
||||
@ -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::CommandPaneOpened => EventType::CommandPaneOpened,
|
||||
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::CommandPaneOpened => ProtobufEventType::CommandPaneOpened,
|
||||
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"
|
||||
);
|
||||
}
|
||||
|
||||
// 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;
|
||||
HidePaneWithId = 88;
|
||||
ShowPaneWithId = 89;
|
||||
OpenCommandPaneBackground = 90;
|
||||
}
|
||||
|
||||
message PluginCommand {
|
||||
@ -161,6 +162,7 @@ message PluginCommand {
|
||||
string reconfigure_payload = 63;
|
||||
HidePaneWithIdPayload hide_pane_with_id_payload = 64;
|
||||
ShowPaneWithIdPayload show_pane_with_id_payload = 65;
|
||||
OpenCommandPanePayload open_command_pane_background_payload = 66;
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,6 +240,7 @@ message UnsubscribePayload {
|
||||
message OpenFilePayload {
|
||||
file.File file_to_open = 1;
|
||||
optional FloatingPaneCoordinates floating_pane_coordinates = 2;
|
||||
repeated ContextItem context = 3;
|
||||
}
|
||||
|
||||
message OpenCommandPanePayload {
|
||||
|
@ -227,7 +227,14 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||
Some(CommandName::OpenFile) => match protobuf_plugin_command.payload {
|
||||
Some(Payload::OpenFilePayload(file_to_open_payload)) => {
|
||||
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"),
|
||||
}
|
||||
},
|
||||
@ -238,10 +245,16 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||
let floating_pane_coordinates = file_to_open_payload
|
||||
.floating_pane_coordinates
|
||||
.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 {
|
||||
Some(file_to_open) => Ok(PluginCommand::OpenFileFloating(
|
||||
file_to_open.try_into()?,
|
||||
floating_pane_coordinates,
|
||||
context,
|
||||
)),
|
||||
None => Err("Malformed open file payload"),
|
||||
}
|
||||
@ -725,7 +738,15 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||
Some(Payload::OpenFileInPlacePayload(file_to_open_payload)) => {
|
||||
match file_to_open_payload.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"),
|
||||
}
|
||||
@ -942,6 +963,25 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||
},
|
||||
_ => 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"),
|
||||
}
|
||||
}
|
||||
@ -981,19 +1021,27 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||
name: CommandName::GetZellijVersion as i32,
|
||||
payload: None,
|
||||
}),
|
||||
PluginCommand::OpenFile(file_to_open) => Ok(ProtobufPluginCommand {
|
||||
PluginCommand::OpenFile(file_to_open, context) => Ok(ProtobufPluginCommand {
|
||||
name: CommandName::OpenFile as i32,
|
||||
payload: Some(Payload::OpenFilePayload(OpenFilePayload {
|
||||
file_to_open: Some(file_to_open.try_into()?),
|
||||
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 {
|
||||
name: CommandName::OpenFileFloating as i32,
|
||||
payload: Some(Payload::OpenFileFloatingPayload(OpenFilePayload {
|
||||
file_to_open: Some(file_to_open.try_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 {
|
||||
file_to_open: Some(cwd.try_into()?),
|
||||
floating_pane_coordinates: None,
|
||||
context: vec![], // will be added in the future
|
||||
})),
|
||||
}),
|
||||
PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => {
|
||||
@ -1010,6 +1059,7 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||
payload: Some(Payload::OpenTerminalFloatingPayload(OpenFilePayload {
|
||||
file_to_open: Some(cwd.try_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 {
|
||||
file_to_open: Some(cwd.try_into()?),
|
||||
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,
|
||||
payload: Some(Payload::OpenFileInPlacePayload(OpenFilePayload {
|
||||
file_to_open: Some(file_to_open.try_into()?),
|
||||
floating_pane_coordinates: None,
|
||||
context: context
|
||||
.into_iter()
|
||||
.map(|(name, value)| ContextItem { name, value })
|
||||
.collect(),
|
||||
})),
|
||||
}),
|
||||
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(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -731,6 +732,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -990,6 +992,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1160,6 +1163,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1188,6 +1192,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -1255,6 +1260,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1786,6 +1792,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2255,6 +2262,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2608,6 +2616,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3043,6 +3052,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3411,6 +3421,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3742,6 +3753,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4097,6 +4109,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4541,6 +4554,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4875,6 +4889,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -5068,6 +5083,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5084,6 +5100,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5392,6 +5409,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
|
@ -234,6 +234,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -731,6 +732,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -990,6 +992,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1160,6 +1163,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1188,6 +1192,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -1255,6 +1260,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1786,6 +1792,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2255,6 +2262,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2608,6 +2616,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3043,6 +3052,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3411,6 +3421,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3742,6 +3753,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4097,6 +4109,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4541,6 +4554,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4875,6 +4889,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -5068,6 +5083,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5084,6 +5100,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5392,6 +5409,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
|
@ -234,6 +234,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -731,6 +732,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -990,6 +992,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1160,6 +1163,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1188,6 +1192,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -1255,6 +1260,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1786,6 +1792,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2255,6 +2262,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2608,6 +2616,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3043,6 +3052,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3411,6 +3421,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3742,6 +3753,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4097,6 +4109,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4541,6 +4554,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4875,6 +4889,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -5068,6 +5083,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5084,6 +5100,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5392,6 +5409,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
|
@ -234,6 +234,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -731,6 +732,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -990,6 +992,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1160,6 +1163,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1188,6 +1192,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -1255,6 +1260,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -1786,6 +1792,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2255,6 +2262,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -2608,6 +2616,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3043,6 +3052,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3411,6 +3421,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -3742,6 +3753,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4097,6 +4109,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4541,6 +4554,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -4875,6 +4889,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
@ -5068,6 +5083,7 @@ Config {
|
||||
Down,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5084,6 +5100,7 @@ Config {
|
||||
Right,
|
||||
),
|
||||
None,
|
||||
false,
|
||||
),
|
||||
SwitchToMode(
|
||||
Normal,
|
||||
@ -5392,6 +5409,7 @@ Config {
|
||||
NewPane(
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
],
|
||||
KeyWithModifier {
|
||||
|
Loading…
Reference in New Issue
Block a user