commit 347529391e4198744e984f99d148fa6a1aefc962
parent d632dedb4dd7fcc273249a94dd610da0f277b879
Author: Sebastian <sebastian@sebsite.pw>
Date: Fri, 29 Sep 2023 22:19:31 -0400
glob: recognize escapes in last path component
So `\*` only matches `*` rather than being treated as a wildcard.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/glob/+test.ha b/glob/+test.ha
@@ -18,6 +18,7 @@ use strings;
("//", flag::NONE),
(".", flag::NONE),
("..", flag::NONE),
+ ("\\*", flag::NONE),
];
for (let i = 0z; i < len(cases); i += 1) {
let gen = glob(cases[i].0, cases[i].1);
@@ -46,18 +47,18 @@ use strings;
@test fn pattern_parse() void = {
const cases: [_](str, bool, str, str, str) = [
- ("foo/bar/baz", true, "foo/bar/", "baz", ""),
- ("foo/b\\ar/baz", true, "foo/b\\ar/", "baz", ""),
- ("foo/b\\ar/baz", false, "foo/bar/", "baz", ""),
- ("/foo/bar/baz", true, "/foo/bar/", "baz", ""),
- ("/foo\\/bar/baz", true, "/foo\\/bar/", "baz", ""),
- ("/foo\\/bar/baz", false, "/foo/bar/", "baz", ""),
- ("/foo/bar\\/baz", true, "/foo/bar\\/", "baz", ""),
- ("/foo/bar\\/baz", false, "/foo/bar/", "baz", ""),
- ("/foobarbaz", true, "/", "foobarbaz", ""),
+ ("foo/bar/baz", true, "foo/bar/baz", "", ""),
+ ("foo/b\\ar/baz", true, "foo/b\\ar/baz", "", ""),
+ ("foo/b\\ar/baz", false, "foo/bar/baz", "", ""),
+ ("/foo/bar/baz", true, "/foo/bar/baz", "", ""),
+ ("/foo\\/bar/baz", true, "/foo\\/bar/baz", "", ""),
+ ("/foo\\/bar/baz", false, "/foo/bar/baz", "", ""),
+ ("/foo/bar\\/baz", true, "/foo/bar\\/baz", "", ""),
+ ("/foo/bar\\/baz", false, "/foo/bar/baz", "", ""),
+ ("/foobarbaz", true, "/foobarbaz", "", ""),
("foo/bar/baz/", true, "foo/bar/baz/", "", ""),
("foobarbaz/", true, "foobarbaz/", "", ""),
- ("foobarbaz", true, "", "foobarbaz", ""),
+ ("foobarbaz", true, "foobarbaz", "", ""),
("foo/b?r/baz", true, "foo/", "b?r/", "baz"),
("foo/b?r\\/baz", true, "foo/", "b?r\\/", "baz"),
("foo/b?r\\/baz", false, "foo/", "b?r/", "baz"),
@@ -70,9 +71,9 @@ use strings;
("foo/b[ar]/baz\\/", false, "foo/", "b[ar]/", "baz\\/"),
("foo/b\\[ar]/baz\\/", true, "foo/", "b\\[ar]/", "baz\\/"),
("foo/b\\[ar]/baz\\/", false, "foo/b[ar]/baz/", "", ""),
- ("fo[o/ba[r/baz", true, "fo[o/ba[r/", "baz", ""),
- ("fo]o/bar/b[az", false, "fo]o/bar/", "b[az", ""),
- ("foo/ba]r/b]az", true, "foo/ba]r/", "b]az", ""),
+ ("fo[o/ba[r/baz", true, "fo[o/ba[r/baz", "", ""),
+ ("fo]o/bar/b[az", false, "fo]o/bar/b[az", "", ""),
+ ("foo/ba]r/b]az", true, "foo/ba]r/b]az", "", ""),
("foo/ba[r/b]az", false, "foo/ba[r/", "b]az", ""),
("fo[o/bar/b]az", true, "fo[o/bar/", "b]az", ""),
];
diff --git a/glob/glob.ha b/glob/glob.ha
@@ -111,6 +111,10 @@ fn next_match(gen: *generator) (str | void | failure) = {
const dir = pattern_dir(&gen.tmpp);
let pat = pattern_pat(&gen.tmpp);
+ if (pat == "") {
+ assert(pattern_rem(&gen.tmpp) == "");
+ return if (os::exists(dir)) dir else void;
+ };
const patm = strings::hassuffix(pat, '/');
if (patm) {
pat = strings::sub(pat, 0, len(pat) - 1);
@@ -217,6 +221,8 @@ fn pattern_parse(p: *pattern, pstr: str, noesc: bool) void = {
for (let brk = false, esc = false; true) {
const r = match (strings::next(&itdir)) {
case void =>
+ memio::concat(&p.dir, memio::string(&p.pat)!)!;
+ memio::reset(&p.pat);
return;
case let r: rune =>
yield r;