This commit is contained in:
@@ -404,13 +404,27 @@ impl ShellModel {
|
||||
///
|
||||
/// Returns [`InvalidExternalOutputPane`] when `pane` is not a terminal.
|
||||
pub fn with_external_output(pane: PaneId) -> Result<Self, InvalidExternalOutputPane> {
|
||||
Self::with_external_outputs([pane])
|
||||
}
|
||||
|
||||
/// Creates the comparison model with actor-driven output for each named
|
||||
/// terminal while non-terminal surfaces retain deterministic updates.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`InvalidExternalOutputPane`] if any pane is not a terminal.
|
||||
pub fn with_external_outputs(
|
||||
panes: impl IntoIterator<Item = PaneId>,
|
||||
) -> Result<Self, InvalidExternalOutputPane> {
|
||||
let mut model = Self::default();
|
||||
let pane_state = &mut model.panes[pane.index()];
|
||||
if pane_state.kind() != SurfaceKind::Terminal {
|
||||
return Err(InvalidExternalOutputPane);
|
||||
for pane in panes {
|
||||
let pane_state = &mut model.panes[pane.index()];
|
||||
if pane_state.kind() != SurfaceKind::Terminal {
|
||||
return Err(InvalidExternalOutputPane);
|
||||
}
|
||||
pane_state.output_source = OutputSource::External;
|
||||
pane_state.lines.clear();
|
||||
}
|
||||
pane_state.output_source = OutputSource::External;
|
||||
pane_state.lines.clear();
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
@@ -990,6 +1004,32 @@ mod tests {
|
||||
assert_eq!(model.counters().external_snapshot_updates, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_external_terminals_keep_independent_output_and_three_fixtures() {
|
||||
let mut model = ShellModel::with_external_outputs([
|
||||
PaneId::CodexRuntime,
|
||||
PaneId::ClaudeUi,
|
||||
PaneId::PiDocs,
|
||||
])
|
||||
.unwrap();
|
||||
let tick = model.dispatch(ShellAction::SyntheticStreamTick);
|
||||
assert_eq!(tick.terminal_lines_appended, 0);
|
||||
assert_eq!(model.counters().surface_updates, 3);
|
||||
|
||||
model.dispatch(ShellAction::ReplaceExternalOutput {
|
||||
pane: PaneId::ClaudeUi,
|
||||
lines: vec!["claude shell".into()],
|
||||
});
|
||||
model.dispatch(ShellAction::ReplaceExternalOutput {
|
||||
pane: PaneId::PiDocs,
|
||||
lines: vec!["pi shell".into()],
|
||||
});
|
||||
assert_eq!(model.pane(PaneId::ClaudeUi).lines(), ["claude shell"]);
|
||||
assert_eq!(model.pane(PaneId::PiDocs).lines(), ["pi shell"]);
|
||||
assert!(model.pane(PaneId::CodexRuntime).lines().is_empty());
|
||||
assert_eq!(model.counters().external_snapshot_updates, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_output_rejects_nonterminals_and_deterministic_panes() {
|
||||
assert!(ShellModel::with_external_output(PaneId::Architecture).is_err());
|
||||
|
||||
Reference in New Issue
Block a user