summaryrefslogtreecommitdiff
path: root/src/list.zig
blob: bf95c2c5c12c51268198babff1e47f2b8e945981 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const std = @import("std");
const zup = @import("zup");

const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
const Config = zup.Config;
const Installation = zup.Installation;
const Installations = zup.Installations;

pub const params =
    \\--active         List the active version
    \\-a, --all        List the active, available, and installed versions
    \\-A, --available  List available versions
    \\-i, --installed  List installed versions
;
pub const description = "Lists Zig versions.  Default is `--active -i`.";
pub const min_args = 0;
pub const max_args = 0;

pub fn main(comptime Result: type, config: Config, res: Result) !void {
    const allocator = config.allocator;
    
    var list_active = res.args.active;
    var list_available = res.args.available;
    var list_installed = res.args.installed;

    if (res.args.all) {
        list_active = true;
        list_available = true;
        list_installed = true;
    } else if (!list_active and !list_available and !list_installed) {
        list_active = true;
        list_installed = true;
    }

    if (list_active) {
        const active = try Installation.getActiveName(allocator);
        defer if (active) |s| allocator.free(s);
        // TODO: zig-bug should I really need to do this?
        try printActive(if (active) |a| a else null);
    }

    if (list_installed) {
        var installed = try Installation.getInstalledList(allocator);
        defer Installation.deinitMap(allocator, &installed);
        try printInstalledList(allocator, installed);
    }

    if (list_available) {
        var available = try Installation.getAvailableList(config);
        defer Installation.deinitMap(allocator, &available);
        try printAvailableList(allocator, available);
    }
}

fn printActive(active: ?[]const u8) !void {
    const writer = std.io.getStdOut().writer();
    try writer.writeAll("Active installation: ");
    if (active) |act| {
        try writer.writeAll(act);
    } else {
        try writer.writeAll("NONE");
    }

    try writer.writeByte('\n');
}

fn printAvailableList(allocator: Allocator, avail: Installations) !void {
    const writer = std.io.getStdOut().writer();
    try writer.writeAll("Available versions:\n");
    try printList(allocator, avail);
}

fn printInstalledList(allocator: Allocator, installed: Installations) !void {
    const writer = std.io.getStdOut().writer();
    try writer.writeAll("Installed versions:\n");
    try printList(allocator, installed);
}

fn printList(allocator: Allocator, installations: Installations) !void {
    const InstallationAndName = struct {
        name: []const u8,
        installation: Installation,

        const Self = @This();

        pub fn lessThan(_: void, lhs: Self, rhs: Self) bool {
            return lhs.installation.version.order(rhs.installation.version) == .lt;
        }
    };

    var list = try ArrayList(InstallationAndName).initCapacity(allocator, installations.unmanaged.size);
    defer list.deinit();

    var it = installations.iterator();
    while (it.next()) |kv| {
        list.appendAssumeCapacity(.{ .name = kv.key_ptr.*, .installation = kv.value_ptr.* });
    }

    std.sort.sort(InstallationAndName, list.items, {}, InstallationAndName.lessThan);

    const writer = std.io.getStdOut().writer();
    for (list.items) |item| {
        try writer.print("  {s}: {}\n", .{ item.name, item.installation.version });
    }
}