termio: sets TERMINFO if we can find the terminfo dir

This commit is contained in:
Mitchell Hashimoto
2023-06-24 12:10:10 -07:00
parent 629f8f93d6
commit 9c8f784386

View File

@ -491,8 +491,27 @@ const Subprocess = struct {
break :env try std.process.getEnvMap(alloc);
};
errdefer env.deinit();
try env.put("TERM", "xterm-256color");
try env.put("COLORTERM", "truecolor");
// Set our TERM var. This is a bit complicated because we want to use
// the ghostty TERM value but we want to only do that if we have
// ghostty in the TERMINFO database.
//
// For now, we just look up a bundled dir but in the future we should
// also load the terminfo database and look for it.
if (try terminfoDir(alloc)) |dir| {
try env.put("TERM", "xterm-ghostty");
try env.put("COLORTERM", "truecolor");
try env.put("TERMINFO", dir);
} else {
if (comptime builtin.target.isDarwin()) {
log.warn("ghostty terminfo not found, using xterm-256color", .{});
log.warn("the terminfo SHOULD exist on macos, please ensure", .{});
log.warn("you're using a valid app bundle.", .{});
}
try env.put("TERM", "xterm-256color");
try env.put("COLORTERM", "truecolor");
}
// When embedding in macOS and running via XCode, XCode injects
// a bunch of things that break our shell process. We remove those.
@ -745,6 +764,41 @@ const Subprocess = struct {
fn killCommandFlatpak(command: *FlatpakHostCommand) !void {
try command.signal(c.SIGHUP, true);
}
/// Gets the directory to the terminfo database, if it can be detected.
/// The memory returned can't be easily freed so the alloc should be
/// an arena or something similar.
fn terminfoDir(alloc: Allocator) !?[]const u8 {
// We only support Mac lookups right now because the terminfo
// DB can be embedded directly in the App bundle.
if (comptime !builtin.target.isDarwin()) return null;
// Get the path to our running binary
var exe_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
var exe = (try internal_os.exePath(&exe_buf)) orelse return null;
// We have an exe path! Climb the tree looking for the terminfo
// bundle as we expect it.
while (std.fs.path.dirname(exe)) |dir| {
exe = dir;
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const path = try std.fmt.bufPrint(
&buf,
"{s}/Contents/Resources/terminfo",
.{dir},
);
if (std.fs.accessAbsolute(path, .{})) {
return try alloc.dupe(u8, path);
} else |_| {
// Folder doesn't exist. If a different error happens its okay
// we just ignore it and move on.
}
}
return null;
}
};
/// The read thread sits in a loop doing the following pseudo code: