aboutsummaryrefslogtreecommitdiff
path: root/src/app/input/modal.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-18 01:55:46 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-18 01:55:46 +0300
commite298e4589050349630d0faaec00ef11555b83ae1 (patch)
treef9487e37bb641cb99e5bb053d7ad8106db13b047 /src/app/input/modal.rs
parent13ce20c4f536892c5b939bd62e5286fac9c2eaee (diff)
feat: add optional workspace name prompt
Diffstat (limited to 'src/app/input/modal.rs')
-rw-r--r--src/app/input/modal.rs72
1 files changed, 62 insertions, 10 deletions
diff --git a/src/app/input/modal.rs b/src/app/input/modal.rs
index 84aed8da..23134ddc 100644
--- a/src/app/input/modal.rs
+++ b/src/app/input/modal.rs
@@ -302,6 +302,7 @@ pub(super) fn open_rename_workspace(
terminal_runtimes: &crate::terminal::TerminalRuntimeRegistry,
ws_idx: usize,
) {
+ state.pending_workspace_create_cwd = None;
state.selected = ws_idx;
state.rename_pane_target = None;
state.name_input =
@@ -310,9 +311,21 @@ pub(super) fn open_rename_workspace(
state.mode = Mode::RenameWorkspace;
}
+pub(crate) fn open_new_workspace_dialog(state: &mut AppState, cwd: std::path::PathBuf) {
+ let suggested_name = crate::workspace::derive_label_from_cwd(&cwd);
+ state.creating_new_tab = false;
+ state.requested_new_tab_name = None;
+ state.pending_workspace_create_cwd = Some(cwd);
+ state.rename_pane_target = None;
+ state.name_input = suggested_name;
+ state.name_input_replace_on_type = true;
+ state.mode = Mode::RenameWorkspace;
+}
+
pub(super) fn open_rename_active_tab(state: &mut AppState, replace_on_type: bool) {
state.creating_new_tab = false;
state.requested_new_tab_name = None;
+ state.pending_workspace_create_cwd = None;
state.rename_pane_target = None;
if let Some(ws) = state.active.and_then(|i| state.workspaces.get(i)) {
if let Some(name) = ws.active_tab_display_name() {
@@ -333,6 +346,7 @@ pub(super) fn open_rename_pane(state: &mut AppState, pane_id: crate::layout::Pan
let terminal = state.terminals.get(&pane.attached_terminal_id);
state.creating_new_tab = false;
state.requested_new_tab_name = None;
+ state.pending_workspace_create_cwd = None;
state.rename_pane_target = Some(pane_id);
state.name_input = terminal
.and_then(|t| t.manual_label.clone())
@@ -341,6 +355,11 @@ pub(super) fn open_rename_pane(state: &mut AppState, pane_id: crate::layout::Pan
state.mode = Mode::RenamePane;
}
+fn workspace_create_label(input: &str, suggested_name: &str) -> Option<String> {
+ let name = input.trim();
+ (!name.is_empty() && name != suggested_name).then(|| name.to_string())
+}
+
fn next_new_tab_default_name(state: &AppState) -> String {
state
.active
@@ -352,6 +371,7 @@ fn next_new_tab_default_name(state: &AppState) -> String {
pub(super) fn open_new_tab_dialog(state: &mut AppState) {
state.creating_new_tab = true;
state.requested_new_tab_name = None;
+ state.pending_workspace_create_cwd = None;
state.rename_pane_target = None;
state.name_input = next_new_tab_default_name(state);
state.name_input_replace_on_type = true;
@@ -423,7 +443,11 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) {
state.name_input.trim().to_string()
};
match state.mode {
- Mode::RenameWorkspace if !state.workspaces.is_empty() && !new_name.is_empty() => {
+ Mode::RenameWorkspace
+ if state.pending_workspace_create_cwd.is_none()
+ && !state.workspaces.is_empty()
+ && !new_name.is_empty() =>
+ {
let workspace_id = state.workspaces[state.selected].id.clone();
state.workspaces[state.selected].set_custom_name(new_name);
crate::logging::workspace_renamed(&workspace_id);
@@ -487,6 +511,7 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) {
_ => {}
}
state.creating_new_tab = false;
+ state.pending_workspace_create_cwd = None;
state.rename_pane_target = None;
state.name_input.clear();
state.name_input_replace_on_type = false;
@@ -499,6 +524,7 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) {
ModalAction::Cancel => {
state.creating_new_tab = false;
state.requested_new_tab_name = None;
+ state.pending_workspace_create_cwd = None;
state.rename_pane_target = None;
state.name_input.clear();
state.name_input_replace_on_type = false;
@@ -916,15 +942,29 @@ impl App {
};
match self.state.mode {
- Mode::RenameWorkspace if !self.state.workspaces.is_empty() && !new_name.is_empty() => {
- let workspace_id = self.public_workspace_id(self.state.selected);
- self.runtime_workspace_rename(
- "tui.workspace.rename",
- crate::api::schema::WorkspaceRenameParams {
- workspace_id,
- label: new_name,
- },
- );
+ Mode::RenameWorkspace => {
+ if let Some(cwd) = self.state.pending_workspace_create_cwd.take() {
+ let suggested_name = crate::workspace::derive_label_from_cwd(&cwd);
+ let label = workspace_create_label(&new_name, &suggested_name);
+ self.runtime_workspace_create(
+ "tui.workspace.create_named",
+ crate::api::schema::WorkspaceCreateParams {
+ cwd: Some(cwd.display().to_string()),
+ focus: true,
+ label,
+ env: Default::default(),
+ },
+ );
+ } else if !self.state.workspaces.is_empty() && !new_name.is_empty() {
+ let workspace_id = self.public_workspace_id(self.state.selected);
+ self.runtime_workspace_rename(
+ "tui.workspace.rename",
+ crate::api::schema::WorkspaceRenameParams {
+ workspace_id,
+ label: new_name,
+ },
+ );
+ }
}
Mode::RenameTab if self.state.creating_new_tab => {
let default_name = next_new_tab_default_name(&self.state);
@@ -1256,6 +1296,7 @@ impl App {
fn cancel_rename_modal(state: &mut AppState) {
state.creating_new_tab = false;
state.requested_new_tab_name = None;
+ state.pending_workspace_create_cwd = None;
state.rename_pane_target = None;
state.name_input.clear();
state.name_input_replace_on_type = false;
@@ -1318,6 +1359,17 @@ mod tests {
app
}
+ #[test]
+ fn workspace_create_label_preserves_auto_name_for_suggestion_or_blank() {
+ assert_eq!(workspace_create_label("project", "project"), None);
+ assert_eq!(workspace_create_label("", "project"), None);
+ assert_eq!(workspace_create_label(" ", "project"), None);
+ assert_eq!(
+ workspace_create_label(" logs ", "project").as_deref(),
+ Some("logs")
+ );
+ }
+
fn mark_worktree_space_member(state: &mut AppState, ws_idx: usize, key: &str) {
state.workspaces[ws_idx].worktree_space = Some(crate::workspace::WorktreeSpaceMembership {
key: key.into(),