From b6f900f2a92e3117f9060fe420f7a5ccfdac2899 Mon Sep 17 00:00:00 2001 From: BrookJeynes Date: Tue, 27 May 2025 20:17:44 +1000 Subject: [PATCH] feat: add `--entry-dir=PATH` arg This arg allows jido to be opened within a specified directory. --- src/app.zig | 4 +-- src/commands.zig | 28 +++++++++------- src/config.zig | 1 + src/directories.zig | 18 ++++++++-- src/main.zig | 82 ++++++++++++++++++++++++++++++--------------- 5 files changed, 89 insertions(+), 44 deletions(-) diff --git a/src/app.zig b/src/app.zig index d1d4d40..02af05a 100644 --- a/src/app.zig +++ b/src/app.zig @@ -131,7 +131,7 @@ images: struct { cache: std.StringHashMap(Image), }, -pub fn init(alloc: std.mem.Allocator) !App { +pub fn init(alloc: std.mem.Allocator, entry_dir: ?[]const u8) !App { var vx = try vaxis.init(alloc, .{ .kitty_keyboard_flags = .{ .report_text = false, @@ -150,7 +150,7 @@ pub fn init(alloc: std.mem.Allocator) !App { .should_quit = false, .vx = vx, .tty = try vaxis.Tty.init(), - .directories = try Directories.init(alloc), + .directories = try Directories.init(alloc, entry_dir), .help_menu = help_menu, .text_input = vaxis.widgets.TextInput.init(alloc, &vx.unicode), .actions = CircStack(Action, actions_len).init(), diff --git a/src/commands.zig b/src/commands.zig index ae337d7..518cc3e 100644 --- a/src/commands.zig +++ b/src/commands.zig @@ -131,25 +131,27 @@ pub fn emptyTrash(app: *App) error{OutOfMemory}!void { try app.repopulateDirectory(""); } +pub fn resolvePath(buf: *[std.fs.max_path_bytes]u8, path: []const u8, dir: std.fs.Dir) []const u8 { + const resolved_path = if (std.mem.startsWith(u8, path, "~")) path: { + var home_dir = (environment.getHomeDir() catch break :path path) orelse break :path path; + defer home_dir.close(); + const relative = std.mem.trim(u8, path[1..], std.fs.path.sep_str); + return home_dir.realpath( + if (relative.len == 0) "." else relative, + buf, + ) catch path; + } else path; + + return dir.realpath(resolved_path, buf) catch path; +} + ///Change directory. pub fn cd(app: *App, path: []const u8) error{OutOfMemory}!void { var message: ?[]const u8 = null; defer if (message) |msg| app.alloc.free(msg); var path_buf: [std.fs.max_path_bytes]u8 = undefined; - const resolved_path = lbl: { - const resolved_path = if (std.mem.startsWith(u8, path, "~")) path: { - var home_dir = (environment.getHomeDir() catch break :path path) orelse break :path path; - defer home_dir.close(); - const relative = std.mem.trim(u8, path[1..], std.fs.path.sep_str); - break :lbl home_dir.realpath( - if (relative.len == 0) "." else relative, - &path_buf, - ) catch path; - } else path; - - break :lbl app.directories.dir.realpath(resolved_path, &path_buf) catch path; - }; + const resolved_path = resolvePath(&path_buf, path, app.directories.dir); const dir = app.directories.dir.openDir(resolved_path, .{ .iterate = true }) catch |err| { message = switch (err) { diff --git a/src/config.zig b/src/config.zig index f06e67a..e741903 100644 --- a/src/config.zig +++ b/src/config.zig @@ -18,6 +18,7 @@ const Config = struct { preview_file: bool = true, empty_trash_on_exit: bool = false, true_dir_size: bool = false, + entry_dir: ?[]const u8 = null, styles: Styles = .{}, keybinds: Keybinds = .{}, diff --git a/src/directories.zig b/src/directories.zig index ae90da3..3994f27 100644 --- a/src/directories.zig +++ b/src/directories.zig @@ -19,10 +19,24 @@ history: CircStack(usize, history_len), child_entries: List([]const u8), searcher: fuzzig.Ascii, -pub fn init(alloc: std.mem.Allocator) !Self { +pub fn init(alloc: std.mem.Allocator, entry_dir: ?[]const u8) !Self { + const dir_path = if (entry_dir) |dir| dir else "."; + const dir = std.fs.cwd().openDir(dir_path, .{ .iterate = true }) catch |err| { + switch (err) { + error.FileNotFound => { + std.log.err("path '{s}' could not be found.", .{dir_path}); + return err; + }, + else => { + std.log.err("{}", .{err}); + return err; + }, + } + }; + return Self{ .alloc = alloc, - .dir = try std.fs.cwd().openDir(".", .{ .iterate = true }), + .dir = dir, .entries = List(std.fs.Dir.Entry).init(alloc), .history = CircStack(usize, history_len).init(), .child_entries = List([]const u8).init(alloc), diff --git a/src/main.zig b/src/main.zig index f3cf470..fdcf62c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5,6 +5,7 @@ const App = @import("app.zig"); const FileLogger = @import("file_logger.zig"); const vaxis = @import("vaxis"); const config = &@import("./config.zig").config; +const resolvePath = @import("./commands.zig").resolvePath; pub const panic = vaxis.panic_handler; @@ -25,9 +26,12 @@ pub fn main() !void { } const alloc = gpa.allocator(); + var entry_buf: [std.fs.max_path_bytes]u8 = undefined; + var entry_dir_path: ?[]const u8 = null; + var args = std.process.args(); _ = args.skip(); - if (args.next()) |arg| { + while (args.next()) |arg| { if (std.mem.eql(u8, arg, "--version") or std.mem.eql(u8, arg, "-v")) { std.debug.print("jido v{}\n", .{options.version}); return; @@ -42,40 +46,64 @@ pub fn main() !void { \\Flags: \\ -h, --help Show help information and exit. \\ -v, --version Print version information and exit. + \\ --entry-dir=PATH Open jido at chosen dir. \\ , .{}); return; } + + if (std.mem.startsWith(u8, arg, "--entry-dir")) { + var path: ?[]const u8 = null; + if (arg.len > 11 and arg[11] == '=') { + var iter = std.mem.tokenizeAny(u8, arg, "="); + _ = iter.next(); + if (iter.next()) |p| path = p; + } else { + if (args.next()) |p| path = p; + } + + if (path) |p| { + var dir = try std.fs.cwd().openDir(".", .{ .iterate = true }); + defer dir.close(); + entry_dir_path = resolvePath(&entry_buf, p, dir); + } + } } - var app = try App.init(alloc); - defer app.deinit(); + { + var app = App.init(alloc, entry_dir_path) catch { + vaxis.recover(); + std.posix.exit(1); + }; + defer app.deinit(); + + config.parse(alloc, &app) catch |err| switch (err) { + error.SyntaxError => { + app.notification.write("Encountered a syntax error while parsing the config file.", .err) catch { + std.log.err("Encountered a syntax error while parsing the config file.", .{}); + }; + }, + error.InvalidCharacter => { + app.notification.write("One or more overriden keybinds are invalid.", .err) catch { + std.log.err("One or more overriden keybinds are invalid.", .{}); + }; + }, + error.DuplicateKeybind => { + // Error logged in function + }, + else => { + const message = try std.fmt.allocPrint(alloc, "Encountend an unknown error while parsing the config file - {}", .{err}); + defer alloc.free(message); - config.parse(alloc, &app) catch |err| switch (err) { - error.SyntaxError => { - app.notification.write("Encountered a syntax error while parsing the config file.", .err) catch { - std.log.err("Encountered a syntax error while parsing the config file.", .{}); - }; - }, - error.InvalidCharacter => { - app.notification.write("One or more overriden keybinds are invalid.", .err) catch { - std.log.err("One or more overriden keybinds are invalid.", .{}); - }; - }, - error.DuplicateKeybind => { - // Error logged in function - }, - else => { - const message = try std.fmt.allocPrint(alloc, "Encountend an unknown error while parsing the config file - {}", .{err}); - defer alloc.free(message); + app.notification.write(message, .err) catch { + std.log.err("Encountend an unknown error while parsing the config file - {}", .{err}); + }; + }, + }; - app.notification.write(message, .err) catch { - std.log.err("Encountend an unknown error while parsing the config file - {}", .{err}); - }; - }, - }; + app.file_logger = if (config.config_dir) |dir| FileLogger.init(dir) else null; - app.file_logger = if (config.config_dir) |dir| FileLogger.init(dir) else null; + try app.run(); + } - try app.run(); } -- 2.51.2