summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-11-05 13:24:33 +0100
committerAram Drevekenin <aram@poor.dev>2023-11-05 13:24:33 +0100
commitcc9dd35ba8bccada9f63ee8d4fbd3051b70b204d (patch)
tree4ed2de7f659aa1dcad8e7e6c052d396c5d900375
parent3ffd9d2a09adb66b428532cfea90ec9974f8f49b (diff)
change session name from the session-manager
-rw-r--r--default-plugins/session-manager/src/main.rs86
-rw-r--r--default-plugins/session-manager/src/resurrectable_sessions.rs3
-rw-r--r--default-plugins/session-manager/src/session_list.rs6
-rw-r--r--default-plugins/session-manager/src/ui/components.rs51
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs10
-rw-r--r--zellij-tile/src/shim.rs8
-rw-r--r--zellij-utils/assets/prost/api.plugin_command.rs7
-rw-r--r--zellij-utils/src/data.rs1
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto2
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs10
10 files changed, 171 insertions, 13 deletions
diff --git a/default-plugins/session-manager/src/main.rs b/default-plugins/session-manager/src/main.rs
index 7e39307d9..ce54ce559 100644
--- a/default-plugins/session-manager/src/main.rs
+++ b/default-plugins/session-manager/src/main.rs
@@ -7,7 +7,7 @@ use std::collections::BTreeMap;
use ui::{
components::{
- render_controls_line, render_new_session_line, render_prompt, render_resurrection_toggle,
+ render_controls_line, render_error, render_renaming_session_screen, render_new_session_line, render_prompt, render_resurrection_toggle,
Colors,
},
SessionUiInfo,
@@ -23,6 +23,8 @@ struct State {
resurrectable_sessions: ResurrectableSessions,
search_term: String,
new_session_name: Option<String>,
+ renaming_session_name: Option<String>,
+ error: Option<String>,
browsing_resurrection_sessions: bool,
colors: Colors,
}
@@ -67,6 +69,9 @@ impl ZellijPlugin for State {
if self.browsing_resurrection_sessions {
self.resurrectable_sessions.render(rows, cols);
return;
+ } else if let Some(new_session_name) = self.renaming_session_name.as_ref() {
+ render_renaming_session_screen(&new_session_name, rows, cols);
+ return;
}
render_resurrection_toggle(cols, false);
render_prompt(
@@ -87,7 +92,11 @@ impl ZellijPlugin for State {
self.sessions.is_searching,
self.colors,
);
- render_controls_line(self.sessions.is_searching, rows, cols, self.colors);
+ if let Some(error) = self.error.as_ref() {
+ render_error(&error, rows, cols);
+ } else {
+ render_controls_line(self.sessions.is_searching, rows, cols, self.colors);
+ }
}
}
@@ -96,6 +105,10 @@ impl State {
self.sessions.reset_selected_index();
}
fn handle_key(&mut self, key: Key) -> bool {
+ if self.error.is_some() {
+ self.error = None;
+ return true;
+ }
let mut should_render = false;
if let Key::Right = key {
if self.new_session_name.is_none() {
@@ -110,14 +123,14 @@ impl State {
} else if let Key::Down = key {
if self.browsing_resurrection_sessions {
self.resurrectable_sessions.move_selection_down();
- } else if self.new_session_name.is_none() {
+ } else if self.new_session_name.is_none() && self.renaming_session_name.is_none() {
self.sessions.move_selection_down();
}
should_render = true;
} else if let Key::Up = key {
if self.browsing_resurrection_sessions {
self.resurrectable_sessions.move_selection_up();
- } else if self.new_session_name.is_none() {
+ } else if self.new_session_name.is_none() && self.renaming_session_name.is_none() {
self.sessions.move_selection_up();
}
should_render = true;
@@ -126,6 +139,8 @@ impl State {
self.handle_selection();
} else if let Some(new_session_name) = self.new_session_name.as_mut() {
new_session_name.push(character);
+ } else if let Some(renaming_session_name) = self.renaming_session_name.as_mut() {
+ renaming_session_name.push(character);
} else if self.browsing_resurrection_sessions {
self.resurrectable_sessions.handle_character(character);
} else {
@@ -141,6 +156,12 @@ impl State {
} else {
new_session_name.pop();
}
+ } else if let Some(renaming_session_name) = self.renaming_session_name.as_mut() {
+ if renaming_session_name.is_empty() {
+ self.renaming_session_name = None;
+ } else {
+ renaming_session_name.pop();
+ }
} else if self.browsing_resurrection_sessions {
self.resurrectable_sessions.handle_backspace();
} else {
@@ -150,7 +171,7 @@ impl State {
}
should_render = true;
} else if let Key::Ctrl('w') = key {
- if self.sessions.is_searching {
+ if self.sessions.is_searching || self.browsing_resurrection_sessions {
// no-op
} else if self.new_session_name.is_some() {
self.new_session_name = None;
@@ -158,6 +179,15 @@ impl State {
self.new_session_name = Some(String::new());
}
should_render = true;
+ } else if let Key::Ctrl('r') = key {
+ if self.sessions.is_searching || self.browsing_resurrection_sessions {
+ // no-op
+ } else if self.renaming_session_name.is_some() {
+ self.renaming_session_name = None;
+ } else {
+ self.renaming_session_name = Some(String::new());
+ }
+ should_render = true;
} else if let Key::Ctrl('c') = key {
if let Some(new_session_name) = self.new_session_name.as_mut() {
if new_session_name.is_empty() {
@@ -165,6 +195,12 @@ impl State {
} else {
new_session_name.clear()
}
+ } else if let Some(renaming_session_name) = self.renaming_session_name.as_mut() {
+ if renaming_session_name.is_empty() {
+ self.renaming_session_name = None;
+ } else {
+ renaming_session_name.clear()
+ }
} else if !self.search_term.is_empty() {
self.search_term.clear();
self.sessions
@@ -190,7 +226,15 @@ impl State {
should_render = true;
}
} else if let Key::Esc = key {
- hide_self();
+ if self.renaming_session_name.is_some() {
+ self.renaming_session_name = None;
+ should_render = true;
+ } else if self.new_session_name.is_some() {
+ self.new_session_name = None;
+ should_render = true;
+ } else {
+ hide_self();
+ }
}
should_render
}
@@ -210,6 +254,26 @@ impl State {
} else {
switch_session(Some(new_session_name));
}
+ } else if let Some(renaming_session_name) = &self.renaming_session_name.take() {
+ if renaming_session_name.is_empty() {
+ // TODO: implement these, then implement the error UI, then implement the renaming
+ // session screen, then test it
+ self.show_error("New name must not be empty.");
+ return; // s that we don't hide self
+ } else if self.session_name.as_ref() == Some(renaming_session_name) {
+ // noop - we're already called that!
+ return; // s that we don't hide self
+ } else if self.sessions.has_session(&renaming_session_name) {
+ self.show_error("A session by this name already exists.");
+ return; // s that we don't hide self
+ } else if self.resurrectable_sessions.has_session(&renaming_session_name) {
+ self.show_error("A resurrectable session by this name already exists.");
+ return; // s that we don't hide self
+ } else {
+ self.update_current_session_name_in_ui(&renaming_session_name);
+ rename_session(&renaming_session_name);
+ return; // s that we don't hide self
+ }
} else if let Some(selected_session_name) = self.sessions.get_selected_session_name() {
let selected_tab = self.sessions.get_selected_tab_position();
let selected_pane = self.sessions.get_selected_pane_id();
@@ -235,6 +299,16 @@ impl State {
.update_search_term(&self.search_term, &self.colors);
hide_self();
}
+ fn show_error(&mut self, error_text: &str) {
+ self.error = Some(error_text.to_owned());
+ }
+ fn update_current_session_name_in_ui(&mut self, new_name: &str) {
+ if let Some(old_session_name) = self.session_name.as_ref() {
+ self.sessions.update_session_name(&old_session_name, new_name);
+ }
+ self.session_name = Some(new_name.to_owned());
+
+ }
fn update_session_infos(&mut self, session_infos: Vec<SessionInfo>) {
let session_infos: Vec<SessionUiInfo> = session_infos
.iter()
diff --git a/default-plugins/session-manager/src/resurrectable_sessions.rs b/default-plugins/session-manager/src/resurrectable_sessions.rs
index beed254fd..79df37a9b 100644
--- a/default-plugins/session-manager/src/resurrectable_sessions.rs
+++ b/default-plugins/session-manager/src/resurrectable_sessions.rs
@@ -308,6 +308,9 @@ impl ResurrectableSessions {
self.search_term.pop();
self.update_search_term();
}
+ pub fn has_session(&self, session_name: &str) -> bool {
+ self.all_resurrectable_sessions.iter().any(|s| s.0 == session_name)
+ }
fn update_search_term(&mut self) {
let mut matches = vec![];
let matcher = SkimMatcherV2::default().use_cache(true);
diff --git a/default-plugins/session-manager/src/session_list.rs b/default-plugins/session-manager/src/session_list.rs
index 788d324f7..cf822ac4e 100644
--- a/default-plugins/session-manager/src/session_list.rs
+++ b/default-plugins/session-manager/src/session_list.rs
@@ -314,6 +314,12 @@ impl SessionList {
pub fn reset_selected_index(&mut self) {
self.selected_index.reset();
}
+ pub fn has_session(&self, session_name: &str) -> bool {
+ self.session_ui_infos.iter().any(|s| s.name == session_name)
+ }
+ pub fn update_session_name(&mut self, old_name: &str, new_name: &str) {
+ self.session_ui_infos.iter_mut().find(|s| s.name == old_name).map(|s| s.name = new_name.to_owned());
+ }
}
#[derive(Debug, Clone, Default)]
diff --git a/default-plugins/session-manager/src/ui/components.rs b/default-plugins/session-manager/src/ui/components.rs
index be3da41df..4d9839c0f 100644
--- a/default-plugins/session-manager/src/ui/components.rs
+++ b/default-plugins/session-manager/src/ui/components.rs
@@ -558,29 +558,68 @@ pub fn render_new_session_line(session_name: &Option<String>, is_searching: bool
}
}
+pub fn render_error(error_text: &str, rows: usize, columns: usize) {
+ print_text_with_coordinates(
+ Text::new(format!("Error: {}", error_text)).color_range(3, ..),
+ 0,
+ rows,
+ Some(columns),
+ None,
+ );
+}
+
+pub fn render_renaming_session_screen(new_session_name: &str, rows: usize, columns: usize) {
+ if rows == 0 || columns == 0 {
+ return;
+ }
+ let prompt_text = "NEW NAME FOR CURRENT SESSION";
+ let new_session_name = format!("{}_", new_session_name);
+ let prompt_y_location = (rows / 2).saturating_sub(1);
+ let session_name_y_location = (rows / 2) + 1;
+ let prompt_x_location = columns.saturating_sub(prompt_text.chars().count()) / 2;
+ let session_name_x_location = columns.saturating_sub(new_session_name.chars().count()) / 2;
+ print_text_with_coordinates(
+ Text::new(prompt_text).color_range(0, ..),
+ prompt_x_location,
+ prompt_y_location,
+ None,
+ None,
+ );
+ print_text_with_coordinates(
+ Text::new(new_session_name).color_range(3, ..),
+ session_name_x_location,
+ session_name_y_location,
+ None,
+ None,
+ );
+}
+
pub fn render_controls_line(is_searching: bool, row: usize, max_cols: usize, colors: Colors) {
let (arrows, navigate) = if is_searching {
(colors.magenta("<↓↑>"), colors.bold("Navigate"))
} else {
(colors.magenta("<←↓↑→>"), colors.bold("Navigate and Expand"))
};
+ let rename = colors.magenta("<Ctrl r>");
+ let rename_text = colors.bold("Rename session");
let enter = colors.magenta("<ENTER>");
let select = colors.bold("Switch to selected");
let esc = colors.magenta("<ESC>");
let to_hide = colors.bold("Hide");
- if max_cols >= 80 {
+ if max_cols >= 104 {
print!(
- "\u{1b}[m\u{1b}[{row}HHelp: {arrows} - {navigate}, {enter} - {select}, {esc} - {to_hide}"
+ "\u{1b}[m\u{1b}[{row}HHelp: {arrows} - {navigate}, {enter} - {select}, {rename} - {rename_text}, {esc} - {to_hide}"
);
- } else if max_cols >= 57 {
+ } else if max_cols >= 73 {
let navigate = colors.bold("Navigate");
let select = colors.bold("Switch");
+ let rename_text = colors.bold("Rename");
print!(
- "\u{1b}[m\u{1b}[{row}HHelp: {arrows} - {navigate}, {enter} - {select}, {esc} - {to_hide}"
+ "\u{1b}[m\u{1b}[{row}HHelp: {arrows} - {navigate}, {enter} - {select}, {rename} - {rename_text}, {esc} - {to_hide}"
);
- } else if max_cols >= 20 {
- print!("\u{1b}[m\u{1b}[{row}H{arrows}/{enter}/{esc}");
+ } else if max_cols >= 28 {
+ print!("\u{1b}[m\u{1b}[{row}H{arrows}/{enter}/{rename}/{esc}");
}
}
diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs
index 38b89ceac..2a2de5e09 100644
--- a/zellij-server/src/plugins/zellij_exports.rs
+++ b/zellij-server/src/plugins/zellij_exports.rs
@@ -237,6 +237,9 @@ fn host_run_plugin_command(env: FunctionEnvMut<ForeignFunctionEnv>) {
PluginCommand::OpenCommandPaneInPlace(command_to_run) => {
open_command_pane_in_place(env, command_to_run)
},
+ PluginCommand::RenameSession(new_session_name) => {
+ rename_session(env, new_session_name)
+ },
},
(PermissionStatus::Denied, permission) => {
log::error!(
@@ -1188,6 +1191,12 @@ fn rename_tab(env: &ForeignFunctionEnv, tab_index: u32, new_name: &str) {
apply_action!(rename_tab_action, error_msg, env);
}
+fn rename_session(env: &ForeignFunctionEnv, new_session_name: String) {
+ let error_msg = || format!("failed to rename session in plugin {}", env.plugin_env.name());
+ let action = Action::RenameSession(new_session_name);
+ apply_action!(action, error_msg, env);
+}
+
// Custom panic handler for plugins.
//
// This is called when a panic occurs in a plugin. Since most panics will likely originate in the
@@ -1315,6 +1324,7 @@ fn check_command_permission(
| PluginCommand::SwitchSession(..)
| PluginCommand::DeleteDeadSession(..)
| PluginCommand::DeleteAllDeadSessions
+ | PluginCommand::RenameSession(..)
| PluginCommand::RenameTab(..) => PermissionType::ChangeApplicationState,
_ => return (PermissionStatus::Granted, None),
};
diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs
index eb898b4fc..8f2b297a3 100644
--- a/zellij-tile/src/shim.rs
+++ b/zellij-tile/src/shim.rs
@@ -682,6 +682,14 @@ pub fn delete_all_dead_sessions() {
unsafe { host_run_plugin_command() };
}
+/// Rename the current session
+pub fn rename_session(name: &str) {
+ let plugin_command = PluginCommand::RenameSession(name.to_owned());
+ 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)]
diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs
index f0d2fe02f..0dd5f6814 100644
--- a/zellij-utils/assets/prost/api.plugin_command.rs
+++ b/zellij-utils/assets/prost/api.plugin_command.rs
@@ -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"
+ 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"
)]
pub payload: ::core::option::Option<plugin_command::Payload>,
}
@@ -102,6 +102,8 @@ pub mod plugin_command {
WebRequestPayload(super::WebRequestPayload),
#[prost(string, tag = "45")]
DeleteDeadSessionPayload(::prost::alloc::string::String),
+ #[prost(string, tag = "46")]
+ RenameSessionPayload(::prost::alloc::string::String),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
@@ -315,6 +317,7 @@ pub enum CommandName {
WebRequest = 72,
DeleteDeadSession = 73,
DeleteAllDeadSessions = 74,
+ RenameSession = 75,
}
impl CommandName {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -398,6 +401,7 @@ impl CommandName {
CommandName::WebRequest => "WebRequest",
CommandName::DeleteDeadSession => "DeleteDeadSession",
CommandName::DeleteAllDeadSessions => "DeleteAllDeadSessions",
+ CommandName::RenameSession => "RenameSession",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -478,6 +482,7 @@ impl CommandName {
"WebRequest" => Some(Self::WebRequest),
"DeleteDeadSession" => Some(Self::DeleteDeadSession),
"DeleteAllDeadSessions" => Some(Self::DeleteAllDeadSessions),
+ "RenameSession" => Some(Self::RenameSession),
_ => None,
}
}
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index 82daf118d..bed6f4747 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -1104,4 +1104,5 @@ pub enum PluginCommand {
Vec<u8>, // body
BTreeMap<String, String>, // context
),
+ RenameSession(String), // String -> new session name
}
diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto
index 0b950ff0e..53994a88c 100644
--- a/zellij-utils/src/plugin_api/plugin_command.proto
+++ b/zellij-utils/src/plugin_api/plugin_command.proto
@@ -86,6 +86,7 @@ enum CommandName {
WebRequest = 72;
DeleteDeadSession = 73;
DeleteAllDeadSessions = 74;
+ RenameSession = 75;
}
message PluginCommand {
@@ -135,6 +136,7 @@ message PluginCommand {
RunCommandPayload run_command_payload = 43;
WebRequestPayload web_request_payload = 44;
string delete_dead_session_payload = 45;
+ string rename_session_payload = 46;
}
}
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs
index 6b70b18eb..ed476687c 100644
--- a/zellij-utils/src/plugin_api/plugin_command.rs
+++ b/zellij-utils/src/plugin_api/plugin_command.rs
@@ -635,6 +635,12 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
_ => Err("Mismatched payload for DeleteDeadSession"),
},
Some(CommandName::DeleteAllDeadSessions) => Ok(PluginCommand::DeleteAllDeadSessions),
+ Some(CommandName::RenameSession) => match protobuf_plugin_command.payload {
+ Some(Payload::RenameSessionPayload(new_session_name)) => {
+ Ok(PluginCommand::RenameSession(new_session_name))
+ },
+ _ => Err("Mismatched payload for RenameSession"),
+ },
None => Err("Unrecognized plugin command"),
}
}
@@ -1059,6 +1065,10 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
name: CommandName::DeleteAllDeadSessions as i32,
payload: None,
}),
+ PluginCommand::RenameSession(new_session_name) => Ok(ProtobufPluginCommand {
+ name: CommandName::RenameSession as i32,
+ payload: Some(Payload::RenameSessionPayload(new_session_name)),
+ }),
}
}
}