diff --git a/src/Glob.elm b/src/Glob.elm new file mode 100644 index 00000000..204b193c --- /dev/null +++ b/src/Glob.elm @@ -0,0 +1,89 @@ +module Glob exposing (..) + + +type Glob a + = Glob String (List String -> a) + + +type GlobMatcher + = Literal String + | Star + + +init : constructor -> Glob constructor +init constructor = + Glob "" (\captures -> constructor) + + +run : List String -> Glob a -> { match : a, pattern : String } +run captures (Glob pattern applyCapture) = + { match = applyCapture captures + , pattern = pattern + } + + +toPattern : Glob a -> String +toPattern (Glob pattern applyCapture) = + pattern + + +keep : GlobMatcher -> Glob (String -> value) -> Glob value +keep matcher (Glob pattern applyCapture) = + Glob (pattern ++ matcherToPattern matcher) + (case matcher of + Literal literalString -> + continueNonCapturing literalString applyCapture + + Star -> + popCapture applyCapture + ) + + +matcherToPattern : GlobMatcher -> String +matcherToPattern matcher = + case matcher of + Literal literalString -> + literalString + + Star -> + "*" + + +continueNonCapturing : String -> (List String -> (String -> value)) -> (List String -> value) +continueNonCapturing hardcodedCaptureValue applyCapture = + \captures -> + applyCapture captures hardcodedCaptureValue + + +popCapture : (List String -> (String -> value)) -> (List String -> value) +popCapture applyCapture = + \captures -> + case captures of + first :: rest -> + applyCapture rest first + + [] -> + applyCapture [] "ERROR" + + +drop : GlobMatcher -> Glob a -> Glob a +drop matcher (Glob pattern applyCapture) = + Glob (pattern ++ matcherToPattern matcher) + (\captures -> + case matcher of + Literal literalString -> + applyCapture captures + + Star -> + applyCapture captures + ) + + +literal : String -> GlobMatcher +literal string = + Literal string + + +star : GlobMatcher +star = + Star diff --git a/tests/GlobTests.elm b/tests/GlobTests.elm new file mode 100644 index 00000000..78a56c02 --- /dev/null +++ b/tests/GlobTests.elm @@ -0,0 +1,45 @@ +module GlobTests exposing (all) + +import Expect +import Glob +import Test exposing (describe, only, test) + + +all = + describe "glob" + [ test "literal" <| + \() -> + Glob.init identity + |> Glob.keep (Glob.literal "hello") + |> expect + { captures = [] + , expectedMatch = "hello" + , expectedPattern = "hello" + } + , test "capture" <| + \() -> + Glob.init identity + |> Glob.keep Glob.star + |> Glob.drop (Glob.literal ".txt") + |> expect + { captures = [ "my-file" ] + , expectedMatch = "my-file" + , expectedPattern = "*.txt" + } + ] + + +expect : + { captures : List String + , expectedMatch : match + , expectedPattern : String + } + -> Glob.Glob match + -> Expect.Expectation +expect { captures, expectedMatch, expectedPattern } glob = + glob + |> Glob.run captures + |> Expect.equal + { pattern = expectedPattern + , match = expectedMatch + }