mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
search for resources dir relative to executing binary on Linux (#245)
* search for resources dir relative to executing binary on Linux From Andrew in #241: This works in all 3 of the possible scenarios I can think of on Linux: * `zig build` with default prefix into `zig-out` * `zig build -p ~/local` (my choice when compiling from source) * ghostty packaged for a linux distribution into /usr/bin and /share * update README
This commit is contained in:

committed by
GitHub

parent
c139279d47
commit
ebbf42eec6
16
README.md
16
README.md
@ -134,16 +134,20 @@ The currently support shell integration features in Ghostty:
|
|||||||
|
|
||||||
#### Shell Integration Installation and Verification
|
#### Shell Integration Installation and Verification
|
||||||
|
|
||||||
**On macOS,** Ghostty will automatically inject the shell integration code for `zsh` and
|
Ghostty will automatically inject the shell integration code for `zsh` and
|
||||||
`fish`. Other shells are not supported. You can also manually load them
|
`fish`. Other shells are not supported. You can also manually load them
|
||||||
in many cases (see `src/shell-integration`). **If you want to disable this feature,**
|
in many cases (see `src/shell-integration`). **If you want to disable this feature,**
|
||||||
set `shell-integration = none` in your configuration file.
|
set `shell-integration = none` in your configuration file.
|
||||||
|
|
||||||
**On Linux,** automatic shell integration requires that you set the
|
**For the automatic shell integration to work,** Ghostty must either be run
|
||||||
`GHOSTTY_RESOURCES_DIR` environment variable to point to the
|
from the macOS app bundle or be installed in a location where the contents of
|
||||||
`zig-out/share` directory after building Ghostty from source.
|
`zig-out/share` are available somewhere above the directory where Ghostty
|
||||||
To validate this directory the file `$GHOSTTY_RESOURCES_DIR/terminfo/ghostty.terminfo`
|
is running from. On Linux, this should automatically work if you run from
|
||||||
should exist.
|
the `zig-out` directory tree structure (a standard FHS-style tree).
|
||||||
|
|
||||||
|
You may also manually set the `GHOSTTY_RESOURCES_DIR` to point to the
|
||||||
|
`zig-out/share` contents. To validate this directory the file
|
||||||
|
`$GHOSTTY_RESOURCES_DIR/terminfo/ghostty.terminfo` should exist.
|
||||||
|
|
||||||
To verify shell integration is working, look for the following log lines:
|
To verify shell integration is working, look for the following log lines:
|
||||||
|
|
||||||
|
@ -534,14 +534,20 @@ const Subprocess = struct {
|
|||||||
// Get our bundled resources directory, if it exists. We use this
|
// Get our bundled resources directory, if it exists. We use this
|
||||||
// for terminfo, shell-integration, etc.
|
// for terminfo, shell-integration, etc.
|
||||||
const resources_key = "GHOSTTY_RESOURCES_DIR";
|
const resources_key = "GHOSTTY_RESOURCES_DIR";
|
||||||
const resources_dir = if (env.get(resources_key)) |dir| dir: {
|
const resources_dir = dir: {
|
||||||
log.info("using Ghostty resources dir from env var: {s}", .{dir});
|
if (env.get(resources_key)) |dir| {
|
||||||
break :dir dir;
|
if (dir.len > 0) {
|
||||||
} else if (try resourcesDir(alloc)) |dir| dir: {
|
log.info("using Ghostty resources dir from env var: {s}", .{dir});
|
||||||
log.info("found Ghostty resources dir: {s}", .{dir});
|
break :dir dir;
|
||||||
try env.put(resources_key, dir);
|
}
|
||||||
break :dir dir;
|
}
|
||||||
} else dir: {
|
|
||||||
|
if (try resourcesDir(alloc)) |dir| {
|
||||||
|
log.info("found Ghostty resources dir: {s}", .{dir});
|
||||||
|
try env.put(resources_key, dir);
|
||||||
|
break :dir dir;
|
||||||
|
}
|
||||||
|
|
||||||
log.warn("Ghostty resources dir not found, some features disabled", .{});
|
log.warn("Ghostty resources dir not found, some features disabled", .{});
|
||||||
break :dir null;
|
break :dir null;
|
||||||
};
|
};
|
||||||
@ -853,7 +859,7 @@ const Subprocess = struct {
|
|||||||
/// an arena or something similar.
|
/// an arena or something similar.
|
||||||
fn terminfoDir(alloc: Allocator, base: ?[]const u8) !?[]const u8 {
|
fn terminfoDir(alloc: Allocator, base: ?[]const u8) !?[]const u8 {
|
||||||
const dir = base orelse return null;
|
const dir = base orelse return null;
|
||||||
return try tryDir(alloc, dir, "terminfo");
|
return try tryDir(alloc, dir, "terminfo", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the directory to the bundled resources directory, if it
|
/// Gets the directory to the bundled resources directory, if it
|
||||||
@ -862,9 +868,9 @@ const Subprocess = struct {
|
|||||||
/// The memory returned can't be easily freed so the alloc should be
|
/// The memory returned can't be easily freed so the alloc should be
|
||||||
/// an arena or something similar.
|
/// an arena or something similar.
|
||||||
fn resourcesDir(alloc: Allocator) !?[]const u8 {
|
fn resourcesDir(alloc: Allocator) !?[]const u8 {
|
||||||
// We only support Mac lookups right now because the terminfo
|
// This is the sentinel value we look for in the path to know
|
||||||
// DB can be embedded directly in the App bundle.
|
// we've found the resources directory.
|
||||||
if (comptime !builtin.target.isDarwin()) return null;
|
const sentinel = "terminfo/67/ghostty";
|
||||||
|
|
||||||
// Get the path to our running binary
|
// Get the path to our running binary
|
||||||
var exe_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
var exe_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||||
@ -874,7 +880,18 @@ const Subprocess = struct {
|
|||||||
// bundle as we expect it.
|
// bundle as we expect it.
|
||||||
while (std.fs.path.dirname(exe)) |dir| {
|
while (std.fs.path.dirname(exe)) |dir| {
|
||||||
exe = dir;
|
exe = dir;
|
||||||
if (try tryDir(alloc, dir, "Contents/Resources")) |v| {
|
|
||||||
|
// On MacOS, we look for the app bundle path.
|
||||||
|
if (comptime builtin.target.isDarwin()) {
|
||||||
|
if (try tryDir(alloc, dir, "Contents/Resources", sentinel)) |v| {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On all platforms, we look for a /usr/share style path. This
|
||||||
|
// is valid even on Mac since there is nothing that requires
|
||||||
|
// Ghostty to be in an app bundle.
|
||||||
|
if (try tryDir(alloc, dir, "share", sentinel)) |v| {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -882,18 +899,20 @@ const Subprocess = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Little helper to check if the "base/sub" directory exists and
|
/// Little helper to check if the "base/sub/suffix" directory exists and
|
||||||
/// if so, duplicate the path and return it.
|
/// if so, duplicate the "base/sub" path and return it.
|
||||||
fn tryDir(
|
fn tryDir(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
base: []const u8,
|
base: []const u8,
|
||||||
sub: []const u8,
|
sub: []const u8,
|
||||||
|
suffix: []const u8,
|
||||||
) !?[]const u8 {
|
) !?[]const u8 {
|
||||||
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||||
const path = try std.fmt.bufPrint(&buf, "{s}/{s}", .{ base, sub });
|
const path = try std.fmt.bufPrint(&buf, "{s}/{s}/{s}", .{ base, sub, suffix });
|
||||||
|
|
||||||
if (std.fs.accessAbsolute(path, .{})) {
|
if (std.fs.accessAbsolute(path, .{})) {
|
||||||
return try alloc.dupe(u8, path);
|
const len = path.len - suffix.len - 1;
|
||||||
|
return try alloc.dupe(u8, path[0..len]);
|
||||||
} else |_| {
|
} else |_| {
|
||||||
// Folder doesn't exist. If a different error happens its okay
|
// Folder doesn't exist. If a different error happens its okay
|
||||||
// we just ignore it and move on.
|
// we just ignore it and move on.
|
||||||
|
Reference in New Issue
Block a user