Zig 0.15: zig build GTK exe
parent
cb295b84a0
commit
d59d754e29
|
|
@ -305,19 +305,19 @@ const DerivedConfig = struct {
|
|||
|
||||
// Build all of our links
|
||||
const links = links: {
|
||||
var links = std.ArrayList(Link).init(alloc);
|
||||
defer links.deinit();
|
||||
var links: std.ArrayList(Link) = .empty;
|
||||
defer links.deinit(alloc);
|
||||
for (config.link.links.items) |link| {
|
||||
var regex = try link.oniRegex();
|
||||
errdefer regex.deinit();
|
||||
try links.append(.{
|
||||
try links.append(alloc, .{
|
||||
.regex = regex,
|
||||
.action = link.action,
|
||||
.highlight = link.highlight,
|
||||
});
|
||||
}
|
||||
|
||||
break :links try links.toOwnedSlice();
|
||||
break :links try links.toOwnedSlice(alloc);
|
||||
};
|
||||
errdefer {
|
||||
for (links) |*link| link.regex.deinit();
|
||||
|
|
@ -2493,7 +2493,7 @@ fn maybeHandleBinding(
|
|||
self.keyboard.bindings = null;
|
||||
|
||||
// Attempt to perform the action
|
||||
log.debug("key event binding flags={} action={}", .{
|
||||
log.debug("key event binding flags={} action={f}", .{
|
||||
leaf.flags,
|
||||
action,
|
||||
});
|
||||
|
|
@ -5119,7 +5119,9 @@ fn writeScreenFile(
|
|||
defer file.close();
|
||||
|
||||
// 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.
|
||||
{
|
||||
|
|
@ -5169,7 +5171,7 @@ fn writeScreenFile(
|
|||
const br = sel.bottomRight(&self.io.terminal.screen);
|
||||
|
||||
try self.io.terminal.screen.dumpString(
|
||||
buf_writer.writer(),
|
||||
buf_writer,
|
||||
.{
|
||||
.tl = tl,
|
||||
.br = br,
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ pub const SetTitle = struct {
|
|||
value: @This(),
|
||||
comptime _: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.title });
|
||||
}
|
||||
|
|
@ -602,7 +602,7 @@ pub const Pwd = struct {
|
|||
value: @This(),
|
||||
comptime _: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.pwd });
|
||||
}
|
||||
|
|
@ -630,7 +630,7 @@ pub const DesktopNotification = struct {
|
|||
value: @This(),
|
||||
comptime _: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
try writer.print("{s}{{ title: {s}, body: {s} }}", .{
|
||||
@typeName(@This()),
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub fn getRuntimeVersion() std.SemanticVersion {
|
|||
}
|
||||
|
||||
pub fn logVersion() void {
|
||||
log.info("libadwaita version build={} runtime={}", .{
|
||||
log.info("libadwaita version build={f} runtime={f}", .{
|
||||
comptime_version,
|
||||
getRuntimeVersion(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ pub fn main() !void {
|
|||
/// Generate the icon resources. This works by looking up all the icons
|
||||
/// specified by `icon_sizes` in `images/icons/`. They are asserted to exist
|
||||
/// by trying to access the file.
|
||||
fn genIcons(writer: anytype) !void {
|
||||
fn genIcons(writer: *std.Io.Writer) !void {
|
||||
try writer.print(
|
||||
\\ <gresource prefix="{s}/icons">
|
||||
\\
|
||||
|
|
@ -208,7 +208,7 @@ fn genIcons(writer: anytype) !void {
|
|||
}
|
||||
|
||||
/// Generate the resources at the root prefix.
|
||||
fn genRoot(writer: anytype) !void {
|
||||
fn genRoot(writer: *std.Io.Writer) !void {
|
||||
try writer.print(
|
||||
\\ <gresource prefix="{s}">
|
||||
\\
|
||||
|
|
@ -240,7 +240,7 @@ fn genRoot(writer: anytype) !void {
|
|||
/// assuming these will be
|
||||
fn genUi(
|
||||
alloc: Allocator,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
files: *const std.ArrayListUnmanaged([]const u8),
|
||||
) !void {
|
||||
try writer.print(
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ pub fn init(
|
|||
) orelse "";
|
||||
if (!std.mem.eql(u8, original, current)) break :transient 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);
|
||||
log.info("transient scope created cgroup={s}", .{transient});
|
||||
|
|
@ -101,21 +101,21 @@ fn enableControllers(alloc: Allocator, cgroup: []const u8) !void {
|
|||
defer alloc.free(raw);
|
||||
|
||||
// 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();
|
||||
|
||||
// Controllers are space-separated
|
||||
var it = std.mem.splitScalar(u8, raw, ' ');
|
||||
while (it.next()) |controller| {
|
||||
try builder.append('+');
|
||||
try builder.appendSlice(controller);
|
||||
if (it.rest().len > 0) try builder.append(' ');
|
||||
try builder.writer.writeByte('+');
|
||||
try builder.writer.writeAll(controller);
|
||||
if (it.rest().len > 0) try builder.writer.writeByte(' ');
|
||||
}
|
||||
|
||||
// Enable them all
|
||||
try internal_os.cgroup.configureControllers(
|
||||
cgroup,
|
||||
builder.items,
|
||||
builder.written(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1044,7 +1044,9 @@ pub const Application = extern struct {
|
|||
defer file.close();
|
||||
|
||||
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,
|
||||
5 * 1024 * 1024, // 5MB,
|
||||
);
|
||||
|
|
@ -1115,8 +1117,8 @@ pub const Application = extern struct {
|
|||
// This should really never, never happen. Its not critical enough
|
||||
// to actually crash, but this is a bug somewhere. An accelerator
|
||||
// for a trigger can't possibly be more than 1024 bytes.
|
||||
error.NoSpaceLeft => {
|
||||
log.warn("accelerator somehow longer than 1024 bytes: {}", .{trigger});
|
||||
error.WriteFailed => {
|
||||
log.warn("accelerator somehow longer than 1024 bytes: {f}", .{trigger});
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -485,10 +485,11 @@ const Command = extern struct {
|
|||
|
||||
const command = priv.command orelse return null;
|
||||
|
||||
priv.action_key = std.fmt.allocPrintZ(
|
||||
priv.action_key = std.fmt.allocPrintSentinel(
|
||||
priv.arena.allocator(),
|
||||
"{}",
|
||||
"{f}",
|
||||
.{command.action},
|
||||
0,
|
||||
) catch null;
|
||||
|
||||
return priv.action_key;
|
||||
|
|
|
|||
|
|
@ -188,9 +188,9 @@ pub const GlobalShortcuts = extern struct {
|
|||
// If there isn't space to translate the trigger, then our
|
||||
// buffer might be too small (but 1024 is insane!). In any case
|
||||
// we don't want to stop registering globals.
|
||||
error.NoSpaceLeft => {
|
||||
error.WriteFailed => {
|
||||
log.warn(
|
||||
"buffer too small to translate trigger, ignoring={}",
|
||||
"buffer too small to translate trigger, ignoring={f}",
|
||||
.{entry.key_ptr.*},
|
||||
);
|
||||
continue;
|
||||
|
|
@ -257,7 +257,7 @@ pub const GlobalShortcuts = extern struct {
|
|||
const trigger = entry.key_ptr.*.ptr;
|
||||
const action = std.fmt.bufPrintZ(
|
||||
&action_buf,
|
||||
"{}",
|
||||
"{f}",
|
||||
.{entry.value_ptr.*},
|
||||
) catch continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ pub const SplitTree = extern struct {
|
|||
);
|
||||
defer new_tree.deinit();
|
||||
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 },
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2117,13 +2117,11 @@ pub const Surface = extern struct {
|
|||
const alloc = Application.default().allocator();
|
||||
|
||||
if (ext.gValueHolds(value, gdk.FileList.getGObjectType())) {
|
||||
var data = std.ArrayList(u8).init(alloc);
|
||||
defer data.deinit();
|
||||
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||
defer stream.deinit();
|
||||
|
||||
var shell_escape_writer: internal_os.ShellEscapeWriter(std.ArrayList(u8).Writer) = .{
|
||||
.child_writer = data.writer(),
|
||||
};
|
||||
const writer = shell_escape_writer.writer();
|
||||
var shell_escape_writer: internal_os.ShellEscapeWriter = .init(&stream.writer);
|
||||
const writer = &shell_escape_writer.writer;
|
||||
|
||||
const list: ?*glib.SList = list: {
|
||||
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});
|
||||
return 0;
|
||||
};
|
||||
|
|
@ -2164,13 +2162,11 @@ pub const Surface = extern struct {
|
|||
const object = value.getObject() orelse return 0;
|
||||
const file = gobject.ext.cast(gio.File, object) orelse return 0;
|
||||
const path = file.getPath() orelse return 0;
|
||||
var data = std.ArrayList(u8).init(alloc);
|
||||
defer data.deinit();
|
||||
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||
defer stream.deinit();
|
||||
|
||||
var shell_escape_writer: internal_os.ShellEscapeWriter(std.ArrayList(u8).Writer) = .{
|
||||
.child_writer = data.writer(),
|
||||
};
|
||||
const writer = shell_escape_writer.writer();
|
||||
var shell_escape_writer: internal_os.ShellEscapeWriter = .init(&stream.writer);
|
||||
const writer = &shell_escape_writer.writer;
|
||||
writer.writeAll(std.mem.span(path)) catch |err| {
|
||||
log.err("unable to write path to buffer: {}", .{err});
|
||||
return 0;
|
||||
|
|
@ -2180,7 +2176,7 @@ pub const Surface = extern struct {
|
|||
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});
|
||||
return 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -405,22 +405,21 @@ pub const Tab = extern struct {
|
|||
};
|
||||
|
||||
// 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();
|
||||
const writer = buf.writer();
|
||||
|
||||
// If our bell is ringing, then we prefix the bell icon to the 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 (zoomed) {
|
||||
writer.writeAll("🔍 ") catch {};
|
||||
buf.writer.writeAll("🔍 ") catch {};
|
||||
}
|
||||
|
||||
writer.writeAll(plain) catch return glib.ext.dupeZ(u8, plain);
|
||||
return glib.ext.dupeZ(u8, buf.items);
|
||||
buf.writer.writeAll(plain) catch return glib.ext.dupeZ(u8, plain);
|
||||
return glib.ext.dupeZ(u8, buf.written());
|
||||
}
|
||||
|
||||
const C = Common(Self, Private);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pub fn getRuntimeVersion() std.SemanticVersion {
|
|||
}
|
||||
|
||||
pub fn logVersion() void {
|
||||
log.info("GTK version build={} runtime={}", .{
|
||||
log.info("GTK version build={f} runtime={f}", .{
|
||||
comptime_version,
|
||||
getRuntimeVersion(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ const winproto = @import("winproto.zig");
|
|||
pub fn accelFromTrigger(
|
||||
buf: []u8,
|
||||
trigger: input.Binding.Trigger,
|
||||
) error{NoSpaceLeft}!?[:0]const u8 {
|
||||
var buf_stream = std.io.fixedBufferStream(buf);
|
||||
const writer = buf_stream.writer();
|
||||
) error{WriteFailed}!?[:0]const u8 {
|
||||
var writer: std.Io.Writer = .fixed(buf);
|
||||
|
||||
// Modifiers
|
||||
if (trigger.mods.shift) try writer.writeAll("<Shift>");
|
||||
|
|
@ -23,11 +22,11 @@ pub fn accelFromTrigger(
|
|||
if (trigger.mods.super) try writer.writeAll("<Super>");
|
||||
|
||||
// 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.
|
||||
try writer.writeByte(0);
|
||||
const slice = buf_stream.getWritten();
|
||||
const slice = writer.buffered();
|
||||
return slice[0 .. slice.len - 1 :0];
|
||||
}
|
||||
|
||||
|
|
@ -36,9 +35,8 @@ pub fn accelFromTrigger(
|
|||
pub fn xdgShortcutFromTrigger(
|
||||
buf: []u8,
|
||||
trigger: input.Binding.Trigger,
|
||||
) error{NoSpaceLeft}!?[:0]const u8 {
|
||||
var buf_stream = std.io.fixedBufferStream(buf);
|
||||
const writer = buf_stream.writer();
|
||||
) error{WriteFailed}!?[:0]const u8 {
|
||||
var writer: std.Io.Writer = .fixed(buf);
|
||||
|
||||
// Modifiers
|
||||
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).
|
||||
// I haven't been able to any evidence to back up that assumption but
|
||||
// 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.
|
||||
try writer.writeByte(0);
|
||||
const slice = buf_stream.getWritten();
|
||||
const slice = writer.buffered();
|
||||
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) {
|
||||
.physical => |k| {
|
||||
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,
|
||||
.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, .{});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@ const std = @import("std");
|
|||
const gen = @import("mdgen.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||
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.genActions(writer);
|
||||
try gen.genConfig(writer, true);
|
||||
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");
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||
const alloc = gpa.allocator();
|
||||
|
||||
const output = std.io.getStdOut().writer();
|
||||
try gen.substitute(alloc, @embedFile("ghostty_5_header.md"), output);
|
||||
try gen.genConfig(output, false);
|
||||
try gen.genKeybindActions(output);
|
||||
try gen.substitute(alloc, @embedFile("ghostty_5_footer.md"), output);
|
||||
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_5_header.md"), writer);
|
||||
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 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(
|
||||
u8,
|
||||
input,
|
||||
|
|
@ -18,7 +18,7 @@ pub fn substitute(alloc: std.mem.Allocator, input: []const u8, writer: anytype)
|
|||
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(
|
||||
\\
|
||||
\\# 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(
|
||||
\\
|
||||
\\# 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(
|
||||
\\
|
||||
\\# KEYBIND ACTIONS
|
||||
|
|
|
|||
|
|
@ -19,18 +19,18 @@ pub const completions = comptimeGenerateBashCompletions();
|
|||
fn comptimeGenerateBashCompletions() []const u8 {
|
||||
comptime {
|
||||
@setEvalBranchQuota(50000);
|
||||
var counter = std.io.countingWriter(std.io.null_writer);
|
||||
try writeBashCompletions(&counter.writer());
|
||||
var counter: std.Io.Writer.Discarding = .init(&.{});
|
||||
try writeBashCompletions(&counter.writer);
|
||||
|
||||
var buf: [counter.bytes_written]u8 = undefined;
|
||||
var stream = std.io.fixedBufferStream(&buf);
|
||||
try writeBashCompletions(stream.writer());
|
||||
var buf: [counter.count]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try writeBashCompletions(&writer);
|
||||
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 pad2 = pad1 ++ pad1;
|
||||
const pad3 = pad2 ++ pad1;
|
||||
|
|
|
|||
|
|
@ -11,18 +11,18 @@ pub const completions = comptimeGenerateCompletions();
|
|||
fn comptimeGenerateCompletions() []const u8 {
|
||||
comptime {
|
||||
@setEvalBranchQuota(50000);
|
||||
var counter = std.io.countingWriter(std.io.null_writer);
|
||||
try writeCompletions(&counter.writer());
|
||||
var counter: std.Io.Writer.Discarding = .init(&.{});
|
||||
try writeCompletions(&counter.writer);
|
||||
|
||||
var buf: [counter.bytes_written]u8 = undefined;
|
||||
var stream = std.io.fixedBufferStream(&buf);
|
||||
try writeCompletions(stream.writer());
|
||||
var buf: [counter.count]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try writeCompletions(&writer);
|
||||
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 \"");
|
||||
var count: usize = 0;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ fn comptimeGenSyntax() []const u8 {
|
|||
}
|
||||
|
||||
/// Writes the syntax file to the given writer.
|
||||
fn writeSyntax(writer: anytype) !void {
|
||||
fn writeSyntax(writer: *std.Io.Writer) !void {
|
||||
try writer.writeAll(
|
||||
\\" Vim syntax file
|
||||
\\" Language: Ghostty config file
|
||||
|
|
|
|||
|
|
@ -12,18 +12,18 @@ const equals_required = "=-:::";
|
|||
fn comptimeGenerateZshCompletions() []const u8 {
|
||||
comptime {
|
||||
@setEvalBranchQuota(50000);
|
||||
var counter = std.io.countingWriter(std.io.null_writer);
|
||||
try writeZshCompletions(&counter.writer());
|
||||
var counter: std.Io.Writer.Discarding = .init(&.{});
|
||||
try writeZshCompletions(&counter.writer);
|
||||
|
||||
var buf: [counter.bytes_written]u8 = undefined;
|
||||
var stream = std.io.fixedBufferStream(&buf);
|
||||
try writeZshCompletions(stream.writer());
|
||||
var buf: [counter.count]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try writeZshCompletions(&writer);
|
||||
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(
|
||||
\\#compdef ghostty
|
||||
\\
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ pub fn clear(self: *Atlas) void {
|
|||
/// swapped because PPM expects RGB. This would be
|
||||
/// easy enough to fix so next time someone needs
|
||||
/// 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(
|
||||
\\P{c}
|
||||
\\{d} {d}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ fn FixedPoint(comptime T: type, int_bits: u64, frac_bits: u64) type {
|
|||
self: Self,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
|
|
@ -176,7 +176,7 @@ pub const SFNT = struct {
|
|||
self: OffsetSubtable,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
|
|
@ -210,7 +210,7 @@ pub const SFNT = struct {
|
|||
self: TableRecord,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ pub const Feature = struct {
|
|||
self: Feature,
|
||||
comptime layout: []const u8,
|
||||
opts: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
_ = layout;
|
||||
_ = opts;
|
||||
|
|
@ -262,7 +262,7 @@ pub const FeatureList = struct {
|
|||
self: FeatureList,
|
||||
comptime layout: []const u8,
|
||||
opts: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
for (self.features.items, 0..) |feature, i| {
|
||||
try feature.format(layout, opts, writer);
|
||||
|
|
|
|||
|
|
@ -600,6 +600,7 @@ fn renderModesWindow(self: *Inspector) void {
|
|||
|
||||
const t = self.surface.renderer_state.terminal;
|
||||
inline for (@typeInfo(terminal.Mode).@"enum".fields) |field| {
|
||||
@setEvalBranchQuota(6000);
|
||||
const tag: terminal.modes.ModeTag = @bitCast(@as(terminal.modes.ModeTag.Backing, field.value));
|
||||
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ pub const VTEvent = struct {
|
|||
) !VTEvent {
|
||||
var md = Metadata.init(alloc);
|
||||
errdefer md.deinit();
|
||||
var buf = std.ArrayList(u8).init(alloc);
|
||||
var buf: std.Io.Writer.Allocating = .init(alloc);
|
||||
defer buf.deinit();
|
||||
try encodeAction(alloc, buf.writer(), &md, action);
|
||||
try encodeAction(alloc, &buf.writer, &md, action);
|
||||
const str = try buf.toOwnedSliceSentinel(0);
|
||||
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.
|
||||
fn encodeAction(
|
||||
alloc: Allocator,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
md: *Metadata,
|
||||
action: terminal.Parser.Action,
|
||||
) !void {
|
||||
|
|
@ -125,16 +125,16 @@ pub const VTEvent = struct {
|
|||
.csi_dispatch => |v| try encodeCSI(writer, v),
|
||||
.esc_dispatch => |v| try encodeEsc(writer, 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;
|
||||
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;
|
||||
switch (ch) {
|
||||
0x00 => try writer.writeAll("NUL"),
|
||||
|
|
@ -158,7 +158,7 @@ pub const VTEvent = struct {
|
|||
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.params, 0..) |v, i| {
|
||||
if (i != 0) try writer.writeByte(';');
|
||||
|
|
@ -168,14 +168,14 @@ pub const VTEvent = struct {
|
|||
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});
|
||||
try writer.writeByte(esc.final);
|
||||
}
|
||||
|
||||
fn encodeOSC(
|
||||
alloc: Allocator,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
md: *Metadata,
|
||||
osc: terminal.osc.Command,
|
||||
) !void {
|
||||
|
|
@ -265,10 +265,10 @@ pub const VTEvent = struct {
|
|||
const s = if (field.type == void)
|
||||
try alloc.dupeZ(u8, tag_name)
|
||||
else
|
||||
try std.fmt.allocPrintZ(alloc, "{s}={}", .{
|
||||
try std.fmt.allocPrintSentinel(alloc, "{s}={}", .{
|
||||
tag_name,
|
||||
@field(value, field.name),
|
||||
});
|
||||
}, 0);
|
||||
|
||||
try md.put(key, s);
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ pub const VTEvent = struct {
|
|||
else => switch (Value) {
|
||||
u8, u16 => try md.put(
|
||||
key,
|
||||
try std.fmt.allocPrintZ(alloc, "{}", .{value}),
|
||||
try std.fmt.allocPrintSentinel(alloc, "{}", .{value}, 0),
|
||||
),
|
||||
|
||||
[]const u8,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ pub fn main() !void {
|
|||
const action = action_ orelse return error.NoAction;
|
||||
|
||||
// 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) {
|
||||
.bash => try writer.writeAll(@import("extra/bash.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;
|
||||
// no other Zig code should EVER access the global state.
|
||||
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);
|
||||
const ErrSet = @TypeOf(err) || error{Unknown};
|
||||
switch (@as(ErrSet, @errorCast(err))) {
|
||||
|
|
@ -54,6 +56,7 @@ pub fn main() !MainReturn {
|
|||
|
||||
else => try stderr.print("invalid CLI invocation err={}\n", .{err}),
|
||||
}
|
||||
try stderr.flush();
|
||||
};
|
||||
defer state.deinit();
|
||||
const alloc = state.alloc;
|
||||
|
|
@ -154,8 +157,12 @@ fn logFn(
|
|||
|
||||
.stderr => {
|
||||
// Always try default to send to stderr
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
nosuspend stderr.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
|
||||
var buffer: [1024]u8 = undefined;
|
||||
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();
|
||||
|
||||
// Read it all into memory -- we don't expect this file to ever be that large.
|
||||
var buf_reader = std.io.bufferedReader(file.reader());
|
||||
const contents = try buf_reader.reader().readAllAlloc(
|
||||
var reader_buf: [4096]u8 = undefined;
|
||||
var reader = file.reader(&reader_buf);
|
||||
const contents = try reader.interface.readAlloc(
|
||||
alloc,
|
||||
1 * 1024 * 1024, // 1MB
|
||||
);
|
||||
|
|
@ -52,7 +53,11 @@ pub fn create(
|
|||
);
|
||||
const file = try std.fs.cwd().openFile(pid_path, .{ .mode = .write_only });
|
||||
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
|
||||
// be that large.
|
||||
var buf_reader = std.io.bufferedReader(file.reader());
|
||||
const contents = try buf_reader.reader().readAllAlloc(
|
||||
var reader_buf: [4096]u8 = undefined;
|
||||
var reader = file.reader(&reader_buf);
|
||||
const contents = try reader.interface.readAlloc(
|
||||
alloc,
|
||||
1 * 1024 * 1024, // 1MB
|
||||
);
|
||||
|
|
@ -213,7 +219,10 @@ pub fn configureControllers(
|
|||
defer file.close();
|
||||
|
||||
// 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) {
|
||||
|
|
@ -242,5 +251,8 @@ pub fn configureLimit(cgroup: []const u8, limit: Limit) !void {
|
|||
defer file.close();
|
||||
|
||||
// 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 testing = std.testing;
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
/// Writer that escapes characters that shells treat specially to reduce the
|
||||
/// risk of injection attacks or other such weirdness. Specifically excludes
|
||||
/// 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.
|
||||
pub fn ShellEscapeWriter(comptime T: type) type {
|
||||
return struct {
|
||||
child_writer: T,
|
||||
/// T should be a Zig type that follows the `std.Io.Writer` interface.
|
||||
pub const ShellEscapeWriter = struct {
|
||||
writer: Writer,
|
||||
child: *Writer,
|
||||
|
||||
fn write(self: *ShellEscapeWriter(T), data: []const u8) error{Error}!usize {
|
||||
var count: usize = 0;
|
||||
for (data) |byte| {
|
||||
const buf = switch (byte) {
|
||||
'\\',
|
||||
'"',
|
||||
'\'',
|
||||
'$',
|
||||
'`',
|
||||
'*',
|
||||
'?',
|
||||
' ',
|
||||
'|',
|
||||
'(',
|
||||
')',
|
||||
=> &[_]u8{ '\\', byte },
|
||||
else => &[_]u8{byte},
|
||||
};
|
||||
self.child_writer.writeAll(buf) catch return error.Error;
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
pub fn init(child: *Writer) ShellEscapeWriter {
|
||||
return .{
|
||||
.writer = .{
|
||||
// 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
|
||||
// full use of the post-Writergate API. However, since we know that
|
||||
// this is going into an Allocating writer anyways, we can be a bit
|
||||
// less strict here.
|
||||
|
||||
var count: usize = 0;
|
||||
for (data[0 .. data.len - 1]) |chunk| try self.writeEscaped(chunk, &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" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("abc");
|
||||
try testing.expectEqualStrings("abc", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("abc");
|
||||
try testing.expectEqualStrings("abc", writer.buffered());
|
||||
}
|
||||
|
||||
test "shell escape 2" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("a c");
|
||||
try testing.expectEqualStrings("a\\ c", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("a c");
|
||||
try testing.expectEqualStrings("a\\ c", writer.buffered());
|
||||
}
|
||||
|
||||
test "shell escape 3" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("a?c");
|
||||
try testing.expectEqualStrings("a\\?c", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("a?c");
|
||||
try testing.expectEqualStrings("a\\?c", writer.buffered());
|
||||
}
|
||||
|
||||
test "shell escape 4" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("a\\c");
|
||||
try testing.expectEqualStrings("a\\\\c", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("a\\c");
|
||||
try testing.expectEqualStrings("a\\\\c", writer.buffered());
|
||||
}
|
||||
|
||||
test "shell escape 5" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("a|c");
|
||||
try testing.expectEqualStrings("a\\|c", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("a|c");
|
||||
try testing.expectEqualStrings("a\\|c", writer.buffered());
|
||||
}
|
||||
|
||||
test "shell escape 6" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("a\"c");
|
||||
try testing.expectEqualStrings("a\\\"c", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("a\"c");
|
||||
try testing.expectEqualStrings("a\\\"c", writer.buffered());
|
||||
}
|
||||
|
||||
test "shell escape 7" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fmt = std.io.fixedBufferStream(&buf);
|
||||
var shell: ShellEscapeWriter(@TypeOf(fmt).Writer) = .{ .child_writer = fmt.writer() };
|
||||
const writer = shell.writer();
|
||||
try writer.writeAll("a(1)");
|
||||
try testing.expectEqualStrings("a\\(1\\)", fmt.getWritten());
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
var shell: ShellEscapeWriter = .{ .child_writer = &writer };
|
||||
try shell.writer.writeAll("a(1)");
|
||||
try testing.expectEqualStrings("a\\(1\\)", writer.buffered());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ const PosixPty = struct {
|
|||
// Reset our signals
|
||||
var sa: posix.Sigaction = .{
|
||||
.handler = .{ .handler = posix.SIG.DFL },
|
||||
.mask = posix.empty_sigset,
|
||||
.mask = posix.sigemptyset(),
|
||||
.flags = 0,
|
||||
};
|
||||
posix.sigaction(posix.SIG.ABRT, &sa, null);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ pub fn loadFromFiles(
|
|||
paths: configpkg.RepeatablePath,
|
||||
target: Target,
|
||||
) ![]const [:0]const u8 {
|
||||
var list = std.ArrayList([:0]const u8).init(alloc_gpa);
|
||||
defer list.deinit();
|
||||
var list: std.ArrayList([:0]const u8) = .empty;
|
||||
defer list.deinit(alloc_gpa);
|
||||
errdefer for (list.items) |shader| alloc_gpa.free(shader);
|
||||
|
||||
for (paths.value.items) |item| {
|
||||
|
|
@ -56,10 +56,10 @@ pub fn loadFromFiles(
|
|||
return err;
|
||||
};
|
||||
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
|
||||
|
|
@ -73,34 +73,35 @@ pub fn loadFromFile(
|
|||
defer arena.deinit();
|
||||
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.
|
||||
var buf_reader = std.io.bufferedReader(file.reader());
|
||||
const src = try buf_reader.reader().readAllAlloc(
|
||||
alloc,
|
||||
4 * 1024 * 1024, // 4MB
|
||||
);
|
||||
const src = src: {
|
||||
// Load the shader file
|
||||
const cwd = std.fs.cwd();
|
||||
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
|
||||
const glsl: [:0]const u8 = glsl: {
|
||||
var list = std.ArrayList(u8).init(alloc);
|
||||
try glslFromShader(list.writer(), src);
|
||||
try list.append(0);
|
||||
break :glsl list.items[0 .. list.items.len - 1 :0];
|
||||
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||
try glslFromShader(&stream.writer, src);
|
||||
try stream.writer.writeByte(0);
|
||||
break :glsl stream.written()[0 .. stream.written().len - 1 :0];
|
||||
};
|
||||
|
||||
// Convert to SPIR-V
|
||||
const spirv: []const u8 = spirv: {
|
||||
// SpirV pointer must be aligned to 4 bytes since we expect
|
||||
// a slice of words.
|
||||
var list = std.ArrayListAligned(u8, @alignOf(u32)).init(alloc);
|
||||
var stream: std.Io.Writer.Allocating = .init(alloc);
|
||||
var errlog: SpirvLog = .{ .alloc = alloc };
|
||||
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) {
|
||||
log.warn("spirv error path={s} info={s} debug={s}", .{
|
||||
path,
|
||||
|
|
@ -111,6 +112,11 @@ pub fn loadFromFile(
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub fn destroy(self: *Ascii, alloc: Allocator) void {
|
|||
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;
|
||||
|
||||
var gen: synthetic.Bytes = .{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ pub fn destroy(self: *Osc, alloc: Allocator) void {
|
|||
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 = .{
|
||||
.rand = rand,
|
||||
.p_valid = self.opts.@"p-valid",
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub fn destroy(self: *Utf8, alloc: Allocator) void {
|
|||
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;
|
||||
|
||||
var gen: synthetic.Utf8 = .{
|
||||
|
|
|
|||
|
|
@ -2723,7 +2723,7 @@ pub fn encodeUtf8(
|
|||
/// 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);
|
||||
|
||||
var active = false;
|
||||
|
|
|
|||
|
|
@ -239,6 +239,11 @@ pub fn deinit(self: *Terminal, alloc: Allocator) void {
|
|||
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.
|
||||
pub fn printString(self: *Terminal, str: []const u8) !void {
|
||||
const view = try std.unicode.Utf8View.init(str);
|
||||
|
|
@ -2531,7 +2536,7 @@ pub fn resize(
|
|||
/// Set the pwd for the terminal.
|
||||
pub fn setPwd(self: *Terminal, pwd: []const u8) !void {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ pub const Response = struct {
|
|||
placement_id: u32 = 0,
|
||||
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.
|
||||
if (self.id == 0 and self.image_number == 0) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ pub const Terminator = enum {
|
|||
self: Terminator,
|
||||
comptime _: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
try writer.writeAll(self.string());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ pub const Style = struct {
|
|||
self: Color,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
|
|
@ -228,7 +228,7 @@ pub const Style = struct {
|
|||
self: Style,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub const Capability = struct {
|
|||
/// Encode as a terminfo source file. The encoding is always done in a
|
||||
/// human-readable format with whitespace. Fields are always written in the
|
||||
/// 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
|
||||
for (self.names, 0..) |name, i| {
|
||||
if (i != 0) try writer.writeAll("|");
|
||||
|
|
|
|||
|
|
@ -591,6 +591,17 @@ const Subprocess = struct {
|
|||
flatpak_command: ?FlatpakHostCommand = null,
|
||||
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
|
||||
/// up the internal state necessary to start it later.
|
||||
pub fn init(gpa: Allocator, cfg: Config) !Subprocess {
|
||||
|
|
@ -897,7 +908,7 @@ const Subprocess = struct {
|
|||
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.
|
||||
// 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);
|
||||
log.debug("waitpid result={}", .{res.pid});
|
||||
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);
|
||||
if (pgid == my_pgid) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -310,11 +310,11 @@ pub const StreamHandler = struct {
|
|||
.kitty => |*kitty_cmd| {
|
||||
if (self.terminal.kittyGraphics(self.alloc, kitty_cmd)) |resp| {
|
||||
var buf: [1024]u8 = undefined;
|
||||
var buf_stream = std.io.fixedBufferStream(&buf);
|
||||
try resp.encode(buf_stream.writer());
|
||||
const final = buf_stream.getWritten();
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try resp.encode(&writer);
|
||||
const final = writer.buffered();
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
@ -1141,7 +1141,7 @@ pub const StreamHandler = struct {
|
|||
|
||||
// We need to unescape the path. We first try to unescape onto
|
||||
// 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: {
|
||||
// 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
|
||||
|
|
@ -1156,15 +1156,16 @@ pub const StreamHandler = struct {
|
|||
break :path .{ path, false };
|
||||
|
||||
// First try to stack-allocate
|
||||
var fba = std.heap.FixedBufferAllocator.init(&pathBuf);
|
||||
if (std.fmt.allocPrint(fba.allocator(), "{raw}", .{uri.path})) |v|
|
||||
break :path .{ v, false }
|
||||
else |_| {}
|
||||
var stack_writer: std.Io.Writer = .fixed(&path_buf);
|
||||
if (uri.path.formatRaw(&stack_writer)) |_| {
|
||||
break :path .{ stack_writer.buffered(), false };
|
||||
} else |_| {}
|
||||
|
||||
// Fall back to heap
|
||||
if (std.fmt.allocPrint(self.alloc, "{raw}", .{uri.path})) |v|
|
||||
break :path .{ v, true }
|
||||
else |_| {}
|
||||
var alloc_writer: std.Io.Writer.Allocating = .init(self.alloc);
|
||||
if (uri.path.formatRaw(&alloc_writer.writer)) |_| {
|
||||
break :path .{ alloc_writer.written(), true };
|
||||
} else |_| {}
|
||||
|
||||
// Fall back to using it directly...
|
||||
log.warn("failed to unescape OSC 7 path, using it directly path={s}", .{path});
|
||||
|
|
@ -1471,15 +1472,15 @@ pub const StreamHandler = struct {
|
|||
self: *StreamHandler,
|
||||
request: terminal.kitty.color.OSC,
|
||||
) !void {
|
||||
var buf = std.ArrayList(u8).init(self.alloc);
|
||||
defer buf.deinit();
|
||||
const writer = buf.writer();
|
||||
var stream: std.Io.Writer.Allocating = .init(self.alloc);
|
||||
defer stream.deinit();
|
||||
const writer = &stream.writer;
|
||||
|
||||
for (request.list.items) |item| {
|
||||
switch (item) {
|
||||
.query => |key| {
|
||||
// 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) {
|
||||
.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,
|
||||
.cursor => self.cursor_color orelse self.default_cursor_color,
|
||||
else => {
|
||||
log.warn("ignoring unsupported kitty color protocol key: {}", .{key});
|
||||
log.warn("ignoring unsupported kitty color protocol key: {f}", .{key});
|
||||
continue;
|
||||
},
|
||||
},
|
||||
} orelse {
|
||||
try writer.print(";{}=", .{key});
|
||||
try writer.print(";{f}=", .{key});
|
||||
continue;
|
||||
};
|
||||
|
||||
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 },
|
||||
);
|
||||
},
|
||||
|
|
@ -1525,7 +1526,7 @@ pub const StreamHandler = struct {
|
|||
},
|
||||
else => {
|
||||
log.warn(
|
||||
"ignoring unsupported kitty color protocol key: {}",
|
||||
"ignoring unsupported kitty color protocol key: {f}",
|
||||
.{v.key},
|
||||
);
|
||||
continue;
|
||||
|
|
@ -1560,7 +1561,7 @@ pub const StreamHandler = struct {
|
|||
},
|
||||
else => {
|
||||
log.warn(
|
||||
"ignoring unsupported kitty color protocol key: {}",
|
||||
"ignoring unsupported kitty color protocol key: {f}",
|
||||
.{key},
|
||||
);
|
||||
continue;
|
||||
|
|
@ -1576,12 +1577,12 @@ pub const StreamHandler = struct {
|
|||
}
|
||||
|
||||
// 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());
|
||||
self.messageWriter(.{
|
||||
.write_alloc = .{
|
||||
.alloc = self.alloc,
|
||||
.data = try buf.toOwnedSlice(),
|
||||
.data = try stream.toOwnedSlice(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue