Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fancy-regex = "0.19"
chrono = { version = "0.4", default-features = false, features = ["std", "clock"] }
chrono-tz = "0.10"
# In-process terminal screen model (terminal feature)
vt100 = "0.16"
vt100 = "0.18"

# Compression
flate2 = "1"
Expand Down
9 changes: 7 additions & 2 deletions crates/bashkit/src/terminal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,9 @@ impl Terminal {
pub fn screen_rows(&self) -> Vec<String> {
self.tty.with_screen(|s| {
let (_, cols) = s.size();
s.rows(0, cols).map(|r| r.trim_end().to_string()).collect()
s.rows(0, cols.get())
.map(|r| r.trim_end().to_string())
.collect()
})
}

Expand Down Expand Up @@ -396,7 +398,10 @@ impl Terminal {
Some(self.tty.with_screen(|s| {
let (row, col) = s.cursor_position();
let (_, cols) = s.size();
let text = s.rows(0, cols).nth(usize::from(row)).unwrap_or_default();
let text = s
.rows(0, cols.get())
.nth(usize::from(row))
.unwrap_or_default();
text.chars().take(usize::from(col)).collect::<String>()
}))
}
Expand Down
22 changes: 19 additions & 3 deletions crates/bashkit/src/terminal/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//! holds the lock across an `.await`.

use std::collections::VecDeque;
use std::num::NonZero;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex, MutexGuard, PoisonError};

Expand All @@ -25,6 +26,15 @@ pub(crate) const MAX_OUTPUT_TAP: usize = 256 * 1024;
/// Lines of primary-screen history kept for `history_text`.
pub(crate) const SCROLLBACK_LINES: usize = 1000;

/// vt100 0.18 takes screen dimensions as `NonZero<u16>`; [`TerminalSize`] keeps
/// plain `u16` because its fields are public API. `TerminalSize::new` already
/// clamps to 2, but the struct can also be built literally, so a zero can still
/// reach here. Clamp it to 1 rather than panic: a degenerate size is the
/// caller's to notice, and it is not worth aborting a session over.
fn nz(v: u16) -> NonZero<u16> {
NonZero::new(v).unwrap_or(NonZero::<u16>::MIN)
}

/// What a blocking terminal read returned.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum TtyEvent {
Expand Down Expand Up @@ -85,7 +95,7 @@ impl Tty {
reading_line: false,
resized: false,
closed: false,
screen: vt100::Parser::new(size.rows, size.cols, SCROLLBACK_LINES),
screen: vt100::Parser::new(nz(size.rows), nz(size.cols), SCROLLBACK_LINES),
output: Vec::new(),
tap: Vec::new(),
tap_total: 0,
Expand Down Expand Up @@ -136,7 +146,9 @@ impl Tty {
pub(crate) fn resize(&self, size: TerminalSize) {
{
let mut st = self.lock();
st.screen.screen_mut().set_size(size.rows, size.cols);
st.screen
.screen_mut()
.set_size(nz(size.rows), nz(size.cols));
st.resized = true;
st.waiting = false;
}
Expand Down Expand Up @@ -190,6 +202,7 @@ impl Tty {
let mut st = self.lock();
let screen = st.screen.screen_mut();
let (rows, cols) = screen.size();
let (rows, cols) = (rows.get(), cols.get());
let rows = usize::from(rows);
screen.set_scrollback(usize::MAX);
let total = screen.scrollback();
Expand All @@ -212,7 +225,10 @@ impl Tty {

pub(crate) fn size(&self) -> TerminalSize {
let (rows, cols) = self.lock().screen.screen().size();
TerminalSize { rows, cols }
TerminalSize {
rows: rows.get(),
cols: cols.get(),
}
}

pub(crate) fn set_raw(&self, raw: bool) {
Expand Down
7 changes: 7 additions & 0 deletions knowledge/integrations/in-process-terminal.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ C FFI, which would break the wasm, PyPI and npm builds, for a feature whose
screen needs are basic (cells, cursor, alternate screen). Revisit only if
fidelity gaps show up that vt100 cannot close.

From vt100 0.18 the screen dimensions are `NonZero<u16>`. `TerminalSize` keeps
plain `u16`, because its fields are public API, and converts at the vt100
boundary only. `TerminalSize::new` clamps to 2, but the struct can also be
built literally, so a zero can still reach that boundary; it clamps to 1 rather
than panicking, since a degenerate size is the caller's to notice and not worth
aborting a session over.

## Decision: device handle via execution extensions

The shell loop passes the `Tty` handle on every `exec_with_options` call
Expand Down
4 changes: 2 additions & 2 deletions supply-chain/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2114,9 +2114,9 @@ version = "0.9.5"
criteria = "safe-to-deploy"

[[exemptions.vt100]]
version = "0.16.2"
version = "0.18.1"
criteria = "safe-to-deploy"
notes = "Terminal screen model for the optional `terminal` feature. Pure parsing/state; reviewed: no unsafe, no host I/O, process, or network access."
notes = "Terminal screen model for the optional `terminal` feature. Pure parsing/state. The exemption moves from 0.16.2 rather than gaining a delta audit: that delta is ~3100 lines across a dozen files plus a new capture.rs, so a delta audit would claim a review that diff does not get. Checked instead for what the exemption asserts, and all of it still holds: zero `unsafe` in src (unchanged from 0.16.2), zero use of std::fs, std::net, std::process or std::env, and no new runtime dependency -- 0.18.1 adds only an optional `embedded-io`, which stays unenabled and is absent from vt100's resolved deps in Cargo.lock (itoa, unicode-width, vte); vte stays at 0.15.0."

[[exemptions.vte]]
version = "0.15.0"
Expand Down
Loading