feat(plugins): APIs to break multiple panes into a new tab or an existing tab (#3610)
* feat(plugins): break multiple panes to a new tab * fix(layouts): properly ignore run instructions when breaking panes * feat(plugins): break multiple panes to existing tab * feat(apis): allow these methods to also specify whether they want focus changed to the tab * various fixes * allow specifying name for the new tab when breaking out panes * style(fmt): rustfmt
This commit is contained in:
parent
5868aa297c
commit
d78f3586dd
31 changed files with 837 additions and 132 deletions
|
|
@ -415,6 +415,22 @@ impl ZellijPlugin for State {
|
|||
BareKey::Char('t') if key.has_modifiers(&[KeyModifier::Alt]) => {
|
||||
close_tab_with_index(2);
|
||||
},
|
||||
BareKey::Char('u') if key.has_modifiers(&[KeyModifier::Alt]) => {
|
||||
let should_change_focus_to_new_tab = true;
|
||||
break_panes_to_new_tab(
|
||||
&[PaneId::Terminal(1), PaneId::Plugin(2)],
|
||||
Some("new_tab_name".to_owned()),
|
||||
should_change_focus_to_new_tab,
|
||||
);
|
||||
},
|
||||
BareKey::Char('v') if key.has_modifiers(&[KeyModifier::Alt]) => {
|
||||
let should_change_focus_to_target_tab = true;
|
||||
break_panes_to_tab_with_index(
|
||||
&[PaneId::Terminal(1), PaneId::Plugin(2)],
|
||||
2,
|
||||
should_change_focus_to_target_tab,
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
},
|
||||
Event::CustomMessage(message, payload) => {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ pub enum PluginInstruction {
|
|||
Option<TiledPaneLayout>,
|
||||
Vec<FloatingPaneLayout>,
|
||||
usize, // tab_index
|
||||
bool, // should change focus to new tab
|
||||
ClientId,
|
||||
),
|
||||
ApplyCachedEvents {
|
||||
|
|
@ -377,6 +378,7 @@ pub(crate) fn plugin_thread_main(
|
|||
mut tab_layout,
|
||||
mut floating_panes_layout,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
) => {
|
||||
// prefer connected clients so as to avoid opening plugins in the background for
|
||||
|
|
@ -444,6 +446,7 @@ pub(crate) fn plugin_thread_main(
|
|||
floating_panes_layout,
|
||||
tab_index,
|
||||
plugin_ids,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
)));
|
||||
},
|
||||
|
|
|
|||
|
|
@ -239,6 +239,60 @@ macro_rules! grant_permissions_and_log_actions_in_thread_naked_variant {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! grant_permissions_and_log_actions_in_thread_struct_variant {
|
||||
( $arc_mutex_log:expr, $exit_event:path, $receiver:expr, $exit_after_count:expr, $permission_type:expr, $cache_path:expr, $plugin_thread_sender:expr, $client_id:expr ) => {
|
||||
std::thread::Builder::new()
|
||||
.name("fake_screen_thread".to_string())
|
||||
.spawn({
|
||||
let log = $arc_mutex_log.clone();
|
||||
let mut exit_event_count = 0;
|
||||
let cache_path = $cache_path.clone();
|
||||
let plugin_thread_sender = $plugin_thread_sender.clone();
|
||||
move || loop {
|
||||
let (event, _err_ctx) = $receiver
|
||||
.recv()
|
||||
.expect("failed to receive event on channel");
|
||||
match event {
|
||||
$exit_event { .. } => {
|
||||
exit_event_count += 1;
|
||||
log.lock().unwrap().push(event);
|
||||
if exit_event_count == $exit_after_count {
|
||||
break;
|
||||
}
|
||||
},
|
||||
ScreenInstruction::RequestPluginPermissions(_, plugin_permission) => {
|
||||
if plugin_permission.permissions.contains($permission_type) {
|
||||
let _ = plugin_thread_sender.send(
|
||||
PluginInstruction::PermissionRequestResult(
|
||||
0,
|
||||
Some($client_id),
|
||||
plugin_permission.permissions,
|
||||
PermissionStatus::Granted,
|
||||
Some(cache_path.clone()),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
let _ = plugin_thread_sender.send(
|
||||
PluginInstruction::PermissionRequestResult(
|
||||
0,
|
||||
Some($client_id),
|
||||
plugin_permission.permissions,
|
||||
PermissionStatus::Denied,
|
||||
Some(cache_path.clone()),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
log.lock().unwrap().push(event);
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
fn create_plugin_thread(
|
||||
zellij_cwd: Option<PathBuf>,
|
||||
) -> (
|
||||
|
|
@ -8120,3 +8174,145 @@ pub fn close_tab_with_index_plugin_command() {
|
|||
.clone();
|
||||
assert_snapshot!(format!("{:#?}", screen_instruction));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
pub fn break_panes_to_new_tab_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_struct_variant!(
|
||||
received_screen_instructions,
|
||||
ScreenInstruction::BreakPanesToNewTab,
|
||||
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('u')).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 screen_instruction = received_screen_instructions
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find_map(|i| {
|
||||
if let ScreenInstruction::BreakPanesToNewTab { .. } = i {
|
||||
Some(i.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.clone();
|
||||
assert_snapshot!(format!("{:#?}", screen_instruction));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
pub fn break_panes_to_tab_with_index_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_struct_variant!(
|
||||
received_screen_instructions,
|
||||
ScreenInstruction::BreakPanesToTabWithIndex,
|
||||
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('v')).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 screen_instruction = received_screen_instructions
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find_map(|i| {
|
||||
if let ScreenInstruction::BreakPanesToTabWithIndex { .. } = i {
|
||||
Some(i.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.clone();
|
||||
assert_snapshot!(format!("{:#?}", screen_instruction));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||
assertion_line: 8246
|
||||
expression: "format!(\"{:#?}\", screen_instruction)"
|
||||
---
|
||||
Some(
|
||||
BreakPanesToNewTab {
|
||||
pane_ids: [
|
||||
Terminal(
|
||||
1,
|
||||
),
|
||||
Plugin(
|
||||
2,
|
||||
),
|
||||
],
|
||||
default_shell: Some(
|
||||
RunCommand(
|
||||
RunCommand {
|
||||
command: ".",
|
||||
args: [],
|
||||
cwd: None,
|
||||
hold_on_close: false,
|
||||
hold_on_start: false,
|
||||
originating_plugin: None,
|
||||
},
|
||||
),
|
||||
),
|
||||
should_change_focus_to_new_tab: true,
|
||||
new_tab_name: Some(
|
||||
"new_tab_name",
|
||||
),
|
||||
client_id: 1,
|
||||
},
|
||||
)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
source: zellij-server/src/plugins/./unit/plugin_tests.rs
|
||||
assertion_line: 8317
|
||||
expression: "format!(\"{:#?}\", screen_instruction)"
|
||||
---
|
||||
Some(
|
||||
BreakPanesToTabWithIndex {
|
||||
pane_ids: [
|
||||
Terminal(
|
||||
1,
|
||||
),
|
||||
Plugin(
|
||||
2,
|
||||
),
|
||||
],
|
||||
tab_index: 2,
|
||||
should_change_focus_to_new_tab: true,
|
||||
client_id: 1,
|
||||
},
|
||||
)
|
||||
|
|
@ -320,6 +320,26 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
|
|||
PluginCommand::CloseTabWithIndex(tab_index) => {
|
||||
close_tab_with_index(env, tab_index)
|
||||
},
|
||||
PluginCommand::BreakPanesToNewTab(
|
||||
pane_ids,
|
||||
new_tab_name,
|
||||
should_change_focus_to_new_tab,
|
||||
) => break_panes_to_new_tab(
|
||||
env,
|
||||
pane_ids.into_iter().map(|p_id| p_id.into()).collect(),
|
||||
new_tab_name,
|
||||
should_change_focus_to_new_tab,
|
||||
),
|
||||
PluginCommand::BreakPanesToTabWithIndex(
|
||||
pane_ids,
|
||||
should_change_focus_to_new_tab,
|
||||
tab_index,
|
||||
) => break_panes_to_tab_with_index(
|
||||
env,
|
||||
pane_ids.into_iter().map(|p_id| p_id.into()).collect(),
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
),
|
||||
},
|
||||
(PermissionStatus::Denied, permission) => {
|
||||
log::error!(
|
||||
|
|
@ -1589,6 +1609,45 @@ fn close_tab_with_index(env: &PluginEnv, tab_index: usize) {
|
|||
.send_to_screen(ScreenInstruction::CloseTabWithIndex(tab_index));
|
||||
}
|
||||
|
||||
fn break_panes_to_new_tab(
|
||||
env: &PluginEnv,
|
||||
pane_ids: Vec<PaneId>,
|
||||
new_tab_name: Option<String>,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
) {
|
||||
let default_shell = env.default_shell.clone().or_else(|| {
|
||||
Some(TerminalAction::RunCommand(RunCommand {
|
||||
command: env.path_to_default_shell.clone(),
|
||||
..Default::default()
|
||||
}))
|
||||
});
|
||||
let _ = env
|
||||
.senders
|
||||
.send_to_screen(ScreenInstruction::BreakPanesToNewTab {
|
||||
pane_ids,
|
||||
default_shell,
|
||||
new_tab_name,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id: env.client_id,
|
||||
});
|
||||
}
|
||||
|
||||
fn break_panes_to_tab_with_index(
|
||||
env: &PluginEnv,
|
||||
pane_ids: Vec<PaneId>,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
tab_index: usize,
|
||||
) {
|
||||
let _ = env
|
||||
.senders
|
||||
.send_to_screen(ScreenInstruction::BreakPanesToTabWithIndex {
|
||||
pane_ids,
|
||||
tab_index,
|
||||
client_id: env.client_id,
|
||||
should_change_focus_to_new_tab,
|
||||
});
|
||||
}
|
||||
|
||||
// Custom panic handler for plugins.
|
||||
//
|
||||
// This is called when a panic occurs in a plugin. Since most panics will likely originate in the
|
||||
|
|
@ -1734,6 +1793,8 @@ fn check_command_permission(
|
|||
| PluginCommand::RerunCommandPane(..)
|
||||
| PluginCommand::ResizePaneIdWithDirection(..)
|
||||
| PluginCommand::CloseTabWithIndex(..)
|
||||
| PluginCommand::BreakPanesToNewTab(..)
|
||||
| PluginCommand::BreakPanesToTabWithIndex(..)
|
||||
| PluginCommand::KillSessions(..) => PermissionType::ChangeApplicationState,
|
||||
PluginCommand::UnblockCliPipeInput(..)
|
||||
| PluginCommand::BlockCliPipeInput(..)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ pub enum PtyInstruction {
|
|||
Vec<FloatingPaneLayout>,
|
||||
usize, // tab_index
|
||||
HashMap<RunPluginOrAlias, Vec<u32>>, // plugin_ids
|
||||
bool, // should change focus to new tab
|
||||
ClientId,
|
||||
), // the String is the tab name
|
||||
ClosePane(PaneId),
|
||||
|
|
@ -542,6 +543,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
|||
floating_panes_layout,
|
||||
tab_index,
|
||||
plugin_ids,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
) => {
|
||||
let err_context = || format!("failed to open new tab for client {}", client_id);
|
||||
|
|
@ -558,6 +560,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
|||
terminal_action.clone(),
|
||||
plugin_ids,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
)
|
||||
.with_context(err_context)?;
|
||||
|
|
@ -1015,6 +1018,7 @@ impl Pty {
|
|||
default_shell: Option<TerminalAction>,
|
||||
plugin_ids: HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||
tab_index: usize,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
client_id: ClientId,
|
||||
) -> Result<()> {
|
||||
let err_context = || format!("failed to spawn terminals for layout for client {client_id}");
|
||||
|
|
@ -1079,6 +1083,7 @@ impl Pty {
|
|||
new_tab_floating_pane_ids,
|
||||
plugin_ids,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
))
|
||||
.with_context(err_context)?;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ pub enum ScreenInstruction {
|
|||
Vec<(u32, HoldForCommand)>, // new floating pane pids
|
||||
HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||
usize, // tab_index
|
||||
bool, // should change focus to new tab
|
||||
ClientId,
|
||||
),
|
||||
SwitchTabNext(ClientId),
|
||||
|
|
@ -395,6 +396,19 @@ pub enum ScreenInstruction {
|
|||
TogglePaneIdFullscreen(PaneId),
|
||||
TogglePaneEmbedOrEjectForPaneId(PaneId),
|
||||
CloseTabWithIndex(usize),
|
||||
BreakPanesToNewTab {
|
||||
pane_ids: Vec<PaneId>,
|
||||
default_shell: Option<TerminalAction>,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
new_tab_name: Option<String>,
|
||||
client_id: ClientId,
|
||||
},
|
||||
BreakPanesToTabWithIndex {
|
||||
pane_ids: Vec<PaneId>,
|
||||
tab_index: usize,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
client_id: ClientId,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<&ScreenInstruction> for ScreenContext {
|
||||
|
|
@ -602,6 +616,10 @@ impl From<&ScreenInstruction> for ScreenContext {
|
|||
ScreenContext::TogglePaneEmbedOrEjectForPaneId
|
||||
},
|
||||
ScreenInstruction::CloseTabWithIndex(..) => ScreenContext::CloseTabWithIndex,
|
||||
ScreenInstruction::BreakPanesToNewTab { .. } => ScreenContext::BreakPanesToNewTab,
|
||||
ScreenInstruction::BreakPanesToTabWithIndex { .. } => {
|
||||
ScreenContext::BreakPanesToTabWithIndex
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1169,7 +1187,10 @@ impl Screen {
|
|||
}
|
||||
}
|
||||
for tab_index in tabs_to_close {
|
||||
self.close_tab_at_index(tab_index).context(err_context)?;
|
||||
// cleanup as needed
|
||||
self.close_tab_at_index(tab_index)
|
||||
.context(err_context)
|
||||
.non_fatal();
|
||||
}
|
||||
if output.is_dirty() {
|
||||
let serialized_output = output.serialize().context(err_context)?;
|
||||
|
|
@ -1254,17 +1275,19 @@ impl Screen {
|
|||
tab_index: usize,
|
||||
swap_layouts: (Vec<SwapTiledLayout>, Vec<SwapFloatingLayout>),
|
||||
tab_name: Option<String>,
|
||||
client_id: ClientId,
|
||||
client_id: Option<ClientId>,
|
||||
) -> Result<()> {
|
||||
let err_context = || format!("failed to create new tab for client {client_id:?}",);
|
||||
|
||||
let client_id = if self.get_active_tab(client_id).is_ok() {
|
||||
client_id
|
||||
} else if let Some(first_client_id) = self.get_first_client_id() {
|
||||
first_client_id
|
||||
} else {
|
||||
client_id
|
||||
};
|
||||
let client_id = client_id.map(|client_id| {
|
||||
if self.get_active_tab(client_id).is_ok() {
|
||||
client_id
|
||||
} else if let Some(first_client_id) = self.get_first_client_id() {
|
||||
first_client_id
|
||||
} else {
|
||||
client_id
|
||||
}
|
||||
});
|
||||
|
||||
let tab_name = tab_name.unwrap_or_else(|| String::new());
|
||||
|
||||
|
|
@ -1314,6 +1337,7 @@ impl Screen {
|
|||
new_floating_terminal_ids: Vec<(u32, HoldForCommand)>,
|
||||
new_plugin_ids: HashMap<RunPluginOrAlias, Vec<u32>>,
|
||||
tab_index: usize,
|
||||
should_change_client_focus: bool,
|
||||
client_id: ClientId,
|
||||
) -> Result<()> {
|
||||
if self.tabs.get(&tab_index).is_none() {
|
||||
|
|
@ -1332,31 +1356,42 @@ impl Screen {
|
|||
let err_context = || format!("failed to apply layout for tab {tab_index:?}",);
|
||||
|
||||
// move the relevant clients out of the current tab and place them in the new one
|
||||
let drained_clients = if self.session_is_mirrored {
|
||||
let client_mode_infos_in_source_tab =
|
||||
if let Ok(active_tab) = self.get_active_tab_mut(client_id) {
|
||||
let drained_clients = if should_change_client_focus {
|
||||
if self.session_is_mirrored {
|
||||
let client_mode_infos_in_source_tab = if let Ok(active_tab) =
|
||||
self.get_active_tab_mut(client_id)
|
||||
{
|
||||
let client_mode_infos_in_source_tab = active_tab.drain_connected_clients(None);
|
||||
if active_tab.has_no_connected_clients() {
|
||||
active_tab.visible(false).with_context(err_context)?;
|
||||
active_tab
|
||||
.visible(false)
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
}
|
||||
Some(client_mode_infos_in_source_tab)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let all_connected_clients: Vec<ClientId> =
|
||||
self.connected_clients.borrow().iter().copied().collect();
|
||||
for client_id in all_connected_clients {
|
||||
let all_connected_clients: Vec<ClientId> =
|
||||
self.connected_clients.borrow().iter().copied().collect();
|
||||
for client_id in all_connected_clients {
|
||||
self.update_client_tab_focus(client_id, tab_index);
|
||||
}
|
||||
client_mode_infos_in_source_tab
|
||||
} else if let Ok(active_tab) = self.get_active_tab_mut(client_id) {
|
||||
let client_mode_info_in_source_tab =
|
||||
active_tab.drain_connected_clients(Some(vec![client_id]));
|
||||
if active_tab.has_no_connected_clients() {
|
||||
active_tab
|
||||
.visible(false)
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
}
|
||||
self.update_client_tab_focus(client_id, tab_index);
|
||||
Some(client_mode_info_in_source_tab)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
client_mode_infos_in_source_tab
|
||||
} else if let Ok(active_tab) = self.get_active_tab_mut(client_id) {
|
||||
let client_mode_info_in_source_tab =
|
||||
active_tab.drain_connected_clients(Some(vec![client_id]));
|
||||
if active_tab.has_no_connected_clients() {
|
||||
active_tab.visible(false).with_context(err_context)?;
|
||||
}
|
||||
self.update_client_tab_focus(client_id, tab_index);
|
||||
Some(client_mode_info_in_source_tab)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -1375,10 +1410,13 @@ impl Screen {
|
|||
client_id,
|
||||
)?;
|
||||
tab.update_input_modes()?;
|
||||
tab.visible(true)?;
|
||||
|
||||
if let Some(drained_clients) = drained_clients {
|
||||
tab.visible(true)?;
|
||||
tab.add_multiple_clients(drained_clients)?;
|
||||
}
|
||||
tab.resize_whole_tab(self.size).with_context(err_context)?;
|
||||
tab.set_force_render();
|
||||
Ok(())
|
||||
})
|
||||
.with_context(err_context)?;
|
||||
|
|
@ -2083,7 +2121,7 @@ impl Screen {
|
|||
default_layout.swap_tiled_layouts.clone(),
|
||||
default_layout.swap_floating_layouts.clone(),
|
||||
);
|
||||
self.new_tab(tab_index, swap_layouts, None, client_id)?;
|
||||
self.new_tab(tab_index, swap_layouts, None, Some(client_id))?;
|
||||
let tab = self.tabs.get_mut(&tab_index).with_context(err_context)?;
|
||||
let (mut tiled_panes_layout, mut floating_panes_layout) = default_layout.new_tab();
|
||||
if pane_to_break_is_floating {
|
||||
|
|
@ -2099,12 +2137,14 @@ impl Screen {
|
|||
tab.add_tiled_pane(active_pane, active_pane_id, Some(client_id))?;
|
||||
tiled_panes_layout.ignore_run_instruction(active_pane_run_instruction.clone());
|
||||
}
|
||||
let should_change_focus_to_new_tab = true;
|
||||
self.bus.senders.send_to_plugin(PluginInstruction::NewTab(
|
||||
None,
|
||||
default_shell,
|
||||
Some(tiled_panes_layout),
|
||||
floating_panes_layout,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
))?;
|
||||
} else {
|
||||
|
|
@ -2122,6 +2162,63 @@ impl Screen {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn break_multiple_panes_to_new_tab(
|
||||
&mut self,
|
||||
pane_ids: Vec<PaneId>,
|
||||
default_shell: Option<TerminalAction>,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
new_tab_name: Option<String>,
|
||||
client_id: ClientId,
|
||||
) -> Result<()> {
|
||||
let err_context = || "failed break multiple panes to a new tab".to_string();
|
||||
|
||||
let all_tabs = self.get_tabs_mut();
|
||||
let mut extracted_panes = vec![];
|
||||
for pane_id in pane_ids {
|
||||
for tab in all_tabs.values_mut() {
|
||||
// here we pass None instead of the client_id we have because we do not need to
|
||||
// necessarily trigger a relayout for this tab
|
||||
if let Some(pane) = tab.extract_pane(pane_id, true, None).take() {
|
||||
extracted_panes.push(pane);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (mut tiled_panes_layout, floating_panes_layout) = self.default_layout.new_tab();
|
||||
let tab_index = self.get_new_tab_index();
|
||||
let swap_layouts = (
|
||||
self.default_layout.swap_tiled_layouts.clone(),
|
||||
self.default_layout.swap_floating_layouts.clone(),
|
||||
);
|
||||
if should_change_focus_to_new_tab {
|
||||
self.new_tab(tab_index, swap_layouts, None, Some(client_id))?;
|
||||
} else {
|
||||
self.new_tab(tab_index, swap_layouts, None, None)?;
|
||||
}
|
||||
let mut tab = self.tabs.get_mut(&tab_index).with_context(err_context)?;
|
||||
if let Some(new_tab_name) = new_tab_name {
|
||||
tab.name = new_tab_name.clone();
|
||||
}
|
||||
for pane in extracted_panes {
|
||||
let run_instruction = pane.invoked_with().clone();
|
||||
let pane_id = pane.pid();
|
||||
// here we pass None instead of the ClientId, because we do not want this pane to be
|
||||
// necessarily focused
|
||||
tab.add_tiled_pane(pane, pane_id, None)?;
|
||||
tiled_panes_layout.ignore_run_instruction(run_instruction.clone());
|
||||
}
|
||||
self.bus.senders.send_to_plugin(PluginInstruction::NewTab(
|
||||
None,
|
||||
default_shell,
|
||||
Some(tiled_panes_layout),
|
||||
floating_panes_layout,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn break_pane_to_new_tab(
|
||||
&mut self,
|
||||
direction: Direction,
|
||||
|
|
@ -2184,6 +2281,57 @@ impl Screen {
|
|||
self.render(None)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn break_multiple_panes_to_tab_with_index(
|
||||
&mut self,
|
||||
pane_ids: Vec<PaneId>,
|
||||
tab_index: usize,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
client_id: ClientId,
|
||||
) -> Result<()> {
|
||||
let all_tabs = self.get_tabs_mut();
|
||||
let has_tab_with_index = all_tabs
|
||||
.values()
|
||||
.find(|t| t.position == tab_index)
|
||||
.is_some();
|
||||
if !has_tab_with_index {
|
||||
log::error!("Cannot find tab with index: {tab_index}");
|
||||
return Ok(());
|
||||
}
|
||||
let mut extracted_panes = vec![];
|
||||
for pane_id in pane_ids {
|
||||
for tab in all_tabs.values_mut() {
|
||||
if tab.position == tab_index {
|
||||
continue;
|
||||
}
|
||||
// here we pass None instead of the client_id we have because we do not need to
|
||||
// necessarily trigger a relayout for this tab
|
||||
if let Some(pane) = tab.extract_pane(pane_id, true, None).take() {
|
||||
extracted_panes.push(pane);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if should_change_focus_to_new_tab {
|
||||
self.go_to_tab(tab_index + 1, client_id)?;
|
||||
}
|
||||
if extracted_panes.is_empty() {
|
||||
// nothing to do here...
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(new_active_tab) = self.get_indexed_tab_mut(tab_index) {
|
||||
for pane in extracted_panes {
|
||||
let pane_id = pane.pid();
|
||||
// here we pass None instead of the ClientId, because we do not want this pane to be
|
||||
// necessarily focused
|
||||
new_active_tab.add_tiled_pane(pane, pane_id, None)?;
|
||||
}
|
||||
} else {
|
||||
log::error!("Could not find tab with index: {:?}", tab_index);
|
||||
}
|
||||
self.log_and_report_session_state()?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn replace_pane(
|
||||
&mut self,
|
||||
new_pane_id: PaneId,
|
||||
|
|
@ -3246,8 +3394,9 @@ pub(crate) fn screen_thread_main(
|
|||
client_id,
|
||||
) => {
|
||||
let tab_index = screen.get_new_tab_index();
|
||||
let should_change_focus_to_new_tab = true;
|
||||
pending_tab_ids.insert(tab_index);
|
||||
screen.new_tab(tab_index, swap_layouts, tab_name.clone(), client_id)?;
|
||||
screen.new_tab(tab_index, swap_layouts, tab_name.clone(), Some(client_id))?;
|
||||
screen
|
||||
.bus
|
||||
.senders
|
||||
|
|
@ -3257,6 +3406,7 @@ pub(crate) fn screen_thread_main(
|
|||
layout,
|
||||
floating_panes_layout,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
))?;
|
||||
},
|
||||
|
|
@ -3267,6 +3417,7 @@ pub(crate) fn screen_thread_main(
|
|||
new_floating_pane_pids,
|
||||
new_plugin_ids,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
) => {
|
||||
screen.apply_layout(
|
||||
|
|
@ -3276,6 +3427,7 @@ pub(crate) fn screen_thread_main(
|
|||
new_floating_pane_pids,
|
||||
new_plugin_ids.clone(),
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
)?;
|
||||
pending_tab_ids.remove(&tab_index);
|
||||
|
|
@ -3363,7 +3515,13 @@ pub(crate) fn screen_thread_main(
|
|||
screen.render(None)?;
|
||||
if create && !tab_exists {
|
||||
let tab_index = screen.get_new_tab_index();
|
||||
screen.new_tab(tab_index, swap_layouts, Some(tab_name), client_id)?;
|
||||
let should_change_focus_to_new_tab = true;
|
||||
screen.new_tab(
|
||||
tab_index,
|
||||
swap_layouts,
|
||||
Some(tab_name),
|
||||
Some(client_id),
|
||||
)?;
|
||||
screen
|
||||
.bus
|
||||
.senders
|
||||
|
|
@ -3373,6 +3531,7 @@ pub(crate) fn screen_thread_main(
|
|||
None,
|
||||
vec![],
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
))?;
|
||||
}
|
||||
|
|
@ -4427,6 +4586,34 @@ pub(crate) fn screen_thread_main(
|
|||
ScreenInstruction::CloseTabWithIndex(tab_index) => {
|
||||
screen.close_tab_at_index(tab_index).non_fatal()
|
||||
},
|
||||
ScreenInstruction::BreakPanesToNewTab {
|
||||
pane_ids,
|
||||
default_shell,
|
||||
should_change_focus_to_new_tab,
|
||||
new_tab_name,
|
||||
client_id,
|
||||
} => {
|
||||
screen.break_multiple_panes_to_new_tab(
|
||||
pane_ids,
|
||||
default_shell,
|
||||
should_change_focus_to_new_tab,
|
||||
new_tab_name,
|
||||
client_id,
|
||||
)?;
|
||||
},
|
||||
ScreenInstruction::BreakPanesToTabWithIndex {
|
||||
pane_ids,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
} => {
|
||||
screen.break_multiple_panes_to_tab_with_index(
|
||||
pane_ids,
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
client_id,
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -256,6 +256,19 @@ impl<'a> LayoutApplier<'a> {
|
|||
position_and_size,
|
||||
layout.borderless,
|
||||
);
|
||||
} else if let Some(position) =
|
||||
positions_in_layout
|
||||
.iter()
|
||||
.position(|(layout, _position_and_size)| {
|
||||
Run::is_terminal(&layout.run) && Run::is_terminal(&run_instruction)
|
||||
})
|
||||
{
|
||||
let (layout, position_and_size) = positions_in_layout.remove(position);
|
||||
self.tiled_panes.set_geom_for_pane_with_run(
|
||||
run_instruction,
|
||||
position_and_size,
|
||||
layout.borderless,
|
||||
);
|
||||
} else {
|
||||
log::error!(
|
||||
"Failed to find room for run instruction: {:?}",
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ impl Tab {
|
|||
auto_layout: bool,
|
||||
connected_clients_in_app: Rc<RefCell<HashSet<ClientId>>>,
|
||||
session_is_mirrored: bool,
|
||||
client_id: ClientId,
|
||||
client_id: Option<ClientId>,
|
||||
copy_options: CopyOptions,
|
||||
terminal_emulator_colors: Rc<RefCell<Palette>>,
|
||||
terminal_emulator_color_codes: Rc<RefCell<HashMap<usize, String>>>,
|
||||
|
|
@ -564,7 +564,9 @@ impl Tab {
|
|||
};
|
||||
|
||||
let mut connected_clients = HashSet::new();
|
||||
connected_clients.insert(client_id);
|
||||
if let Some(client_id) = client_id {
|
||||
connected_clients.insert(client_id);
|
||||
}
|
||||
let viewport: Viewport = display_area.into();
|
||||
let viewport = Rc::new(RefCell::new(viewport));
|
||||
let display_area = Rc::new(RefCell::new(display_area));
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab {
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -322,7 +322,7 @@ fn create_new_tab_with_swap_layouts(
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -403,7 +403,7 @@ fn create_new_tab_with_os_api(
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -470,7 +470,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str)
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -551,7 +551,7 @@ fn create_new_tab_with_mock_pty_writer(
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -623,7 +623,7 @@ fn create_new_tab_with_sixel_support(
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ fn create_new_tab(size: Size) -> Tab {
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -248,7 +248,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab {
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
@ -318,7 +318,7 @@ fn create_new_tab_with_cell_size(
|
|||
auto_layout,
|
||||
connected_clients,
|
||||
session_is_mirrored,
|
||||
client_id,
|
||||
Some(client_id),
|
||||
copy_options,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
|
|
|
|||
|
|
@ -387,6 +387,7 @@ impl MockScreen {
|
|||
floating_pane_ids,
|
||||
plugin_ids,
|
||||
tab_index,
|
||||
true,
|
||||
self.main_client_id,
|
||||
));
|
||||
self.last_opened_tab_index = Some(tab_index);
|
||||
|
|
@ -471,6 +472,7 @@ impl MockScreen {
|
|||
floating_pane_ids,
|
||||
plugin_ids,
|
||||
tab_index,
|
||||
true,
|
||||
self.main_client_id,
|
||||
));
|
||||
self.last_opened_tab_index = Some(tab_index);
|
||||
|
|
@ -502,6 +504,7 @@ impl MockScreen {
|
|||
vec![], // floating panes ids
|
||||
plugin_ids,
|
||||
0,
|
||||
true,
|
||||
self.main_client_id,
|
||||
));
|
||||
self.last_opened_tab_index = Some(tab_index);
|
||||
|
|
@ -649,7 +652,7 @@ fn new_tab(screen: &mut Screen, pid: u32, tab_index: usize) {
|
|||
let new_terminal_ids = vec![(pid, None)];
|
||||
let new_plugin_ids = HashMap::new();
|
||||
screen
|
||||
.new_tab(tab_index, (vec![], vec![]), None, client_id)
|
||||
.new_tab(tab_index, (vec![], vec![]), None, Some(client_id))
|
||||
.expect("TEST");
|
||||
screen
|
||||
.apply_layout(
|
||||
|
|
@ -659,6 +662,7 @@ fn new_tab(screen: &mut Screen, pid: u32, tab_index: usize) {
|
|||
vec![], // new floating terminal ids
|
||||
new_plugin_ids,
|
||||
tab_index,
|
||||
true,
|
||||
client_id,
|
||||
)
|
||||
.expect("TEST");
|
||||
|
|
@ -3248,6 +3252,7 @@ pub fn screen_can_break_pane_to_a_new_tab() {
|
|||
vec![], // floating panes ids
|
||||
Default::default(),
|
||||
1,
|
||||
true,
|
||||
1,
|
||||
));
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
|
@ -3349,6 +3354,7 @@ pub fn screen_can_break_floating_pane_to_a_new_tab() {
|
|||
vec![], // floating panes ids
|
||||
Default::default(),
|
||||
1,
|
||||
true,
|
||||
1,
|
||||
));
|
||||
std::thread::sleep(std::time::Duration::from_millis(200));
|
||||
|
|
@ -3418,6 +3424,7 @@ pub fn screen_can_break_plugin_pane_to_a_new_tab() {
|
|||
vec![], // floating panes ids
|
||||
Default::default(),
|
||||
1,
|
||||
true,
|
||||
1,
|
||||
));
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
|
@ -3491,6 +3498,7 @@ pub fn screen_can_break_floating_plugin_pane_to_a_new_tab() {
|
|||
vec![], // floating panes ids
|
||||
Default::default(),
|
||||
1,
|
||||
true,
|
||||
1,
|
||||
));
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 2849
|
||||
assertion_line: 3374
|
||||
expression: "format!(\"{}\", snapshot)"
|
||||
---
|
||||
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
|
||||
|
|
@ -8,18 +8,18 @@ expression: "format!(\"{}\", snapshot)"
|
|||
02 (C): │ │
|
||||
03 (C): │ │
|
||||
04 (C): │ │
|
||||
05 (C): │ │
|
||||
06 (C): │ │
|
||||
07 (C): │ ┌ floating_pane_to_eject ──────────────┐ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ │ │ │
|
||||
15 (C): │ │ │ │
|
||||
16 (C): │ └──────────────────────────────────────┘ │
|
||||
05 (C): │ ┌ floating_pane_to_eject ──────────────┐ │
|
||||
06 (C): │ │ │ │
|
||||
07 (C): │ │ │ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ └──────────────────────────────────────┘ │
|
||||
15 (C): │ │
|
||||
16 (C): │ │
|
||||
17 (C): │ │
|
||||
18 (C): │ │
|
||||
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 2849
|
||||
assertion_line: 3374
|
||||
expression: "format!(\"{}\", snapshot)"
|
||||
---
|
||||
00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐
|
||||
|
|
@ -8,18 +8,18 @@ expression: "format!(\"{}\", snapshot)"
|
|||
02 (C): │ │
|
||||
03 (C): │ │
|
||||
04 (C): │ │
|
||||
05 (C): │ │
|
||||
06 (C): │ │
|
||||
07 (C): │ ┌ floating_pane_to_eject ──────────────┐ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ │ │ │
|
||||
15 (C): │ │ │ │
|
||||
16 (C): │ └──────────────────────────────────────┘ │
|
||||
05 (C): │ ┌ floating_pane_to_eject ──────────────┐ │
|
||||
06 (C): │ │ │ │
|
||||
07 (C): │ │ │ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ └──────────────────────────────────────┘ │
|
||||
15 (C): │ │
|
||||
16 (C): │ │
|
||||
17 (C): │ │
|
||||
18 (C): │ │
|
||||
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 3512
|
||||
assertion_line: 3516
|
||||
expression: "format!(\"{}\", snapshot)"
|
||||
---
|
||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||
|
|
@ -8,18 +8,18 @@ expression: "format!(\"{}\", snapshot)"
|
|||
02 (C): │ │
|
||||
03 (C): │ │
|
||||
04 (C): │ │
|
||||
05 (C): │ │
|
||||
06 (C): │ │
|
||||
07 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ │ │ │
|
||||
15 (C): │ │ │ │
|
||||
16 (C): │ └──────────────────────────────────────┘ │
|
||||
05 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
06 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
07 (C): │ │ │ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ └──────────────────────────────────────┘ │
|
||||
15 (C): │ │
|
||||
16 (C): │ │
|
||||
17 (C): │ │
|
||||
18 (C): │ │
|
||||
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 3512
|
||||
assertion_line: 3516
|
||||
expression: "format!(\"{}\", snapshot)"
|
||||
---
|
||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||
|
|
@ -8,18 +8,18 @@ expression: "format!(\"{}\", snapshot)"
|
|||
02 (C): │ │
|
||||
03 (C): │ │
|
||||
04 (C): │ │
|
||||
05 (C): │ │
|
||||
06 (C): │ │
|
||||
07 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ │ │ │
|
||||
15 (C): │ │ │ │
|
||||
16 (C): │ └──────────────────────────────────────┘ │
|
||||
05 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
06 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
07 (C): │ │ │ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ └──────────────────────────────────────┘ │
|
||||
15 (C): │ │
|
||||
16 (C): │ │
|
||||
17 (C): │ │
|
||||
18 (C): │ │
|
||||
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 3512
|
||||
assertion_line: 3516
|
||||
expression: "format!(\"{}\", snapshot)"
|
||||
---
|
||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||
|
|
@ -8,18 +8,18 @@ expression: "format!(\"{}\", snapshot)"
|
|||
02 (C): │ │
|
||||
03 (C): │ │
|
||||
04 (C): │ │
|
||||
05 (C): │ │
|
||||
06 (C): │ │
|
||||
07 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ │ │ │
|
||||
15 (C): │ │ │ │
|
||||
16 (C): │ └──────────────────────────────────────┘ │
|
||||
05 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
06 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
07 (C): │ │ │ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ └──────────────────────────────────────┘ │
|
||||
15 (C): │ │
|
||||
16 (C): │ │
|
||||
17 (C): │ │
|
||||
18 (C): │ │
|
||||
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 3512
|
||||
assertion_line: 3516
|
||||
expression: "format!(\"{}\", snapshot)"
|
||||
---
|
||||
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
|
||||
|
|
@ -8,18 +8,18 @@ expression: "format!(\"{}\", snapshot)"
|
|||
02 (C): │ │
|
||||
03 (C): │ │
|
||||
04 (C): │ │
|
||||
05 (C): │ │
|
||||
06 (C): │ │
|
||||
07 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
08 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ │ │ │
|
||||
15 (C): │ │ │ │
|
||||
16 (C): │ └──────────────────────────────────────┘ │
|
||||
05 (C): │ ┌ floating_plugin_pane_to_eject ───────┐ │
|
||||
06 (C): │ │Loading file:/path/to/fake/plugin │ │
|
||||
07 (C): │ │ │ │
|
||||
08 (C): │ │ │ │
|
||||
09 (C): │ │ │ │
|
||||
10 (C): │ │ │ │
|
||||
11 (C): │ │ │ │
|
||||
12 (C): │ │ │ │
|
||||
13 (C): │ │ │ │
|
||||
14 (C): │ └──────────────────────────────────────┘ │
|
||||
15 (C): │ │
|
||||
16 (C): │ │
|
||||
17 (C): │ │
|
||||
18 (C): │ │
|
||||
19 (C): └──────────────────────────────────────────────────────────────────────────────┘
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 2246
|
||||
assertion_line: 2665
|
||||
expression: "format!(\"{:#?}\", new_tab_action)"
|
||||
---
|
||||
Some(
|
||||
|
|
@ -60,6 +60,7 @@ Some(
|
|||
),
|
||||
[],
|
||||
0,
|
||||
true,
|
||||
1,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 2292
|
||||
assertion_line: 2711
|
||||
expression: "format!(\"{:#?}\", new_tab_instruction)"
|
||||
---
|
||||
NewTab(
|
||||
|
|
@ -87,5 +87,6 @@ NewTab(
|
|||
),
|
||||
[],
|
||||
1,
|
||||
true,
|
||||
10,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 1825
|
||||
assertion_line: 2183
|
||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||
---
|
||||
[StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, Write([102, 111, 111], 0), Write([102, 111, 111], 1), ApplyCachedResizes, Exit]
|
||||
[StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ResizePty(0, 58, 18, None, None), ResizePty(1, 59, 18, None, None), ResizePty(0, 58, 18, None, None), ResizePty(1, 59, 18, None, None), ResizePty(0, 58, 18, None, None), ResizePty(1, 59, 18, None, None), ResizePty(0, 58, 18, None, None), ResizePty(1, 59, 18, None, None), ResizePty(0, 59, 18, None, None), ResizePty(1, 58, 18, None, None), ApplyCachedResizes, ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, Write([102, 111, 111], 0), Write([102, 111, 111], 1), ApplyCachedResizes, Exit]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 1065
|
||||
assertion_line: 1423
|
||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||
---
|
||||
[StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, Write([102, 111, 111], 0), ApplyCachedResizes, Exit]
|
||||
[StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ApplyCachedResizes, ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, Write([102, 111, 111], 0), ApplyCachedResizes, Exit]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: zellij-server/src/./unit/screen_tests.rs
|
||||
assertion_line: 1039
|
||||
assertion_line: 1397
|
||||
expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())"
|
||||
---
|
||||
[StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, Write([105, 110, 112, 117, 116, 32, 102, 114, 111, 109, 32, 116, 104, 101, 32, 99, 108, 105], 0), ApplyCachedResizes, Exit]
|
||||
[StartCachingResizes, ApplyCachedResizes, StartCachingResizes, ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ResizePty(0, 119, 18, None, None), ApplyCachedResizes, ApplyCachedResizes, StartCachingResizes, ApplyCachedResizes, StartCachingResizes, Write([105, 110, 112, 117, 116, 32, 102, 114, 111, 109, 32, 116, 104, 101, 32, 99, 108, 105], 0), ApplyCachedResizes, Exit]
|
||||
|
|
|
|||
|
|
@ -1030,6 +1030,38 @@ where
|
|||
unsafe { host_run_plugin_command() };
|
||||
}
|
||||
|
||||
/// Create a new tab that includes the specified pane ids
|
||||
pub fn break_panes_to_new_tab(
|
||||
pane_ids: &[PaneId],
|
||||
new_tab_name: Option<String>,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
) {
|
||||
let plugin_command = PluginCommand::BreakPanesToNewTab(
|
||||
pane_ids.to_vec(),
|
||||
new_tab_name,
|
||||
should_change_focus_to_new_tab,
|
||||
);
|
||||
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||
unsafe { host_run_plugin_command() };
|
||||
}
|
||||
|
||||
/// Create a new tab that includes the specified pane ids
|
||||
pub fn break_panes_to_tab_with_index(
|
||||
pane_ids: &[PaneId],
|
||||
tab_index: usize,
|
||||
should_change_focus_to_new_tab: bool,
|
||||
) {
|
||||
let plugin_command = PluginCommand::BreakPanesToTabWithIndex(
|
||||
pane_ids.to_vec(),
|
||||
tab_index,
|
||||
should_change_focus_to_new_tab,
|
||||
);
|
||||
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||
unsafe { host_run_plugin_command() };
|
||||
}
|
||||
|
||||
// Utility Functions
|
||||
|
||||
#[allow(unused)]
|
||||
|
|
|
|||
|
|
@ -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, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83"
|
||||
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, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85"
|
||||
)]
|
||||
pub payload: ::core::option::Option<plugin_command::Payload>,
|
||||
}
|
||||
|
|
@ -164,10 +164,34 @@ pub mod plugin_command {
|
|||
),
|
||||
#[prost(message, tag = "83")]
|
||||
CloseTabWithIndexPayload(super::CloseTabWithIndexPayload),
|
||||
#[prost(message, tag = "84")]
|
||||
BreakPanesToNewTabPayload(super::BreakPanesToNewTabPayload),
|
||||
#[prost(message, tag = "85")]
|
||||
BreakPanesToTabWithIndexPayload(super::BreakPanesToTabWithIndexPayload),
|
||||
}
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct BreakPanesToTabWithIndexPayload {
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub pane_ids: ::prost::alloc::vec::Vec<PaneId>,
|
||||
#[prost(uint32, tag = "2")]
|
||||
pub tab_index: u32,
|
||||
#[prost(bool, tag = "3")]
|
||||
pub should_change_focus_to_target_tab: bool,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct BreakPanesToNewTabPayload {
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub pane_ids: ::prost::alloc::vec::Vec<PaneId>,
|
||||
#[prost(bool, tag = "2")]
|
||||
pub should_change_focus_to_new_tab: bool,
|
||||
#[prost(string, optional, tag = "3")]
|
||||
pub new_tab_name: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct MovePaneWithPaneIdPayload {
|
||||
#[prost(message, optional, tag = "1")]
|
||||
pub pane_id: ::core::option::Option<PaneId>,
|
||||
|
|
@ -634,6 +658,8 @@ pub enum CommandName {
|
|||
TogglePaneIdFullscreen = 105,
|
||||
TogglePaneEmbedOrEjectForPaneId = 106,
|
||||
CloseTabWithIndex = 107,
|
||||
BreakPanesToNewTab = 108,
|
||||
BreakPanesToTabWithIndex = 109,
|
||||
}
|
||||
impl CommandName {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
|
|
@ -752,6 +778,8 @@ impl CommandName {
|
|||
"TogglePaneEmbedOrEjectForPaneId"
|
||||
}
|
||||
CommandName::CloseTabWithIndex => "CloseTabWithIndex",
|
||||
CommandName::BreakPanesToNewTab => "BreakPanesToNewTab",
|
||||
CommandName::BreakPanesToTabWithIndex => "BreakPanesToTabWithIndex",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
|
|
@ -867,6 +895,8 @@ impl CommandName {
|
|||
Some(Self::TogglePaneEmbedOrEjectForPaneId)
|
||||
}
|
||||
"CloseTabWithIndex" => Some(Self::CloseTabWithIndex),
|
||||
"BreakPanesToNewTab" => Some(Self::BreakPanesToNewTab),
|
||||
"BreakPanesToTabWithIndex" => Some(Self::BreakPanesToTabWithIndex),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1836,4 +1836,10 @@ pub enum PluginCommand {
|
|||
TogglePaneIdFullscreen(PaneId),
|
||||
TogglePaneEmbedOrEjectForPaneId(PaneId),
|
||||
CloseTabWithIndex(usize), // usize - tab_index
|
||||
BreakPanesToNewTab(Vec<PaneId>, Option<String>, bool), // bool -
|
||||
// should_change_focus_to_new_tab,
|
||||
// Option<String> - optional name for
|
||||
// the new tab
|
||||
BreakPanesToTabWithIndex(Vec<PaneId>, usize, bool), // usize - tab_index, bool -
|
||||
// should_change_focus_to_new_tab
|
||||
}
|
||||
|
|
|
|||
|
|
@ -370,6 +370,8 @@ pub enum ScreenContext {
|
|||
TogglePaneIdFullscreen,
|
||||
TogglePaneEmbedOrEjectForPaneId,
|
||||
CloseTabWithIndex,
|
||||
BreakPanesToNewTab,
|
||||
BreakPanesToTabWithIndex,
|
||||
}
|
||||
|
||||
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
|
||||
|
|
|
|||
|
|
@ -938,7 +938,16 @@ impl TiledPaneLayout {
|
|||
.len()
|
||||
.saturating_sub(successfully_ignored)
|
||||
{
|
||||
if let Some(position) = run_instructions.iter().position(|i| i == &None) {
|
||||
if let Some(position) = run_instructions.iter().position(|i| {
|
||||
match i {
|
||||
// this is because a bare CWD instruction should be overidden by a terminal
|
||||
// in run_instructions_to_ignore (for cases where the cwd for example comes
|
||||
// from a global layout cwd and the pane is actually just a bare pane that
|
||||
// wants to be overidden)
|
||||
Some(Run::Cwd(_)) | None => true,
|
||||
_ => false,
|
||||
}
|
||||
}) {
|
||||
run_instructions.remove(position);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ enum CommandName {
|
|||
TogglePaneIdFullscreen = 105;
|
||||
TogglePaneEmbedOrEjectForPaneId = 106;
|
||||
CloseTabWithIndex = 107;
|
||||
BreakPanesToNewTab = 108;
|
||||
BreakPanesToTabWithIndex = 109;
|
||||
}
|
||||
|
||||
message PluginCommand {
|
||||
|
|
@ -197,9 +199,23 @@ message PluginCommand {
|
|||
TogglePaneIdFullscreenPayload toggle_pane_id_fullscreen_payload = 81;
|
||||
TogglePaneEmbedOrEjectForPaneIdPayload toggle_pane_embed_or_eject_for_pane_id_payload = 82;
|
||||
CloseTabWithIndexPayload close_tab_with_index_payload = 83;
|
||||
BreakPanesToNewTabPayload break_panes_to_new_tab_payload = 84;
|
||||
BreakPanesToTabWithIndexPayload break_panes_to_tab_with_index_payload = 85;
|
||||
}
|
||||
}
|
||||
|
||||
message BreakPanesToTabWithIndexPayload {
|
||||
repeated PaneId pane_ids = 1;
|
||||
uint32 tab_index = 2;
|
||||
bool should_change_focus_to_target_tab = 3;
|
||||
}
|
||||
|
||||
message BreakPanesToNewTabPayload {
|
||||
repeated PaneId pane_ids = 1;
|
||||
bool should_change_focus_to_new_tab = 2;
|
||||
optional string new_tab_name = 3;
|
||||
}
|
||||
|
||||
message MovePaneWithPaneIdPayload {
|
||||
PaneId pane_id = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ pub use super::generated_api::api::{
|
|||
event::{EventNameList as ProtobufEventNameList, Header},
|
||||
input_mode::InputMode as ProtobufInputMode,
|
||||
plugin_command::{
|
||||
plugin_command::Payload, ClearScreenForPaneIdPayload, CliPipeOutputPayload,
|
||||
CloseTabWithIndexPayload, CommandName, ContextItem, EditScrollbackForPaneWithIdPayload,
|
||||
EnvVariable, ExecCmdPayload, FixedOrPercent as ProtobufFixedOrPercent,
|
||||
plugin_command::Payload, BreakPanesToNewTabPayload, BreakPanesToTabWithIndexPayload,
|
||||
ClearScreenForPaneIdPayload, CliPipeOutputPayload, CloseTabWithIndexPayload, CommandName,
|
||||
ContextItem, EditScrollbackForPaneWithIdPayload, EnvVariable, ExecCmdPayload,
|
||||
FixedOrPercent as ProtobufFixedOrPercent,
|
||||
FixedOrPercentValue as ProtobufFixedOrPercentValue,
|
||||
FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, HidePaneWithIdPayload,
|
||||
HttpVerb as ProtobufHttpVerb, IdAndNewName, KillSessionsPayload, MessageToPluginPayload,
|
||||
|
|
@ -1174,6 +1175,34 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
|||
),
|
||||
_ => Err("Mismatched payload for CloseTabWithIndex"),
|
||||
},
|
||||
Some(CommandName::BreakPanesToNewTab) => match protobuf_plugin_command.payload {
|
||||
Some(Payload::BreakPanesToNewTabPayload(break_panes_to_new_tab_payload)) => {
|
||||
Ok(PluginCommand::BreakPanesToNewTab(
|
||||
break_panes_to_new_tab_payload
|
||||
.pane_ids
|
||||
.into_iter()
|
||||
.filter_map(|p_id| p_id.try_into().ok())
|
||||
.collect(),
|
||||
break_panes_to_new_tab_payload.new_tab_name,
|
||||
break_panes_to_new_tab_payload.should_change_focus_to_new_tab,
|
||||
))
|
||||
},
|
||||
_ => Err("Mismatched payload for BreakPanesToNewTab"),
|
||||
},
|
||||
Some(CommandName::BreakPanesToTabWithIndex) => match protobuf_plugin_command.payload {
|
||||
Some(Payload::BreakPanesToTabWithIndexPayload(
|
||||
break_panes_to_tab_with_index_payload,
|
||||
)) => Ok(PluginCommand::BreakPanesToTabWithIndex(
|
||||
break_panes_to_tab_with_index_payload
|
||||
.pane_ids
|
||||
.into_iter()
|
||||
.filter_map(|p_id| p_id.try_into().ok())
|
||||
.collect(),
|
||||
break_panes_to_tab_with_index_payload.tab_index as usize,
|
||||
break_panes_to_tab_with_index_payload.should_change_focus_to_target_tab,
|
||||
)),
|
||||
_ => Err("Mismatched payload for BreakPanesToTabWithIndex"),
|
||||
},
|
||||
None => Err("Unrecognized plugin command"),
|
||||
}
|
||||
}
|
||||
|
|
@ -1922,6 +1951,40 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
|||
},
|
||||
)),
|
||||
}),
|
||||
PluginCommand::BreakPanesToNewTab(
|
||||
pane_ids,
|
||||
new_tab_name,
|
||||
should_change_focus_to_new_tab,
|
||||
) => Ok(ProtobufPluginCommand {
|
||||
name: CommandName::BreakPanesToNewTab as i32,
|
||||
payload: Some(Payload::BreakPanesToNewTabPayload(
|
||||
BreakPanesToNewTabPayload {
|
||||
pane_ids: pane_ids
|
||||
.into_iter()
|
||||
.filter_map(|p_id| p_id.try_into().ok())
|
||||
.collect(),
|
||||
should_change_focus_to_new_tab,
|
||||
new_tab_name,
|
||||
},
|
||||
)),
|
||||
}),
|
||||
PluginCommand::BreakPanesToTabWithIndex(
|
||||
pane_ids,
|
||||
tab_index,
|
||||
should_change_focus_to_target_tab,
|
||||
) => Ok(ProtobufPluginCommand {
|
||||
name: CommandName::BreakPanesToTabWithIndex as i32,
|
||||
payload: Some(Payload::BreakPanesToTabWithIndexPayload(
|
||||
BreakPanesToTabWithIndexPayload {
|
||||
pane_ids: pane_ids
|
||||
.into_iter()
|
||||
.filter_map(|p_id| p_id.try_into().ok())
|
||||
.collect(),
|
||||
tab_index: tab_index as u32,
|
||||
should_change_focus_to_target_tab,
|
||||
},
|
||||
)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue