diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-22 02:21:12 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-22 02:23:35 +0300 |
| commit | 0148c1379b76c5c0a9d05588c07dcb06ec32f93f (patch) | |
| tree | 554766d959c738ca2aa433c3d4b4a7de25568008 /src/app/mod.rs | |
| parent | a9ff4012bdca0dbdbc77bc6e53a430689fc899be (diff) | |
feat: add git worktree workspace management
refs #137
Diffstat (limited to 'src/app/mod.rs')
| -rw-r--r-- | src/app/mod.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs index 107a4393..a1ae4a74 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -17,6 +17,7 @@ mod session; pub mod state; mod terminal_targets; mod theme_sync; +mod worktrees; use std::collections::{HashMap, HashSet}; use std::future::pending; @@ -234,6 +235,7 @@ impl App { sidebar_width, sidebar_width_source, sidebar_section_split, + collapsed_space_keys, ) = if no_session { ( Vec::new(), @@ -243,6 +245,7 @@ impl App { config.ui.sidebar_width, state::SidebarWidthSource::ConfigDefault, 0.5_f32, + std::collections::HashSet::new(), ) } else if let Some(snap) = crate::persist::load() { let (ws, terminals, terminal_runtimes) = crate::persist::restore( @@ -271,6 +274,7 @@ impl App { state::SidebarWidthSource::ConfigDefault }, snap.sidebar_section_split.unwrap_or(0.5), + snap.collapsed_space_keys, ) } else { crate::logging::session_restored(ws.len(), "ok"); @@ -288,6 +292,7 @@ impl App { state::SidebarWidthSource::ConfigDefault }, snap.sidebar_section_split.unwrap_or(0.5), + snap.collapsed_space_keys, ) } } else { @@ -299,6 +304,7 @@ impl App { config.ui.sidebar_width, state::SidebarWidthSource::ConfigDefault, 0.5_f32, + std::collections::HashSet::new(), ) }; @@ -320,6 +326,8 @@ impl App { (18, 36) }); + let worktree_directory = crate::worktree::expand_tilde_path(&config.worktrees.directory); + info!( pane_scrollback_limit_bytes = config.advanced.scrollback_limit_bytes, "using pane scrollback configuration" @@ -357,12 +365,24 @@ impl App { detach_requested: false, request_new_workspace: false, request_new_tab: false, + request_new_linked_worktree: None, + request_open_existing_worktree: None, + request_new_workspace_cwd: None, + request_remove_linked_worktree: None, + request_submit_worktree_create: false, + request_submit_worktree_open: false, + request_submit_worktree_remove: false, request_reload_config: false, request_client_sound_config_reload: false, request_clipboard_write: None, creating_new_tab: false, requested_new_tab_name: None, rename_pane_target: None, + worktree_create: None, + worktree_open: None, + worktree_remove: None, + worktree_directory, + collapsed_space_keys, request_complete_onboarding: false, name_input: String::new(), name_input_replace_on_type: false, @@ -569,6 +589,47 @@ impl App { needs_render = true; } + if let Some(ws_idx) = self.state.request_new_linked_worktree.take() { + self.open_new_linked_worktree_dialog(ws_idx); + needs_render = true; + } + + if let Some(ws_idx) = self.state.request_open_existing_worktree.take() { + self.open_existing_worktree_dialog(ws_idx); + needs_render = true; + } + + if let Some(cwd) = self.state.request_new_workspace_cwd.take() { + if let Err(err) = self.create_workspace_with_options(cwd, true) { + tracing::error!(err = %err, "failed to create workspace at requested cwd"); + self.state.mode = Mode::Navigate; + } + needs_render = true; + } + + if let Some(ws_idx) = self.state.request_remove_linked_worktree.take() { + self.open_remove_linked_worktree_confirmation(ws_idx); + needs_render = true; + } + + if self.state.request_submit_worktree_create { + self.state.request_submit_worktree_create = false; + self.start_worktree_add(); + needs_render = true; + } + + if self.state.request_submit_worktree_open { + self.state.request_submit_worktree_open = false; + self.open_selected_existing_worktree(); + needs_render = true; + } + + if self.state.request_submit_worktree_remove { + self.state.request_submit_worktree_remove = false; + self.start_worktree_remove(); + needs_render = true; + } + if self.state.request_reload_config { self.state.request_reload_config = false; self.reload_config(); @@ -945,6 +1006,11 @@ impl App { self.state.default_shell = config.terminal.default_shell.clone(); } + if !invalid_section("worktrees") { + self.state.worktree_directory = + crate::worktree::expand_tilde_path(&config.worktrees.directory); + } + if !invalid_section("theme") { self.state.palette = resolve_palette_with_legacy_accent(config, !invalid_section("ui")); self.state.theme_name = config @@ -1105,6 +1171,15 @@ impl App { Mode::RenameWorkspace | Mode::RenameTab | Mode::RenamePane => { input::handle_rename_key(&mut self.state, key_event); } + Mode::NewLinkedWorktree => { + self.handle_worktree_create_key(key_event); + } + Mode::OpenExistingWorktree => { + self.handle_worktree_open_key(key_event); + } + Mode::ConfirmRemoveWorktree => { + self.handle_worktree_remove_key(key_event); + } Mode::Resize => { input::handle_resize_key(&mut self.state, key); } @@ -1255,6 +1330,7 @@ mod tests { resolved_identity_cwd, branch: Some("render-dirty-test".into()), ahead_behind: Some((1, 0)), + space: None, }], }); |
