mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-23 07:45:20 +00:00
@@ -434,13 +434,13 @@ pub const Action = union(enum) {
|
||||
/// The default OS editor is determined by using `open` on macOS
|
||||
/// and `xdg-open` on Linux.
|
||||
///
|
||||
write_scrollback_file: WriteScreenAction,
|
||||
write_scrollback_file: WriteScreen,
|
||||
|
||||
/// Write the contents of the screen into a temporary file with the
|
||||
/// specified action.
|
||||
///
|
||||
/// See `write_scrollback_file` for possible actions.
|
||||
write_screen_file: WriteScreenAction,
|
||||
write_screen_file: WriteScreen,
|
||||
|
||||
/// Write the currently selected text into a temporary file with the
|
||||
/// specified action.
|
||||
@@ -448,7 +448,7 @@ pub const Action = union(enum) {
|
||||
/// See `write_scrollback_file` for possible actions.
|
||||
///
|
||||
/// Does nothing when no text is selected.
|
||||
write_selection_file: WriteScreenAction,
|
||||
write_selection_file: WriteScreen,
|
||||
|
||||
/// Open a new window.
|
||||
///
|
||||
@@ -811,6 +811,15 @@ pub const Action = union(enum) {
|
||||
.application = try alloc.dupe(u8, self.application),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: CursorKey,
|
||||
writer: *std.Io.Writer,
|
||||
) std.Io.Writer.Error!void {
|
||||
_ = self;
|
||||
_ = writer;
|
||||
@panic("formatting not supported");
|
||||
}
|
||||
};
|
||||
|
||||
pub const AdjustSelection = enum {
|
||||
@@ -902,10 +911,64 @@ pub const Action = union(enum) {
|
||||
pub const default: CopyToClipboard = .mixed;
|
||||
};
|
||||
|
||||
pub const WriteScreenAction = enum {
|
||||
copy,
|
||||
paste,
|
||||
open,
|
||||
pub const WriteScreen = struct {
|
||||
action: WriteScreen.Action,
|
||||
emit: WriteScreen.Format,
|
||||
|
||||
pub const copy: WriteScreen = .{ .action = .copy, .emit = .plain };
|
||||
pub const paste: WriteScreen = .{ .action = .paste, .emit = .plain };
|
||||
pub const open: WriteScreen = .{ .action = .open, .emit = .plain };
|
||||
|
||||
pub const Action = enum {
|
||||
copy,
|
||||
paste,
|
||||
open,
|
||||
};
|
||||
|
||||
pub const Format = enum {
|
||||
plain,
|
||||
vt,
|
||||
html,
|
||||
};
|
||||
|
||||
pub fn parse(param: []const u8) !WriteScreen {
|
||||
// If we don't have a `,`, default to the plain format. This is
|
||||
// also very important for backwards compatibility before Ghostty
|
||||
// 1.3 which didn't support output formats.
|
||||
const idx = std.mem.indexOfScalar(u8, param, ',') orelse return .{
|
||||
.action = try Binding.Action.parseEnum(
|
||||
WriteScreen.Action,
|
||||
param,
|
||||
),
|
||||
.emit = .plain,
|
||||
};
|
||||
|
||||
return .{
|
||||
.action = try Binding.Action.parseEnum(
|
||||
WriteScreen.Action,
|
||||
param[0..idx],
|
||||
),
|
||||
.emit = try Binding.Action.parseEnum(
|
||||
WriteScreen.Format,
|
||||
param[idx + 1 ..],
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn clone(
|
||||
self: WriteScreen,
|
||||
alloc: Allocator,
|
||||
) Allocator.Error!WriteScreen {
|
||||
_ = alloc;
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn format(self: WriteScreen, writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||
try writer.print("{t},{t}", .{
|
||||
self.action,
|
||||
self.emit,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Extern because it is used in the embedded runtime ABI.
|
||||
@@ -948,7 +1011,7 @@ pub const Action = union(enum) {
|
||||
if (@hasDecl(field.type, "parse") and
|
||||
@typeInfo(@TypeOf(field.type.parse)) == .@"fn")
|
||||
{
|
||||
return field.type.parse(param);
|
||||
return try field.type.parse(param);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1244,12 +1307,19 @@ pub const Action = union(enum) {
|
||||
.@"enum" => try writer.print("{t}", .{value}),
|
||||
.float => try writer.print("{d}", .{value}),
|
||||
.int => try writer.print("{d}", .{value}),
|
||||
.@"struct" => |info| if (!info.is_tuple) {
|
||||
try writer.print("{} (not configurable)", .{value});
|
||||
} else {
|
||||
inline for (info.fields, 0..) |field, i| {
|
||||
try formatValue(writer, @field(value, field.name));
|
||||
if (i + 1 < info.fields.len) try writer.writeAll(",");
|
||||
.@"struct" => |info| format: {
|
||||
if (@hasDecl(Value, "format")) {
|
||||
try value.format(writer);
|
||||
break :format;
|
||||
}
|
||||
|
||||
if (!info.is_tuple) {
|
||||
@compileError("unhandled struct type: " ++ @typeName(Value));
|
||||
} else {
|
||||
inline for (info.fields, 0..) |field, i| {
|
||||
try formatValue(writer, @field(value, field.name));
|
||||
if (i + 1 < info.fields.len) try writer.writeAll(",");
|
||||
}
|
||||
}
|
||||
},
|
||||
else => @compileError("unhandled type: " ++ @typeName(Value)),
|
||||
@@ -3274,6 +3344,62 @@ test "parse: copy to clipboard explicit" {
|
||||
}
|
||||
}
|
||||
|
||||
test "parse: write screen file no format" {
|
||||
const testing = std.testing;
|
||||
|
||||
// parameter
|
||||
{
|
||||
const binding = try parseSingle("a=write_screen_file:copy");
|
||||
try testing.expect(binding.action == .write_screen_file);
|
||||
try testing.expectEqual(Action.WriteScreen.copy, binding.action.write_screen_file);
|
||||
}
|
||||
}
|
||||
|
||||
test "parse: write screen file format" {
|
||||
const testing = std.testing;
|
||||
|
||||
// parameter
|
||||
{
|
||||
const binding = try parseSingle("a=write_screen_file:copy,html");
|
||||
try testing.expect(binding.action == .write_screen_file);
|
||||
try testing.expectEqual(Action.WriteScreen{
|
||||
.action = .copy,
|
||||
.emit = .html,
|
||||
}, binding.action.write_screen_file);
|
||||
}
|
||||
}
|
||||
|
||||
test "parse: write screen file format as string" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
{
|
||||
var buf: std.Io.Writer.Allocating = .init(alloc);
|
||||
defer buf.deinit();
|
||||
const binding = try parseSingle("a=write_screen_file:copy,html");
|
||||
try binding.action.format(&buf.writer);
|
||||
try testing.expectEqualStrings("write_screen_file:copy,html", buf.written());
|
||||
}
|
||||
}
|
||||
|
||||
test "parse: write screen file invalid" {
|
||||
const testing = std.testing;
|
||||
|
||||
// paramet r
|
||||
try testing.expectError(Error.InvalidFormat, parseSingle(
|
||||
"a=write_screen_file:",
|
||||
));
|
||||
try testing.expectError(Error.InvalidFormat, parseSingle(
|
||||
"a=write_screen_file:,",
|
||||
));
|
||||
try testing.expectError(Error.InvalidFormat, parseSingle(
|
||||
"a=write_screen_file:copy,",
|
||||
));
|
||||
try testing.expectError(Error.InvalidFormat, parseSingle(
|
||||
"a=write_screen_file:copy,html,extra",
|
||||
));
|
||||
}
|
||||
|
||||
test "action: format" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
Reference in New Issue
Block a user