╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ main.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
35 36 var stdout_writer = std.Io.File.stdout().writer(io, &.{}); 37 var stderr_writer = std.Io.File.stderr().writer(io, &.{}); 38 const run_opts = RunOpts{ .out = &stdout_writer.interface, .err = &stderr_writer.interface }; 39 40 const cwd_path = try std.process.currentPathAlloc(io, allocator); 41 defer allocator.free(cwd_path); 42 43 run(.xit, .{}, io, allocator, args.items, cwd_path, run_opts) catch |err| switch (err) { 44 error.HandledError => return 1, 45 else => |e| return e, 46 }; 47 48 return 0; 49 } 50 51 pub fn run( 52 comptime repo_kind: rp.RepoKind, 53 comptime any_repo_opts: rp.AnyRepoOpts(repo_kind), 54 io: std.Io, 55 allocator: std.mem.Allocator, 56 args: []const []const u8, 57 cwd_path: []const u8, 58 run_opts: RunOpts, 59 ) !void { 60 var cmd_args = try cmd.CommandArgs.init(allocator, args); 61 defer cmd_args.deinit(); 62 63 switch (try cmd.CommandDispatch.init(&cmd_args)) { 64 .invalid => |invalid| switch (invalid) { 65 .command => |command| { 66 try run_opts.err.print("\"{s}\" is not a valid command\n\n", .{command}); 67 try cmd.printHelp(null, run_opts.err); 68 return error.HandledError; 69 }, 70 .argument => |argument| { 71 try run_opts.err.print("\"{s}\" is not a valid argument\n\n", .{argument.value}); 72 try cmd.printHelp(argument.command, run_opts.err); 73 return error.HandledError; 74 }, 75 }, 76 .help => |cmd_kind_maybe| try cmd.printHelp(cmd_kind_maybe, run_opts.out), 77 .local => { 78 // session-lifetime allocations (the repo path, session state) 79 var session_arena = std.heap.ArenaAllocator.init(allocator); 80 defer session_arena.deinit(); 81 82 // probe both backends for a repo; the nearest one wins, so a repo 83 // isn't shadowed by one it is nested inside. only the work path 84 // and backend kind are kept; pages re-open the repo on each build. 85 const local: ui.RepoSource = blk: { 86 var found: ?ui.RepoSource = null; 87 inline for ([_]rp.RepoKind{ .git, .xit }) |probe_kind| { 88 if (rp.AnyRepo(probe_kind, .{}).open(io, allocator, .{ .path = cwd_path })) |repo| { 89 var opened = repo; 90 defer opened.deinit(io, allocator); 91 const work_path = switch (opened) { 92 inline else => |*r| r.core.work_path, 93 }; 94 const found_len = if (found) |f| f.path.len else 0; 95 if (work_path.len > found_len) { 96 found = .{ .path = try session_arena.allocator().dupe(u8, work_path), .repo_kind = probe_kind }; 97 } 98 } else |err| switch (err) { 99 error.RepoNotFound => {}, 100 else => |e| return e, 101 } 102 } 103 break :blk found orelse { 104 try run_opts.err.print("no git or xit repo found in the current directory\n", .{}); 105 return error.HandledError; 106 }; 107 }; 108 109 var session = ui.Session{ 110 .arena = &session_arena, 111 .page_arena = &session_arena, 112 .io = io, 113 .local = local, 114 .is_terminal = true, 115 .data = .{ 116 // the files root; local routes carry no identity 117 .current_page = .{ .repo_files = .{ .name = .{} } }, 118 .is_local = true, 119 }, 120 }; 121 122 // serve the web UI in the background while the TUI runs in the 123 // foreground; the footer points at whatever port it bound. 124 const Runnable = struct { 125 io: std.Io, 126 allocator: std.mem.Allocator, 127 session: *ui.Session, 128 129 pub fn run(self: @This(), web_port: u16) !void { 130 self.session.web_port = web_port; 131 try ui.run(self.io, self.allocator, self.session, null); 132 } 133 }; 134 135 try srv.runLocal(io, allocator, local, run_opts.err, Runnable{ .io = io, .allocator = allocator, .session = &session }); 136 }, 137 .cli => |cli_cmd| switch (cli_cmd) { 138 .serve => |options| try srv.run(repo_kind, any_repo_opts, io, allocator, cwd_path, options, run_opts.err, {}), 139 }, 140 } 141 } 142