pub const Installation = @import("Installation.zig"); pub const Installations = Installation.Installations; pub const SubCommand = @import("subcommand.zig").SubCommand; pub const help = SubCommand(Help); pub const install = SubCommand(@import("install.zig")); pub const list = SubCommand(@import("list.zig")); pub const remove = SubCommand(@import("remove.zig")); pub const @"switch" = SubCommand(@import("switch.zig")); pub const update = SubCommand(@import("update.zig")); pub const version = SubCommand(Version); const std = @import("std"); const zup_config = @import("zup-config"); const Allocator = std.mem.Allocator; const ArgIterator = std.process.ArgIterator; const ComptimeStringMap = std.ComptimeStringMap; const GPA = std.heap.GeneralPurposeAllocator(.{}); const Tuple = std.meta.Tuple; // TODO: config for supported triples. while smth like x86_64-macos on aarch64-macos can be hardcoded, that won't be // the case for someone with qemu-user on linux pub fn main() !void { var gpa = GPA{}; const allocator = gpa.allocator(); defer _ = gpa.deinit(); var args = try std.process.argsWithAllocator(allocator); defer args.deinit(); _ = args.skip(); const cmd = args.next() orelse { return Help.mainHelp(); }; return dispatch(cmd, "main", unknownCmd, .{ cmd, allocator, &args }); } pub fn printVersion() !void { return std.io.getStdErr().writer().print("{}\n", .{zup_config.version}); } const Command = enum { help, install, list, remove, @"switch", update, version, }; const CommandMap = blk: { const Pair = Tuple(&.{ []const u8, Command }); const commands = @typeInfo(Command).Enum.fields; var map_data: [commands.len + 2]Pair = undefined; map_data[0] = .{ "--help", .help }; map_data[1] = .{ "--version", .version }; var idx: usize = 2; inline for (commands) |command| { map_data[idx] = .{ command.name, @intToEnum(Command, command.value) }; idx += 1; } break :blk ComptimeStringMap(Command, map_data); }; fn dispatch( cmd: []const u8, comptime fn_name: []const u8, comptime default_fn: anytype, args: anytype, ) !void { // TODO: This can still be improved, currently we're looping through all possible values, it could be somehow made // into a switch. const cmd_enum = CommandMap.get(cmd) orelse return @call(.{}, default_fn, args); const commands = @typeInfo(Command).Enum.fields; inline for (commands) |command| { if (@enumToInt(cmd_enum) == command.value) { // TODO: zig-bug it cries about modifying a constant if // I just write `return @call(.{}, fun, args);` const fun = @field(@field(@This(), command.name), fn_name); return call(fun, args); } } unreachable; } inline fn call(fun: anytype, args: anytype) !void { return @call(.{}, fun, args); } fn unknownCmd(cmd: []const u8, _: Allocator, _: *ArgIterator) !void { std.log.err("Unknown subcommand: {s}", .{cmd}); return error.ArgError; } const Help = struct { pub const params = ""; pub const description = "Displays help for the specified ."; pub const min_args = 0; pub const max_args = 1; pub fn main(comptime Result: type, _: Allocator, res: Result) !void { if (res.positionals.len == 0) { return mainHelp(); } const cmd = res.positionals[0]; return dispatch(cmd, "help", unknownHelp, .{cmd}); } pub fn mainHelp() !void { const writer = std.io.getStdErr().writer(); try writer.writeAll( \\USAGE: zup \\ \\These are the common Zup commands: \\ \\ install Install a Zig version \\ help See the help for various topics \\ list List Zig versions \\ remove Remove an installed Zig version \\ switch Switch between installed Zig versions \\ update Update installed Zig versions \\ version Print the version of Zup \\ \\You can find out more about a command by running `zup help `. \\ ); } fn unknownHelp(cmd: []const u8) !void { std.log.err("Unknown subcommand: {s}", .{cmd}); try mainHelp(); return error.ArgError; } }; const Version = struct { pub const params = ""; pub const description = "Print the version of Zup and exit."; pub const min_args = 0; pub const max_args = 0; pub fn main(comptime Result: type, _: Allocator, _: Result) !void { return printVersion(); } }; test "basic test" { try std.testing.expectEqual(10, 3 + 7); }