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,
|
cols: size.CellCountInt,
|
||||||
rows: size.CellCountInt,
|
rows: size.CellCountInt,
|
||||||
max_scrollback: usize = 10_000,
|
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.
|
/// Initialize a new terminal.
|
||||||
@ -216,6 +220,10 @@ pub fn init(
|
|||||||
.right = cols - 1,
|
.right = cols - 1,
|
||||||
},
|
},
|
||||||
.pwd = std.ArrayList(u8).init(alloc),
|
.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.endHyperlink();
|
||||||
self.screen.charset = .{};
|
self.screen.charset = .{};
|
||||||
self.modes = .{};
|
self.modes.reset();
|
||||||
self.flags = .{};
|
self.flags = .{};
|
||||||
self.tabstops.reset(TABSTOP_INTERVAL);
|
self.tabstops.reset(TABSTOP_INTERVAL);
|
||||||
self.screen.kitty_keyboard = .{};
|
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());
|
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
|
// https://github.com/mitchellh/ghostty/issues/272
|
||||||
// This is also tested in depth in screen resize tests but I want to keep
|
// 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.
|
// 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 CursorStyleReq = ansi.CursorStyle;
|
||||||
pub const DeviceAttributeReq = ansi.DeviceAttributeReq;
|
pub const DeviceAttributeReq = ansi.DeviceAttributeReq;
|
||||||
pub const Mode = modes.Mode;
|
pub const Mode = modes.Mode;
|
||||||
|
pub const ModePacked = modes.ModePacked;
|
||||||
pub const ModifyKeyFormat = ansi.ModifyKeyFormat;
|
pub const ModifyKeyFormat = ansi.ModifyKeyFormat;
|
||||||
pub const ProtectedMode = ansi.ProtectedMode;
|
pub const ProtectedMode = ansi.ProtectedMode;
|
||||||
pub const StatusLineType = ansi.StatusLineType;
|
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.
|
/// a real-world issue but we need to be aware of a DoS vector.
|
||||||
saved: ModePacked = .{},
|
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.
|
/// Set a mode to a value.
|
||||||
pub fn set(self: *ModeState, mode: Mode, value: bool) void {
|
pub fn set(self: *ModeState, mode: Mode, value: bool) void {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -127,6 +127,23 @@ pub const DerivedConfig = struct {
|
|||||||
/// This will also start the child process if the termio is configured
|
/// This will also start the child process if the termio is configured
|
||||||
/// to run a child process.
|
/// to run a child process.
|
||||||
pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
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
|
// Create our terminal
|
||||||
var term = try terminal.Terminal.init(alloc, opts: {
|
var term = try terminal.Terminal.init(alloc, opts: {
|
||||||
const grid_size = opts.size.grid();
|
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,
|
.cols = grid_size.columns,
|
||||||
.rows = grid_size.rows,
|
.rows = grid_size.rows,
|
||||||
.max_scrollback = opts.full_config.@"scrollback-limit",
|
.max_scrollback = opts.full_config.@"scrollback-limit",
|
||||||
|
.default_modes = default_modes,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
errdefer term.deinit(alloc);
|
errdefer term.deinit(alloc);
|
||||||
term.default_palette = opts.config.palette;
|
term.default_palette = opts.config.palette;
|
||||||
term.color_palette.colors = 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
|
// Set the image size limits
|
||||||
try term.screen.kitty_images.setLimit(
|
try term.screen.kitty_images.setLimit(
|
||||||
alloc,
|
alloc,
|
||||||
@ -159,12 +170,6 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
|||||||
opts.config.image_storage_limit,
|
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
|
// Set our default cursor style
|
||||||
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user