Panics · P18 Terminal: paint faults log, a pty side caps at what it holds, a default shell past the list keeps the last

This commit is contained in:
ZacharyZhang-NY committed 2026-10-06 21:34:44 -04:00
1 parent b29d66ccc0
commit 0bb3f4e858
6 files changed
+114 -23

No files matched your search

+21 -9
View File
@@ -100,9 +100,17 @@ pub(crate) fn grid(
&runs,
Some(cell.width),
);
shaped
.paint_background(at(ix, 0), cell.height, TextAlign::Left, None, window, cx)
.expect("a terminal row's ground paints");
let ground = shaped.paint_background(
at(ix, 0),
cell.height,
TextAlign::Left,
None,
window,
cx,
);
if let Err(error) = ground {
log::error!("terminal: row {ix}'s ground failed to paint: {error:#}");
}
for (_, columns, why) in frame.lit.iter().filter(|(row, ..)| *row == ix) {
let wash = match why {
Lit::Selected => look.selection,
@@ -112,9 +120,11 @@ pub(crate) fn grid(
let extent = size(cell.width * columns.len() as f32, cell.height);
window.paint_quad(fill(Bounds::new(at(ix, columns.start), extent), wash));
}
shaped
.paint(at(ix, 0), cell.height, TextAlign::Left, None, window, cx)
.expect("a terminal row paints");
if let Err(error) =
shaped.paint(at(ix, 0), cell.height, TextAlign::Left, None, window, cx)
{
log::error!("terminal: row {ix} failed to paint: {error:#}");
}
for (column, cluster, style) in &row.clusters {
let run = TextRun {
len: cluster.len(),
@@ -124,7 +134,7 @@ pub(crate) fn grid(
underline: None,
strikethrough: None,
};
window
let painted = window
.text_system()
.shape_line(cluster.clone().into(), look.size, &[run], None)
.paint(
@@ -134,8 +144,10 @@ pub(crate) fn grid(
None,
window,
cx,
)
.expect("a terminal cluster paints");
);
if let Err(error) = painted {
log::error!("terminal: a cluster in row {ix} failed to paint: {error:#}");
}
}
}
if let Some((row, columns, _)) = &hovered {
+28 -4
View File
@@ -99,16 +99,40 @@ pub(crate) fn spawn(launch: &Launch, size: TermSize, cell: (u16, u16)) -> anyhow
}
pub(crate) fn window_size(size: &TermSize, cell: (u16, u16)) -> WindowSize {
let cells =
|count: usize| u16::try_from(count).expect("a terminal is under 65536 cells a side");
let cells = |count: usize, side: u16| {
let most = (i16::MAX as u16).min(u16::MAX / side.max(1));
let kept = u16::try_from(count).unwrap_or(u16::MAX).min(most);
if usize::from(kept) < count {
log::error!("terminal: {count} cells of {side} px pass what a pty holds; {kept} kept");
}
kept
};
WindowSize {
num_lines: cells(size.screen_lines),
num_cols: cells(size.columns),
num_lines: cells(size.screen_lines, cell.1),
num_cols: cells(size.columns, cell.0),
cell_width: cell.0,
cell_height: cell.1,
}
}
#[cfg(test)]
mod sizes {
use alacritty_terminal::term::test::TermSize;
use super::window_size;
#[test]
fn more_cells_than_a_pty_holds_cap_at_its_most() {
let size = window_size(&TermSize::new(70_000, 24), (8, 16));
assert_eq!((size.num_cols, size.num_lines), (u16::MAX / 8, 24));
let tiny = window_size(&TermSize::new(70_000, 70_000), (1, 1));
assert_eq!(
(tiny.num_cols, tiny.num_lines),
(i16::MAX as u16, i16::MAX as u16)
);
}
}
#[cfg(all(test, unix))]
mod tests {
use alacritty_terminal::index::{Column, Line};
+24 -4
View File
@@ -46,10 +46,13 @@ impl ShellSelector {
}
pub fn default_shell(mut self, default: usize) -> Self {
assert!(
default < self.shells.len(),
"the default is one of the shells"
);
if default >= self.shells.len() {
log::error!(
"shell selector: no shell {default} of {}; the default stays",
self.shells.len()
);
return self;
}
self.default = default;
self
}
@@ -193,3 +196,20 @@ impl RenderOnce for TerminalToolbar {
}))
}
}
#[cfg(test)]
mod tests {
use super::{ShellChoice, ShellSelector};
#[test]
fn a_default_past_the_shells_keeps_the_one_before() {
let shell = |name: &'static str| ShellChoice {
name: name.into(),
program: name.into(),
};
let picker = ShellSelector::new("shells", [shell("zsh"), shell("bash")])
.default_shell(1)
.default_shell(5);
assert_eq!(picker.default, 1);
}
}
+31
View File
@@ -79,3 +79,34 @@ fn a_link_keeps_its_combining_marks(cx: &mut TestAppContext) {
assert_eq!(target, Target::Url("https://e.dev/cafe\u{301}/x".into()));
});
}
#[gpui::test]
fn a_pixel_size_query_of_a_wide_grid_answers(cx: &mut TestAppContext) {
use gpui::AppContext as _;
cx.update(Theme::init);
for columns in [80, 8192] {
let terminal = cx.new(|cx| Terminal::replay(b"\x1b[14t", columns, 1, cx));
cx.run_until_parked();
terminal.read_with(cx, |terminal, _| {
assert_eq!(terminal.title().as_ref(), "Output")
});
}
}
#[cfg(windows)]
#[test]
fn more_cells_than_a_windows_pty_holds_resize_it() {
use alacritty_terminal::{event::OnResize, term::test::TermSize, tty};
let options = tty::Options {
shell: Some(tty::Shell::new(
"cmd.exe".into(),
vec!["/c".into(), "exit".into()],
)),
escape_args: true,
..tty::Options::default()
};
let size = |columns| super::pty::window_size(&TermSize::new(columns, 24), (8, 16));
let mut pty = tty::new(&options, size(80), 0).expect("a pty starts");
pty.on_resize(size(80));
pty.on_resize(size(70_000));
}
+8 -5
View File
@@ -282,11 +282,14 @@ impl Render for Terminal {
let text = theme.text_size(TextSize::Sm);
let mono = font(theme.mono_family.clone());
let pixels = text.to_pixels(window.rem_size());
let advance = window
.text_system()
.advance(window.text_system().resolve_font(&mono), pixels, 'm')
.expect("the code font has an m")
.width;
let resolved = window.text_system().resolve_font(&mono);
let advance = match window.text_system().advance(resolved, pixels, 'm') {
Ok(advance) => advance.width,
Err(error) => {
log::error!("terminal: no advance for the code font: {error:#}; cells guessed");
pixels * 0.6
}
};
self.cell = size(advance, (pixels * LEADING).round());
let (found, current) = self.search.visible();
self.shown = Rc::new(frame(&self.term.lock(), &ink, found, current));