1
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! Session restore operations for PaneManager
//!
//! Handles rebuilding a live pane tree from a saved session layout,
//! including fallback CWD validation for missing directories.
use super::PaneManager;
use crate::config::Config;
use crate::pane::types::{Pane, PaneNode};
use crate::session::SessionPaneNode;
use anyhow::Result;
use std::sync::Arc;
use tokio::runtime::Runtime;
impl PaneManager {
// =========================================================================
// Session Restore
// =========================================================================
/// Build a pane tree from a saved session layout
///
/// Recursively constructs live `PaneNode` tree from a `SessionPaneNode`,
/// creating new terminal panes for each leaf. If a leaf's CWD no longer
/// exists, falls back to `$HOME`.
pub fn build_from_layout(
&mut self,
layout: &SessionPaneNode,
config: &Config,
runtime: Arc<Runtime>,
) -> Result<()> {
let root = self.build_node_from_layout(layout, config, runtime)?;
let first_id = root.all_pane_ids().first().copied();
self.root = Some(root);
self.focused_pane_id = first_id;
self.recalculate_bounds();
// Apply per-pane backgrounds from config to restored panes
let panes = self.all_panes_mut();
for (index, pane) in panes.into_iter().enumerate() {
if let Some((image_path, mode, opacity, darken)) = config.get_pane_background(index) {
pane.set_background(crate::pane::PaneBackground {
image_path: Some(image_path),
mode,
opacity,
darken,
});
}
}
Ok(())
}
/// Recursively build a PaneNode from a SessionPaneNode
fn build_node_from_layout(
&mut self,
layout: &SessionPaneNode,
config: &Config,
runtime: Arc<Runtime>,
) -> Result<PaneNode> {
match layout {
SessionPaneNode::Leaf { cwd, user_title } => {
let id = self.next_pane_id;
self.next_pane_id += 1;
let validated_cwd = crate::session::restore::validate_cwd(cwd);
let mut pane = Pane::new(id, config, runtime, validated_cwd)?;
// A persisted user title re-marks the pane user-named so
// automatic titles never overwrite it; automatic titles are
// not persisted and re-derive from the fresh terminal.
if let Some(title) = user_title.as_deref().filter(|t| !t.is_empty()) {
pane.user_named = true;
pane.has_default_title = false;
pane.title = title.to_string();
}
Ok(PaneNode::leaf(pane))
}
SessionPaneNode::Split {
direction,
ratio,
first,
second,
} => {
let first_node = self.build_node_from_layout(first, config, runtime.clone())?;
let second_node = self.build_node_from_layout(second, config, runtime)?;
Ok(PaneNode::split(*direction, *ratio, first_node, second_node))
}
}
}
}