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
2 changes: 1 addition & 1 deletion crates/libghostty-vt-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::process::Command;

/// Pinned ghostty commit. Update this to pull a newer version.
const GHOSTTY_REPO: &str = "https://github.com/aislopware/ghostty.git";
const GHOSTTY_COMMIT: &str = "d266f39d98a3d77e70adf7d9775d4e92d73a6e3d";
const GHOSTTY_COMMIT: &str = "42c228683ccd28844f03e18a8f1da699a01f5359";

/// File name of the static archive on Windows. Ghostty installs it under this
/// name for every Windows ABI so it does not collide with `ghostty-vt.lib`,
Expand Down
6 changes: 5 additions & 1 deletion crates/libghostty-vt-sys/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3556,8 +3556,10 @@ pub struct FormatterTerminalOptions {
pub extra: FormatterTerminalExtra,
#[doc = " Optional selection to restrict output to a range.\n If NULL, the entire screen is formatted."]
pub selection: *const Selection,
#[doc = " For VT, emit every row's prompt flag and every cell's semantic\n content (OSC 133), so a replay into a fresh terminal restores them.\n Rows with no text but a prompt flag are emitted too. No effect when\n unwrap is set."]
#[doc = " For VT, emit every row's prompt flag and every cell's semantic\n content (OSC 133), so a replay into a fresh terminal restores them.\n Rows with no text but a prompt flag are emitted too."]
pub semantic_prompt: bool,
#[doc = " For VT, end with the blank rows after the last one with text, as\n newlines, so a replay into a fresh terminal of the same size has\n every row that was formatted."]
pub trailing_rows: bool,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
Expand All @@ -3579,6 +3581,8 @@ const _: () = {
[::std::mem::offset_of!(FormatterTerminalOptions, selection) - 48usize];
["Offset of field: FormatterTerminalOptions::semantic_prompt"]
[::std::mem::offset_of!(FormatterTerminalOptions, semantic_prompt) - 56usize];
["Offset of field: FormatterTerminalOptions::trailing_rows"]
[::std::mem::offset_of!(FormatterTerminalOptions, trailing_rows) - 57usize];
};
impl Default for FormatterTerminalOptions {
fn default() -> Self {
Expand Down
26 changes: 24 additions & 2 deletions crates/libghostty-vt/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ impl<'t, 's> FormatterOptions<'t, 's> {
self.inner.emit = value.into();
self
}
/// Specify whether to unwrap soft-wrapped lines.
/// Specify whether to unwrap soft-wrapped lines. VT output then leaves
/// a soft-wrapped row for a replaying terminal of the same width to
/// wrap itself.
pub fn with_unwrap(mut self, value: bool) -> Self {
self.inner.unwrap = value;
self
Expand All @@ -60,11 +62,17 @@ impl<'t, 's> FormatterOptions<'t, 's> {
/// Specify whether VT output carries every row's prompt flag and every
/// cell's semantic content (OSC 133), so a replay into a fresh terminal
/// restores them. Rows with no text but a prompt flag are emitted too.
/// No effect with [`with_unwrap`](Self::with_unwrap).
pub fn with_semantic_prompt(mut self, value: bool) -> Self {
self.inner.semantic_prompt = value;
self
}
/// Specify whether VT output ends with the blank rows after the last
/// one with text, so a replay into a fresh terminal of the same size
/// has every row: a screen with history keeps it whole.
pub fn with_trailing_rows(mut self, value: bool) -> Self {
self.inner.trailing_rows = value;
self
}
/// Specify the selection to restrict output to a range.
///
/// If a selection is not given, the formatter defaults to formatting
Expand Down Expand Up @@ -390,6 +398,20 @@ mod tests {
assert!(!has(&vt(false)), "only when asked");
}

#[test]
fn vt_output_ends_with_the_trailing_rows_when_asked() {
let mut terminal = Terminal::new(10, 4).unwrap();
terminal.vt_write(b"top\r\n\r\n");
let vt = |trailing| {
let options = FormatterOptions::new()
.with_format(Format::Vt)
.with_trailing_rows(trailing);
format_buf(&mut Formatter::new(&terminal, options).unwrap())
};
assert!(vt(true).ends_with(b"top\r\n\r\n\r\n"), "every row but the last ends");
assert_eq!(vt(false), b"top", "left out unless asked");
}

#[test]
fn writer_output_matches_buffer_output_in_every_format() {
let mut terminal = Terminal::new(20, 3).unwrap();
Expand Down
Loading