This commit is contained in:
+215
-275
@@ -39,11 +39,11 @@ const SIDEBAR_WIDTH: f32 = 248.0;
|
||||
const APP_HEADER_HEIGHT: f32 = 48.0;
|
||||
const TAB_BAR_HEIGHT: f32 = 38.0;
|
||||
const APP_FOOTER_HEIGHT: f32 = 32.0;
|
||||
const TERMINAL_CHROME_HEIGHT: f32 = 72.0;
|
||||
const TERMINAL_CONTENT_VERTICAL_INSET: f32 = 24.0;
|
||||
const TERMINAL_HORIZONTAL_INSET: f32 = 32.0;
|
||||
const TERMINAL_CELL_WIDTH: f32 = 8.4;
|
||||
const TERMINAL_CELL_HEIGHT: f32 = 18.0;
|
||||
const WORK_LANE_GAP: f32 = 4.0;
|
||||
const WORK_PANEL_GAP: f32 = 4.0;
|
||||
const TERMINAL_ROW_STEP: u16 = 2;
|
||||
const TERMINAL_COLUMN_STEP: u16 = 10;
|
||||
|
||||
@@ -78,7 +78,6 @@ struct LumbridgeShell {
|
||||
terminal_snapshot: TerminalSnapshot,
|
||||
last_runtime_sequence: u64,
|
||||
root_focus: FocusHandle,
|
||||
pane_focus: [FocusHandle; 6],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@@ -119,10 +118,6 @@ impl LiveRuntimeStatus {
|
||||
}
|
||||
}
|
||||
|
||||
const fn is_fault(&self) -> bool {
|
||||
matches!(self, Self::Fault(_))
|
||||
}
|
||||
|
||||
const fn is_terminal(&self) -> bool {
|
||||
matches!(self, Self::Exited(_) | Self::Fault(_))
|
||||
}
|
||||
@@ -280,14 +275,15 @@ fn dim_color(color: u32) -> u32 {
|
||||
fn terminal_dimensions_for_window(window_size: Size<Pixels>) -> TerminalDimensions {
|
||||
let width = f32::from(window_size.width);
|
||||
let height = f32::from(window_size.height);
|
||||
let lane_count = visible_lane_count(window_size);
|
||||
let panel_count = visible_panel_count(window_size);
|
||||
let workspace_height =
|
||||
(height - APP_HEADER_HEIGHT - TAB_BAR_HEIGHT - APP_FOOTER_HEIGHT).max(0.0);
|
||||
let terminal_height = (workspace_height * 0.60 - TERMINAL_CHROME_HEIGHT).max(0.0);
|
||||
let terminal_height =
|
||||
(workspace_height * 0.60 - TERMINAL_CONTENT_VERTICAL_INSET).max(0.0);
|
||||
let workspace_width = (width - SIDEBAR_WIDTH).max(0.0);
|
||||
let lane_gaps = WORK_LANE_GAP * lane_count.saturating_sub(1) as f32;
|
||||
let lane_width = ((workspace_width - lane_gaps).max(0.0) / lane_count as f32).max(0.0);
|
||||
let terminal_width = (lane_width - TERMINAL_HORIZONTAL_INSET).max(0.0);
|
||||
let panel_gaps = WORK_PANEL_GAP * panel_count.saturating_sub(1) as f32;
|
||||
let panel_width = ((workspace_width - panel_gaps).max(0.0) / panel_count as f32).max(0.0);
|
||||
let terminal_width = (panel_width - TERMINAL_HORIZONTAL_INSET).max(0.0);
|
||||
let rows = (terminal_height / TERMINAL_CELL_HEIGHT)
|
||||
.floor()
|
||||
.clamp(2.0, f32::from(u16::MAX));
|
||||
@@ -303,7 +299,7 @@ fn terminal_dimensions_for_window(window_size: Size<Pixels>) -> TerminalDimensio
|
||||
.expect("geometry clamps terminal dimensions above zero")
|
||||
}
|
||||
|
||||
fn visible_lane_count(window_size: Size<Pixels>) -> usize {
|
||||
fn visible_panel_count(window_size: Size<Pixels>) -> usize {
|
||||
let workspace_width = (f32::from(window_size.width) - SIDEBAR_WIDTH).max(0.0);
|
||||
if workspace_width >= 2_800.0 {
|
||||
5
|
||||
@@ -314,8 +310,12 @@ fn visible_lane_count(window_size: Size<Pixels>) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn visible_lane_range(total: usize, selected: usize, lane_count: usize) -> std::ops::Range<usize> {
|
||||
let count = lane_count.clamp(1, total.max(1)).min(total);
|
||||
fn visible_panel_range(
|
||||
total: usize,
|
||||
selected: usize,
|
||||
panel_count: usize,
|
||||
) -> std::ops::Range<usize> {
|
||||
let count = panel_count.clamp(1, total.max(1)).min(total);
|
||||
let start = selected
|
||||
.saturating_sub(count / 2)
|
||||
.min(total.saturating_sub(count));
|
||||
@@ -363,11 +363,6 @@ impl RenderTiming {
|
||||
|
||||
impl LumbridgeShell {
|
||||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let pane_focus = std::array::from_fn(|index| {
|
||||
cx.focus_handle()
|
||||
.tab_index(index as isize + 1)
|
||||
.tab_stop(true)
|
||||
});
|
||||
let root_focus = cx.focus_handle();
|
||||
window.focus(&root_focus);
|
||||
|
||||
@@ -433,7 +428,6 @@ impl LumbridgeShell {
|
||||
terminal_snapshot,
|
||||
last_runtime_sequence: 0,
|
||||
root_focus,
|
||||
pane_focus,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,83 +701,6 @@ impl LumbridgeShell {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn pane_selector(
|
||||
pane: &PaneState,
|
||||
selected: bool,
|
||||
runtime_status: LiveRuntimeStatus,
|
||||
focus: FocusHandle,
|
||||
cx: &mut Context<Self>,
|
||||
) -> gpui::AnyElement {
|
||||
let id = pane.id();
|
||||
let needs_input = pane.needs_input();
|
||||
let external = pane.output_source() == OutputSource::External;
|
||||
let label = if external {
|
||||
runtime_status.badge()
|
||||
} else {
|
||||
match pane.kind() {
|
||||
SurfaceKind::Terminal => pane.status().label(),
|
||||
_ => pane.fixture().badge,
|
||||
}
|
||||
};
|
||||
let state_color = if needs_input || (external && runtime_status.is_fault()) {
|
||||
ATTENTION
|
||||
} else if matches!(pane.kind(), SurfaceKind::Terminal) {
|
||||
SUCCESS
|
||||
} else {
|
||||
ACCENT
|
||||
};
|
||||
|
||||
div()
|
||||
.id(("pane", id.index()))
|
||||
.track_focus(&focus)
|
||||
.tab_index(id.index() as isize + 1)
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.gap_3()
|
||||
.h_full()
|
||||
.min_w(px(172.0))
|
||||
.px_3()
|
||||
.bg(rgb(if selected { PANEL_ACTIVE } else { PANEL_ALT }))
|
||||
.border_1()
|
||||
.border_color(rgb(if selected || needs_input {
|
||||
state_color
|
||||
} else {
|
||||
BORDER_QUIET
|
||||
}))
|
||||
.rounded(px(5.0))
|
||||
.on_click(cx.listener(move |shell, _, window, cx| {
|
||||
shell.select_pane(id, window, cx);
|
||||
}))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.min_w_0()
|
||||
.child(
|
||||
div()
|
||||
.truncate()
|
||||
.text_sm()
|
||||
.text_color(rgb(TEXT))
|
||||
.child(if external {
|
||||
"Terminal · local shell"
|
||||
} else {
|
||||
pane.fixture().title
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.mt_1()
|
||||
.truncate()
|
||||
.text_xs()
|
||||
.text_color(rgb(MUTED))
|
||||
.child(pane.fixture().target.to_owned()),
|
||||
),
|
||||
)
|
||||
.child(div().text_xs().text_color(rgb(state_color)).child(label))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn terminal_run(run: TerminalPaintRun) -> gpui::AnyElement {
|
||||
let cursor = run.cursor;
|
||||
div()
|
||||
@@ -851,13 +768,7 @@ impl LumbridgeShell {
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn work_surface(
|
||||
&self,
|
||||
pane: &PaneState,
|
||||
selected: bool,
|
||||
cx: &mut Context<Self>,
|
||||
) -> gpui::AnyElement {
|
||||
let pane_id = pane.id();
|
||||
fn pane_context(&self, pane: &PaneState, selected: bool) -> gpui::AnyElement {
|
||||
let external = pane.output_source() == OutputSource::External;
|
||||
let status = if external {
|
||||
self.runtime_status.badge()
|
||||
@@ -909,6 +820,90 @@ impl LumbridgeShell {
|
||||
.child(label)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.px_3()
|
||||
.py_2()
|
||||
.bg(rgb(if selected { PANEL_ACTIVE } else { PANEL_ALT }))
|
||||
.border_b_1()
|
||||
.border_color(rgb(BORDER))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(
|
||||
div()
|
||||
.min_w_0()
|
||||
.child(
|
||||
div()
|
||||
.truncate()
|
||||
.text_sm()
|
||||
.text_color(rgb(TEXT))
|
||||
.child(pane.fixture().title),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.mt_1()
|
||||
.truncate()
|
||||
.text_xs()
|
||||
.text_color(rgb(MUTED))
|
||||
.child(detail),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex_none()
|
||||
.text_xs()
|
||||
.text_color(rgb(if pane.needs_input() {
|
||||
ATTENTION
|
||||
} else if selected {
|
||||
SUCCESS
|
||||
} else {
|
||||
MUTED
|
||||
}))
|
||||
.child(surface_status),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.h(px(28.0))
|
||||
.flex_none()
|
||||
.mt_2()
|
||||
.overflow_hidden()
|
||||
.border_t_1()
|
||||
.border_color(rgb(BORDER_QUIET))
|
||||
.children(tabs),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.mt_2()
|
||||
.text_xs()
|
||||
.text_color(rgb(MUTED))
|
||||
.child("TOOLS · CONTEXT · GOAL")
|
||||
.child(if pane.needs_input() {
|
||||
"NEEDS INPUT"
|
||||
} else if selected {
|
||||
"KEYBOARD OWNER"
|
||||
} else {
|
||||
"RUNNING"
|
||||
}),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn pane_work_surface(&self, pane: &PaneState) -> gpui::AnyElement {
|
||||
let external = pane.output_source() == OutputSource::External;
|
||||
let content = if external {
|
||||
self.terminal_view()
|
||||
} else {
|
||||
@@ -927,63 +922,15 @@ impl LumbridgeShell {
|
||||
};
|
||||
|
||||
div()
|
||||
.id(("work-lane", pane_id.index()))
|
||||
.on_click(cx.listener(move |shell, _, window, cx| {
|
||||
shell.select_pane(pane_id, window, cx);
|
||||
}))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.min_w_0()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.bg(rgb(PANEL))
|
||||
.border_1()
|
||||
.border_color(rgb(if selected { ACCENT } else { BORDER }))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.h(px(36.0))
|
||||
.flex_none()
|
||||
.px_3()
|
||||
.bg(rgb(PANEL_ALT))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.min_w_0()
|
||||
.text_sm()
|
||||
.child(div().flex_none().child(pane.fixture().title))
|
||||
.child(
|
||||
div()
|
||||
.truncate()
|
||||
.text_xs()
|
||||
.text_color(rgb(MUTED))
|
||||
.child(detail),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex_none()
|
||||
.text_xs()
|
||||
.text_color(rgb(if selected { SUCCESS } else { MUTED }))
|
||||
.child(surface_status),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.h(px(28.0))
|
||||
.flex_none()
|
||||
.px_1()
|
||||
.bg(rgb(PANEL_ALT))
|
||||
.border_t_1()
|
||||
.border_color(rgb(BORDER_QUIET))
|
||||
.children(tabs),
|
||||
)
|
||||
.bg(rgb(BG))
|
||||
.border_y_1()
|
||||
.border_color(rgb(BORDER))
|
||||
.child(
|
||||
div()
|
||||
.flex_1()
|
||||
@@ -995,22 +942,36 @@ impl LumbridgeShell {
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn decision_region(&self) -> gpui::AnyElement {
|
||||
let choice = |label: &'static str, detail: &'static str| {
|
||||
fn pane_decision_region(&self, pane: &PaneState) -> gpui::AnyElement {
|
||||
let choice = |label: &'static str, detail: &'static str, attention: bool| {
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.min_w(px(200.0))
|
||||
.px_3()
|
||||
.py_2()
|
||||
.rounded(px(5.0))
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.min_w_0()
|
||||
.px_2()
|
||||
.py_1()
|
||||
.rounded(px(4.0))
|
||||
.border_1()
|
||||
.border_color(rgb(BORDER))
|
||||
.border_color(rgb(if attention { ATTENTION } else { BORDER }))
|
||||
.bg(rgb(PANEL_ALT))
|
||||
.text_sm()
|
||||
.text_xs()
|
||||
.text_color(rgb(TEXT))
|
||||
.child(label)
|
||||
.child(div().mt_1().text_xs().text_color(rgb(MUTED)).child(detail))
|
||||
.child(div().truncate().text_color(rgb(MUTED)).child(detail))
|
||||
};
|
||||
let choices = if pane.needs_input() {
|
||||
[
|
||||
("Review request", "inspect scope", true),
|
||||
("Steer…", "edit response", false),
|
||||
("Dismiss", "leave inert", false),
|
||||
]
|
||||
} else {
|
||||
[
|
||||
("Continue", "keep moving", false),
|
||||
("Review plan", "inspect commands", false),
|
||||
("Ask…", "refine prompt", false),
|
||||
]
|
||||
};
|
||||
div()
|
||||
.flex()
|
||||
@@ -1018,9 +979,11 @@ impl LumbridgeShell {
|
||||
.size_full()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.px_3()
|
||||
.px_2()
|
||||
.py_2()
|
||||
.bg(rgb(PANEL))
|
||||
.border_t_1()
|
||||
.border_color(rgb(BORDER))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
@@ -1030,23 +993,78 @@ impl LumbridgeShell {
|
||||
.child(
|
||||
div()
|
||||
.text_color(rgb(MUTED))
|
||||
.child("DECISION SHELF · answer, choices, approvals"),
|
||||
.child("DECISION SHELF"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(rgb(ATTENTION))
|
||||
.child("LOCAL ANALYST OFF · suggestions inert"),
|
||||
.text_color(rgb(if pane.needs_input() {
|
||||
ATTENTION
|
||||
} else {
|
||||
MUTED
|
||||
}))
|
||||
.child(if pane.needs_input() {
|
||||
"REVIEW REQUIRED"
|
||||
} else {
|
||||
"SUGGESTIONS INERT"
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.mt_2()
|
||||
.child(choice("Continue", "Keep the selected agent moving"))
|
||||
.child(choice("Review plan", "Inspect capability-scoped commands"))
|
||||
.child(choice("Ask…", "Refine before any action")),
|
||||
.children(choices.map(|(label, detail, attention)| {
|
||||
choice(label, detail, attention)
|
||||
})),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn workspace_panel(
|
||||
&self,
|
||||
pane: &PaneState,
|
||||
selected: bool,
|
||||
cx: &mut Context<Self>,
|
||||
) -> gpui::AnyElement {
|
||||
let pane_id = pane.id();
|
||||
div()
|
||||
.id(("workspace-panel", pane_id.index()))
|
||||
.on_click(cx.listener(move |shell, _, window, cx| {
|
||||
shell.select_pane(pane_id, window, cx);
|
||||
}))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.min_w_0()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.border_1()
|
||||
.border_color(rgb(if selected { ACCENT } else { BORDER }))
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.20))
|
||||
.flex_none()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.child(self.pane_context(pane, selected)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.60))
|
||||
.flex_none()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.child(self.pane_work_surface(pane)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.20))
|
||||
.flex_none()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.child(self.pane_decision_region(pane)),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
@@ -1140,6 +1158,7 @@ impl LumbridgeShell {
|
||||
impl Render for LumbridgeShell {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let attention = self.model.pane(PaneId::ClaudeUi);
|
||||
let panel_count = visible_panel_count(window.bounds().size);
|
||||
let sidebar = div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
@@ -1303,117 +1322,38 @@ impl Render for LumbridgeShell {
|
||||
.px_3()
|
||||
.text_xs()
|
||||
.text_color(rgb(MUTED))
|
||||
.child("1 interactive VT · 5 deterministic · 1 waiting"),
|
||||
.child(format!(
|
||||
"{panel_count} visible panels · 1 interactive VT · 1 waiting"
|
||||
)),
|
||||
);
|
||||
|
||||
let pane_selectors = self
|
||||
.model
|
||||
.panes()
|
||||
.iter()
|
||||
.map(|pane| {
|
||||
Self::pane_selector(
|
||||
pane,
|
||||
self.model.selected_pane() == pane.id(),
|
||||
self.runtime_status.clone(),
|
||||
self.pane_focus[pane.id().index()].clone(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let selected = self.model.pane(self.model.selected_pane());
|
||||
let lane_count = visible_lane_count(window.bounds().size);
|
||||
let lane_range = visible_lane_range(
|
||||
let panel_range = visible_panel_range(
|
||||
PaneId::ALL.len(),
|
||||
self.model.selected_pane().index(),
|
||||
lane_count,
|
||||
panel_count,
|
||||
);
|
||||
let work_lanes = lane_range
|
||||
let workspace_panels = panel_range
|
||||
.map(|index| {
|
||||
let pane = self.model.pane(PaneId::ALL[index]);
|
||||
div()
|
||||
.flex_1()
|
||||
.min_w_0()
|
||||
.min_h_0()
|
||||
.child(self.work_surface(
|
||||
.child(self.workspace_panel(
|
||||
pane,
|
||||
pane.id() == self.model.selected_pane(),
|
||||
cx,
|
||||
))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let workspace_stack = div()
|
||||
let workspace_row = div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.flex_1()
|
||||
.min_w_0()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.20))
|
||||
.flex_none()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.px_3()
|
||||
.py_2()
|
||||
.bg(rgb(PANEL))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.text_xs()
|
||||
.child(
|
||||
div()
|
||||
.text_color(rgb(MUTED))
|
||||
.child("CONTEXT · panes, agents, tools, goal"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(rgb(if selected.needs_input() {
|
||||
ATTENTION
|
||||
} else {
|
||||
SUCCESS
|
||||
}))
|
||||
.child(if selected.needs_input() {
|
||||
"NEEDS INPUT · decision below"
|
||||
} else {
|
||||
"WORKSPACE HEALTHY"
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.mt_2()
|
||||
.flex_1()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.children(pane_selectors),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.60))
|
||||
.flex_none()
|
||||
.flex()
|
||||
.gap_1()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.children(work_lanes),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.20))
|
||||
.flex_none()
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.child(self.decision_region()),
|
||||
);
|
||||
.children(workspace_panels);
|
||||
|
||||
let counters = self.model.counters();
|
||||
let footer_left = format!(
|
||||
@@ -1511,7 +1451,7 @@ impl Render for LumbridgeShell {
|
||||
.min_h_0()
|
||||
.overflow_hidden()
|
||||
.child(tabs)
|
||||
.child(workspace_stack),
|
||||
.child(workspace_row),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -1658,7 +1598,7 @@ mod tests {
|
||||
use super::{
|
||||
KeyModifiers, TerminalEngine, TerminalEngineOptions, TerminalKey, TerminalScroll,
|
||||
indexed_terminal_color, terminal_dimensions_for_window, terminal_key_from_parts,
|
||||
terminal_paint_rows, terminal_scroll_from_parts, visible_lane_count, visible_lane_range,
|
||||
terminal_paint_rows, terminal_scroll_from_parts, visible_panel_count, visible_panel_range,
|
||||
};
|
||||
use gpui::{px, size};
|
||||
|
||||
@@ -1685,24 +1625,24 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn terminal_geometry_tracks_the_middle_sixty_percent() {
|
||||
fn terminal_geometry_tracks_middle_sixty_percent_per_panel() {
|
||||
let dimensions = terminal_dimensions_for_window(size(px(1500.0), px(960.0)));
|
||||
assert_eq!(dimensions.rows(), 24);
|
||||
assert_eq!(dimensions.rows(), 26);
|
||||
assert_eq!(dimensions.columns(), 45);
|
||||
|
||||
let ultrawide = size(px(3440.0), px(1440.0));
|
||||
assert_eq!(visible_lane_count(ultrawide), 5);
|
||||
assert_eq!(visible_panel_count(ultrawide), 5);
|
||||
let dimensions = terminal_dimensions_for_window(ultrawide);
|
||||
assert_eq!(dimensions.rows(), 40);
|
||||
assert_eq!(dimensions.rows(), 42);
|
||||
assert_eq!(dimensions.columns(), 71);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lane_window_keeps_the_selected_pane_visible() {
|
||||
assert_eq!(visible_lane_range(6, 0, 5), 0..5);
|
||||
assert_eq!(visible_lane_range(6, 5, 5), 1..6);
|
||||
assert_eq!(visible_lane_range(6, 3, 3), 2..5);
|
||||
assert_eq!(visible_lane_range(6, 4, 1), 4..5);
|
||||
fn panel_window_keeps_the_selected_pane_visible() {
|
||||
assert_eq!(visible_panel_range(6, 0, 5), 0..5);
|
||||
assert_eq!(visible_panel_range(6, 5, 5), 1..6);
|
||||
assert_eq!(visible_panel_range(6, 3, 3), 2..5);
|
||||
assert_eq!(visible_panel_range(6, 4, 1), 4..5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user