termio/exec: style the exec failure error better

This commit is contained in:
Mitchell Hashimoto
2023-12-30 19:34:45 -08:00
parent f3aaa884c6
commit 53dffc8e18
2 changed files with 36 additions and 32 deletions

View File

@ -425,7 +425,7 @@ fn clearPromptForResize(self: *Terminal) void {
/// encoded as "\n". This omits any formatting such as fg/bg. /// encoded as "\n". This omits any formatting such as fg/bg.
/// ///
/// The caller must free the string. /// The caller must free the string.
fn plainString(self: *Terminal, alloc: Allocator) ![]const u8 { pub fn plainString(self: *Terminal, alloc: Allocator) ![]const u8 {
return try self.screen.testString(alloc, .viewport); return try self.screen.testString(alloc, .viewport);
} }
@ -715,9 +715,7 @@ pub fn invokeCharset(
/// Print UTF-8 encoded string to the terminal. This string must be /// Print UTF-8 encoded string to the terminal. This string must be
/// a single line, newlines and carriage returns and other control /// a single line, newlines and carriage returns and other control
/// characters are not processed. /// characters are not processed.
/// pub fn printString(self: *Terminal, str: []const u8) !void {
/// This is not public because it is only used for tests rigt now.
fn printString(self: *Terminal, str: []const u8) !void {
const view = try std.unicode.Utf8View.init(str); const view = try std.unicode.Utf8View.init(str);
var it = view.iterator(); var it = view.iterator();
while (it.nextCodepoint()) |cp| try self.print(cp); while (it.nextCodepoint()) |cp| try self.print(cp);

View File

@ -555,43 +555,49 @@ pub fn childExitedAbnormally(self: *Exec) !void {
); );
defer self.alloc.free(command); defer self.alloc.free(command);
// Build our error message. Do this outside of the renderer lock.
var msg = std.ArrayList(u8).init(self.alloc);
defer msg.deinit();
var writer = msg.writer();
try writer.print(
\\Ghostty failed to launch the requested command.
\\Please check your "command" configuration.
\\
\\Command: {s}
\\
\\Press any key to close this window.
, .{command});
// Modify the terminal to show our error message. This // Modify the terminal to show our error message. This
// requires grabbing the renderer state lock. // requires grabbing the renderer state lock.
self.renderer_state.mutex.lock(); self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock(); defer self.renderer_state.mutex.unlock();
const t = self.renderer_state.terminal; const t = self.renderer_state.terminal;
// Reset the terminal completely. // No matter what move the cursor back to the column 0.
// NOTE: The error output is in the terminal at this point. In the t.carriageReturn();
// future, we can make an even better error message by scrolling,
// writing at the bottom, etc.
t.fullReset(self.alloc);
// Write our message out. // Reset styles
const view = try std.unicode.Utf8View.init(msg.items); try t.setAttribute(.{ .unset = {} });
var it = view.iterator();
while (it.nextCodepoint()) |cp| {
if (cp == '\n') {
t.carriageReturn();
try t.linefeed();
continue;
}
try t.print(cp); // If there is data in the viewport, we want to scroll down
// a little bit and write a horizontal rule before writing
// our message. This lets the use see the error message the
// command may have output.
const viewport_str = try t.plainString(self.alloc);
defer self.alloc.free(viewport_str);
if (viewport_str.len > 0) {
try t.linefeed();
for (0..t.cols) |_| try t.print(0x2501);
t.carriageReturn();
try t.linefeed();
try t.linefeed();
} }
// Output our error message
try t.setAttribute(.{ .@"8_fg" = .bright_red });
try t.setAttribute(.{ .bold = {} });
try t.printString("Ghostty failed to launch the requested command:");
try t.setAttribute(.{ .unset = {} });
try t.setAttribute(.{ .faint = {} });
t.carriageReturn();
try t.linefeed();
try t.printString(command);
try t.setAttribute(.{ .unset = {} });
t.carriageReturn();
try t.linefeed();
try t.linefeed();
try t.printString("Press any key to close the window.");
// Hide the cursor
t.modes.set(.cursor_visible, false);
} }
pub inline fn queueWrite(self: *Exec, data: []const u8, linefeed: bool) !void { pub inline fn queueWrite(self: *Exec, data: []const u8, linefeed: bool) !void {