mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00

This fixes a regression from #2454. In that PR, we added an error when positional arguments are detected. I believe that's correct, but we were silently relying on the previous behavior in the CLI commands. This commit changes the CLI commands to use a new argsIterator function that creates an iterator that skips the first argument (argv0). This is the same behavior that the config parsing does and now uses this shared logic. This also makes it so the argsIterator ignores actions (`+things`) and we document that we expect those to be handled earlier.
81 lines
2.5 KiB
Zig
81 lines
2.5 KiB
Zig
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const args = @import("args.zig");
|
|
const Action = @import("action.zig").Action;
|
|
const Config = @import("../config.zig").Config;
|
|
const crash = @import("../crash/main.zig");
|
|
|
|
pub const Options = struct {
|
|
pub fn deinit(self: Options) void {
|
|
_ = self;
|
|
}
|
|
|
|
/// Enables "-h" and "--help" to work.
|
|
pub fn help(self: Options) !void {
|
|
_ = self;
|
|
return Action.help_error;
|
|
}
|
|
};
|
|
|
|
/// The `crash-report` command is used to inspect and send crash reports.
|
|
///
|
|
/// When executed without any arguments, this will list existing crash reports.
|
|
///
|
|
/// This command currently only supports listing crash reports. Viewing
|
|
/// and sending crash reports is unimplemented and will be added in the future.
|
|
pub fn run(alloc_gpa: Allocator) !u8 {
|
|
// Use an arena for the whole command to avoid manual memory management.
|
|
var arena = std.heap.ArenaAllocator.init(alloc_gpa);
|
|
defer arena.deinit();
|
|
const alloc = arena.allocator();
|
|
|
|
var opts: Options = .{};
|
|
defer opts.deinit();
|
|
|
|
{
|
|
var iter = try args.argsIterator(alloc_gpa);
|
|
defer iter.deinit();
|
|
try args.parse(Options, alloc_gpa, &opts, &iter);
|
|
}
|
|
|
|
const crash_dir = try crash.defaultDir(alloc);
|
|
var reports = std.ArrayList(crash.Report).init(alloc);
|
|
|
|
var it = try crash_dir.iterator();
|
|
while (try it.next()) |report| try reports.append(.{
|
|
.name = try alloc.dupe(u8, report.name),
|
|
.mtime = report.mtime,
|
|
});
|
|
|
|
const stdout = std.io.getStdOut();
|
|
|
|
// If we have no reports, then we're done. If we have a tty then we
|
|
// print a message, otherwise we do nothing.
|
|
if (reports.items.len == 0) {
|
|
if (std.posix.isatty(stdout.handle)) {
|
|
try stdout.writeAll("No crash reports! 👻");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
std.mem.sort(crash.Report, reports.items, {}, lt);
|
|
|
|
const writer = stdout.writer();
|
|
for (reports.items) |report| {
|
|
var buf: [128]u8 = undefined;
|
|
const now = std.time.nanoTimestamp();
|
|
const diff = now - report.mtime;
|
|
const since = if (diff <= 0) "now" else s: {
|
|
const d = Config.Duration{ .duration = @intCast(diff) };
|
|
break :s try std.fmt.bufPrint(&buf, "{s} ago", .{d.round(std.time.ns_per_s)});
|
|
};
|
|
try writer.print("{s} ({s})\n", .{ report.name, since });
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
fn lt(_: void, lhs: crash.Report, rhs: crash.Report) bool {
|
|
return lhs.mtime > rhs.mtime;
|
|
}
|