╭ changed ──────╮ │src/command.zig│ ╰───────────────╯ ╭────────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 const srv = @import("./serve.zig"); │ │3 const ssh = @import("./ssh_git.zig"); │ │4 +const ssh_tui = @import("./ssh_tui.zig");│ │5 │ │6 pub const CommandKind = enum { │ │7 serve, │ ╰────────────────────────────────────────────╯ ╭─────────────────────────╮ │ 8 ssh_git, │ │ 9 + ssh_tui, │ │10 }; │ │11 │ │12 const Help = struct {│ ╰─────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │33 , │ │34 .example = │ │35 \\haxy ssh-git --ssh-connect 127.0.0.1:8081 --service upload-pack <directory> │ │36 + , │ │37 + }, │ │38 + .ssh_tui => .{ │ │39 + .name = "ssh-tui", │ │40 + .descrip = │ │41 + \\a helper run by sshd that forwards a TUI session to serve over a raw byte stream.│ │42 + , │ │43 + .example = │ │44 + \\haxy ssh-tui --tui-connect 127.0.0.1:8082 --user-key SHA256:... │ │45 , │ │46 }, │ │47 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────╮ │106 const value_flags = std.StaticStringMap(void).initComptime(.{│ │107 .{"--http-listen"}, │ │108 .{"--ssh-listen"}, │ │109 + .{"--tui-listen"}, │ │110 .{"--wui-listen"}, │ │111 .{"--ssh-connect"}, │ │112 + .{"--tui-connect"}, │ │113 + .{"--user-key"}, │ │114 .{"--data-dir"}, │ │115 .{"--service"}, │ │116 }); │ ╰──────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────╮ │205 pub const Command = union(CommandKind) { │ │206 serve: srv.Options, │ │207 ssh_git: ssh.Options, │ │208 + ssh_tui: ssh_tui.Options, │ │209 │ │210 pub fn initMaybe(cmd_args: *CommandArgs) !?Command { │ │211 const command_kind = cmd_args.command_kind orelse return null;│ ╰───────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │220 } │ │221 if (cmd_args.get("--ssh-listen")) |val_maybe| { │ │222 options.ssh_listen = val_maybe orelse return error.SshListenNeedsValue;│ │223 + } │ │224 + if (cmd_args.get("--tui-listen")) |val_maybe| { │ │225 + options.tui_listen = val_maybe orelse return error.TuiListenNeedsValue;│ │226 } │ │227 if (cmd_args.get("--wui-listen")) |val_maybe| { │ │228 options.wui_listen = val_maybe orelse return error.WuiListenNeedsValue;│ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │247 options.dir = if (cmd_args.positional_args.len == 1) cmd_args.positional_args[0] else null;│ │248 │ │249 return .{ .ssh_git = options }; │ │250 + }, │ │251 + .ssh_tui => { │ │252 + if (cmd_args.positional_args.len != 0) return null; │ │253 + │ │254 + var options: ssh_tui.Options = .{}; │ │255 + │ │256 + if (cmd_args.get("--tui-connect")) |val_maybe| { │ │257 + options.tui_connect = val_maybe orelse return error.TuiConnectNeedsValue; │ │258 + } │ │259 + if (cmd_args.get("--user-key")) |val_maybe| { │ │260 + options.user_key = val_maybe orelse return error.UserKeyNeedsValue; │ │261 + } │ │262 + │ │263 + return .{ .ssh_tui = options }; │ │264 }, │ │265 } │ │266 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───╮ │src/main.zig│ ╰────────────╯ ╭─────────────────────────────────────────────╮ │ 5 const cmd = @import("./command.zig"); │ │ 6 const srv = @import("./serve.zig"); │ │ 7 const ssh = @import("./ssh_git.zig"); │ │ 8 +const ssh_tui = @import("./ssh_tui.zig");│ │ 9 │ │10 pub const RunOpts = struct { │ │11 out: *std.Io.Writer, │ ╰─────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │80 .cli => |cli_cmd| switch (cli_cmd) { │ │81 .serve => |options| try srv.run(repo_kind, any_repo_opts, io, allocator, cwd_path, options, run_opts.err, {}),│ │82 .ssh_git => |options| try ssh.run(io, allocator, options, run_opts.environ_map), │ │83 + .ssh_tui => |options| try ssh_tui.run(io, allocator, options, run_opts.environ_map), │ │84 }, │ │85 } │ │86 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────╮ │src/serve.zig│ ╰─────────────╯ ╭───────────────────────────────────────────────────╮ │ 8 pub const Options = struct { │ │ 9 http_listen: []const u8 = "127.0.0.1:8080",│ │10 ssh_listen: []const u8 = "127.0.0.1:8081", │ │11 + tui_listen: []const u8 = "127.0.0.1:8082", │ │12 wui_listen: []const u8 = "127.0.0.1:8000", │ │13 data_dir: []const u8 = ".", │ │14 }; │ ╰───────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯