diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/os/open.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/os/open.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/os/open.zig | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/os/open.zig b/vendor/libghostty-vt/src/os/open.zig new file mode 100644 index 00000000..0cead555 --- /dev/null +++ b/vendor/libghostty-vt/src/os/open.zig @@ -0,0 +1,97 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const Allocator = std.mem.Allocator; +const build_config = @import("../build_config.zig"); +const apprt = @import("../apprt.zig"); + +const log = std.log.scoped(.@"os-open"); + +/// Open a URL in the default handling application. +/// +/// Any output on stderr is logged as a warning in the application logs. +/// Output on stdout is ignored. The allocator is used to buffer the +/// log output and may allocate from another thread. +/// +/// This function is purposely simple for the sake of providing +/// some portable way to open URLs. If you are implementing an +/// apprt for Ghostty, you should consider doing something special-cased +/// for your platform. +pub fn open( + alloc: Allocator, + kind: apprt.action.OpenUrl.Kind, + url: []const u8, +) !void { + var exe: std.process.Child = switch (builtin.os.tag) { + .linux, .freebsd => .init( + &.{ "xdg-open", url }, + alloc, + ), + + .windows => .init( + &.{ "rundll32", "url.dll,FileProtocolHandler", url }, + alloc, + ), + + .macos => .init( + switch (kind) { + .text => &.{ "open", "-t", url }, + .html, .unknown => &.{ "open", url }, + }, + alloc, + ), + + .ios => return error.Unimplemented, + else => @compileError("unsupported OS"), + }; + + // Pipe stdout/stderr so we can collect output from the command. + // This must be set before spawning the process. + exe.stdout_behavior = .Pipe; + exe.stderr_behavior = .Pipe; + + // In the snap on Linux the launcher exports LD_LIBRARY_PATH pointing at + // the snap's bundled libraries. Leaking this into child process can + // can be problematic, so let's drop it from the env + var snap_env: std.process.EnvMap = if (comptime build_config.snap) blk: { + var env = try std.process.getEnvMap(alloc); + env.remove("LD_LIBRARY_PATH"); + break :blk env; + } else undefined; + defer if (comptime build_config.snap) snap_env.deinit(); + if (comptime build_config.snap) exe.env_map = &snap_env; + + // Spawn the process on our same thread so we can detect failure + // quickly. + try exe.spawn(); + + // Create a thread that handles collecting output and reaping + // the process. This is done in a separate thread because SOME + // open implementations block and some do not. It's easier to just + // spawn a thread to handle this so that we never block. + const thread = try std.Thread.spawn(.{}, openThread, .{ alloc, exe }); + thread.detach(); +} + +fn openThread(alloc: Allocator, exe_: std.process.Child) !void { + // 50 KiB is the default value used by std.process.Child.run and should + // be enough to get the output we care about. + const output_max_size = 50 * 1024; + + var stdout: std.ArrayListUnmanaged(u8) = .{}; + var stderr: std.ArrayListUnmanaged(u8) = .{}; + defer { + stdout.deinit(alloc); + stderr.deinit(alloc); + } + + // Copy the exe so it is non-const. This is necessary because wait() + // requires a mutable reference and we can't have one as a thread + // param. + var exe = exe_; + try exe.collectOutput(alloc, &stdout, &stderr, output_max_size); + _ = try exe.wait(); + + // If we have any stderr output we log it. This makes it easier for + // users to debug why some open commands may not work as expected. + if (stderr.items.len > 0) log.warn("wait stderr={s}", .{stderr.items}); +} |
