Skip to content

Commit

Permalink
Merge pull request #192 from eWert-Online/fix-185
Browse files Browse the repository at this point in the history
Glob: Make double asterisk match zero or more directories
  • Loading branch information
rgrinberg authored Jul 28, 2021
2 parents 0ce5bf9 + c4180d7 commit 42c84b0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Unreleased
* Add the `[:alpha:]` character class in `Re.Perl` (#169)
* Double asterisk (`**`) in `Re.Glob` (#172)
Like `*` but also match `/` characters when `pathname` is set.
* Double asterisk should match 0 or more directories unless in trailing
position. (#192, fixes #185)

1.9.0 (05-Apr-2019)
-------------------
Expand Down
24 changes: 23 additions & 1 deletion lib/glob.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ let of_string ~double_asterisk s : t =
r
in

(**
[read_ahead pattern] will attempt to read [pattern] and will return [true] if it was successful.
If it fails, it will return [false] and not increment the read index.
*)
let read_ahead pattern =
let pattern_len = String.length pattern in
(* if the pattern we are looking for exeeds the remaining length of s, return false immediately *)
if !i + pattern_len >= l then
false
else
try
for j = 0 to pattern_len - 1 do
let found = not (eos ()) && s.[!i + j] = pattern.[j] in
if not found then raise_no_trace Exit;
done;
i := !i + pattern_len;
true
with | Exit -> false
in

let char () =
ignore (read '\\' : bool);
if eos () then raise Parse_error;
Expand Down Expand Up @@ -75,7 +95,9 @@ let of_string ~double_asterisk s : t =
in

let piece () =
if read '*'
if double_asterisk && read_ahead "/**" && not (eos ())
then ManyMany
else if read '*'
then if double_asterisk && read '*'
then ManyMany
else Many
Expand Down
11 changes: 11 additions & 0 deletions lib_test/test_glob.ml
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,20 @@ let _ =
assert (re_match (glob ~anchored "foo/**/bar") "foo/far/oof/bar");
assert (re_match (glob ~anchored "foo/**bar") "foo/far/oofbar");
assert (re_match (glob ~anchored "foo/**bar") "foo/bar");
assert (re_match (glob ~anchored "foo/**bar") "foo/foobar");
assert (re_match (glob ~anchored "/**") "//foo");
assert (re_match (glob ~anchored "**") "foo//bar");

assert (re_match (glob ~anchored "foo/bar/**/*.ml") "foo/bar/baz/foobar.ml");
assert (re_match (glob ~anchored "foo/bar/**/*.ml") "foo/bar/foobar.ml");

assert (re_match (glob ~anchored "foo/**/bar/**/baz") "foo/bar/baz");
assert (re_match (glob ~anchored "foo/**/bar/**/baz") "foo/bar/x/y/z/baz");
assert (re_match (glob ~anchored "foo/**/bar/**/baz") "foo/x/y/z/bar/baz");
assert (re_match (glob ~anchored "foo/**/bar/**/baz") "foo/bar/x/bar/x/baz");
assert (re_mismatch (glob ~anchored "foo/**/bar/**/baz") "foo/bar/../x/baz");
assert (re_mismatch (glob ~anchored "foo/**/bar/**/baz") "foo/bar/./x/baz");

(* Interaction with [~period] *)
let period = true in
assert (re_mismatch (glob ~anchored ~period "**") ".foobar");
Expand Down

0 comments on commit 42c84b0

Please sign in to comment.