Logo

dhall-buildkite / 1.0.0 / Lib / SelectFiles.dhall

Source

{- A DSL for representing file globbing; compiles into egrep-compatible regexp
-}
let Prelude = ../External/Prelude.dhall

let P = Prelude

let PathPattern = < Lit : Text | Any >

let FilePattern =
      { Type =
          { dir : Optional (List PathPattern)
          , exts : Optional (List Text)
          , strictStart : Bool
          , strictEnd : Bool
          }
      , default =
        { dir = None (List PathPattern)
        , exts = None (List Text)
        , strictStart = False
        , strictEnd = False
        }
      }

let strictlyStart
    : FilePattern.Type -> FilePattern.Type
    = \(pattern : FilePattern.Type) -> pattern // { strictStart = True }

let strictlyEnd
    : FilePattern.Type -> FilePattern.Type
    = \(pattern : FilePattern.Type) -> pattern // { strictEnd = True }

let strictly
    : FilePattern.Type -> FilePattern.Type
    = \(pattern : FilePattern.Type) -> strictlyEnd (strictlyStart pattern)

let everything
    : FilePattern.Type
    = FilePattern.default

let contains
    : Text -> FilePattern.Type
    = \(s : Text) -> FilePattern::{ dir = Some [ PathPattern.Lit s ] }

let exactly
    : Text -> Text -> FilePattern.Type
    = \(dir : Text) ->
      \(ext : Text) ->
        FilePattern::{
        , dir = Some [ PathPattern.Lit dir ]
        , exts = Some [ ext ]
        , strictStart = True
        , strictEnd = True
        }

let exactly_noext
    : Text -> FilePattern.Type
    = \(dir : Text) ->
        FilePattern::{
        , dir = Some [ PathPattern.Lit dir ]
        , strictStart = True
        , strictEnd = True
        }

let any
    : List Text -> Text
    = P.Text.concatSep "|"

let compileExt
    : Text -> Text
    = \(ext : Text) -> "\\." ++ ext

let compileExts
    : List Text -> Text
    = \(exts : List Text) ->
        let exts_ = P.List.map Text Text compileExt exts

        in  "(" ++ any exts_ ++ ")"

let compilePath
    : PathPattern -> Text
    = \(path : PathPattern) ->
        merge { Lit = \(text : Text) -> text, Any = ".*" } path

let compilePaths
    : List PathPattern -> Text
    = \(paths : List PathPattern) ->
        let paths_ = P.List.map PathPattern Text compilePath paths

        in  P.Text.concat paths_

let compileFile
    : FilePattern.Type -> Text
    = \(pattern : FilePattern.Type) ->
        let dirPart =
              P.Optional.fold
                (List PathPattern)
                pattern.dir
                Text
                compilePaths
                ".*"

        let extPart =
              P.Optional.fold (List Text) pattern.exts Text compileExts ""

        let startPart = if pattern.strictStart then "^" else ""

        let endPart =
              if        pattern.strictEnd
                    ||  P.Bool.not (P.Optional.null (List Text) pattern.exts)
              then  "\\\$"
              else  ""

        in  startPart ++ dirPart ++ extPart ++ endPart

let compile
    : List FilePattern.Type -> Text
    = \(patterns : List FilePattern.Type) ->
        let patterns_ = P.List.map FilePattern.Type Text compileFile patterns

        in  any patterns_

let everythingExample = assert : compile [ everything ] === ".*"

let exactlyExample =
        assert
      :     compile [ exactly "scripts/compile" "py" ]
        ===  "^scripts/compile(\\.py)\\\$"

let containsExample =
        assert
      : compile [ contains "buildkite/Makefile" ] === "buildkite/Makefile"

let strictContainsExample =
        assert
      :     compile [ strictly (contains "buildkite/Makefile") ]
        ===  "^buildkite/Makefile\\\$"

let D = PathPattern

let realisticExample =
        assert
      :     compile
              [ strictly
                  FilePattern::{
                  , dir = Some [ D.Lit "buildkite/", D.Any ]
                  , exts = Some [ "dhall" ]
                  }
              , strictly (contains "buildkite/Makefile")
              , exactly "buildkite/scripts/generate-jobs" "sh"
              ]
        ===  "^buildkite/.*(\\.dhall)\\\$|^buildkite/Makefile\\\$|^buildkite/scripts/generate-jobs(\\.sh)\\\$"

in      { compile
        , everything
        , contains
        , exactly
        , exactly_noext
        , strictlyStart
        , strictlyEnd
        , strictly
        , PathPattern
        }
    //  FilePattern