aboutsummaryrefslogtreecommitdiff
path: root/src/app/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/state.rs')
-rw-r--r--src/app/state.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/app/state.rs b/src/app/state.rs
index 45473435..daed47f0 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -818,6 +818,10 @@ pub enum SidebarWidthSource {
/// All application state — pure data, no channels or async runtime.
/// Testable without PTYs or a tokio runtime.
pub struct AppState {
+ pub terminals:
+ std::collections::HashMap<crate::terminal::TerminalId, crate::terminal::TerminalState>,
+ pub terminal_runtimes:
+ std::collections::HashMap<crate::terminal::TerminalId, crate::terminal::TerminalRuntime>,
pub workspaces: Vec<Workspace>,
pub active: Option<usize>,
pub selected: usize,
@@ -953,6 +957,57 @@ impl AppState {
/// Returns true when the given (workspace, tab, pane) refers to the
/// currently focused pane in the active workspace's active tab.
+ pub(crate) fn runtime_for_pane_in_workspace(
+ &self,
+ ws_idx: usize,
+ pane_id: crate::layout::PaneId,
+ ) -> Option<&crate::terminal::TerminalRuntime> {
+ #[cfg(test)]
+ if let Some(runtime) = self.workspaces.get(ws_idx)?.test_runtimes.get(&pane_id) {
+ return Some(runtime);
+ }
+ #[cfg(test)]
+ if let Some(runtime) = self
+ .workspaces
+ .get(ws_idx)?
+ .tabs
+ .iter()
+ .find_map(|tab| tab.runtimes.get(&pane_id))
+ {
+ return Some(runtime);
+ }
+ let terminal_id = self.workspaces.get(ws_idx)?.terminal_id(pane_id)?;
+ self.terminal_runtimes.get(terminal_id)
+ }
+
+ #[cfg(test)]
+ pub(crate) fn runtime_for_pane(
+ &self,
+ pane_id: crate::layout::PaneId,
+ ) -> Option<&crate::terminal::TerminalRuntime> {
+ self.workspaces.iter().find_map(|ws| {
+ #[cfg(test)]
+ if let Some(runtime) = ws.test_runtimes.get(&pane_id) {
+ return Some(runtime);
+ }
+ #[cfg(test)]
+ if let Some(runtime) = ws.tabs.iter().find_map(|tab| tab.runtimes.get(&pane_id)) {
+ return Some(runtime);
+ }
+ let terminal_id = ws.terminal_id(pane_id)?;
+ self.terminal_runtimes.get(terminal_id)
+ })
+ }
+
+ pub(crate) fn focused_runtime_in_workspace(
+ &self,
+ ws_idx: usize,
+ ) -> Option<&crate::terminal::TerminalRuntime> {
+ let ws = self.workspaces.get(ws_idx)?;
+ let pane_id = ws.focused_pane_id()?;
+ self.runtime_for_pane_in_workspace(ws_idx, pane_id)
+ }
+
pub fn is_active_pane(
&self,
ws_idx: usize,
@@ -1003,6 +1058,8 @@ impl AppState {
/// Create an AppState for testing — no channels, no PTYs.
pub fn test_new() -> Self {
Self {
+ terminals: std::collections::HashMap::new(),
+ terminal_runtimes: std::collections::HashMap::new(),
workspaces: Vec::new(),
active: None,
selected: 0,
@@ -1155,6 +1212,40 @@ impl AppState {
session_dirty: false,
}
}
+
+ /// Populate missing `TerminalState` entries for every pane so tests that
+ /// read or write terminal metadata don't need to manually create them.
+ pub fn ensure_test_terminals(&mut self) {
+ use crate::terminal::TerminalState;
+ for ws in &self.workspaces {
+ for tab in &ws.tabs {
+ for pane in tab.panes.values() {
+ if !self.terminals.contains_key(&pane.attached_terminal_id) {
+ let cwd = ws.identity_cwd.clone();
+ self.terminals.insert(
+ pane.attached_terminal_id.clone(),
+ TerminalState::new(pane.attached_terminal_id.clone(), cwd),
+ );
+ }
+ }
+ }
+ }
+ }
+
+ pub fn insert_test_runtime(
+ &mut self,
+ pane_id: crate::layout::PaneId,
+ runtime: crate::terminal::TerminalRuntime,
+ ) {
+ let Some(terminal_id) = self
+ .workspaces
+ .iter()
+ .find_map(|ws| ws.terminal_id(pane_id).cloned())
+ else {
+ return;
+ };
+ self.terminal_runtimes.insert(terminal_id, runtime);
+ }
}
#[cfg(test)]