module Shikensu.Utilities ( cleanPath , commonDirectory , compilePatterns , compileParentPath , compilePathToRoot , globDir , io , mapIO , replaceSingleDot , stripPrefix , takeDirName ) where import Data.Maybe (fromMaybe) import Data.Tuple (fst) import Flow import Shikensu.Types import System.FilePath import qualified Data.List as List (map, stripPrefix) import qualified System.FilePath.Glob as Glob {-| "Clean up" a path. `/directory/./nested/` -> `directory/nested` `./` -> `` `.` -> `` -} cleanPath :: FilePath -> FilePath cleanPath = normalise .> dropTrailingPathSeparator .> dropDrive .> replaceSingleDot {-| Get the common directory from a Pattern. -} commonDirectory :: Pattern -> FilePath commonDirectory pattern = (Glob.compile .> Glob.commonDirectory .> fst) pattern {-| Compile a list of `Pattern`s to `Glob.Pattern`s. -} compilePatterns :: [Pattern] -> [Glob.Pattern] compilePatterns = List.map Glob.compile {-| Path to parent, when there is one. Just "../" or Nothing -} compileParentPath :: FilePath -> Maybe FilePath compileParentPath dirname = case dirname of "" -> Nothing _ -> Just "../" {-| Path to root. Example, if `dirname` is 'example/subdir', then this will be `../../`. If the `dirname` is empty, then this will be empty as well. -} compilePathToRoot :: FilePath -> FilePath compilePathToRoot dirname = if dirname == "" then "" else dirname |> splitDirectories |> fmap (\_ -> "..") |> joinPath |> addTrailingPathSeparator {-| List contents of a directory using a glob pattern. Returns a relative path, based on the given rootDirname. -} globDir :: FilePath -> [Glob.Pattern] -> IO [[FilePath]] globDir rootDir patterns = Glob.globDir patterns rootDir |> fmap (fst) |> fmap (List.map . List.map . makeRelative $ rootDir) {-| IO Sequence helpers -} io :: ([Definition] -> [IO Definition]) -> Dictionary -> IO Dictionary io fn = sequence . fn mapIO :: (Definition -> IO Definition) -> Dictionary -> IO Dictionary mapIO = io . fmap {-| If the path is a single dot, return an empty string. Otherwise return the path. -} replaceSingleDot :: String -> String replaceSingleDot path = if path == "." then "" else path {-| Strip prefix. -} stripPrefix :: String -> String -> String stripPrefix prefix target = fromMaybe target (List.stripPrefix prefix target) {-| Take dirname. -} takeDirName :: FilePath -> FilePath takeDirName = replaceSingleDot . takeDirectory