summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 0000000..f2868b6
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,155 @@
1pub const Installation = @import("Installation.zig");
2pub const Installations = Installation.Installations;
3pub const SubCommand = @import("subcommand.zig").SubCommand;
4
5pub const help = SubCommand(Help);
6pub const install = SubCommand(@import("install.zig"));
7pub const list = SubCommand(@import("list.zig"));
8pub const remove = SubCommand(@import("remove.zig"));
9pub const @"switch" = SubCommand(@import("switch.zig"));
10pub const update = SubCommand(@import("update.zig"));
11pub const version = SubCommand(Version);
12
13const std = @import("std");
14const zup_config = @import("zup-config");
15
16const Allocator = std.mem.Allocator;
17const ArgIterator = std.process.ArgIterator;
18const ComptimeStringMap = std.ComptimeStringMap;
19const GPA = std.heap.GeneralPurposeAllocator(.{});
20const Tuple = std.meta.Tuple;
21
22// TODO: config for supported triples. while smth like x86_64-macos on aarch64-macos can be hardcoded, that won't be
23// the case for someone with qemu-user on linux
24
25pub fn main() !void {
26 var gpa = GPA{};
27 const allocator = gpa.allocator();
28 defer _ = gpa.deinit();
29
30 var args = try std.process.argsWithAllocator(allocator);
31 defer args.deinit();
32
33 _ = args.skip();
34 const cmd = args.next() orelse {
35 return Help.mainHelp();
36 };
37
38 return dispatch(cmd, "main", unknownCmd, .{ cmd, allocator, &args });
39}
40
41pub fn printVersion() !void {
42 return std.io.getStdErr().writer().print("{}\n", .{zup_config.version});
43}
44
45const Command = enum {
46 help,
47 install,
48 list,
49 remove,
50 @"switch",
51 update,
52 version,
53};
54
55const CommandMap = blk: {
56 const Pair = Tuple(&.{ []const u8, Command });
57 const commands = @typeInfo(Command).Enum.fields;
58 var map_data: [commands.len + 2]Pair = undefined;
59 map_data[0] = .{ "--help", .help };
60 map_data[1] = .{ "--version", .version };
61 var idx: usize = 2;
62 inline for (commands) |command| {
63 map_data[idx] = .{ command.name, @intToEnum(Command, command.value) };
64 idx += 1;
65 }
66
67 break :blk ComptimeStringMap(Command, map_data);
68};
69
70fn dispatch(
71 cmd: []const u8,
72 comptime fn_name: []const u8,
73 comptime default_fn: anytype,
74 args: anytype,
75) !void {
76 // TODO: This can still be improved, currently we're looping through all possible values, it could be somehow made
77 // into a switch.
78 const cmd_enum = CommandMap.get(cmd) orelse return @call(.{}, default_fn, args);
79 const commands = @typeInfo(Command).Enum.fields;
80 inline for (commands) |command| {
81 if (@enumToInt(cmd_enum) == command.value) {
82 // TODO: zig-bug it cries about modifying a constant if
83 // I just write `return @call(.{}, fun, args);`
84 const fun = @field(@field(@This(), command.name), fn_name);
85 return call(fun, args);
86 }
87 }
88 unreachable;
89}
90
91inline fn call(fun: anytype, args: anytype) !void {
92 return @call(.{}, fun, args);
93}
94
95fn unknownCmd(cmd: []const u8, _: Allocator, _: *ArgIterator) !void {
96 std.log.err("Unknown subcommand: {s}", .{cmd});
97 return error.ArgError;
98}
99
100const Help = struct {
101 pub const params = "<COMMAND>";
102 pub const description = "Displays help for the specified <COMMAND>.";
103 pub const min_args = 0;
104 pub const max_args = 1;
105
106 pub fn main(comptime Result: type, _: Allocator, res: Result) !void {
107 if (res.positionals.len == 0) {
108 return mainHelp();
109 }
110
111 const cmd = res.positionals[0];
112 return dispatch(cmd, "help", unknownHelp, .{cmd});
113 }
114
115 pub fn mainHelp() !void {
116 const writer = std.io.getStdErr().writer();
117 try writer.writeAll(
118 \\USAGE: zup <COMMAND>
119 \\
120 \\These are the common Zup commands:
121 \\
122 \\ install Install a Zig version
123 \\ help See the help for various topics
124 \\ list List Zig versions
125 \\ remove Remove an installed Zig version
126 \\ switch Switch between installed Zig versions
127 \\ update Update installed Zig versions
128 \\ version Print the version of Zup
129 \\
130 \\You can find out more about a command by running `zup help <command>`.
131 \\
132 );
133 }
134
135 fn unknownHelp(cmd: []const u8) !void {
136 std.log.err("Unknown subcommand: {s}", .{cmd});
137 try mainHelp();
138 return error.ArgError;
139 }
140};
141
142const Version = struct {
143 pub const params = "";
144 pub const description = "Print the version of Zup and exit.";
145 pub const min_args = 0;
146 pub const max_args = 0;
147
148 pub fn main(comptime Result: type, _: Allocator, _: Result) !void {
149 return printVersion();
150 }
151};
152
153test "basic test" {
154 try std.testing.expectEqual(10, 3 + 7);
155}