地圖 (Jido) is a lightweight Unix TUI file explorer designed for speed and simplicity.
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add `--choose-dir` arg

This arg treats jido like a directory chooser writing the last visited
directory to STDOUT on exit.

+86 -37
+86 -37
src/main.zig
··· 8 8 const resolvePath = @import("./commands.zig").resolvePath; 9 9 10 10 pub const panic = vaxis.panic_handler; 11 + const help_menu = 12 + \\Usage: jido 13 + \\ 14 + \\a lightweight Unix TUI file explorer 15 + \\ 16 + \\Flags: 17 + \\ -h, --help Show help information and exit. 18 + \\ -v, --version Print version information and exit. 19 + \\ --entry-dir=PATH Open jido at chosen dir. 20 + \\ --choose-dir Makes jido act like a directory chooser. When jido 21 + \\ quits, it will write the name of the last visited 22 + \\ directory to STDOUT. 23 + \\ 24 + ; 11 25 12 26 pub const std_options: std.Options = .{ 13 27 .log_scope_levels = &.{ ··· 16 30 }, 17 31 }; 18 32 33 + const Options = struct { 34 + help: bool = false, 35 + version: bool = false, 36 + @"choose-dir": bool = false, 37 + @"entry-path": []const u8 = ".", 38 + 39 + fn optKind(a: []const u8) enum { short, long, positional } { 40 + if (std.mem.startsWith(u8, a, "--")) return .long; 41 + if (std.mem.startsWith(u8, a, "-")) return .short; 42 + return .positional; 43 + } 44 + }; 45 + 19 46 pub fn main() !void { 20 47 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 21 48 defer { ··· 26 53 } 27 54 const alloc = gpa.allocator(); 28 55 29 - var entry_buf: [std.fs.max_path_bytes]u8 = undefined; 30 - var entry_dir_path: ?[]const u8 = null; 56 + var last_dir: ?[]const u8 = null; 57 + var entry_path_buf: [std.fs.max_path_bytes]u8 = undefined; 31 58 59 + var opts = Options{}; 32 60 var args = std.process.args(); 33 61 _ = args.skip(); 34 62 while (args.next()) |arg| { 35 - if (std.mem.eql(u8, arg, "--version") or std.mem.eql(u8, arg, "-v")) { 36 - std.debug.print("jido v{}\n", .{options.version}); 37 - return; 63 + switch (Options.optKind(arg)) { 64 + .short => { 65 + const str = arg[1..]; 66 + for (str) |b| { 67 + switch (b) { 68 + 'v' => opts.version = true, 69 + 'h' => opts.help = true, 70 + else => { 71 + std.log.err("Invalid opt: '{c}'", .{b}); 72 + std.process.exit(1); 73 + }, 74 + } 75 + } 76 + }, 77 + .long => { 78 + var split = std.mem.splitScalar(u8, arg[2..], '='); 79 + const opt = split.first(); 80 + const val = split.rest(); 81 + if (std.mem.eql(u8, opt, "version")) { 82 + opts.version = true; 83 + } else if (std.mem.eql(u8, opt, "help")) { 84 + opts.help = true; 85 + } else if (std.mem.eql(u8, opt, "choose-dir")) { 86 + opts.@"choose-dir" = true; 87 + } else if (std.mem.eql(u8, opt, "entry-dir")) { 88 + const path = if (std.mem.eql(u8, val, "")) "." else val; 89 + var dir = try std.fs.cwd().openDir(".", .{ .iterate = true }); 90 + defer dir.close(); 91 + opts.@"entry-path" = resolvePath(&entry_path_buf, path, dir); 92 + } 93 + }, 94 + .positional => { 95 + std.log.err("Invalid opt: '{s}'. Jido does not take positional arguments.", .{arg}); 96 + std.process.exit(1); 97 + }, 38 98 } 99 + } 39 100 40 - if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) { 41 - std.debug.print( 42 - \\Usage: jido 43 - \\ 44 - \\a lightweight Unix TUI file explorer 45 - \\ 46 - \\Flags: 47 - \\ -h, --help Show help information and exit. 48 - \\ -v, --version Print version information and exit. 49 - \\ --entry-dir=PATH Open jido at chosen dir. 50 - \\ 51 - , .{}); 52 - return; 53 - } 101 + if (opts.help) { 102 + std.debug.print(help_menu, .{}); 103 + return; 104 + } 54 105 55 - if (std.mem.startsWith(u8, arg, "--entry-dir")) { 56 - var path: ?[]const u8 = null; 57 - if (arg.len > 11 and arg[11] == '=') { 58 - var iter = std.mem.tokenizeAny(u8, arg, "="); 59 - _ = iter.next(); 60 - if (iter.next()) |p| path = p; 61 - } else { 62 - if (args.next()) |p| path = p; 63 - } 64 - 65 - if (path) |p| { 66 - var dir = try std.fs.cwd().openDir(".", .{ .iterate = true }); 67 - defer dir.close(); 68 - entry_dir_path = resolvePath(&entry_buf, p, dir); 69 - } 70 - } 106 + if (opts.version) { 107 + std.debug.print("jido v{}\n", .{options.version}); 108 + return; 71 109 } 72 110 73 111 { 74 - var app = App.init(alloc, entry_dir_path) catch { 112 + var app = App.init(alloc, opts.@"entry-path") catch { 75 113 vaxis.recover(); 76 - std.posix.exit(1); 114 + std.process.exit(1); 77 115 }; 78 116 defer app.deinit(); 79 117 ··· 104 142 app.file_logger = if (config.config_dir) |dir| FileLogger.init(dir) else null; 105 143 106 144 try app.run(); 145 + 146 + if (opts.@"choose-dir") { 147 + last_dir = alloc.dupe(u8, try app.directories.fullPath(".")) catch null; 148 + } 107 149 } 108 150 151 + // Must be printed after app has deinit as part of that process clears 152 + // the screen. 153 + if (last_dir) |path| { 154 + const stdout = std.io.getStdOut().writer(); 155 + stdout.print("{s}\n", .{path}) catch {}; 156 + alloc.free(path); 157 + } 109 158 }