mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
terminal: reset should preserve desired default mode values
Fixes #2857 Some terminal modes always reset, but there are others that should be conditional based on how the terminal's default state is configured. Primarily from #2857 is the grapheme clustering mode (mode 2027) which was always resetting to false but should be conditional based on the the `grapheme-width-method` configuration.
This commit is contained in:
@ -193,6 +193,10 @@ pub const Options = struct {
|
||||
cols: size.CellCountInt,
|
||||
rows: size.CellCountInt,
|
||||
max_scrollback: usize = 10_000,
|
||||
|
||||
/// The default mode state. When the terminal gets a reset, it
|
||||
/// will revert back to this state.
|
||||
default_modes: modes.ModePacked = .{},
|
||||
};
|
||||
|
||||
/// Initialize a new terminal.
|
||||
@ -216,6 +220,10 @@ pub fn init(
|
||||
.right = cols - 1,
|
||||
},
|
||||
.pwd = std.ArrayList(u8).init(alloc),
|
||||
.modes = .{
|
||||
.values = opts.default_modes,
|
||||
.default = opts.default_modes,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -2680,7 +2688,7 @@ fn resetCommonState(self: *Terminal) void {
|
||||
|
||||
self.screen.endHyperlink();
|
||||
self.screen.charset = .{};
|
||||
self.modes = .{};
|
||||
self.modes.reset();
|
||||
self.flags = .{};
|
||||
self.tabstops.reset(TABSTOP_INTERVAL);
|
||||
self.screen.kitty_keyboard = .{};
|
||||
@ -10555,6 +10563,18 @@ test "Terminal: fullReset clears alt screen kitty keyboard state" {
|
||||
try testing.expectEqual(0, t.secondary_screen.kitty_keyboard.current().int());
|
||||
}
|
||||
|
||||
test "Terminal: fullReset default modes" {
|
||||
var t = try init(testing.allocator, .{
|
||||
.cols = 10,
|
||||
.rows = 10,
|
||||
.default_modes = .{ .grapheme_cluster = true },
|
||||
});
|
||||
defer t.deinit(testing.allocator);
|
||||
try testing.expect(t.modes.get(.grapheme_cluster));
|
||||
t.fullReset();
|
||||
try testing.expect(t.modes.get(.grapheme_cluster));
|
||||
}
|
||||
|
||||
// https://github.com/mitchellh/ghostty/issues/272
|
||||
// This is also tested in depth in screen resize tests but I want to keep
|
||||
// this test around to ensure we don't regress at multiple layers.
|
||||
|
@ -47,6 +47,7 @@ pub const CursorStyle = Screen.CursorStyle;
|
||||
pub const CursorStyleReq = ansi.CursorStyle;
|
||||
pub const DeviceAttributeReq = ansi.DeviceAttributeReq;
|
||||
pub const Mode = modes.Mode;
|
||||
pub const ModePacked = modes.ModePacked;
|
||||
pub const ModifyKeyFormat = ansi.ModifyKeyFormat;
|
||||
pub const ProtectedMode = ansi.ProtectedMode;
|
||||
pub const StatusLineType = ansi.StatusLineType;
|
||||
|
@ -21,6 +21,17 @@ pub const ModeState = struct {
|
||||
/// a real-world issue but we need to be aware of a DoS vector.
|
||||
saved: ModePacked = .{},
|
||||
|
||||
/// The default values for the modes. This is used to reset
|
||||
/// the modes to their default values during reset.
|
||||
default: ModePacked = .{},
|
||||
|
||||
/// Reset the modes to their default values. This also clears the
|
||||
/// saved state.
|
||||
pub fn reset(self: *ModeState) void {
|
||||
self.values = self.default;
|
||||
self.saved = .{};
|
||||
}
|
||||
|
||||
/// Set a mode to a value.
|
||||
pub fn set(self: *ModeState, mode: Mode, value: bool) void {
|
||||
switch (mode) {
|
||||
|
@ -127,6 +127,23 @@ pub const DerivedConfig = struct {
|
||||
/// This will also start the child process if the termio is configured
|
||||
/// to run a child process.
|
||||
pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
||||
// The default terminal modes based on our config.
|
||||
const default_modes: terminal.ModePacked = modes: {
|
||||
var modes: terminal.ModePacked = .{};
|
||||
|
||||
// Setup our initial grapheme cluster support if enabled. We use a
|
||||
// switch to ensure we get a compiler error if more cases are added.
|
||||
switch (opts.full_config.@"grapheme-width-method") {
|
||||
.unicode => modes.grapheme_cluster = true,
|
||||
.legacy => {},
|
||||
}
|
||||
|
||||
// Set default cursor blink settings
|
||||
modes.cursor_blinking = opts.config.cursor_blink orelse true;
|
||||
|
||||
break :modes modes;
|
||||
};
|
||||
|
||||
// Create our terminal
|
||||
var term = try terminal.Terminal.init(alloc, opts: {
|
||||
const grid_size = opts.size.grid();
|
||||
@ -134,19 +151,13 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
||||
.cols = grid_size.columns,
|
||||
.rows = grid_size.rows,
|
||||
.max_scrollback = opts.full_config.@"scrollback-limit",
|
||||
.default_modes = default_modes,
|
||||
};
|
||||
});
|
||||
errdefer term.deinit(alloc);
|
||||
term.default_palette = opts.config.palette;
|
||||
term.color_palette.colors = opts.config.palette;
|
||||
|
||||
// Setup our initial grapheme cluster support if enabled. We use a
|
||||
// switch to ensure we get a compiler error if more cases are added.
|
||||
switch (opts.full_config.@"grapheme-width-method") {
|
||||
.unicode => term.modes.set(.grapheme_cluster, true),
|
||||
.legacy => {},
|
||||
}
|
||||
|
||||
// Set the image size limits
|
||||
try term.screen.kitty_images.setLimit(
|
||||
alloc,
|
||||
@ -159,12 +170,6 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
||||
opts.config.image_storage_limit,
|
||||
);
|
||||
|
||||
// Set default cursor blink settings
|
||||
term.modes.set(
|
||||
.cursor_blinking,
|
||||
opts.config.cursor_blink orelse true,
|
||||
);
|
||||
|
||||
// Set our default cursor style
|
||||
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
||||
|
||||
|
Reference in New Issue
Block a user