Skip to content

Instantly share code, notes, and snippets.

@JeffreyVdb
Created November 29, 2021 15:56
Show Gist options
  • Save JeffreyVdb/6bcda6e79259b70a460030b664d922ee to your computer and use it in GitHub Desktop.
Save JeffreyVdb/6bcda6e79259b70a460030b664d922ee to your computer and use it in GitHub Desktop.
Prioritize paths
const std = @import("std");
const HashMap = std.HashMap;
const Allocator = std.mem.Allocator;
const StringHashMap = std.hash_map.StringHashMap;
const SinglyLinkedList = std.SinglyLinkedList;
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
var prioArgs = try readArgsIntoSet(allocator, args[1..]);
defer prioArgs.deinit();
const stdout = std.io.getStdOut().writer();
const osPaths = try getOSPaths(allocator);
const AL = AppendableLinkedList([]const u8);
var prioPaths = AL{};
var windowsPaths = AL{};
var otherPaths = AL{};
var osPathIt = osPaths.first;
var dataSize: usize = 0;
while (osPathIt) |node| : (osPathIt = node.next) {
dataSize += node.data.len + 1;
if (prioArgs.getPtr(node.data)) |_| {
try prioPaths.append(allocator, node.data);
} else if (std.mem.startsWith(u8, node.data, "/mnt/c")) {
try windowsPaths.append(allocator, node.data);
} else {
try otherPaths.append(allocator, node.data);
}
}
const buffer = try allocator.alloc(u8, dataSize);
const pathLists = [_]AL{ prioPaths, otherPaths, windowsPaths };
var index: usize = 0;
for (pathLists) |lst| {
var it = lst.linkedList.first;
while (it) |node| : (it = node.next) {
const dest = buffer[index..];
std.mem.copy(u8, dest, node.data);
dest[node.data.len] = ':';
index += node.data.len + 1;
}
}
_ = try stdout.print("{s}", .{buffer[0 .. buffer.len - 1]});
}
fn AppendableLinkedList(comptime T: type) type {
return struct {
const L = SinglyLinkedList(T);
const Self = @This();
linkedList: L = L{},
lastNode: ?*L.Node = null,
pub fn append(self: *Self, allocator: *Allocator, v: T) !void {
var node = try allocator.create(L.Node);
node.data = v;
if (self.lastNode) |currentNode| {
currentNode.insertAfter(node);
} else {
self.linkedList.prepend(node);
}
self.lastNode = node;
}
};
}
fn getOSPaths(allocator: *Allocator) !SinglyLinkedList([]const u8) {
const pathEnv = std.os.getenv("PATH").?;
const delim = [_]u8{std.fs.path.delimiter};
var pathIter = std.mem.split(pathEnv, delim[0..]);
const L = SinglyLinkedList([]const u8);
var list = L{};
var lastNode: *L.Node = undefined;
if (pathIter.next()) |path| {
var firstNode = try allocator.create(L.Node);
firstNode.data = path;
list.prepend(firstNode);
lastNode = firstNode;
}
while (pathIter.next()) |path| {
var newNode = try allocator.create(L.Node);
newNode.data = path;
lastNode.insertAfter(newNode);
lastNode = newNode;
}
return list;
}
fn readArgsIntoSet(allocator: *Allocator, args: [][]u8) !StringHashMap(void) {
var map = StringHashMap(void).init(allocator);
for (args) |arg| {
try map.put(arg, .{});
}
return map;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment