Hi,
I created a library for working with globs in URI references. The library is inspired by
URL Pattern.
Features
- Parsing: Parsing of URI references with support for captures.
- Matching: Matching URI references against a glob.
- Expanding: Expanding of URI globs to all possible combinations of URI strings.
- Scanning: Scanning of iterators of URI references for matches.
Usage
The following snippet shows how to use the library:
const std = @import("std");
const heap = std.heap;
const mem = std.mem;
const debug = std.debug;
const urig = @import("uri_glob");
pub fn main() !void {
var gpa = heap.GeneralPurposeAllocator(.{}){};
defer debug.assert(gpa.deinit() == .ok);
var arena = heap.ArenaAllocator.init(gpa.allocator());
defer arena.deinit();
const allocator = arena.allocator();
debug.print("- Creating glob.\n", .{});
const template = "./repos/{repo}/index.(css|html|[jt]s?[x])";
var glob, const remaining = try urig.Sequence.create(allocator, template);
// Ensure that the whole `template` has been parsed.
debug.assert(remaining.len == 0);
debug.print("- Parsing.\n", .{});
const parse_filenames = &[_][]const u8{
"./repos/website/index.css",
"./repos/website/index.html",
"./repos/website/index.js",
};
for (parse_filenames, 0..) |filename, i| {
const parsed, const captures = try glob.parse(filename);
debug.assert(mem.eql(u8, parse_filenames[i], parsed));
debug.assert(mem.eql(u8, "website", captures.get("repo").?));
}
debug.print("- Matching.\n", .{});
const match_filename = "./repos/website/index.tsx";
debug.assert(glob.match(match_filename));
debug.print("- Expanding.\n", .{});
const capture_entries = &[_]urig.Glob.ExpansionVariableEntry{
.{ "repo", "website" },
};
const expansion_expectations = &[_][]const u8{
"./repos/website/index.css",
"./repos/website/index.html",
"./repos/website/index.js",
"./repos/website/index.ts",
"./repos/website/index.jsx",
"./repos/website/index.tsx",
};
const expansions = try glob.expand(capture_entries);
debug.assert(expansion_expectations.len == expansions.len);
for (expansion_expectations, 0..) |expected, i| {
debug.assert(mem.eql(u8, expected, expansions[i]));
}
debug.print("- Scanning.\n", .{});
const base_uri_reference = "./repos/website/";
const scan_filenames = &[_][]const u8{
"index.css",
"index.html",
"src/index.html",
"index.js",
"main.js",
};
const Iterator = urig.Glob.UriListIterator;
var iterator = Iterator{ .data = .{ .list = scan_filenames } };
var uri_iterator = urig.Glob.UriIterator(Iterator){
.data = &iterator,
.next = Iterator.next,
};
var scanner = glob.scan(Iterator, &uri_iterator, base_uri_reference);
const scan_expectations = &[_][]const u8{
"./repos/website/index.css",
"./repos/website/index.html",
"./repos/website/index.js",
};
var i: usize = 0;
while (scanner.next()) |match| : (i += 1) {
debug.assert(mem.eql(u8, scan_expectations[i], match));
}
debug.assert(scan_expectations.len == i);
debug.print("- Done!\n", .{});
}
Examples
Some of the URI references the library can handle are shown the table below.
| Glob | Example URI |
|---|---|
https://github.com/{owner}/{repo} |
https://github.com/oven-sh/bun |
https://{sub_domain}(+[[:alnum:]]).google.com |
https://mail.google.com |
*(*/)*.zig |
project/src/main.zig |
https+[.] |
https://zig.guide |
Installation
The library is published on GitHub.