summaryrefslogtreecommitdiffstats
path: root/zellij-server
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2024-02-06 14:26:14 +0100
committerGitHub <noreply@github.com>2024-02-06 14:26:14 +0100
commit6b20a958f4e8db5614fffb27fe5d32f07ddfe855 (patch)
treec8383fb7941b5e0c23cb348a655f2ea0fafd8668 /zellij-server
parent286f7ccc28e3a091e2d3ef5663ae7878056551e6 (diff)
feat(sessions): welcome screen (#3112)
* prototype - can send layout name for new session from session-manager * feat(sessions): ui for selecting layout for new session in the session-manager * fix: send available layouts to plugins * make tests compile * fix tests * improve ui * fix: respect built-in layouts * ui for built-in layouts * some cleanups * style(fmt): rustfmt * welcome screen ui * fix: make sure layout config is not shared between sessions * allow disconnecting other users from current session and killing other sessions * fix: respect default layout * add welcome screen layout * tests(plugins): new api methods * fix(session-manager): do not quit welcome screen on esc and break * fix(plugins): adjust permissions * style(fmt): rustfmt * style(fmt): fix warnings
Diffstat (limited to 'zellij-server')
-rw-r--r--zellij-server/src/lib.rs35
-rw-r--r--zellij-server/src/plugins/unit/plugin_tests.rs240
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__disconnect_other_clients_plugins_command.snap10
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap18
-rw-r--r--zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap22
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs41
-rw-r--r--zellij-server/src/screen.rs21
-rw-r--r--zellij-server/src/tab/mod.rs2
-rw-r--r--zellij-server/src/unit/screen_tests.rs12
9 files changed, 392 insertions, 9 deletions
diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs
index 437f465bd..008955705 100644
--- a/zellij-server/src/lib.rs
+++ b/zellij-server/src/lib.rs
@@ -44,7 +44,7 @@ use zellij_utils::{
consts::{DEFAULT_SCROLL_BUFFER_SIZE, SCROLL_BUFFER_SIZE},
data::{ConnectToSession, Event, PluginCapabilities},
errors::{prelude::*, ContextType, ErrorInstruction, FatalError, ServerContext},
- home::get_default_data_dir,
+ home::{default_layout_dir, get_default_data_dir},
input::{
command::{RunCommand, TerminalAction},
get_mode_info,
@@ -93,6 +93,7 @@ pub enum ServerInstruction {
pipe_id: String,
client_id: ClientId,
},
+ DisconnectAllClientsExcept(ClientId),
}
impl From<&ServerInstruction> for ServerContext {
@@ -117,6 +118,9 @@ impl From<&ServerInstruction> for ServerContext {
ServerInstruction::AssociatePipeWithClient { .. } => {
ServerContext::AssociatePipeWithClient
},
+ ServerInstruction::DisconnectAllClientsExcept(..) => {
+ ServerContext::DisconnectAllClientsExcept
+ },
}
}
}
@@ -133,6 +137,7 @@ pub(crate) struct SessionMetaData {
pub client_attributes: ClientAttributes,
pub default_shell: Option<TerminalAction>,
pub layout: Box<Layout>,
+ pub config_options: Box<Options>,
screen_thread: Option<thread::JoinHandle<()>>,
pty_thread: Option<thread::JoinHandle<()>>,
plugin_thread: Option<thread::JoinHandle<()>>,
@@ -650,6 +655,21 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
}
break;
},
+ ServerInstruction::DisconnectAllClientsExcept(client_id) => {
+ let client_ids: Vec<ClientId> = session_state
+ .read()
+ .unwrap()
+ .client_ids()
+ .iter()
+ .copied()
+ .filter(|c| c != &client_id)
+ .collect();
+ for client_id in client_ids {
+ let _ = os_input
+ .send_to_client(client_id, ServerToClientMsg::Exit(ExitReason::Normal));
+ remove_client!(client_id, os_input, session_state);
+ }
+ },
ServerInstruction::DetachSession(client_ids) => {
for client_id in client_ids {
let _ = os_input
@@ -749,7 +769,16 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
session_state
);
},
- ServerInstruction::SwitchSession(connect_to_session, client_id) => {
+ ServerInstruction::SwitchSession(mut connect_to_session, client_id) => {
+ let layout_dir = session_data
+ .read()
+ .unwrap()
+ .as_ref()
+ .and_then(|c| c.config_options.layout_dir.clone())
+ .or_else(|| default_layout_dir());
+ if let Some(layout_dir) = layout_dir {
+ connect_to_session.apply_layout_dir(&layout_dir);
+ }
if let Some(min_size) = session_state.read().unwrap().min_client_terminal_size() {
session_data
.write()
@@ -906,6 +935,7 @@ fn init_session(
let client_attributes_clone = client_attributes.clone();
let debug = opts.debug;
let layout = layout.clone();
+ let config_options = config_options.clone();
move || {
screen_thread_main(
screen_bus,
@@ -1006,6 +1036,7 @@ fn init_session(
default_shell,
client_attributes,
layout,
+ config_options: config_options.clone(),
screen_thread: Some(screen_thread),
pty_thread: Some(pty_thread),
plugin_thread: Some(plugin_thread),
diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs
index 6791213c7..6b6e345e1 100644
--- a/zellij-server/src/plugins/unit/plugin_tests.rs
+++ b/zellij-server/src/plugins/unit/plugin_tests.rs
@@ -5970,3 +5970,243 @@ pub fn pipe_message_to_plugin_plugin_command() {
});
assert_snapshot!(format!("{:#?}", plugin_bytes_event));
}
+
+#[test]
+#[ignore]
+pub fn switch_session_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, server_receiver, screen_receiver, teardown) =
+ create_plugin_thread_with_server_receiver(Some(plugin_host_folder));
+ let plugin_should_float = Some(false);
+ let plugin_title = Some("test_plugin".to_owned());
+ let run_plugin = RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
+ configuration: 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_naked_variant!(
+ received_screen_instructions,
+ ScreenInstruction::Exit,
+ screen_receiver,
+ 1,
+ &PermissionType::ChangeApplicationState,
+ cache_path,
+ plugin_thread_sender,
+ client_id
+ );
+ let received_server_instruction = Arc::new(Mutex::new(vec![]));
+ let server_thread = log_actions_in_thread!(
+ received_server_instruction,
+ ServerInstruction::SwitchSession,
+ server_receiver,
+ 1
+ );
+
+ 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(Key::Ctrl('5')), // this triggers the enent in the fixture plugin
+ )]));
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ teardown();
+ server_thread.join().unwrap(); // this might take a while if the cache is cold
+ let switch_session_event = received_server_instruction
+ .lock()
+ .unwrap()
+ .iter()
+ .rev()
+ .find_map(|i| {
+ if let ServerInstruction::SwitchSession(..) = i {
+ Some(i.clone())
+ } else {
+ None
+ }
+ })
+ .clone();
+ assert_snapshot!(format!("{:#?}", switch_session_event));
+}
+
+#[test]
+#[ignore]
+pub fn switch_session_with_layout_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, server_receiver, screen_receiver, teardown) =
+ create_plugin_thread_with_server_receiver(Some(plugin_host_folder));
+ let plugin_should_float = Some(false);
+ let plugin_title = Some("test_plugin".to_owned());
+ let run_plugin = RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
+ configuration: 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_naked_variant!(
+ received_screen_instructions,
+ ScreenInstruction::Exit,
+ screen_receiver,
+ 1,
+ &PermissionType::ChangeApplicationState,
+ cache_path,
+ plugin_thread_sender,
+ client_id
+ );
+ let received_server_instruction = Arc::new(Mutex::new(vec![]));
+ let server_thread = log_actions_in_thread!(
+ received_server_instruction,
+ ServerInstruction::SwitchSession,
+ server_receiver,
+ 1
+ );
+
+ 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(Key::Ctrl('7')), // this triggers the enent in the fixture plugin
+ )]));
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ teardown();
+ server_thread.join().unwrap(); // this might take a while if the cache is cold
+ let switch_session_event = received_server_instruction
+ .lock()
+ .unwrap()
+ .iter()
+ .rev()
+ .find_map(|i| {
+ if let ServerInstruction::SwitchSession(..) = i {
+ Some(i.clone())
+ } else {
+ None
+ }
+ })
+ .clone();
+ assert_snapshot!(format!("{:#?}", switch_session_event));
+}
+
+#[test]
+#[ignore]
+pub fn disconnect_other_clients_plugins_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, server_receiver, screen_receiver, teardown) =
+ create_plugin_thread_with_server_receiver(Some(plugin_host_folder));
+ let plugin_should_float = Some(false);
+ let plugin_title = Some("test_plugin".to_owned());
+ let run_plugin = RunPlugin {
+ _allow_exec_host_cmd: false,
+ location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)),
+ configuration: 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_naked_variant!(
+ received_screen_instructions,
+ ScreenInstruction::Exit,
+ screen_receiver,
+ 1,
+ &PermissionType::ChangeApplicationState,
+ cache_path,
+ plugin_thread_sender,
+ client_id
+ );
+ let received_server_instruction = Arc::new(Mutex::new(vec![]));
+ let server_thread = log_actions_in_thread!(
+ received_server_instruction,
+ ServerInstruction::DisconnectAllClientsExcept,
+ server_receiver,
+ 1
+ );
+
+ 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(Key::Ctrl('6')), // this triggers the enent in the fixture plugin
+ )]));
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ teardown();
+ server_thread.join().unwrap(); // this might take a while if the cache is cold
+ let switch_session_event = received_server_instruction
+ .lock()
+ .unwrap()
+ .iter()
+ .rev()
+ .find_map(|i| {
+ if let ServerInstruction::DisconnectAllClientsExcept(..) = i {
+ Some(i.clone())
+ } else {
+ None
+ }
+ })
+ .clone();
+ assert_snapshot!(format!("{:#?}", switch_session_event));
+}
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__disconnect_other_clients_plugins_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__disconnect_other_clients_plugins_command.snap
new file mode 100644
index 000000000..d463df1c0
--- /dev/null
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__disconnect_other_clients_plugins_command.snap
@@ -0,0 +1,10 @@
+---
+source: zellij-server/src/plugins/./unit/plugin_tests.rs
+assertion_line: 6131
+expression: "format!(\"{:#?}\", switch_session_event)"
+---
+Some(
+ DisconnectAllClientsExcept(
+ 1,
+ ),
+)
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap
new file mode 100644
index 000000000..f254f0398
--- /dev/null
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap
@@ -0,0 +1,18 @@
+---
+source: zellij-server/src/plugins/./unit/plugin_tests.rs
+assertion_line: 6051
+expression: "format!(\"{:#?}\", switch_session_event)"
+---
+Some(
+ SwitchSession(
+ ConnectToSession {
+ name: Some(
+ "my_new_session",
+ ),
+ tab_position: None,
+ pane_id: None,
+ layout: None,
+ },
+ 1,
+ ),
+)
diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap
new file mode 100644
index 000000000..46f6819a5
--- /dev/null
+++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap
@@ -0,0 +1,22 @@
+---
+source: zellij-server/src/plugins/./unit/plugin_tests.rs
+assertion_line: 6131
+expression: "format!(\"{:#?}\", switch_session_event)"
+---
+Some(
+ SwitchSession(
+ ConnectToSession {
+ name: Some(
+ "my_other_new_session",
+ ),
+ tab_position: None,
+ pane_id: None,
+ layout: Some(
+ BuiltIn(
+ "compact",
+ ),
+ ),
+ },
+ 1,
+ ),
+)
diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs
index 8791e128e..e6787c240 100644
--- a/zellij-server/src/plugins/zellij_exports.rs
+++ b/zellij-server/src/plugins/zellij_exports.rs
@@ -18,10 +18,14 @@ use std::{
use wasmer::{imports, AsStoreMut, Function, FunctionEnv, FunctionEnvMut, Imports};
use wasmer_wasi::WasiEnv;
use zellij_utils::data::{
- CommandType, ConnectToSession, HttpVerb, MessageToPlugin, PermissionStatus, PermissionType,
- PluginPermission,
+ CommandType, ConnectToSession, HttpVerb, LayoutInfo, MessageToPlugin, PermissionStatus,
+ PermissionType, PluginPermission,
};
use zellij_utils::input::permission::PermissionCache;
+use zellij_utils::{
+ interprocess::local_socket::LocalSocketStream,
+ ipc::{ClientToServerMsg, IpcSenderWithContext},
+};
use url::Url;
@@ -225,6 +229,7 @@ fn host_run_plugin_command(env: FunctionEnvMut<ForeignFunctionEnv>) {
connect_to_session.name,
connect_to_session.tab_position,
connect_to_session.pane_id,
+ connect_to_session.layout,
)?,
PluginCommand::DeleteDeadSession(session_name) => {
delete_dead_session(session_name)?
@@ -252,6 +257,8 @@ fn host_run_plugin_command(env: FunctionEnvMut<ForeignFunctionEnv>) {
cli_pipe_output(env, pipe_name, output)?
},
PluginCommand::MessageToPlugin(message) => message_to_plugin(env, message)?,
+ PluginCommand::DisconnectOtherClients => disconnect_other_clients(env),
+ PluginCommand::KillSessions(session_list) => kill_sessions(session_list),
},
(PermissionStatus::Denied, permission) => {
log::error!(
@@ -900,6 +907,7 @@ fn switch_session(
session_name: Option<String>,
tab_position: Option<usize>,
pane_id: Option<(u32, bool)>,
+ layout: Option<LayoutInfo>,
) -> Result<()> {
// pane_id is (id, is_plugin)
let err_context = || format!("Failed to switch session");
@@ -909,6 +917,7 @@ fn switch_session(
name: session_name,
tab_position,
pane_id,
+ layout,
};
env.plugin_env
.senders
@@ -1278,6 +1287,30 @@ fn rename_session(env: &ForeignFunctionEnv, new_session_name: String) {
apply_action!(action, error_msg, env);
}
+fn disconnect_other_clients(env: &ForeignFunctionEnv) {
+ let _ = env
+ .plugin_env
+ .senders
+ .send_to_server(ServerInstruction::DisconnectAllClientsExcept(
+ env.plugin_env.client_id,
+ ))
+ .context("failed to send disconnect other clients instruction");
+}
+
+fn kill_sessions(session_names: Vec<String>) {
+ for session_name in session_names {
+ let path = &*ZELLIJ_SOCK_DIR.join(&session_name);
+ match LocalSocketStream::connect(path) {
+ Ok(stream) => {
+ let _ = IpcSenderWithContext::new(stream).send(ClientToServerMsg::KillSession);
+ },
+ Err(e) => {
+ log::error!("Failed to kill session {}: {:?}", session_name, e);
+ },
+ };
+ }
+}
+
// Custom panic handler for plugins.
//
// This is called when a panic occurs in a plugin. Since most panics will likely originate in the
@@ -1406,7 +1439,9 @@ fn check_command_permission(
| PluginCommand::DeleteDeadSession(..)
| PluginCommand::DeleteAllDeadSessions
| PluginCommand::RenameSession(..)
- | PluginCommand::RenameTab(..) => PermissionType::ChangeApplicationState,
+ | PluginCommand::RenameTab(..)
+ | PluginCommand::DisconnectOtherClients
+ | PluginCommand::KillSessions(..) => PermissionType::ChangeApplicationState,
PluginCommand::UnblockCliPipeInput(..)
| PluginCommand::BlockCliPipeInput(..)
| PluginCommand::CliPipeOutput(..) => PermissionType::ReadCliPipes,
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index c312480dc..5b0b6bea1 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -577,6 +577,8 @@ pub(crate) struct Screen {
default_shell: Option<PathBuf>,
styled_underlines: bool,
arrow_fonts: bool,
+ layout_dir: Option<PathBuf>,
+ default_layout_name: Option<String>,
}
impl Screen {
@@ -592,12 +594,14 @@ impl Screen {
copy_options: CopyOptions,
debug: bool,
default_layout: Box<Layout>,
+ default_layout_name: Option<String>,
default_shell: Option<PathBuf>,
session_serialization: bool,
serialize_pane_viewport: bool,
scrollback_lines_to_serialize: Option<usize>,
styled_underlines: bool,
arrow_fonts: bool,
+ layout_dir: Option<PathBuf>,
) -> Self {
let session_name = mode_info.session_name.clone().unwrap_or_default();
let session_info = SessionInfo::new(session_name.clone());
@@ -629,6 +633,7 @@ impl Screen {
session_name,
session_infos_on_machine,
default_layout,
+ default_layout_name,
default_shell,
session_serialization,
serialize_pane_viewport,
@@ -636,6 +641,7 @@ impl Screen {
styled_underlines,
arrow_fonts,
resurrectable_sessions,
+ layout_dir,
}
}
@@ -1412,12 +1418,21 @@ impl Screen {
// generate own session info
let pane_manifest = self.generate_and_report_pane_state()?;
let tab_infos = self.generate_and_report_tab_state()?;
+ // in the context of unit/integration tests, we don't need to list available layouts
+ // because this is mostly about HD access - it does however throw off the timing in the
+ // tests and causes them to flake, which is why we skip it here
+ #[cfg(not(test))]
+ let available_layouts =
+ Layout::list_available_layouts(self.layout_dir.clone(), &self.default_layout_name);
+ #[cfg(test)]
+ let available_layouts = vec![];
let session_info = SessionInfo {
name: self.session_name.clone(),
tabs: tab_infos,
panes: pane_manifest,
connected_clients: self.active_tab_indices.keys().len(),
is_current_session: true,
+ available_layouts,
};
self.bus
.senders
@@ -2101,7 +2116,11 @@ pub(crate) fn screen_thread_main(
let serialize_pane_viewport = config_options.serialize_pane_viewport.unwrap_or(false);
let scrollback_lines_to_serialize = config_options.scrollback_lines_to_serialize;
let session_is_mirrored = config_options.mirror_session.unwrap_or(false);
+ let layout_dir = config_options.layout_dir;
let default_shell = config_options.default_shell;
+ let default_layout_name = config_options
+ .default_layout
+ .map(|l| format!("{}", l.display()));
let copy_options = CopyOptions::new(
config_options.copy_command,
config_options.copy_clipboard.unwrap_or_default(),
@@ -2128,12 +2147,14 @@ pub(crate) fn screen_thread_main(
copy_options,
debug,
default_layout,
+ default_layout_name,
default_shell,
session_serialization,
serialize_pane_viewport,
scrollback_lines_to_serialize,
styled_underlines,
arrow_fonts,
+ layout_dir,
);
let mut pending_tab_ids: HashSet<usize> = HashSet::new();
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs
index 0352eb96d..2ed9eb35b 100644
--- a/zellij-server/src/tab/mod.rs
+++ b/zellij-server/src/tab/mod.rs
@@ -847,7 +847,7 @@ impl Tab {
pub fn rename_session(&mut self, new_session_name: String) -> Result<()> {
{
let mode_infos = &mut self.mode_info.borrow_mut();
- for (_client_id, mut mode_info) in mode_infos.iter_mut() {
+ for (_client_id, mode_info) in mode_infos.iter_mut() {
mode_info.session_name = Some(new_session_name.clone());
}
self.default_mode_info.session_name = Some(new_session_name);
diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs
index 34076d700..4ce4dbc14 100644
--- a/zellij-server/src/unit/screen_tests.rs
+++ b/zellij-server/src/unit/screen_tests.rs
@@ -241,10 +241,12 @@ fn create_new_screen(size: Size) -> Screen {
let session_is_mirrored = true;
let copy_options = CopyOptions::default();
let default_layout = Box::new(Layout::default());
+ le