From b7ea2bd8aa1eb930794464b6cdf4153126f8085a Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Tue, 3 Dec 2024 21:36:53 +0530 Subject: [PATCH 1/4] add cova as dependency --- build.zig | 2 ++ build.zig.zon | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/build.zig b/build.zig index 3503075..3998b40 100644 --- a/build.zig +++ b/build.zig @@ -6,6 +6,7 @@ pub fn build(b: *std.Build) !void { const optimize = b.standardOptimizeOption(.{}); const zip = b.dependency("zip", .{}); + const cova = b.dependency("cova", .{}); const common = b.createModule(.{ .root_source_file = b.path("src/common/root.zig") }); const default_os = target.result.os.tag; @@ -32,6 +33,7 @@ pub fn build(b: *std.Build) !void { zigverm.root_module.addImport("common", common); zigverm.root_module.addImport("zip", zip.module("zip")); + zigverm.root_module.addImport("cova", cova.module("cova")); zig.root_module.addImport("common", common); b.installArtifact(zigverm); b.installArtifact(zig); diff --git a/build.zig.zon b/build.zig.zon index 891e263..a2859e7 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,6 +8,10 @@ .url = "https://github.com/AMythicDev/zip.zig/archive/refs/tags/v0.1.0.tar.gz", .hash = "1220b5e3ecda108ccae1749479ec7e02f1f2ddcbb8102a2b5a7cd92bc8aebb4d153d", }, + .cova = .{ + .url = "https://github.com/00JCIV00/cova/archive/refs/tags/v0.10.1-beta.tar.gz", + .hash = "12202782cc66e88f0c15b9acea9d6d1d50dbe941d68b5297927243f6d0377dbb1123", + }, }, .paths = .{ From 88941986eef5a3d373a88ea32d4fc3bb1f13fdee Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Tue, 3 Dec 2024 23:43:32 +0530 Subject: [PATCH 2/4] write the cli spec --- src/cli.zig | 160 ++++++++++++++++++++++++--------------------------- src/main.zig | 88 +++++++++++++++------------- 2 files changed, 121 insertions(+), 127 deletions(-) diff --git a/src/cli.zig b/src/cli.zig index 6517827..6360e28 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -36,94 +36,82 @@ const helptext = \\ -V --version Print version info ; -pub const OverrideArrgs = struct { +const cova = @import("cova"); +pub const CommandT = cova.Command.Base(); +pub const OptionT = CommandT.OptionT; +pub const ValueT = CommandT.ValueT; + +pub const Install = struct { version: []const u8, - directory: ?[]const u8, }; -pub const Cli = union(enum) { - install: []const u8, - remove: []const u8, - show, - update_self, - override: OverrideArrgs, - override_rm: ?[]const u8, - update: ?[]const u8, - std: ?[]const u8, - reference: ?[]const u8, - - pub fn read_args(alloc: Allocator) anyerror!Cli { - var arg_iter = try std.process.argsWithAllocator(alloc); - defer arg_iter.deinit(); - - _ = arg_iter.next(); - - var command: Cli = undefined; - - var cmd: []const u8 = undefined; - - { - const trycmd = arg_iter.next(); - if (trycmd) |c| - cmd = c - else - incorrectUsage(null); - } - - if (streql(cmd, "install")) { - const rel = arg_iter.next().?; - command = Cli{ .install = try alloc.dupe(u8, rel) }; - } else if (streql(cmd, "remove")) { - const rel = arg_iter.next().?; - command = Cli{ .remove = try alloc.dupe(u8, rel) }; - } else if (streql(cmd, "update")) { - const rel = arg_iter.next(); - command = Cli{ .update = if (rel) |r| try alloc.dupe(u8, r) else null }; - } else if (streql(cmd, "std")) { - const rel = arg_iter.next(); - command = Cli{ .std = if (rel) |r| try alloc.dupe(u8, r) else null }; - } else if (streql(cmd, "reference")) { - const rel = arg_iter.next(); - command = Cli{ .reference = if (rel) |r| try alloc.dupe(u8, r) else null }; - } else if (streql(cmd, "info")) { - command = Cli.show; - } else if (streql(cmd, "-h") or streql(cmd, "--help")) { - utils.printStdOut("{s}\n", .{helptext}); - std.process.exit(0); - } else if (streql(cmd, "-V") or streql(cmd, "--version")) { - utils.printStdOut("{s}\n", .{Version}); - std.process.exit(0); - } else if (streql(cmd, "update-self")) { - command = Cli.update_self; - } else if (streql(cmd, "override")) { - const rel_or_directory = arg_iter.next() orelse return incorrectUsage(null); - const rel = arg_iter.next(); - - var override_args = OverrideArrgs{ .version = undefined, .directory = null }; - - if (rel != null) { - override_args.version = try alloc.dupe(u8, rel.?); - override_args.directory = try alloc.dupe(u8, rel_or_directory); - } else { - override_args.version = try alloc.dupe(u8, rel_or_directory); - } - - command = Cli{ .override = override_args }; - } else if (streql(cmd, "override-rm")) { - const directory = arg_iter.next() orelse return incorrectUsage(null); - command = Cli{ .override_rm = directory }; - } else incorrectUsage(cmd); - - return command; - } +pub const Cli = CommandT{ + .name = "zigverm", + .description = "A version manager for the Zig programming language", + .sub_cmds = &.{ + .{ + .name = "install", + .description = "Install a specific version", + .vals = &.{ + ValueT.ofType([]const u8, .{ .name = "version", .description = "Version can be any valid semantic version or master or stable" }), + }, + }, + .{ + .name = "remove", + .description = "Remove a already installed specific version.", + .vals = &.{ + ValueT.ofType([]const u8, .{ .name = "version", .description = "Version can be any valid semantic version or master or stable" }), + }, + }, + .{ + .name = "override", + .description = "Override the version of zig used", + .vals = &.{ + ValueT.ofType([]const u8, .{ .name = "directory", .description = + \\DIRECTORY can be + \\ - Path to a directory, under which to override + \\ - "default", to change the default version + \\ - ommited to use the current directory + , .default_val = "" }), + ValueT.ofType([]const u8, .{ .name = "version", .description = "Version can be any valid semantic version or master or stable" }), + }, + }, + .{ + .name = "override-rm", + .description = "Override the version of zig used", + .vals = &.{ + ValueT.ofType([]const u8, .{ .name = "directory", .description = "DIRECTORY should be path to a directory, for which to remove override" }), + ValueT.ofType([]const u8, .{ .name = "version", .description = "Version can be any valid semantic version or master or stable" }), + }, + }, + .{ + .name = "std", + .description = "Open the standard library documentation in the default web browser.", + .vals = &.{ + ValueT.ofType([]const u8, .{ .name = "version", .description = "Opens for this VERSION. If not specified, opens for the active Zig version in the current directory.", .default_val = "" }), + }, + }, + .{ + .name = "reference", + .description = "Open the language reference in the default web browser.", + .vals = &.{ + ValueT.ofType([]const u8, .{ .name = "version", .description = "Opens for this VERSION. If not specified, opens for the active version on the current directory.", .default_val = "" }), + }, + }, + .{ + .name = "info", + .description = "Show information about installations", + }, + .{ + .name = "update-self", + .description = "Update zigverm itself", + }, + }, }; -fn incorrectUsage(cmd: ?[]const u8) noreturn { - if (cmd != null) { - std.debug.print("Incorrect usage for '{s}'. Please see help by using --help\n", .{cmd.?}); - std.process.exit(1); - } else { - std.debug.print("Incorrect usage. Please see help by using --help\n", .{}); - std.process.exit(1); - } -} +// ValueT.GenericT{ +// .string, .{ +// .name = "version", +// .description = "install", +// }, +// }, diff --git a/src/main.zig b/src/main.zig index aa9301e..1dd3f55 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,10 +1,13 @@ const std = @import("std"); const utils = @import("utils.zig"); const builtin = @import("builtin"); -const Cli = @import("cli.zig").Cli; +const cli = @import("cli.zig"); const common = @import("common"); const update_self = @import("update-self.zig"); +const cova = @import("cova"); +const Cli = cli.Cli; +const CommandT = cli.CommandT; const Client = std.http.Client; const http = std.http; const paths = common.paths; @@ -22,50 +25,53 @@ pub fn main() !void { var aa = std.heap.ArenaAllocator.init(std.heap.page_allocator); const alloc = aa.allocator(); - const command = try Cli.read_args(alloc); + const command = try Cli.init(alloc, .{}); + var args_iter = try cova.ArgIteratorGeneric.init(alloc); + const stdout = std.io.getStdOut().writer(); + try cova.parseArgs(&args_iter, CommandT, command, stdout, .{}); var cp = try CommonPaths.resolve(alloc); defer cp.close(); - switch (command) { - Cli.install => |version| { - var rel = try Release.releasefromVersion(version); - if (cp.install_dir.openDir(try common.release_name(alloc, rel), .{})) |_| { - std.log.err("Version already installled. Quitting", .{}); - std.process.exit(0); - } else |_| {} - - var client = Client{ .allocator = alloc }; - defer client.deinit(); - - const resp = try install.get_json_dslist(&client); - const releases = try json.parseFromSliceLeaky(json.Value, alloc, resp.body[0..resp.length], .{}); - - try install.install_release(alloc, &client, releases, &rel, cp); - }, - Cli.remove => |version| { - const rel = try Release.releasefromVersion(version); - try remove_release(alloc, rel, cp); - }, - Cli.show => try show_info(alloc, cp), - Cli.std => |ver| try open_std(alloc, cp, ver), - Cli.reference => |ver| try open_reference(alloc, cp, ver), - Cli.override => |oa| { - var override_args = oa; - const rel = try Release.releasefromVersion(override_args.version); - if (override_args.directory != null and !streql(override_args.directory.?, "default")) { - override_args.directory = try std.fs.realpathAlloc(alloc, override_args.directory.?); - } - const directory = override_args.directory orelse try std.process.getCwdAlloc(alloc); - try override(alloc, cp, rel, directory); - }, - Cli.override_rm => |dir| { - const directory = dir orelse try std.process.getCwdAlloc(alloc); - try override_rm(alloc, cp, directory); - }, - Cli.update_self => try update_self.update_self(alloc, cp), - Cli.update => |version_possible| try update_zig_installation(alloc, cp, version_possible), - } + // switch (command) { + // Cli.install => |version| { + // var rel = try Release.releasefromVersion(version); + // if (cp.install_dir.openDir(try common.release_name(alloc, rel), .{})) |_| { + // std.log.err("Version already installled. Quitting", .{}); + // std.process.exit(0); + // } else |_| {} + // + // var client = Client{ .allocator = alloc }; + // defer client.deinit(); + // + // const resp = try install.get_json_dslist(&client); + // const releases = try json.parseFromSliceLeaky(json.Value, alloc, resp.body[0..resp.length], .{}); + // + // try install.install_release(alloc, &client, releases, &rel, cp); + // }, + // Cli.remove => |version| { + // const rel = try Release.releasefromVersion(version); + // try remove_release(alloc, rel, cp); + // }, + // Cli.show => try show_info(alloc, cp), + // Cli.std => |ver| try open_std(alloc, cp, ver), + // Cli.reference => |ver| try open_reference(alloc, cp, ver), + // Cli.override => |oa| { + // var override_args = oa; + // const rel = try Release.releasefromVersion(override_args.version); + // if (override_args.directory != null and !streql(override_args.directory.?, "default")) { + // override_args.directory = try std.fs.realpathAlloc(alloc, override_args.directory.?); + // } + // const directory = override_args.directory orelse try std.process.getCwdAlloc(alloc); + // try override(alloc, cp, rel, directory); + // }, + // Cli.override_rm => |dir| { + // const directory = dir orelse try std.process.getCwdAlloc(alloc); + // try override_rm(alloc, cp, directory); + // }, + // Cli.update_self => try update_self.update_self(alloc, cp), + // Cli.update => |version_possible| try update_zig_installation(alloc, cp, version_possible), + // } } fn remove_release(alloc: Allocator, rel: Release, cp: CommonPaths) !void { From 9a968689b47d2f1b4ee6161047fb21975d2102ad Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Fri, 20 Dec 2024 16:38:50 +0530 Subject: [PATCH 3/4] refactor: cleanup code --- src/cli.zig | 64 ++++++++++++----------------------------------------- 1 file changed, 14 insertions(+), 50 deletions(-) diff --git a/src/cli.zig b/src/cli.zig index 6360e28..f35d73d 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -4,47 +4,11 @@ const streql = @import("common").streql; const Version = @import("main.zig").Version; const utils = @import("utils.zig"); -const helptext = - \\zigverm - A version manager for Zig - \\ - \\zigverm [options] [command] - \\ - \\Commands: - \\ install Install a specific version. Version can be any valid semantic version - \\ or master or stable - \\ override [DIRECTORY] Override the version of zig used under DIRECTORY. DIRECTORY can be - \\ - Path to a directory, under which to override - \\ - "default", to change the default version - \\ - ommited to use the current directory - \\ override-rm Override the version of zig used under DIRECTORY. DIRECTORY should - \\ be path to a directory, for which to remove override - \\ update [VERSION] Update version to its latest available point release, If [VERSION] is - \\ not provided, it will update all installed versions - \\ update-self Update zigverm itself - \\ std [VERSION] Open the standard library documentation in the default web browser. - \\ If [VERSION] is specified, it will open the documentation for that version - \\ otherwise it will default to of the active version on the current directory. - \\ reference [VERSION] Open the language reference in the default web browser. - \\ If [VERSION] is specified, it will open the reference for that version - \\ otherwise it will default to of the active version on the current directory. - \\ remove Remove a already installed specific version. Version can be any - \\ valid semantic version or master or stable - \\ info Show information about installations - \\ - \\Options: - \\ -h --help Show this help message - \\ -V --version Print version info -; - const cova = @import("cova"); pub const CommandT = cova.Command.Base(); pub const OptionT = CommandT.OptionT; pub const ValueT = CommandT.ValueT; -pub const Install = struct { - version: []const u8, -}; - pub const Cli = CommandT{ .name = "zigverm", .description = "A version manager for the Zig programming language", @@ -66,13 +30,21 @@ pub const Cli = CommandT{ .{ .name = "override", .description = "Override the version of zig used", + .opts = &.{OptionT{ + .name = "directory", + .short_name = 'd', + .long_name = "dir", + .description = + \\ DIRECTORY can be + \\ - Path to a directory, under which to override + \\ - "default", to change the default version + \\ - ommited to use the current directory + , + .val = ValueT.ofType([]const u8, .{ + .name = "directory", + }), + }}, .vals = &.{ - ValueT.ofType([]const u8, .{ .name = "directory", .description = - \\DIRECTORY can be - \\ - Path to a directory, under which to override - \\ - "default", to change the default version - \\ - ommited to use the current directory - , .default_val = "" }), ValueT.ofType([]const u8, .{ .name = "version", .description = "Version can be any valid semantic version or master or stable" }), }, }, @@ -81,7 +53,6 @@ pub const Cli = CommandT{ .description = "Override the version of zig used", .vals = &.{ ValueT.ofType([]const u8, .{ .name = "directory", .description = "DIRECTORY should be path to a directory, for which to remove override" }), - ValueT.ofType([]const u8, .{ .name = "version", .description = "Version can be any valid semantic version or master or stable" }), }, }, .{ @@ -108,10 +79,3 @@ pub const Cli = CommandT{ }, }, }; - -// ValueT.GenericT{ -// .string, .{ -// .name = "version", -// .description = "install", -// }, -// }, From e8b12d183a1ff1cc62b536d4a8a00be6d2a6b3e0 Mon Sep 17 00:00:00 2001 From: Arijit Dey Date: Fri, 20 Dec 2024 23:55:17 +0530 Subject: [PATCH 4/4] std and reference cmd not take optional values --- src/cli.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cli.zig b/src/cli.zig index f35d73d..0885cf5 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -61,6 +61,7 @@ pub const Cli = CommandT{ .vals = &.{ ValueT.ofType([]const u8, .{ .name = "version", .description = "Opens for this VERSION. If not specified, opens for the active Zig version in the current directory.", .default_val = "" }), }, + .vals_mandatory = false, }, .{ .name = "reference", @@ -68,6 +69,7 @@ pub const Cli = CommandT{ .vals = &.{ ValueT.ofType([]const u8, .{ .name = "version", .description = "Opens for this VERSION. If not specified, opens for the active version on the current directory.", .default_val = "" }), }, + .vals_mandatory = false, }, .{ .name = "info",