mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
@ -256,7 +256,10 @@ pub fn expandPath(alloc: Allocator, cmd: []const u8) !?[]u8 {
|
||||
const full_path = path_buf[0..path_len :0];
|
||||
|
||||
// Stat it
|
||||
const f = std.fs.openFileAbsolute(full_path, .{}) catch |err| switch (err) {
|
||||
const f = std.fs.cwd().openFile(
|
||||
full_path,
|
||||
.{},
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => continue,
|
||||
error.AccessDenied => {
|
||||
// Accumulate this and return it later so we can try other
|
||||
|
@ -9,7 +9,7 @@ const Config = @import("../config.zig").Config;
|
||||
pub const Message = union(enum) {
|
||||
/// Represents a write request. Magic number comes from the max size
|
||||
/// we want this union to be.
|
||||
pub const WriteReq = termio.MessageData(u8, 256);
|
||||
pub const WriteReq = termio.MessageData(u8, 255);
|
||||
|
||||
/// Set the title of the surface.
|
||||
/// TODO: we should change this to a "WriteReq" style structure in
|
||||
|
@ -378,7 +378,11 @@ fn doAction(self: *Parser, action: TransitionAction, c: u8) ?Action {
|
||||
self.param_acc *|= 10;
|
||||
}
|
||||
self.param_acc +|= c - '0';
|
||||
self.param_acc_idx += 1;
|
||||
|
||||
// Increment our accumulator index. If we overflow then
|
||||
// we're out of bounds and we exit immediately.
|
||||
self.param_acc_idx, const overflow = @addWithOverflow(self.param_acc_idx, 1);
|
||||
if (overflow > 0) break :param null;
|
||||
|
||||
// The client is expected to perform no action.
|
||||
break :param null;
|
||||
@ -388,6 +392,9 @@ fn doAction(self: *Parser, action: TransitionAction, c: u8) ?Action {
|
||||
break :osc_put null;
|
||||
},
|
||||
.csi_dispatch => csi_dispatch: {
|
||||
// Ignore too many parameters
|
||||
if (self.params_idx >= MAX_PARAMS) break :csi_dispatch null;
|
||||
|
||||
// Finalize parameters if we have one
|
||||
if (self.param_acc_idx > 0) {
|
||||
self.params[self.params_idx] = self.param_acc;
|
||||
@ -904,3 +911,22 @@ test "csi followed by utf8" {
|
||||
try testing.expect(a[2] == null);
|
||||
}
|
||||
}
|
||||
|
||||
test "csi: too many params" {
|
||||
var p = init();
|
||||
_ = p.next(0x1B);
|
||||
_ = p.next('[');
|
||||
for (0..100) |_| {
|
||||
_ = p.next('1');
|
||||
_ = p.next(';');
|
||||
}
|
||||
_ = p.next('1');
|
||||
|
||||
{
|
||||
const a = p.next('C');
|
||||
try testing.expect(p.state == .ground);
|
||||
try testing.expect(a[0] == null);
|
||||
try testing.expect(a[1] == null);
|
||||
try testing.expect(a[2] == null);
|
||||
}
|
||||
}
|
||||
|
@ -969,43 +969,52 @@ pub fn Stream(comptime Handler: type) type {
|
||||
.change_window_title => |title| {
|
||||
if (@hasDecl(T, "changeWindowTitle")) {
|
||||
try self.handler.changeWindowTitle(title);
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.clipboard_contents => |clip| {
|
||||
if (@hasDecl(T, "clipboardContents")) {
|
||||
try self.handler.clipboardContents(clip.kind, clip.data);
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.prompt_start => |v| {
|
||||
if (@hasDecl(T, "promptStart")) switch (v.kind) {
|
||||
.primary, .right => try self.handler.promptStart(v.aid, v.redraw),
|
||||
.continuation => try self.handler.promptContinuation(v.aid),
|
||||
if (@hasDecl(T, "promptStart")) {
|
||||
switch (v.kind) {
|
||||
.primary, .right => try self.handler.promptStart(v.aid, v.redraw),
|
||||
.continuation => try self.handler.promptContinuation(v.aid),
|
||||
}
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.prompt_end => {
|
||||
if (@hasDecl(T, "promptEnd")) {
|
||||
try self.handler.promptEnd();
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.end_of_input => {
|
||||
if (@hasDecl(T, "endOfInput")) {
|
||||
try self.handler.endOfInput();
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.end_of_command => |end| {
|
||||
if (@hasDecl(T, "endOfCommand")) {
|
||||
try self.handler.endOfCommand(end.exit_code);
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.report_pwd => |v| {
|
||||
if (@hasDecl(T, "reportPwd")) {
|
||||
try self.handler.reportPwd(v.value);
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
@ -1017,12 +1026,14 @@ pub fn Stream(comptime Handler: type) type {
|
||||
};
|
||||
|
||||
try self.handler.setMouseShape(shape);
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
.report_default_color => |v| {
|
||||
if (@hasDecl(T, "reportDefaultColor")) {
|
||||
try self.handler.reportDefaultColor(v.kind, v.terminator);
|
||||
return;
|
||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||
},
|
||||
|
||||
@ -1031,6 +1042,13 @@ pub fn Stream(comptime Handler: type) type {
|
||||
else
|
||||
log.warn("unimplemented OSC command: {}", .{cmd}),
|
||||
}
|
||||
|
||||
// Fall through for when we don't have a handler.
|
||||
if (@hasDecl(T, "oscUnimplemented")) {
|
||||
try self.handler.oscUnimplemented(cmd);
|
||||
} else {
|
||||
log.warn("unimplemented OSC command: {s}", .{@tagName(cmd)});
|
||||
}
|
||||
}
|
||||
|
||||
fn configureCharset(
|
||||
@ -1598,3 +1616,28 @@ test "stream: insert characters" {
|
||||
for ("\x1B[?42@") |c| try s.next(c);
|
||||
try testing.expect(!s.handler.called);
|
||||
}
|
||||
|
||||
test "stream: too many csi params" {
|
||||
const H = struct {
|
||||
pub fn setCursorRight(self: *@This(), v: u16) !void {
|
||||
_ = v;
|
||||
_ = self;
|
||||
unreachable;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
try s.nextSlice("\x1B[1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1C");
|
||||
}
|
||||
|
||||
test "stream: csi param too long" {
|
||||
const H = struct {
|
||||
pub fn setCursorRight(self: *@This(), v: u16) !void {
|
||||
_ = v;
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
try s.nextSlice("\x1B[1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111C");
|
||||
}
|
||||
|
@ -90,8 +90,9 @@ pub fn MessageData(comptime Elem: type, comptime small_size: comptime_int) type
|
||||
pub const Small = struct {
|
||||
pub const Max = small_size;
|
||||
pub const Array = [Max]Elem;
|
||||
pub const Len = std.math.IntFittingRange(0, small_size);
|
||||
data: Array = undefined,
|
||||
len: u8 = 0,
|
||||
len: Len = 0,
|
||||
};
|
||||
|
||||
pub const Alloc = struct {
|
||||
@ -182,3 +183,14 @@ test "MessageData init alloc" {
|
||||
try testing.expect(io == .alloc);
|
||||
io.alloc.alloc.free(io.alloc.data);
|
||||
}
|
||||
|
||||
test "MessageData small fits non-u8 sized data" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
const len = 500;
|
||||
const Data = MessageData(u8, len);
|
||||
const input: []const u8 = "X" ** len;
|
||||
const io = try Data.init(alloc, input);
|
||||
try testing.expect(io == .small);
|
||||
}
|
||||
|
Reference in New Issue
Block a user