Zig 0.15: zig build GTK exe
parent
cb295b84a0
commit
d59d754e29
|
|
@ -305,19 +305,19 @@ const DerivedConfig = struct {
|
||||||
|
|
||||||
// Build all of our links
|
// Build all of our links
|
||||||
const links = links: {
|
const links = links: {
|
||||||
var links = std.ArrayList(Link).init(alloc);
|
var links: std.ArrayList(Link) = .empty;
|
||||||
defer links.deinit();
|
defer links.deinit(alloc);
|
||||||
for (config.link.links.items) |link| {
|
for (config.link.links.items) |link| {
|
||||||
var regex = try link.oniRegex();
|
var regex = try link.oniRegex();
|
||||||
errdefer regex.deinit();
|
errdefer regex.deinit();
|
||||||
try links.append(.{
|
try links.append(alloc, .{
|
||||||
.regex = regex,
|
.regex = regex,
|
||||||
.action = link.action,
|
.action = link.action,
|
||||||
.highlight = link.highlight,
|
.highlight = link.highlight,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
break :links try links.toOwnedSlice();
|
break :links try links.toOwnedSlice(alloc);
|
||||||
};
|
};
|
||||||
errdefer {
|
errdefer {
|
||||||
for (links) |*link| link.regex.deinit();
|
for (links) |*link| link.regex.deinit();
|
||||||
|
|
@ -2493,7 +2493,7 @@ fn maybeHandleBinding(
|
||||||
self.keyboard.bindings = null;
|
self.keyboard.bindings = null;
|
||||||
|
|
||||||
// Attempt to perform the action
|
// Attempt to perform the action
|
||||||
log.debug("key event binding flags={} action={}", .{
|
log.debug("key event binding flags={} action={f}", .{
|
||||||
leaf.flags,
|
leaf.flags,
|
||||||
action,
|
action,
|
||||||
});
|
});
|
||||||
|
|
@ -5119,7 +5119,9 @@ fn writeScreenFile(
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
// Screen.dumpString writes byte-by-byte, so buffer it
|
// Screen.dumpString writes byte-by-byte, so buffer it
|
||||||
var buf_writer = std.io.bufferedWriter(file.writer());
|
var buf: [4096]u8 = undefined;
|
||||||
|
var file_writer = file.writer(&buf);
|
||||||
|
var buf_writer = &file_writer.interface;
|
||||||
|
|
||||||
// Write the scrollback contents. This requires a lock.
|
// Write the scrollback contents. This requires a lock.
|
||||||
{
|
{
|
||||||
|
|
@ -5169,7 +5171,7 @@ fn writeScreenFile(
|
||||||
const br = sel.bottomRight(&self.io.terminal.screen);
|
const br = sel.bottomRight(&self.io.terminal.screen);
|
||||||
|
|
||||||
try self.io.terminal.screen.dumpString(
|
try self.io.terminal.screen.dumpString(
|
||||||
buf_writer.writer(),
|
buf_writer,
|
||||||
.{
|
.{
|
||||||
.tl = tl,
|
.tl = tl,
|
||||||
.br = br,
|
.br = br,
|
||||||
|
|
|
||||||
|
|
@ -578,7 +578,7 @@ pub const SetTitle = struct {
|
||||||
value: @This(),
|
value: @This(),
|
||||||
comptime _: []const u8,
|
comptime _: []const u8,
|
||||||
_: std.fmt.FormatOptions,
|
_: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.title });
|
try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.title });
|
||||||
}
|
}
|
||||||
|
|
@ -602,7 +602,7 @@ pub const Pwd = struct {
|
||||||
value: @This(),
|
value: @This(),
|
||||||
comptime _: []const u8,
|
comptime _: []const u8,
|
||||||
_: std.fmt.FormatOptions,
|
_: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.pwd });
|
try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.pwd });
|
||||||
}
|
}
|
||||||
|
|
@ -630,7 +630,7 @@ pub const DesktopNotification = struct {
|
||||||
value: @This(),
|
value: @This(),
|
||||||
comptime _: []const u8,
|
comptime _: []const u8,
|
||||||
_: std.fmt.FormatOptions,
|
_: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
try writer.print("{s}{{ title: {s}, body: {s} }}", .{
|
try writer.print("{s}{{ title: {s}, body: {s} }}", .{
|
||||||
@typeName(@This()),
|
@typeName(@This()),
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ pub fn getRuntimeVersion() std.SemanticVersion {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logVersion() void {
|
pub fn logVersion() void {
|
||||||
log.info("libadwaita version build={} runtime={}", .{
|
log.info("libadwaita version build={f} runtime={f}", .{
|
||||||
comptime_version,
|
comptime_version,
|
||||||
getRuntimeVersion(),
|
getRuntimeVersion(),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ pub fn main() !void {
|
||||||
/// Generate the icon resources. This works by looking up all the icons
|
/// Generate the icon resources. This works by looking up all the icons
|
||||||
/// specified by `icon_sizes` in `images/icons/`. They are asserted to exist
|
/// specified by `icon_sizes` in `images/icons/`. They are asserted to exist
|
||||||
/// by trying to access the file.
|
/// by trying to access the file.
|
||||||
fn genIcons(writer: anytype) !void {
|
fn genIcons(writer: *std.Io.Writer) !void {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\ <gresource prefix="{s}/icons">
|
\\ <gresource prefix="{s}/icons">
|
||||||
\\
|
\\
|
||||||
|
|
@ -208,7 +208,7 @@ fn genIcons(writer: anytype) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate the resources at the root prefix.
|
/// Generate the resources at the root prefix.
|
||||||
fn genRoot(writer: anytype) !void {
|
fn genRoot(writer: *std.Io.Writer) !void {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\ <gresource prefix="{s}">
|
\\ <gresource prefix="{s}">
|
||||||
\\
|
\\
|
||||||
|
|
@ -240,7 +240,7 @@ fn genRoot(writer: anytype) !void {
|
||||||
/// assuming these will be
|
/// assuming these will be
|
||||||
fn genUi(
|
fn genUi(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
files: *const std.ArrayListUnmanaged([]const u8),
|
files: *const std.ArrayListUnmanaged([]const u8),
|
||||||
) !void {
|
) !void {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ pub fn init(
|
||||||
) orelse "";
|
) orelse "";
|
||||||
if (!std.mem.eql(u8, original, current)) break :transient current;
|
if (!std.mem.eql(u8, original, current)) break :transient current;
|
||||||
alloc.free(current);
|
alloc.free(current);
|
||||||
std.time.sleep(25 * std.time.ns_per_ms);
|
std.Thread.sleep(25 * std.time.ns_per_ms);
|
||||||
};
|
};
|
||||||
errdefer alloc.free(transient);
|
errdefer alloc.free(transient);
|
||||||
log.info("transient scope created cgroup={s}", .{transient});
|
log.info("transient scope created cgroup={s}", .{transient});
|
||||||
|
|
@ -101,21 +101,21 @@ fn enableControllers(alloc: Allocator, cgroup: []const u8) !void {
|
||||||
defer alloc.free(raw);
|
defer alloc.free(raw);
|
||||||
|
|
||||||
// Build our string builder for enabling all controllers
|
// Build our string builder for enabling all controllers
|
||||||
var builder = std.ArrayList(u8).init(alloc);
|
var builder: std.Io.Writer.Allocating = .init(alloc);
|
||||||
defer builder.deinit();
|
defer builder.deinit();
|
||||||
|
|
||||||
// Controllers are space-separated
|
// Controllers are space-separated
|
||||||
var it = std.mem.splitScalar(u8, raw, ' ');
|
var it = std.mem.splitScalar(u8, raw, ' ');
|
||||||
while (it.next()) |controller| {
|
while (it.next()) |controller| {
|
||||||
try builder.append('+');
|
try builder.writer.writeByte('+');
|
||||||
try builder.appendSlice(controller);
|
try builder.writer.writeAll(controller);
|
||||||
if (it.rest().len > 0) try builder.append(' ');
|
if (it.rest().len > 0) try builder.writer.writeByte(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable them all
|
// Enable them all
|
||||||
try internal_os.cgroup.configureControllers(
|
try internal_os.cgroup.configureControllers(
|
||||||
cgroup,
|
cgroup,
|
||||||
builder.items,
|
builder.written(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1044,7 +1044,9 @@ pub const Application = extern struct {
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
log.info("loading gtk-custom-css path={s}", .{path});
|
log.info("loading gtk-custom-css path={s}", .{path});
|
||||||
const contents = try file.reader().readAllAlloc(
|
var buf: [4096]u8 = undefined;
|
||||||
|
var reader = file.reader(&buf);
|
||||||
|
const contents = try reader.interface.readAlloc(
|
||||||
alloc,
|
alloc,
|
||||||
5 * 1024 * 1024, // 5MB,
|
5 * 1024 * 1024, // 5MB,
|
||||||
);
|
);
|
||||||
|
|
@ -1115,8 +1117,8 @@ pub const Application = extern struct {
|
||||||
// This should really never, never happen. Its not critical enough
|
// This should really never, never happen. Its not critical enough
|
||||||
// to actually crash, but this is a bug somewhere. An accelerator
|
// to actually crash, but this is a bug somewhere. An accelerator
|
||||||
// for a trigger can't possibly be more than 1024 bytes.
|
// for a trigger can't possibly be more than 1024 bytes.
|
||||||
error.NoSpaceLeft => {
|
error.WriteFailed => {
|
||||||
log.warn("accelerator somehow longer than 1024 bytes: {}", .{trigger});
|
log.warn("accelerator somehow longer than 1024 bytes: {f}", .{trigger});
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -485,10 +485,11 @@ const Command = extern struct {
|
||||||
|
|
||||||
const command = priv.command orelse return null;
|
const command = priv.command orelse return null;
|
||||||
|
|
||||||
priv.action_key = std.fmt.allocPrintZ(
|
priv.action_key = std.fmt.allocPrintSentinel(
|
||||||
priv.arena.allocator(),
|
priv.arena.allocator(),
|
||||||
"{}",
|
"{f}",
|
||||||
.{command.action},
|
.{command.action},
|
||||||
|
0,
|
||||||
) catch null;
|
) catch null;
|
||||||
|
|
||||||
return priv.action_key;
|
return priv.action_key;
|
||||||
|
|
|
||||||
|
|
@ -188,9 +188,9 @@ pub const GlobalShortcuts = extern struct {
|
||||||
// If there isn't space to translate the trigger, then our
|
// If there isn't space to translate the trigger, then our
|
||||||
// buffer might be too small (but 1024 is insane!). In any case
|
// buffer might be too small (but 1024 is insane!). In any case
|
||||||
// we don't want to stop registering globals.
|
// we don't want to stop registering globals.
|
||||||
error.NoSpaceLeft => {
|
error.WriteFailed => {
|
||||||
log.warn(
|
log.warn(
|
||||||
"buffer too small to translate trigger, ignoring={}",
|
"buffer too small to translate trigger, ignoring={f}",
|
||||||
.{entry.key_ptr.*},
|
.{entry.key_ptr.*},
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -257,7 +257,7 @@ pub const GlobalShortcuts = extern struct {
|
||||||
const trigger = entry.key_ptr.*.ptr;
|
const trigger = entry.key_ptr.*.ptr;
|
||||||
const action = std.fmt.bufPrintZ(
|
const action = std.fmt.bufPrintZ(
|
||||||
&action_buf,
|
&action_buf,
|
||||||
"{}",
|
"{f}",
|
||||||
.{entry.value_ptr.*},
|
.{entry.value_ptr.*},
|
||||||
) catch continue;
|
) catch continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ pub const SplitTree = extern struct {
|
||||||
);
|
);
|
||||||
defer new_tree.deinit();
|
defer new_tree.deinit();
|
||||||
log.debug(
|
log.debug(
|
||||||
"new split at={} direction={} old_tree={} new_tree={}",
|
"new split at={} direction={} old_tree={f} new_tree={f}",
|
||||||
.{ handle, direction, old_tree, &new_tree },
|
.{ handle, direction, old_tree, &new_tree },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2117,13 +2117,11 @@ pub const Surface = extern struct {
|
||||||
const alloc = Application.default().allocator();
|
const alloc = Application.default().allocator();
|
||||||
|
|
||||||
if (ext.gValueHolds(value, gdk.FileList.getGObjectType())) {
|
if (ext.gValueHolds(value, gdk.FileList.getGObjectType())) {
|
||||||
var data = std.ArrayList(u8).init(alloc);
|
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||||
defer data.deinit();
|
defer stream.deinit();
|
||||||
|
|
||||||
var shell_escape_writer: internal_os.ShellEscapeWriter(std.ArrayList(u8).Writer) = .{
|
var shell_escape_writer: internal_os.ShellEscapeWriter = .init(&stream.writer);
|
||||||
.child_writer = data.writer(),
|
const writer = &shell_escape_writer.writer;
|
||||||
};
|
|
||||||
const writer = shell_escape_writer.writer();
|
|
||||||
|
|
||||||
const list: ?*glib.SList = list: {
|
const list: ?*glib.SList = list: {
|
||||||
const unboxed = value.getBoxed() orelse return 0;
|
const unboxed = value.getBoxed() orelse return 0;
|
||||||
|
|
@ -2151,7 +2149,7 @@ pub const Surface = extern struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const string = data.toOwnedSliceSentinel(0) catch |err| {
|
const string = stream.toOwnedSliceSentinel(0) catch |err| {
|
||||||
log.err("unable to convert to a slice: {}", .{err});
|
log.err("unable to convert to a slice: {}", .{err});
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
@ -2164,13 +2162,11 @@ pub const Surface = extern struct {
|
||||||
const object = value.getObject() orelse return 0;
|
const object = value.getObject() orelse return 0;
|
||||||
const file = gobject.ext.cast(gio.File, object) orelse return 0;
|
const file = gobject.ext.cast(gio.File, object) orelse return 0;
|
||||||
const path = file.getPath() orelse return 0;
|
const path = file.getPath() orelse return 0;
|
||||||
var data = std.ArrayList(u8).init(alloc);
|
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||||
defer data.deinit();
|
defer stream.deinit();
|
||||||
|
|
||||||
var shell_escape_writer: internal_os.ShellEscapeWriter(std.ArrayList(u8).Writer) = .{
|
var shell_escape_writer: internal_os.ShellEscapeWriter = .init(&stream.writer);
|
||||||
.child_writer = data.writer(),
|
const writer = &shell_escape_writer.writer;
|
||||||
};
|
|
||||||
const writer = shell_escape_writer.writer();
|
|
||||||
writer.writeAll(std.mem.span(path)) catch |err| {
|
writer.writeAll(std.mem.span(path)) catch |err| {
|
||||||
log.err("unable to write path to buffer: {}", .{err});
|
log.err("unable to write path to buffer: {}", .{err});
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2180,7 +2176,7 @@ pub const Surface = extern struct {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const string = data.toOwnedSliceSentinel(0) catch |err| {
|
const string = stream.toOwnedSliceSentinel(0) catch |err| {
|
||||||
log.err("unable to convert to a slice: {}", .{err});
|
log.err("unable to convert to a slice: {}", .{err});
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -405,22 +405,21 @@ pub const Tab = extern struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use an allocator to build up our string as we write it.
|
// Use an allocator to build up our string as we write it.
|
||||||
var buf: std.ArrayList(u8) = .init(Application.default().allocator());
|
var buf: std.Io.Writer.Allocating = .init(Application.default().allocator());
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
const writer = buf.writer();
|
|
||||||
|
|
||||||
// If our bell is ringing, then we prefix the bell icon to the title.
|
// If our bell is ringing, then we prefix the bell icon to the title.
|
||||||
if (bell_ringing and config.@"bell-features".title) {
|
if (bell_ringing and config.@"bell-features".title) {
|
||||||
writer.writeAll("🔔 ") catch {};
|
buf.writer.writeAll("🔔 ") catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're zoomed, prefix with the magnifying glass emoji.
|
// If we're zoomed, prefix with the magnifying glass emoji.
|
||||||
if (zoomed) {
|
if (zoomed) {
|
||||||
writer.writeAll("🔍 ") catch {};
|
buf.writer.writeAll("🔍 ") catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeAll(plain) catch return glib.ext.dupeZ(u8, plain);
|
buf.writer.writeAll(plain) catch return glib.ext.dupeZ(u8, plain);
|
||||||
return glib.ext.dupeZ(u8, buf.items);
|
return glib.ext.dupeZ(u8, buf.written());
|
||||||
}
|
}
|
||||||
|
|
||||||
const C = Common(Self, Private);
|
const C = Common(Self, Private);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub fn getRuntimeVersion() std.SemanticVersion {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logVersion() void {
|
pub fn logVersion() void {
|
||||||
log.info("GTK version build={} runtime={}", .{
|
log.info("GTK version build={f} runtime={f}", .{
|
||||||
comptime_version,
|
comptime_version,
|
||||||
getRuntimeVersion(),
|
getRuntimeVersion(),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,8 @@ const winproto = @import("winproto.zig");
|
||||||
pub fn accelFromTrigger(
|
pub fn accelFromTrigger(
|
||||||
buf: []u8,
|
buf: []u8,
|
||||||
trigger: input.Binding.Trigger,
|
trigger: input.Binding.Trigger,
|
||||||
) error{NoSpaceLeft}!?[:0]const u8 {
|
) error{WriteFailed}!?[:0]const u8 {
|
||||||
var buf_stream = std.io.fixedBufferStream(buf);
|
var writer: std.Io.Writer = .fixed(buf);
|
||||||
const writer = buf_stream.writer();
|
|
||||||
|
|
||||||
// Modifiers
|
// Modifiers
|
||||||
if (trigger.mods.shift) try writer.writeAll("<Shift>");
|
if (trigger.mods.shift) try writer.writeAll("<Shift>");
|
||||||
|
|
@ -23,11 +22,11 @@ pub fn accelFromTrigger(
|
||||||
if (trigger.mods.super) try writer.writeAll("<Super>");
|
if (trigger.mods.super) try writer.writeAll("<Super>");
|
||||||
|
|
||||||
// Write our key
|
// Write our key
|
||||||
if (!try writeTriggerKey(writer, trigger)) return null;
|
if (!try writeTriggerKey(&writer, trigger)) return null;
|
||||||
|
|
||||||
// We need to make the string null terminated.
|
// We need to make the string null terminated.
|
||||||
try writer.writeByte(0);
|
try writer.writeByte(0);
|
||||||
const slice = buf_stream.getWritten();
|
const slice = writer.buffered();
|
||||||
return slice[0 .. slice.len - 1 :0];
|
return slice[0 .. slice.len - 1 :0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,9 +35,8 @@ pub fn accelFromTrigger(
|
||||||
pub fn xdgShortcutFromTrigger(
|
pub fn xdgShortcutFromTrigger(
|
||||||
buf: []u8,
|
buf: []u8,
|
||||||
trigger: input.Binding.Trigger,
|
trigger: input.Binding.Trigger,
|
||||||
) error{NoSpaceLeft}!?[:0]const u8 {
|
) error{WriteFailed}!?[:0]const u8 {
|
||||||
var buf_stream = std.io.fixedBufferStream(buf);
|
var writer: std.Io.Writer = .fixed(buf);
|
||||||
const writer = buf_stream.writer();
|
|
||||||
|
|
||||||
// Modifiers
|
// Modifiers
|
||||||
if (trigger.mods.shift) try writer.writeAll("SHIFT+");
|
if (trigger.mods.shift) try writer.writeAll("SHIFT+");
|
||||||
|
|
@ -52,15 +50,18 @@ pub fn xdgShortcutFromTrigger(
|
||||||
// to *X11's* keysyms (which I assume is a subset of libxkbcommon's).
|
// to *X11's* keysyms (which I assume is a subset of libxkbcommon's).
|
||||||
// I haven't been able to any evidence to back up that assumption but
|
// I haven't been able to any evidence to back up that assumption but
|
||||||
// this works for now
|
// this works for now
|
||||||
if (!try writeTriggerKey(writer, trigger)) return null;
|
if (!try writeTriggerKey(&writer, trigger)) return null;
|
||||||
|
|
||||||
// We need to make the string null terminated.
|
// We need to make the string null terminated.
|
||||||
try writer.writeByte(0);
|
try writer.writeByte(0);
|
||||||
const slice = buf_stream.getWritten();
|
const slice = writer.buffered();
|
||||||
return slice[0 .. slice.len - 1 :0];
|
return slice[0 .. slice.len - 1 :0];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeTriggerKey(writer: anytype, trigger: input.Binding.Trigger) error{NoSpaceLeft}!bool {
|
fn writeTriggerKey(
|
||||||
|
writer: *std.Io.Writer,
|
||||||
|
trigger: input.Binding.Trigger,
|
||||||
|
) error{WriteFailed}!bool {
|
||||||
switch (trigger.key) {
|
switch (trigger.key) {
|
||||||
.physical => |k| {
|
.physical => |k| {
|
||||||
const keyval = keyvalFromKey(k) orelse return false;
|
const keyval = keyvalFromKey(k) orelse return false;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ pub fn init(b: *std.Build, cfg: *const Config, deps: *const SharedDeps) !Ghostty
|
||||||
.omit_frame_pointer = cfg.strip,
|
.omit_frame_pointer = cfg.strip,
|
||||||
.unwind_tables = if (cfg.strip) .none else .sync,
|
.unwind_tables = if (cfg.strip) .none else .sync,
|
||||||
}),
|
}),
|
||||||
|
// Crashes on x86_64 self-hosted on 0.15.1
|
||||||
|
.use_llvm = true,
|
||||||
});
|
});
|
||||||
const install_step = b.addInstallArtifact(exe, .{});
|
const install_step = b.addInstallArtifact(exe, .{});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,15 @@ const std = @import("std");
|
||||||
const gen = @import("mdgen.zig");
|
const gen = @import("mdgen.zig");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||||
const alloc = gpa.allocator();
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
const writer = std.io.getStdOut().writer();
|
var buffer: [1024]u8 = undefined;
|
||||||
|
var stdout_writer = std.fs.File.stdout().writer(&buffer);
|
||||||
|
const writer = &stdout_writer.interface;
|
||||||
try gen.substitute(alloc, @embedFile("ghostty_1_header.md"), writer);
|
try gen.substitute(alloc, @embedFile("ghostty_1_header.md"), writer);
|
||||||
try gen.genActions(writer);
|
try gen.genActions(writer);
|
||||||
try gen.genConfig(writer, true);
|
try gen.genConfig(writer, true);
|
||||||
try gen.substitute(alloc, @embedFile("ghostty_1_footer.md"), writer);
|
try gen.substitute(alloc, @embedFile("ghostty_1_footer.md"), writer);
|
||||||
|
try writer.flush();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,15 @@ const std = @import("std");
|
||||||
const gen = @import("mdgen.zig");
|
const gen = @import("mdgen.zig");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||||
const alloc = gpa.allocator();
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
const output = std.io.getStdOut().writer();
|
var buffer: [1024]u8 = undefined;
|
||||||
try gen.substitute(alloc, @embedFile("ghostty_5_header.md"), output);
|
var stdout_writer = std.fs.File.stdout().writer(&buffer);
|
||||||
try gen.genConfig(output, false);
|
const writer = &stdout_writer.interface;
|
||||||
try gen.genKeybindActions(output);
|
try gen.substitute(alloc, @embedFile("ghostty_5_header.md"), writer);
|
||||||
try gen.substitute(alloc, @embedFile("ghostty_5_footer.md"), output);
|
try gen.genConfig(writer, false);
|
||||||
|
try gen.genKeybindActions(writer);
|
||||||
|
try gen.substitute(alloc, @embedFile("ghostty_5_footer.md"), writer);
|
||||||
|
try writer.flush();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const Config = @import("../../config/Config.zig");
|
||||||
const Action = @import("../../cli/ghostty.zig").Action;
|
const Action = @import("../../cli/ghostty.zig").Action;
|
||||||
const KeybindAction = @import("../../input/Binding.zig").Action;
|
const KeybindAction = @import("../../input/Binding.zig").Action;
|
||||||
|
|
||||||
pub fn substitute(alloc: std.mem.Allocator, input: []const u8, writer: anytype) !void {
|
pub fn substitute(alloc: std.mem.Allocator, input: []const u8, writer: *std.Io.Writer) !void {
|
||||||
const output = try alloc.alloc(u8, std.mem.replacementSize(
|
const output = try alloc.alloc(u8, std.mem.replacementSize(
|
||||||
u8,
|
u8,
|
||||||
input,
|
input,
|
||||||
|
|
@ -18,7 +18,7 @@ pub fn substitute(alloc: std.mem.Allocator, input: []const u8, writer: anytype)
|
||||||
try writer.writeAll(output);
|
try writer.writeAll(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn genConfig(writer: anytype, cli: bool) !void {
|
pub fn genConfig(writer: *std.Io.Writer, cli: bool) !void {
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
\\
|
\\
|
||||||
\\# CONFIGURATION OPTIONS
|
\\# CONFIGURATION OPTIONS
|
||||||
|
|
@ -48,7 +48,7 @@ pub fn genConfig(writer: anytype, cli: bool) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn genActions(writer: anytype) !void {
|
pub fn genActions(writer: *std.Io.Writer) !void {
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
\\
|
\\
|
||||||
\\# COMMAND LINE ACTIONS
|
\\# COMMAND LINE ACTIONS
|
||||||
|
|
@ -83,7 +83,7 @@ pub fn genActions(writer: anytype) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn genKeybindActions(writer: anytype) !void {
|
pub fn genKeybindActions(writer: *std.Io.Writer) !void {
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
\\
|
\\
|
||||||
\\# KEYBIND ACTIONS
|
\\# KEYBIND ACTIONS
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,18 @@ pub const completions = comptimeGenerateBashCompletions();
|
||||||
fn comptimeGenerateBashCompletions() []const u8 {
|
fn comptimeGenerateBashCompletions() []const u8 {
|
||||||
comptime {
|
comptime {
|
||||||
@setEvalBranchQuota(50000);
|
@setEvalBranchQuota(50000);
|
||||||
var counter = std.io.countingWriter(std.io.null_writer);
|
var counter: std.Io.Writer.Discarding = .init(&.{});
|
||||||
try writeBashCompletions(&counter.writer());
|
try writeBashCompletions(&counter.writer);
|
||||||
|
|
||||||
var buf: [counter.bytes_written]u8 = undefined;
|
var buf: [counter.count]u8 = undefined;
|
||||||
var stream = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
try writeBashCompletions(stream.writer());
|
try writeBashCompletions(&writer);
|
||||||
const final = buf;
|
const final = buf;
|
||||||
return final[0..stream.getWritten().len];
|
return final[0..writer.end];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeBashCompletions(writer: anytype) !void {
|
fn writeBashCompletions(writer: *std.Io.Writer) !void {
|
||||||
const pad1 = " ";
|
const pad1 = " ";
|
||||||
const pad2 = pad1 ++ pad1;
|
const pad2 = pad1 ++ pad1;
|
||||||
const pad3 = pad2 ++ pad1;
|
const pad3 = pad2 ++ pad1;
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,18 @@ pub const completions = comptimeGenerateCompletions();
|
||||||
fn comptimeGenerateCompletions() []const u8 {
|
fn comptimeGenerateCompletions() []const u8 {
|
||||||
comptime {
|
comptime {
|
||||||
@setEvalBranchQuota(50000);
|
@setEvalBranchQuota(50000);
|
||||||
var counter = std.io.countingWriter(std.io.null_writer);
|
var counter: std.Io.Writer.Discarding = .init(&.{});
|
||||||
try writeCompletions(&counter.writer());
|
try writeCompletions(&counter.writer);
|
||||||
|
|
||||||
var buf: [counter.bytes_written]u8 = undefined;
|
var buf: [counter.count]u8 = undefined;
|
||||||
var stream = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
try writeCompletions(stream.writer());
|
try writeCompletions(&writer);
|
||||||
const final = buf;
|
const final = buf;
|
||||||
return final[0..stream.getWritten().len];
|
return final[0..writer.end];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeCompletions(writer: anytype) !void {
|
fn writeCompletions(writer: *std.Io.Writer) !void {
|
||||||
{
|
{
|
||||||
try writer.writeAll("set -l commands \"");
|
try writer.writeAll("set -l commands \"");
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ fn comptimeGenSyntax() []const u8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes the syntax file to the given writer.
|
/// Writes the syntax file to the given writer.
|
||||||
fn writeSyntax(writer: anytype) !void {
|
fn writeSyntax(writer: *std.Io.Writer) !void {
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
\\" Vim syntax file
|
\\" Vim syntax file
|
||||||
\\" Language: Ghostty config file
|
\\" Language: Ghostty config file
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,18 @@ const equals_required = "=-:::";
|
||||||
fn comptimeGenerateZshCompletions() []const u8 {
|
fn comptimeGenerateZshCompletions() []const u8 {
|
||||||
comptime {
|
comptime {
|
||||||
@setEvalBranchQuota(50000);
|
@setEvalBranchQuota(50000);
|
||||||
var counter = std.io.countingWriter(std.io.null_writer);
|
var counter: std.Io.Writer.Discarding = .init(&.{});
|
||||||
try writeZshCompletions(&counter.writer());
|
try writeZshCompletions(&counter.writer);
|
||||||
|
|
||||||
var buf: [counter.bytes_written]u8 = undefined;
|
var buf: [counter.count]u8 = undefined;
|
||||||
var stream = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
try writeZshCompletions(stream.writer());
|
try writeZshCompletions(&writer);
|
||||||
const final = buf;
|
const final = buf;
|
||||||
return final[0..stream.getWritten().len];
|
return final[0..writer.end];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeZshCompletions(writer: anytype) !void {
|
fn writeZshCompletions(writer: *std.Io.Writer) !void {
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
\\#compdef ghostty
|
\\#compdef ghostty
|
||||||
\\
|
\\
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ pub fn clear(self: *Atlas) void {
|
||||||
/// swapped because PPM expects RGB. This would be
|
/// swapped because PPM expects RGB. This would be
|
||||||
/// easy enough to fix so next time someone needs
|
/// easy enough to fix so next time someone needs
|
||||||
/// to debug a color atlas they should fix it.
|
/// to debug a color atlas they should fix it.
|
||||||
pub fn dump(self: Atlas, writer: anytype) !void {
|
pub fn dump(self: Atlas, writer: *std.Io.Writer) !void {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\P{c}
|
\\P{c}
|
||||||
\\{d} {d}
|
\\{d} {d}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ fn FixedPoint(comptime T: type, int_bits: u64, frac_bits: u64) type {
|
||||||
self: Self,
|
self: Self,
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
options: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
_ = fmt;
|
_ = fmt;
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|
@ -176,7 +176,7 @@ pub const SFNT = struct {
|
||||||
self: OffsetSubtable,
|
self: OffsetSubtable,
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
options: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
_ = fmt;
|
_ = fmt;
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|
@ -210,7 +210,7 @@ pub const SFNT = struct {
|
||||||
self: TableRecord,
|
self: TableRecord,
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
options: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
_ = fmt;
|
_ = fmt;
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ pub const Feature = struct {
|
||||||
self: Feature,
|
self: Feature,
|
||||||
comptime layout: []const u8,
|
comptime layout: []const u8,
|
||||||
opts: std.fmt.FormatOptions,
|
opts: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
_ = layout;
|
_ = layout;
|
||||||
_ = opts;
|
_ = opts;
|
||||||
|
|
@ -262,7 +262,7 @@ pub const FeatureList = struct {
|
||||||
self: FeatureList,
|
self: FeatureList,
|
||||||
comptime layout: []const u8,
|
comptime layout: []const u8,
|
||||||
opts: std.fmt.FormatOptions,
|
opts: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
for (self.features.items, 0..) |feature, i| {
|
for (self.features.items, 0..) |feature, i| {
|
||||||
try feature.format(layout, opts, writer);
|
try feature.format(layout, opts, writer);
|
||||||
|
|
|
||||||
|
|
@ -600,6 +600,7 @@ fn renderModesWindow(self: *Inspector) void {
|
||||||
|
|
||||||
const t = self.surface.renderer_state.terminal;
|
const t = self.surface.renderer_state.terminal;
|
||||||
inline for (@typeInfo(terminal.Mode).@"enum".fields) |field| {
|
inline for (@typeInfo(terminal.Mode).@"enum".fields) |field| {
|
||||||
|
@setEvalBranchQuota(6000);
|
||||||
const tag: terminal.modes.ModeTag = @bitCast(@as(terminal.modes.ModeTag.Backing, field.value));
|
const tag: terminal.modes.ModeTag = @bitCast(@as(terminal.modes.ModeTag.Backing, field.value));
|
||||||
|
|
||||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ pub const VTEvent = struct {
|
||||||
) !VTEvent {
|
) !VTEvent {
|
||||||
var md = Metadata.init(alloc);
|
var md = Metadata.init(alloc);
|
||||||
errdefer md.deinit();
|
errdefer md.deinit();
|
||||||
var buf = std.ArrayList(u8).init(alloc);
|
var buf: std.Io.Writer.Allocating = .init(alloc);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
try encodeAction(alloc, buf.writer(), &md, action);
|
try encodeAction(alloc, &buf.writer, &md, action);
|
||||||
const str = try buf.toOwnedSliceSentinel(0);
|
const str = try buf.toOwnedSliceSentinel(0);
|
||||||
errdefer alloc.free(str);
|
errdefer alloc.free(str);
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ pub const VTEvent = struct {
|
||||||
/// Encode a parser action as a string that we show in the logs.
|
/// Encode a parser action as a string that we show in the logs.
|
||||||
fn encodeAction(
|
fn encodeAction(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
md: *Metadata,
|
md: *Metadata,
|
||||||
action: terminal.Parser.Action,
|
action: terminal.Parser.Action,
|
||||||
) !void {
|
) !void {
|
||||||
|
|
@ -125,16 +125,16 @@ pub const VTEvent = struct {
|
||||||
.csi_dispatch => |v| try encodeCSI(writer, v),
|
.csi_dispatch => |v| try encodeCSI(writer, v),
|
||||||
.esc_dispatch => |v| try encodeEsc(writer, v),
|
.esc_dispatch => |v| try encodeEsc(writer, v),
|
||||||
.osc_dispatch => |v| try encodeOSC(alloc, writer, md, v),
|
.osc_dispatch => |v| try encodeOSC(alloc, writer, md, v),
|
||||||
else => try writer.print("{}", .{action}),
|
else => try writer.print("{f}", .{action}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encodePrint(writer: anytype, action: terminal.Parser.Action) !void {
|
fn encodePrint(writer: *std.Io.Writer, action: terminal.Parser.Action) !void {
|
||||||
const ch = action.print;
|
const ch = action.print;
|
||||||
try writer.print("'{u}' (U+{X})", .{ ch, ch });
|
try writer.print("'{u}' (U+{X})", .{ ch, ch });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encodeExecute(writer: anytype, action: terminal.Parser.Action) !void {
|
fn encodeExecute(writer: *std.Io.Writer, action: terminal.Parser.Action) !void {
|
||||||
const ch = action.execute;
|
const ch = action.execute;
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
0x00 => try writer.writeAll("NUL"),
|
0x00 => try writer.writeAll("NUL"),
|
||||||
|
|
@ -158,7 +158,7 @@ pub const VTEvent = struct {
|
||||||
try writer.print(" (0x{X})", .{ch});
|
try writer.print(" (0x{X})", .{ch});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encodeCSI(writer: anytype, csi: terminal.Parser.Action.CSI) !void {
|
fn encodeCSI(writer: *std.Io.Writer, csi: terminal.Parser.Action.CSI) !void {
|
||||||
for (csi.intermediates) |v| try writer.print("{c} ", .{v});
|
for (csi.intermediates) |v| try writer.print("{c} ", .{v});
|
||||||
for (csi.params, 0..) |v, i| {
|
for (csi.params, 0..) |v, i| {
|
||||||
if (i != 0) try writer.writeByte(';');
|
if (i != 0) try writer.writeByte(';');
|
||||||
|
|
@ -168,14 +168,14 @@ pub const VTEvent = struct {
|
||||||
try writer.writeByte(csi.final);
|
try writer.writeByte(csi.final);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encodeEsc(writer: anytype, esc: terminal.Parser.Action.ESC) !void {
|
fn encodeEsc(writer: *std.Io.Writer, esc: terminal.Parser.Action.ESC) !void {
|
||||||
for (esc.intermediates) |v| try writer.print("{c} ", .{v});
|
for (esc.intermediates) |v| try writer.print("{c} ", .{v});
|
||||||
try writer.writeByte(esc.final);
|
try writer.writeByte(esc.final);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encodeOSC(
|
fn encodeOSC(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
md: *Metadata,
|
md: *Metadata,
|
||||||
osc: terminal.osc.Command,
|
osc: terminal.osc.Command,
|
||||||
) !void {
|
) !void {
|
||||||
|
|
@ -265,10 +265,10 @@ pub const VTEvent = struct {
|
||||||
const s = if (field.type == void)
|
const s = if (field.type == void)
|
||||||
try alloc.dupeZ(u8, tag_name)
|
try alloc.dupeZ(u8, tag_name)
|
||||||
else
|
else
|
||||||
try std.fmt.allocPrintZ(alloc, "{s}={}", .{
|
try std.fmt.allocPrintSentinel(alloc, "{s}={}", .{
|
||||||
tag_name,
|
tag_name,
|
||||||
@field(value, field.name),
|
@field(value, field.name),
|
||||||
});
|
}, 0);
|
||||||
|
|
||||||
try md.put(key, s);
|
try md.put(key, s);
|
||||||
}
|
}
|
||||||
|
|
@ -283,7 +283,7 @@ pub const VTEvent = struct {
|
||||||
else => switch (Value) {
|
else => switch (Value) {
|
||||||
u8, u16 => try md.put(
|
u8, u16 => try md.put(
|
||||||
key,
|
key,
|
||||||
try std.fmt.allocPrintZ(alloc, "{}", .{value}),
|
try std.fmt.allocPrintSentinel(alloc, "{}", .{value}, 0),
|
||||||
),
|
),
|
||||||
|
|
||||||
[]const u8,
|
[]const u8,
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ pub fn main() !void {
|
||||||
const action = action_ orelse return error.NoAction;
|
const action = action_ orelse return error.NoAction;
|
||||||
|
|
||||||
// Our output always goes to stdout.
|
// Our output always goes to stdout.
|
||||||
const writer = std.io.getStdOut().writer();
|
var buffer: [1024]u8 = undefined;
|
||||||
|
var stdout_writer = std.fs.File.stdout().writer(&buffer);
|
||||||
|
const writer = &stdout_writer.interface;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
.bash => try writer.writeAll(@import("extra/bash.zig").completions),
|
.bash => try writer.writeAll(@import("extra/bash.zig").completions),
|
||||||
.fish => try writer.writeAll(@import("extra/fish.zig").completions),
|
.fish => try writer.writeAll(@import("extra/fish.zig").completions),
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ pub fn main() !MainReturn {
|
||||||
// a global is because the C API needs to be able to access this state;
|
// a global is because the C API needs to be able to access this state;
|
||||||
// no other Zig code should EVER access the global state.
|
// no other Zig code should EVER access the global state.
|
||||||
state.init() catch |err| {
|
state.init() catch |err| {
|
||||||
const stderr = std.io.getStdErr().writer();
|
var buffer: [1024]u8 = undefined;
|
||||||
|
var stderr_writer = std.fs.File.stderr().writer(&buffer);
|
||||||
|
const stderr = &stderr_writer.interface;
|
||||||
defer posix.exit(1);
|
defer posix.exit(1);
|
||||||
const ErrSet = @TypeOf(err) || error{Unknown};
|
const ErrSet = @TypeOf(err) || error{Unknown};
|
||||||
switch (@as(ErrSet, @errorCast(err))) {
|
switch (@as(ErrSet, @errorCast(err))) {
|
||||||
|
|
@ -54,6 +56,7 @@ pub fn main() !MainReturn {
|
||||||
|
|
||||||
else => try stderr.print("invalid CLI invocation err={}\n", .{err}),
|
else => try stderr.print("invalid CLI invocation err={}\n", .{err}),
|
||||||
}
|
}
|
||||||
|
try stderr.flush();
|
||||||
};
|
};
|
||||||
defer state.deinit();
|
defer state.deinit();
|
||||||
const alloc = state.alloc;
|
const alloc = state.alloc;
|
||||||
|
|
@ -154,8 +157,12 @@ fn logFn(
|
||||||
|
|
||||||
.stderr => {
|
.stderr => {
|
||||||
// Always try default to send to stderr
|
// Always try default to send to stderr
|
||||||
const stderr = std.io.getStdErr().writer();
|
var buffer: [1024]u8 = undefined;
|
||||||
nosuspend stderr.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
|
var stderr = std.fs.File.stderr().writer(&buffer);
|
||||||
|
const writer = &stderr.interface;
|
||||||
|
nosuspend writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
|
||||||
|
// TODO: Do we want to use flushless stderr in the future?
|
||||||
|
writer.flush() catch {};
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ pub fn current(alloc: Allocator, pid: std.os.linux.pid_t) !?[]const u8 {
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
// Read it all into memory -- we don't expect this file to ever be that large.
|
// Read it all into memory -- we don't expect this file to ever be that large.
|
||||||
var buf_reader = std.io.bufferedReader(file.reader());
|
var reader_buf: [4096]u8 = undefined;
|
||||||
const contents = try buf_reader.reader().readAllAlloc(
|
var reader = file.reader(&reader_buf);
|
||||||
|
const contents = try reader.interface.readAlloc(
|
||||||
alloc,
|
alloc,
|
||||||
1 * 1024 * 1024, // 1MB
|
1 * 1024 * 1024, // 1MB
|
||||||
);
|
);
|
||||||
|
|
@ -52,7 +53,11 @@ pub fn create(
|
||||||
);
|
);
|
||||||
const file = try std.fs.cwd().openFile(pid_path, .{ .mode = .write_only });
|
const file = try std.fs.cwd().openFile(pid_path, .{ .mode = .write_only });
|
||||||
defer file.close();
|
defer file.close();
|
||||||
try file.writer().print("{}", .{pid});
|
|
||||||
|
var file_buf: [64]u8 = undefined;
|
||||||
|
var writer = file.writer(&file_buf);
|
||||||
|
try writer.interface.print("{}", .{pid});
|
||||||
|
try writer.interface.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,8 +187,9 @@ pub fn controllers(alloc: Allocator, cgroup: []const u8) ![]const u8 {
|
||||||
|
|
||||||
// Read it all into memory -- we don't expect this file to ever
|
// Read it all into memory -- we don't expect this file to ever
|
||||||
// be that large.
|
// be that large.
|
||||||
var buf_reader = std.io.bufferedReader(file.reader());
|
var reader_buf: [4096]u8 = undefined;
|
||||||
const contents = try buf_reader.reader().readAllAlloc(
|
var reader = file.reader(&reader_buf);
|
||||||
|
const contents = try reader.interface.readAlloc(
|
||||||
alloc,
|
alloc,
|
||||||
1 * 1024 * 1024, // 1MB
|
1 * 1024 * 1024, // 1MB
|
||||||
);
|
);
|
||||||
|
|
@ -213,7 +219,10 @@ pub fn configureControllers(
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
try file.writer().writeAll(v);
|
var writer_buf: [4096]u8 = undefined;
|
||||||
|
var writer = file.writer(&writer_buf);
|
||||||
|
try writer.interface.writeAll(v);
|
||||||
|
try writer.interface.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Limit = union(enum) {
|
pub const Limit = union(enum) {
|
||||||
|
|
@ -242,5 +251,8 @@ pub fn configureLimit(cgroup: []const u8, limit: Limit) !void {
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
// Write our limit in bytes
|
// Write our limit in bytes
|
||||||
try file.writer().print("{}", .{size});
|
var writer_buf: [4096]u8 = undefined;
|
||||||
|
var writer = file.writer(&writer_buf);
|
||||||
|
try writer.interface.print("{}", .{size});
|
||||||
|
try writer.interface.flush();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
157
src/os/shell.zig
157
src/os/shell.zig
|
|
@ -1,110 +1,121 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
const Writer = std.Io.Writer;
|
||||||
|
|
||||||
/// Writer that escapes characters that shells treat specially to reduce the
|
/// Writer that escapes characters that shells treat specially to reduce the
|
||||||
/// risk of injection attacks or other such weirdness. Specifically excludes
|
/// risk of injection attacks or other such weirdness. Specifically excludes
|
||||||
/// linefeeds so that they can be used to delineate lists of file paths.
|
/// linefeeds so that they can be used to delineate lists of file paths.
|
||||||
///
|
///
|
||||||
/// T should be a Zig type that follows the `std.io.Writer` interface.
|
/// T should be a Zig type that follows the `std.Io.Writer` interface.
|
||||||
pub fn ShellEscapeWriter(comptime T: type) type {
|
pub const ShellEscapeWriter = struct {
|
||||||
return struct {
|
writer: Writer,
|
||||||
child_writer: T,
|
child: *Writer,
|
||||||
|
|
||||||
fn write(self: *ShellEscapeWriter(T), data: []const u8) error{Error}!usize {
|
pub fn init(child: *Writer) ShellEscapeWriter {
|
||||||
var count: usize = 0;
|
return .{
|
||||||
for (data) |byte| {
|
.writer = .{
|
||||||
const buf = switch (byte) {
|
// TODO: Actually use a buffer here
|
||||||
'\\',
|
.buffer = &.{},
|
||||||
'"',
|
.vtable = &.{ .drain = ShellEscapeWriter.drain },
|
||||||
'\'',
|
},
|
||||||
'$',
|
.child = child,
|
||||||
'`',
|
};
|
||||||
'*',
|
}
|
||||||
'?',
|
|
||||||
' ',
|
fn drain(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
|
||||||
'|',
|
const self: *ShellEscapeWriter = @fieldParentPtr("writer", w);
|
||||||
'(',
|
|
||||||
')',
|
// TODO: This is a very naive implementation and does not really make
|
||||||
=> &[_]u8{ '\\', byte },
|
// full use of the post-Writergate API. However, since we know that
|
||||||
else => &[_]u8{byte},
|
// this is going into an Allocating writer anyways, we can be a bit
|
||||||
};
|
// less strict here.
|
||||||
self.child_writer.writeAll(buf) catch return error.Error;
|
|
||||||
count += 1;
|
var count: usize = 0;
|
||||||
}
|
for (data[0 .. data.len - 1]) |chunk| try self.writeEscaped(chunk, &count);
|
||||||
return count;
|
|
||||||
|
for (0..splat) |_| try self.writeEscaped(data[data.len], &count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writeEscaped(
|
||||||
|
self: *ShellEscapeWriter,
|
||||||
|
s: []const u8,
|
||||||
|
count: *usize,
|
||||||
|
) Writer.Error!void {
|
||||||
|
for (s) |byte| {
|
||||||
|
const buf = switch (byte) {
|
||||||
|
'\\',
|
||||||
|
'"',
|
||||||
|
'\'',
|
||||||
|
'$',
|
||||||
|
'`',
|
||||||
|
'*',
|
||||||
|
'?',
|
||||||
|
' ',
|
||||||
|
'|',
|
||||||
|
'(',
|
||||||
|
')',
|
||||||
|
=> &[_]u8{ '\\', byte },
|
||||||
|
else => &[_]u8{byte},
|
||||||
|
};
|
||||||
|
try self.child.writeAll(buf);
|
||||||
|
count.* += 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const Writer = std.io.Writer(*ShellEscapeWriter(T), error{Error}, write);
|
};
|
||||||
|
|
||||||
pub fn init(child_writer: T) ShellEscapeWriter(T) {
|
|
||||||
return .{ .child_writer = child_writer };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writer(self: *ShellEscapeWriter(T)) Writer {
|
|
||||||
return .{ .context = self };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
test "shell escape 1" {
|
test "shell escape 1" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("abc");
|
||||||
try writer.writeAll("abc");
|
try testing.expectEqualStrings("abc", writer.buffered());
|
||||||
try testing.expectEqualStrings("abc", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "shell escape 2" {
|
test "shell escape 2" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("a c");
|
||||||
try writer.writeAll("a c");
|
try testing.expectEqualStrings("a\\ c", writer.buffered());
|
||||||
try testing.expectEqualStrings("a\\ c", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "shell escape 3" {
|
test "shell escape 3" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("a?c");
|
||||||
try writer.writeAll("a?c");
|
try testing.expectEqualStrings("a\\?c", writer.buffered());
|
||||||
try testing.expectEqualStrings("a\\?c", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "shell escape 4" {
|
test "shell escape 4" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("a\\c");
|
||||||
try writer.writeAll("a\\c");
|
try testing.expectEqualStrings("a\\\\c", writer.buffered());
|
||||||
try testing.expectEqualStrings("a\\\\c", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "shell escape 5" {
|
test "shell escape 5" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("a|c");
|
||||||
try writer.writeAll("a|c");
|
try testing.expectEqualStrings("a\\|c", writer.buffered());
|
||||||
try testing.expectEqualStrings("a\\|c", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "shell escape 6" {
|
test "shell escape 6" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("a\"c");
|
||||||
try writer.writeAll("a\"c");
|
try testing.expectEqualStrings("a\\\"c", writer.buffered());
|
||||||
try testing.expectEqualStrings("a\\\"c", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "shell escape 7" {
|
test "shell escape 7" {
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
var fmt = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||||
const writer = shell.writer();
|
try shell.writer.writeAll("a(1)");
|
||||||
try writer.writeAll("a(1)");
|
try testing.expectEqualStrings("a\\(1\\)", writer.buffered());
|
||||||
try testing.expectEqualStrings("a\\(1\\)", fmt.getWritten());
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ const PosixPty = struct {
|
||||||
// Reset our signals
|
// Reset our signals
|
||||||
var sa: posix.Sigaction = .{
|
var sa: posix.Sigaction = .{
|
||||||
.handler = .{ .handler = posix.SIG.DFL },
|
.handler = .{ .handler = posix.SIG.DFL },
|
||||||
.mask = posix.empty_sigset,
|
.mask = posix.sigemptyset(),
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
posix.sigaction(posix.SIG.ABRT, &sa, null);
|
posix.sigaction(posix.SIG.ABRT, &sa, null);
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ pub fn loadFromFiles(
|
||||||
paths: configpkg.RepeatablePath,
|
paths: configpkg.RepeatablePath,
|
||||||
target: Target,
|
target: Target,
|
||||||
) ![]const [:0]const u8 {
|
) ![]const [:0]const u8 {
|
||||||
var list = std.ArrayList([:0]const u8).init(alloc_gpa);
|
var list: std.ArrayList([:0]const u8) = .empty;
|
||||||
defer list.deinit();
|
defer list.deinit(alloc_gpa);
|
||||||
errdefer for (list.items) |shader| alloc_gpa.free(shader);
|
errdefer for (list.items) |shader| alloc_gpa.free(shader);
|
||||||
|
|
||||||
for (paths.value.items) |item| {
|
for (paths.value.items) |item| {
|
||||||
|
|
@ -56,10 +56,10 @@ pub fn loadFromFiles(
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
log.info("loaded custom shader path={s}", .{path});
|
log.info("loaded custom shader path={s}", .{path});
|
||||||
try list.append(shader);
|
try list.append(alloc_gpa, shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
return try list.toOwnedSlice();
|
return try list.toOwnedSlice(alloc_gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load a single shader from a file and convert it to the target language
|
/// Load a single shader from a file and convert it to the target language
|
||||||
|
|
@ -73,34 +73,35 @@ pub fn loadFromFile(
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
const alloc = arena.allocator();
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
// Load the shader file
|
|
||||||
const cwd = std.fs.cwd();
|
|
||||||
const file = try cwd.openFile(path, .{});
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
// Read it all into memory -- we don't expect shaders to be large.
|
// Read it all into memory -- we don't expect shaders to be large.
|
||||||
var buf_reader = std.io.bufferedReader(file.reader());
|
const src = src: {
|
||||||
const src = try buf_reader.reader().readAllAlloc(
|
// Load the shader file
|
||||||
alloc,
|
const cwd = std.fs.cwd();
|
||||||
4 * 1024 * 1024, // 4MB
|
const file = try cwd.openFile(path, .{});
|
||||||
);
|
defer file.close();
|
||||||
|
|
||||||
|
var buf: [4096]u8 = undefined;
|
||||||
|
var reader = file.reader(&buf);
|
||||||
|
break :src try reader.interface.readAlloc(
|
||||||
|
alloc,
|
||||||
|
4 * 1024 * 1024, // 4MB
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// Convert to full GLSL
|
// Convert to full GLSL
|
||||||
const glsl: [:0]const u8 = glsl: {
|
const glsl: [:0]const u8 = glsl: {
|
||||||
var list = std.ArrayList(u8).init(alloc);
|
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||||
try glslFromShader(list.writer(), src);
|
try glslFromShader(&stream.writer, src);
|
||||||
try list.append(0);
|
try stream.writer.writeByte(0);
|
||||||
break :glsl list.items[0 .. list.items.len - 1 :0];
|
break :glsl stream.written()[0 .. stream.written().len - 1 :0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert to SPIR-V
|
// Convert to SPIR-V
|
||||||
const spirv: []const u8 = spirv: {
|
const spirv: []const u8 = spirv: {
|
||||||
// SpirV pointer must be aligned to 4 bytes since we expect
|
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||||
// a slice of words.
|
|
||||||
var list = std.ArrayListAligned(u8, @alignOf(u32)).init(alloc);
|
|
||||||
var errlog: SpirvLog = .{ .alloc = alloc };
|
var errlog: SpirvLog = .{ .alloc = alloc };
|
||||||
defer errlog.deinit();
|
defer errlog.deinit();
|
||||||
spirvFromGlsl(list.writer(), &errlog, glsl) catch |err| {
|
spirvFromGlsl(&stream.writer, &errlog, glsl) catch |err| {
|
||||||
if (errlog.info.len > 0 or errlog.debug.len > 0) {
|
if (errlog.info.len > 0 or errlog.debug.len > 0) {
|
||||||
log.warn("spirv error path={s} info={s} debug={s}", .{
|
log.warn("spirv error path={s} info={s} debug={s}", .{
|
||||||
path,
|
path,
|
||||||
|
|
@ -111,6 +112,11 @@ pub fn loadFromFile(
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SpirV pointer must be aligned to 4 bytes since we expect
|
||||||
|
// a slice of words.
|
||||||
|
var list: std.ArrayListAligned(u8, .of(u32)) = .empty;
|
||||||
|
try list.appendSlice(alloc, stream.written());
|
||||||
break :spirv list.items;
|
break :spirv list.items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pub fn destroy(self: *Ascii, alloc: Allocator) void {
|
||||||
alloc.destroy(self);
|
alloc.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self: *Ascii, writer: anytype, rand: std.Random) !void {
|
pub fn run(self: *Ascii, writer: *std.Io.Writer, rand: std.Random) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
|
|
||||||
var gen: synthetic.Bytes = .{
|
var gen: synthetic.Bytes = .{
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ pub fn destroy(self: *Osc, alloc: Allocator) void {
|
||||||
alloc.destroy(self);
|
alloc.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self: *Osc, writer: anytype, rand: std.Random) !void {
|
pub fn run(self: *Osc, writer: *std.Io.Writer, rand: std.Random) !void {
|
||||||
var gen: synthetic.Osc = .{
|
var gen: synthetic.Osc = .{
|
||||||
.rand = rand,
|
.rand = rand,
|
||||||
.p_valid = self.opts.@"p-valid",
|
.p_valid = self.opts.@"p-valid",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pub fn destroy(self: *Utf8, alloc: Allocator) void {
|
||||||
alloc.destroy(self);
|
alloc.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self: *Utf8, writer: anytype, rand: std.Random) !void {
|
pub fn run(self: *Utf8, writer: *std.Io.Writer, rand: std.Random) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
|
|
||||||
var gen: synthetic.Utf8 = .{
|
var gen: synthetic.Utf8 = .{
|
||||||
|
|
|
||||||
|
|
@ -2723,7 +2723,7 @@ pub fn encodeUtf8(
|
||||||
/// 1 | etc.| | 4
|
/// 1 | etc.| | 4
|
||||||
/// +-----+ :
|
/// +-----+ :
|
||||||
/// +--------+
|
/// +--------+
|
||||||
pub fn diagram(self: *const PageList, writer: anytype) !void {
|
pub fn diagram(self: *const PageList, writer: *std.Io.Writer) !void {
|
||||||
const active_pin = self.getTopLeft(.active);
|
const active_pin = self.getTopLeft(.active);
|
||||||
|
|
||||||
var active = false;
|
var active = false;
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,11 @@ pub fn deinit(self: *Terminal, alloc: Allocator) void {
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The general allocator we should use for this terminal.
|
||||||
|
fn gpa(self: *Terminal) Allocator {
|
||||||
|
return self.screen.alloc;
|
||||||
|
}
|
||||||
|
|
||||||
/// Print UTF-8 encoded string to the terminal.
|
/// Print UTF-8 encoded string to the terminal.
|
||||||
pub fn printString(self: *Terminal, str: []const u8) !void {
|
pub fn printString(self: *Terminal, str: []const u8) !void {
|
||||||
const view = try std.unicode.Utf8View.init(str);
|
const view = try std.unicode.Utf8View.init(str);
|
||||||
|
|
@ -2531,7 +2536,7 @@ pub fn resize(
|
||||||
/// Set the pwd for the terminal.
|
/// Set the pwd for the terminal.
|
||||||
pub fn setPwd(self: *Terminal, pwd: []const u8) !void {
|
pub fn setPwd(self: *Terminal, pwd: []const u8) !void {
|
||||||
self.pwd.clearRetainingCapacity();
|
self.pwd.clearRetainingCapacity();
|
||||||
try self.pwd.appendSlice(pwd);
|
try self.pwd.appendSlice(self.gpa(), pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the pwd for the terminal, if any. The memory is owned by the
|
/// Returns the pwd for the terminal, if any. The memory is owned by the
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ pub const Response = struct {
|
||||||
placement_id: u32 = 0,
|
placement_id: u32 = 0,
|
||||||
message: []const u8 = "OK",
|
message: []const u8 = "OK",
|
||||||
|
|
||||||
pub fn encode(self: Response, writer: anytype) !void {
|
pub fn encode(self: Response, writer: *std.Io.Writer) !void {
|
||||||
// We only encode a result if we have either an id or an image number.
|
// We only encode a result if we have either an id or an image number.
|
||||||
if (self.id == 0 and self.image_number == 0) return;
|
if (self.id == 0 and self.image_number == 0) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ pub const Terminator = enum {
|
||||||
self: Terminator,
|
self: Terminator,
|
||||||
comptime _: []const u8,
|
comptime _: []const u8,
|
||||||
_: std.fmt.FormatOptions,
|
_: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
try writer.writeAll(self.string());
|
try writer.writeAll(self.string());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ pub const Style = struct {
|
||||||
self: Color,
|
self: Color,
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
options: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
_ = fmt;
|
_ = fmt;
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|
@ -228,7 +228,7 @@ pub const Style = struct {
|
||||||
self: Style,
|
self: Style,
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
options: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
_ = fmt;
|
_ = fmt;
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ pub const Capability = struct {
|
||||||
/// Encode as a terminfo source file. The encoding is always done in a
|
/// Encode as a terminfo source file. The encoding is always done in a
|
||||||
/// human-readable format with whitespace. Fields are always written in the
|
/// human-readable format with whitespace. Fields are always written in the
|
||||||
/// order of the slices on this struct; this will not do any reordering.
|
/// order of the slices on this struct; this will not do any reordering.
|
||||||
pub fn encode(self: Source, writer: anytype) !void {
|
pub fn encode(self: Source, writer: *std.Io.Writer) !void {
|
||||||
// Encode the names in the order specified
|
// Encode the names in the order specified
|
||||||
for (self.names, 0..) |name, i| {
|
for (self.names, 0..) |name, i| {
|
||||||
if (i != 0) try writer.writeAll("|");
|
if (i != 0) try writer.writeAll("|");
|
||||||
|
|
|
||||||
|
|
@ -591,6 +591,17 @@ const Subprocess = struct {
|
||||||
flatpak_command: ?FlatpakHostCommand = null,
|
flatpak_command: ?FlatpakHostCommand = null,
|
||||||
linux_cgroup: Command.LinuxCgroup = Command.linux_cgroup_default,
|
linux_cgroup: Command.LinuxCgroup = Command.linux_cgroup_default,
|
||||||
|
|
||||||
|
const ArgsFormatter = struct {
|
||||||
|
args: []const [:0]const u8,
|
||||||
|
|
||||||
|
pub fn format(this: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
|
for (this.args, 0..) |a, i| {
|
||||||
|
if (i > 0) try writer.writeAll(", ");
|
||||||
|
try writer.print("`{s}`", .{a});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Initialize the subprocess. This will NOT start it, this only sets
|
/// Initialize the subprocess. This will NOT start it, this only sets
|
||||||
/// up the internal state necessary to start it later.
|
/// up the internal state necessary to start it later.
|
||||||
pub fn init(gpa: Allocator, cfg: Config) !Subprocess {
|
pub fn init(gpa: Allocator, cfg: Config) !Subprocess {
|
||||||
|
|
@ -897,7 +908,7 @@ const Subprocess = struct {
|
||||||
self.pty = null;
|
self.pty = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
log.debug("starting command command={s}", .{self.args});
|
log.debug("starting command command={f}", .{ArgsFormatter{ .args = self.args }});
|
||||||
|
|
||||||
// If we can't access the cwd, then don't set any cwd and inherit.
|
// If we can't access the cwd, then don't set any cwd and inherit.
|
||||||
// This is important because our cwd can be set by the shell (OSC 7)
|
// This is important because our cwd can be set by the shell (OSC 7)
|
||||||
|
|
@ -1157,7 +1168,7 @@ const Subprocess = struct {
|
||||||
const res = posix.waitpid(pid, std.c.W.NOHANG);
|
const res = posix.waitpid(pid, std.c.W.NOHANG);
|
||||||
log.debug("waitpid result={}", .{res.pid});
|
log.debug("waitpid result={}", .{res.pid});
|
||||||
if (res.pid != 0) break;
|
if (res.pid != 0) break;
|
||||||
std.time.sleep(10 * std.time.ns_per_ms);
|
std.Thread.sleep(10 * std.time.ns_per_ms);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1180,7 +1191,7 @@ const Subprocess = struct {
|
||||||
const pgid = c.getpgid(pid);
|
const pgid = c.getpgid(pid);
|
||||||
if (pgid == my_pgid) {
|
if (pgid == my_pgid) {
|
||||||
log.warn("pgid is our own, retrying", .{});
|
log.warn("pgid is our own, retrying", .{});
|
||||||
std.time.sleep(10 * std.time.ns_per_ms);
|
std.Thread.sleep(10 * std.time.ns_per_ms);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -310,11 +310,11 @@ pub const StreamHandler = struct {
|
||||||
.kitty => |*kitty_cmd| {
|
.kitty => |*kitty_cmd| {
|
||||||
if (self.terminal.kittyGraphics(self.alloc, kitty_cmd)) |resp| {
|
if (self.terminal.kittyGraphics(self.alloc, kitty_cmd)) |resp| {
|
||||||
var buf: [1024]u8 = undefined;
|
var buf: [1024]u8 = undefined;
|
||||||
var buf_stream = std.io.fixedBufferStream(&buf);
|
var writer: std.Io.Writer = .fixed(&buf);
|
||||||
try resp.encode(buf_stream.writer());
|
try resp.encode(&writer);
|
||||||
const final = buf_stream.getWritten();
|
const final = writer.buffered();
|
||||||
if (final.len > 2) {
|
if (final.len > 2) {
|
||||||
log.debug("kitty graphics response: {s}", .{std.fmt.fmtSliceHexLower(final)});
|
log.debug("kitty graphics response: {x}", .{final});
|
||||||
self.messageWriter(try termio.Message.writeReq(self.alloc, final));
|
self.messageWriter(try termio.Message.writeReq(self.alloc, final));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1141,7 +1141,7 @@ pub const StreamHandler = struct {
|
||||||
|
|
||||||
// We need to unescape the path. We first try to unescape onto
|
// We need to unescape the path. We first try to unescape onto
|
||||||
// the stack and fall back to heap allocation if we have to.
|
// the stack and fall back to heap allocation if we have to.
|
||||||
var pathBuf: [1024]u8 = undefined;
|
var path_buf: [1024]u8 = undefined;
|
||||||
const path, const heap = path: {
|
const path, const heap = path: {
|
||||||
// Get the raw string of the URI. Its unclear to me if the various
|
// Get the raw string of the URI. Its unclear to me if the various
|
||||||
// tags of this enum guarantee no percent-encoding so we just
|
// tags of this enum guarantee no percent-encoding so we just
|
||||||
|
|
@ -1156,15 +1156,16 @@ pub const StreamHandler = struct {
|
||||||
break :path .{ path, false };
|
break :path .{ path, false };
|
||||||
|
|
||||||
// First try to stack-allocate
|
// First try to stack-allocate
|
||||||
var fba = std.heap.FixedBufferAllocator.init(&pathBuf);
|
var stack_writer: std.Io.Writer = .fixed(&path_buf);
|
||||||
if (std.fmt.allocPrint(fba.allocator(), "{raw}", .{uri.path})) |v|
|
if (uri.path.formatRaw(&stack_writer)) |_| {
|
||||||
break :path .{ v, false }
|
break :path .{ stack_writer.buffered(), false };
|
||||||
else |_| {}
|
} else |_| {}
|
||||||
|
|
||||||
// Fall back to heap
|
// Fall back to heap
|
||||||
if (std.fmt.allocPrint(self.alloc, "{raw}", .{uri.path})) |v|
|
var alloc_writer: std.Io.Writer.Allocating = .init(self.alloc);
|
||||||
break :path .{ v, true }
|
if (uri.path.formatRaw(&alloc_writer.writer)) |_| {
|
||||||
else |_| {}
|
break :path .{ alloc_writer.written(), true };
|
||||||
|
} else |_| {}
|
||||||
|
|
||||||
// Fall back to using it directly...
|
// Fall back to using it directly...
|
||||||
log.warn("failed to unescape OSC 7 path, using it directly path={s}", .{path});
|
log.warn("failed to unescape OSC 7 path, using it directly path={s}", .{path});
|
||||||
|
|
@ -1471,15 +1472,15 @@ pub const StreamHandler = struct {
|
||||||
self: *StreamHandler,
|
self: *StreamHandler,
|
||||||
request: terminal.kitty.color.OSC,
|
request: terminal.kitty.color.OSC,
|
||||||
) !void {
|
) !void {
|
||||||
var buf = std.ArrayList(u8).init(self.alloc);
|
var stream: std.Io.Writer.Allocating = .init(self.alloc);
|
||||||
defer buf.deinit();
|
defer stream.deinit();
|
||||||
const writer = buf.writer();
|
const writer = &stream.writer;
|
||||||
|
|
||||||
for (request.list.items) |item| {
|
for (request.list.items) |item| {
|
||||||
switch (item) {
|
switch (item) {
|
||||||
.query => |key| {
|
.query => |key| {
|
||||||
// If the writer buffer is empty, we need to write our prefix
|
// If the writer buffer is empty, we need to write our prefix
|
||||||
if (buf.items.len == 0) try writer.writeAll("\x1b]21");
|
if (stream.written().len == 0) try writer.writeAll("\x1b]21");
|
||||||
|
|
||||||
const color: terminal.color.RGB = switch (key) {
|
const color: terminal.color.RGB = switch (key) {
|
||||||
.palette => |palette| self.terminal.color_palette.colors[palette],
|
.palette => |palette| self.terminal.color_palette.colors[palette],
|
||||||
|
|
@ -1488,17 +1489,17 @@ pub const StreamHandler = struct {
|
||||||
.background => self.background_color orelse self.default_background_color,
|
.background => self.background_color orelse self.default_background_color,
|
||||||
.cursor => self.cursor_color orelse self.default_cursor_color,
|
.cursor => self.cursor_color orelse self.default_cursor_color,
|
||||||
else => {
|
else => {
|
||||||
log.warn("ignoring unsupported kitty color protocol key: {}", .{key});
|
log.warn("ignoring unsupported kitty color protocol key: {f}", .{key});
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} orelse {
|
} orelse {
|
||||||
try writer.print(";{}=", .{key});
|
try writer.print(";{f}=", .{key});
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
try writer.print(
|
try writer.print(
|
||||||
";{}=rgb:{x:0>2}/{x:0>2}/{x:0>2}",
|
";{f}=rgb:{x:0>2}/{x:0>2}/{x:0>2}",
|
||||||
.{ key, color.r, color.g, color.b },
|
.{ key, color.r, color.g, color.b },
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -1525,7 +1526,7 @@ pub const StreamHandler = struct {
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
log.warn(
|
log.warn(
|
||||||
"ignoring unsupported kitty color protocol key: {}",
|
"ignoring unsupported kitty color protocol key: {f}",
|
||||||
.{v.key},
|
.{v.key},
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1560,7 +1561,7 @@ pub const StreamHandler = struct {
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
log.warn(
|
log.warn(
|
||||||
"ignoring unsupported kitty color protocol key: {}",
|
"ignoring unsupported kitty color protocol key: {f}",
|
||||||
.{key},
|
.{key},
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1576,12 +1577,12 @@ pub const StreamHandler = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we had any writes to our buffer, we queue them now
|
// If we had any writes to our buffer, we queue them now
|
||||||
if (buf.items.len > 0) {
|
if (stream.written().len > 0) {
|
||||||
try writer.writeAll(request.terminator.string());
|
try writer.writeAll(request.terminator.string());
|
||||||
self.messageWriter(.{
|
self.messageWriter(.{
|
||||||
.write_alloc = .{
|
.write_alloc = .{
|
||||||
.alloc = self.alloc,
|
.alloc = self.alloc,
|
||||||
.data = try buf.toOwnedSlice(),
|
.data = try stream.toOwnedSlice(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue