feat: implement scroll-to-bottom on output option

Implements the `output` option for the `scroll-to-bottom` configuration,
which scrolls the viewport to the bottom when new lines are printed.

Co-Authored-By: Sachin <sachinbeniwal0101@gmail.com>
This commit is contained in:
benodiwal
2025-12-17 16:45:18 +05:30
committed by Mitchell Hashimoto
parent f2a5f36f26
commit 81f537e992
3 changed files with 13 additions and 1 deletions

View File

@@ -906,7 +906,7 @@ palette: Palette = .{},
/// anything but modifiers or keybinds that are processed by Ghostty).
///
/// - `output` If set, scroll the surface to the bottom if there is new data
/// to display. (Currently unimplemented.)
/// to display (e.g., when new lines are printed to the terminal).
///
/// The default is `keystroke, no-output`.
@"scroll-to-bottom": ScrollToBottom = .default,

View File

@@ -166,6 +166,7 @@ pub const DerivedConfig = struct {
clipboard_write: configpkg.ClipboardAccess,
enquiry_response: []const u8,
conditional_state: configpkg.ConditionalState,
scroll_to_bottom: configpkg.Config.ScrollToBottom,
pub fn init(
alloc_gpa: Allocator,
@@ -207,6 +208,7 @@ pub const DerivedConfig = struct {
.clipboard_write = config.@"clipboard-write",
.enquiry_response = try alloc.dupe(u8, config.@"enquiry-response"),
.conditional_state = config._conditional_state,
.scroll_to_bottom = config.@"scroll-to-bottom",
// This has to be last so that we copy AFTER the arena allocations
// above happen (Zig assigns in order).
@@ -301,6 +303,7 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
.enquiry_response = opts.config.enquiry_response,
.default_cursor_style = opts.config.cursor_style,
.default_cursor_blink = opts.config.cursor_blink,
.scroll_to_bottom_on_output = opts.config.scroll_to_bottom.output,
};
const thread_enter_state = try ThreadEnterState.create(

View File

@@ -56,6 +56,9 @@ pub const StreamHandler = struct {
/// The clipboard write access configuration.
clipboard_write: configpkg.ClipboardAccess,
/// The scroll-to-bottom behavior configuration.
scroll_to_bottom_on_output: bool,
//---------------------------------------------------------------
// Internal state
@@ -112,6 +115,7 @@ pub const StreamHandler = struct {
self.enquiry_response = config.enquiry_response;
self.default_cursor_style = config.cursor_style;
self.default_cursor_blink = config.cursor_blink;
self.scroll_to_bottom_on_output = config.scroll_to_bottom.output;
// If our cursor is the default, then we update it immediately.
if (self.default_cursor) self.setCursorStyle(.default) catch |err| {
@@ -576,6 +580,11 @@ pub const StreamHandler = struct {
// Small optimization: call index instead of linefeed because they're
// identical and this avoids one layer of function call overhead.
try self.terminal.index();
// If configured, scroll to bottom on output so the user sees new content
if (self.scroll_to_bottom_on_output) {
try self.terminal.scrollViewport(.bottom);
}
}
pub inline fn reverseIndex(self: *StreamHandler) !void {