summaryrefslogtreecommitdiff
path: root/src/workspace.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-01 15:48:22 +0300
committerGitHub <noreply@github.com>2026-09-01 15:48:22 +0300
commit207be3c771d281baae6e5fa0fb74be9a056e97a2 (patch)
treed7b037ecdf629224a048c841d11659efdc23507d /src/workspace.rs
parent8a6d697308162874a236c84aac0b0f8c7ac01f83 (diff)
refactor: render the shell in the client (#3487)
* feat: add opt-in client-rendered shell * feat: add client-owned shell mouse controls * feat: complete client-owned shell chrome * feat: add client-owned shell settings and notifications * feat: run client shell custom commands * feat: render popup terminals in client shell * feat: add client-owned scrollback and copy mode * fix: preserve client worktree trust defaults * feat: render startup diagnostics in client shell * feat: render onboarding in client shell * feat: render product announcements in client shell * feat: render release notes in client shell * feat: render mobile switcher in client shell * feat: render kitty graphics in client shell * fix: preserve client shell lifecycle coherence * refactor: route client shell commands through endpoint connections * refactor: make the client-rendered shell the default * refactor: remove monolithic launch mode * refactor: complete client-rendered shell cutover * perf: retain client pane surface updates * perf: scale retained pane surface updates * perf: remove remote pane input latency * test: make client shell checks platform-independent * fix: prevent client timer starvation * test: fix client shell platform gates * test: accept retained surfaces in cross-area checks * test: make client mode assertions platform-neutral * fix: badge only outdated integrations
Diffstat (limited to 'src/workspace.rs')
-rw-r--r--src/workspace.rs170
1 files changed, 16 insertions, 154 deletions
diff --git a/src/workspace.rs b/src/workspace.rs
index 0a719ab1..b4bba45d 100644
--- a/src/workspace.rs
+++ b/src/workspace.rs
@@ -19,8 +19,6 @@ mod aggregate;
mod git;
mod tab;
-#[cfg(test)]
-use self::git::git_ahead_behind;
use self::git::git_status_cache_key_for_space;
pub(crate) use self::{git::git_status_snapshot_for_cwd_with_demand, tab::MovedPane};
pub use self::{
@@ -274,9 +272,6 @@ impl Workspace {
}
}
- // Test modules construct workspaces through the default constructor; production paths
- // use the env-aware variant so pane identity env is always explicit.
- #[cfg_attr(not(test), allow(dead_code))]
pub fn new(
initial_cwd: PathBuf,
rows: u16,
@@ -289,7 +284,7 @@ impl Workspace {
render_notify: Arc<Notify>,
render_dirty: Arc<RenderSignal>,
) -> std::io::Result<(Self, TerminalState, TerminalRuntime)> {
- Self::new_with_extra_env(
+ Self::new_with_tab(
initial_cwd,
rows,
cols,
@@ -300,6 +295,7 @@ impl Workspace {
events,
render_notify,
render_dirty,
+ None,
Vec::new(),
)
}
@@ -318,6 +314,20 @@ impl Workspace {
render_dirty: Arc<RenderSignal>,
extra_env: Vec<(String, String)>,
) -> std::io::Result<(Self, TerminalState, TerminalRuntime)> {
+ if extra_env.is_empty() {
+ return Self::new(
+ initial_cwd,
+ rows,
+ cols,
+ scrollback_limit_bytes,
+ host_terminal_theme,
+ host_terminal_appearance,
+ shell_config,
+ events,
+ render_notify,
+ render_dirty,
+ );
+ }
Self::new_with_tab(
initial_cwd,
rows,
@@ -334,65 +344,6 @@ impl Workspace {
)
}
- // Kept for tests that do not need launch-env customization.
- #[allow(dead_code)]
- pub fn new_argv_command(
- initial_cwd: PathBuf,
- rows: u16,
- cols: u16,
- argv: &[String],
- scrollback_limit_bytes: usize,
- host_terminal_theme: crate::terminal_theme::TerminalTheme,
- host_terminal_appearance: Option<crate::terminal_theme::HostAppearance>,
- events: mpsc::Sender<AppEvent>,
- render_notify: Arc<Notify>,
- render_dirty: Arc<RenderSignal>,
- ) -> std::io::Result<(Self, TerminalState, TerminalRuntime)> {
- Self::new_argv_command_with_extra_env(
- initial_cwd,
- rows,
- cols,
- argv,
- scrollback_limit_bytes,
- host_terminal_theme,
- host_terminal_appearance,
- events,
- render_notify,
- render_dirty,
- Vec::new(),
- )
- }
-
- #[allow(clippy::too_many_arguments)]
- pub fn new_argv_command_with_extra_env(
- initial_cwd: PathBuf,
- rows: u16,
- cols: u16,
- argv: &[String],
- scrollback_limit_bytes: usize,
- host_terminal_theme: crate::terminal_theme::TerminalTheme,
- host_terminal_appearance: Option<crate::terminal_theme::HostAppearance>,
- events: mpsc::Sender<AppEvent>,
- render_notify: Arc<Notify>,
- render_dirty: Arc<RenderSignal>,
- extra_env: Vec<(String, String)>,
- ) -> std::io::Result<(Self, TerminalState, TerminalRuntime)> {
- Self::new_with_tab(
- initial_cwd,
- rows,
- cols,
- scrollback_limit_bytes,
- host_terminal_theme,
- host_terminal_appearance,
- crate::pane::PaneShellConfig::new("", crate::config::ShellModeConfig::NonLogin),
- events,
- render_notify,
- render_dirty,
- Some(argv),
- extra_env,
- )
- }
-
#[allow(clippy::too_many_arguments)]
fn new_with_tab(
initial_cwd: PathBuf,
@@ -671,43 +622,6 @@ impl Workspace {
self.close_tab(self.active_tab)
}
- #[cfg(test)]
- pub fn split_focused(
- &mut self,
- direction: Direction,
- rows: u16,
- cols: u16,
- cwd: Option<PathBuf>,
- scrollback_limit_bytes: usize,
- host_terminal_theme: crate::terminal_theme::TerminalTheme,
- host_terminal_appearance: Option<crate::terminal_theme::HostAppearance>,
- shell_config: crate::pane::PaneShellConfig<'_>,
- extra_env: Vec<(String, String)>,
- ) -> std::io::Result<crate::workspace::tab::NewPane> {
- let pane_number = self.next_public_pane_number;
- let tab_number = self
- .active_tab()
- .map(|tab| tab.number)
- .expect("workspace must always have at least one tab");
- let launch_env = self.launch_env_for_new_pane(tab_number, pane_number, extra_env);
- let new_pane = self
- .active_tab_mut()
- .expect("workspace must always have at least one tab")
- .split_focused(
- direction,
- rows,
- cols,
- cwd,
- scrollback_limit_bytes,
- host_terminal_theme,
- host_terminal_appearance,
- shell_config,
- &launch_env,
- )?;
- self.register_new_pane_with_number(new_pane.pane_id, pane_number);
- Ok(new_pane)
- }
-
#[allow(clippy::too_many_arguments)]
pub fn split_focused_command(
&mut self,
@@ -1174,14 +1088,6 @@ impl Workspace {
self.worktree_space.as_ref()
}
- #[cfg(test)]
- pub fn refresh_git_ahead_behind(&mut self) {
- let cwd = self.resolved_identity_cwd();
- self.cached_git_branch = cwd.as_deref().and_then(git_branch);
- self.cached_git_ahead_behind = cwd.as_deref().and_then(git_ahead_behind);
- self.cached_git_space = cwd.as_deref().and_then(git_space_metadata);
- }
-
pub fn find_tab_index_for_pane(&self, pane_id: PaneId) -> Option<usize> {
self.tabs
.iter()
@@ -1663,50 +1569,6 @@ mod tests {
assert!(!target.tabs[0].panes.contains_key(&source_pane));
}
- #[tokio::test]
- async fn new_workspace_retains_discovered_git_metadata() {
- let stamp = std::time::SystemTime::now()
- .duration_since(std::time::UNIX_EPOCH)
- .expect("clock should be after unix epoch")
- .as_nanos();
- let root = std::env::temp_dir().join(format!(
- "herdr-workspace-git-metadata-{}-{stamp}",
- std::process::id()
- ));
- std::fs::create_dir_all(root.join(".git")).expect("create git directory");
- std::fs::write(root.join(".git/HEAD"), "ref: refs/heads/main\n").expect("write git head");
- #[cfg(windows)]
- let command = "C:\\Windows\\System32\\whoami.exe";
- #[cfg(not(windows))]
- let command = "/usr/bin/true";
- let argv = vec![command.to_string()];
- let (events, _) = mpsc::channel(64);
- let render_notify = Arc::new(Notify::new());
- let render_dirty = Arc::new(RenderSignal::new());
-
- let (workspace, _terminal, runtime) = Workspace::new_argv_command(
- root.clone(),
- 24,
- 80,
- &argv,
- 1024,
- crate::terminal_theme::TerminalTheme::default(),
- None,
- events,
- render_notify,
- render_dirty,
- )
- .expect("create workspace");
-
- let space = workspace
- .git_space()
- .expect("workspace should retain discovered git metadata");
- assert_eq!(space.repo_root, root);
-
- runtime.shutdown();
- std::fs::remove_dir_all(root).expect("remove test repo");
- }
-
#[test]
fn linked_worktree_auto_label_uses_checkout_name_not_repo_name() {
let (base, repo, checkout) =