Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configuration errors improvements: exit on CLI errors, include line number and filepath #2454

Merged
merged 8 commits into from
Oct 18, 2024
7 changes: 3 additions & 4 deletions include/ghostty.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ typedef struct {

typedef struct {
const char* message;
} ghostty_error_s;
} ghostty_diagnostic_s;

typedef struct {
double tl_px_x;
Expand Down Expand Up @@ -607,16 +607,15 @@ ghostty_info_s ghostty_info(void);
ghostty_config_t ghostty_config_new();
void ghostty_config_free(ghostty_config_t);
void ghostty_config_load_cli_args(ghostty_config_t);
void ghostty_config_load_string(ghostty_config_t, const char*, uintptr_t);
void ghostty_config_load_default_files(ghostty_config_t);
void ghostty_config_load_recursive_files(ghostty_config_t);
void ghostty_config_finalize(ghostty_config_t);
bool ghostty_config_get(ghostty_config_t, void*, const char*, uintptr_t);
ghostty_input_trigger_s ghostty_config_trigger(ghostty_config_t,
const char*,
uintptr_t);
uint32_t ghostty_config_errors_count(ghostty_config_t);
ghostty_error_s ghostty_config_get_error(ghostty_config_t, uint32_t);
uint32_t ghostty_config_diagnostics_count(ghostty_config_t);
ghostty_diagnostic_s ghostty_config_get_diagnostic(ghostty_config_t, uint32_t);
void ghostty_config_open();

ghostty_app_t ghostty_app_new(const ghostty_runtime_config_s*,
Expand Down
30 changes: 15 additions & 15 deletions macos/Sources/Ghostty/Ghostty.Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ extension Ghostty {
var errors: [String] {
guard let cfg = self.config else { return [] }

var errors: [String] = [];
let errCount = ghostty_config_errors_count(cfg)
for i in 0..<errCount {
let err = ghostty_config_get_error(cfg, UInt32(i))
let message = String(cString: err.message)
errors.append(message)
var diags: [String] = [];
let diagsCount = ghostty_config_diagnostics_count(cfg)
for i in 0..<diagsCount {
let diag = ghostty_config_get_diagnostic(cfg, UInt32(i))
let message = String(cString: diag.message)
diags.append(message)
}

return errors
return diags
}

init() {
Expand Down Expand Up @@ -69,14 +69,14 @@ extension Ghostty {

// Log any configuration errors. These will be automatically shown in a
// pop-up window too.
let errCount = ghostty_config_errors_count(cfg)
if errCount > 0 {
logger.warning("config error: \(errCount) configuration errors on reload")
var errors: [String] = [];
for i in 0..<errCount {
let err = ghostty_config_get_error(cfg, UInt32(i))
let message = String(cString: err.message)
errors.append(message)
let diagsCount = ghostty_config_diagnostics_count(cfg)
if diagsCount > 0 {
logger.warning("config error: \(diagsCount) configuration errors on reload")
var diags: [String] = [];
for i in 0..<diagsCount {
let diag = ghostty_config_get_diagnostic(cfg, UInt32(i))
let message = String(cString: diag.message)
diags.append(message)
logger.warning("config error: \(message)")
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/App.zig
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,19 @@ fn drainMailbox(self: *App, rt_app: *apprt.App) !void {
.open_config => try self.performAction(rt_app, .open_config),
.new_window => |msg| try self.newWindow(rt_app, msg),
.close => |surface| self.closeSurface(surface),
.quit => self.setQuit(),
.surface_message => |msg| try self.surfaceMessage(msg.surface, msg.message),
.redraw_surface => |surface| self.redrawSurface(rt_app, surface),
.redraw_inspector => |surface| self.redrawInspector(rt_app, surface),

// If we're quitting, then we set the quit flag and stop
// draining the mailbox immediately. This lets us defer
// mailbox processing to the next tick so that the apprt
// can try to quick as quickly as possible.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/quick/quit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snuck this into #2455

.quit => {
log.info("quit message received, short circuiting mailbox drain", .{});
self.setQuit();
return;
},
}
}
}
Expand Down
20 changes: 17 additions & 3 deletions src/apprt/glfw.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const Allocator = std.mem.Allocator;
const glfw = @import("glfw");
const macos = @import("macos");
const objc = @import("objc");
const cli = @import("../cli.zig");
const input = @import("../input.zig");
const internal_os = @import("../os/main.zig");
const renderer = @import("../renderer.zig");
Expand Down Expand Up @@ -69,13 +70,26 @@ pub const App = struct {
errdefer config.deinit();

// If we had configuration errors, then log them.
if (!config._errors.empty()) {
for (config._errors.list.items) |err| {
log.warn("configuration error: {s}", .{err.message});
if (!config._diagnostics.empty()) {
var buf = std.ArrayList(u8).init(core_app.alloc);
defer buf.deinit();
for (config._diagnostics.items()) |diag| {
try diag.write(buf.writer());
log.warn("configuration error: {s}", .{buf.items});
buf.clearRetainingCapacity();
}

// If we have any CLI errors, exit.
if (config._diagnostics.containsLocation(.cli)) {
log.warn("CLI errors detected, exiting", .{});
_ = core_app.mailbox.push(.{
.quit = {},
}, .{ .forever = {} });
}
}

// Queue a single new window that starts on launch
// Note: above we may send a quit so this may never happen
_ = core_app.mailbox.push(.{
.new_window = .{},
}, .{ .forever = {} });
Expand Down
23 changes: 15 additions & 8 deletions src/apprt/gtk/App.zig
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,19 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
errdefer config.deinit();

// If we had configuration errors, then log them.
if (!config._errors.empty()) {
for (config._errors.list.items) |err| {
log.warn("configuration error: {s}", .{err.message});
if (!config._diagnostics.empty()) {
var buf = std.ArrayList(u8).init(core_app.alloc);
defer buf.deinit();
for (config._diagnostics.items()) |diag| {
try diag.write(buf.writer());
log.warn("configuration error: {s}", .{buf.items});
buf.clearRetainingCapacity();
}

// If we have any CLI errors, exit.
if (config._diagnostics.containsLocation(.cli)) {
log.warn("CLI errors detected, exiting", .{});
std.posix.exit(1);
}
}

Expand Down Expand Up @@ -815,7 +825,7 @@ fn syncConfigChanges(self: *App) !void {
/// there are new configuration errors and hide the window if the errors
/// are resolved.
fn updateConfigErrors(self: *App) !void {
if (!self.config._errors.empty()) {
if (!self.config._diagnostics.empty()) {
if (self.config_errors_window == null) {
try ConfigErrorsWindow.create(self);
assert(self.config_errors_window != null);
Expand Down Expand Up @@ -1364,10 +1374,7 @@ fn gtkActionQuit(
ud: ?*anyopaque,
) callconv(.C) void {
const self: *App = @ptrCast(@alignCast(ud orelse return));
self.core_app.setQuit() catch |err| {
log.warn("error setting quit err={}", .{err});
return;
};
self.core_app.setQuit();
}

/// Action sent by the window manager asking us to present a specific surface to
Expand Down
19 changes: 16 additions & 3 deletions src/apprt/gtk/ConfigErrorsWindow.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn create(app: *App) !void {
}

pub fn update(self: *ConfigErrors) void {
if (self.app.config._errors.empty()) {
if (self.app.config._diagnostics.empty()) {
c.gtk_window_destroy(@ptrCast(self.window));
return;
}
Expand Down Expand Up @@ -130,8 +130,21 @@ const PrimaryView = struct {
const buf = c.gtk_text_buffer_new(null);
errdefer c.g_object_unref(buf);

for (config._errors.list.items) |err| {
c.gtk_text_buffer_insert_at_cursor(buf, err.message, @intCast(err.message.len));
var msg_buf: [4096]u8 = undefined;
var fbs = std.io.fixedBufferStream(&msg_buf);

for (config._diagnostics.items()) |diag| {
fbs.reset();
diag.write(fbs.writer()) catch |err| {
log.warn(
"error writing diagnostic to buffer err={}",
.{err},
);
continue;
};

const msg = fbs.getWritten();
c.gtk_text_buffer_insert_at_cursor(buf, msg.ptr, @intCast(msg.len));
c.gtk_text_buffer_insert_at_cursor(buf, "\n", -1);
}

Expand Down
5 changes: 5 additions & 0 deletions src/cli.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
const diags = @import("cli/diagnostics.zig");

pub const args = @import("cli/args.zig");
pub const Action = @import("cli/action.zig").Action;
pub const DiagnosticList = diags.DiagnosticList;
pub const Diagnostic = diags.Diagnostic;
pub const Location = diags.Location;

test {
@import("std").testing.refAllDecls(@This());
Expand Down
Loading