Add some operations
This commit is contained in:
parent
1e5b6675c2
commit
c4895949ee
83
src/Path.hs
83
src/Path.hs
@ -23,6 +23,12 @@ module Path
|
|||||||
,mkRelDir
|
,mkRelDir
|
||||||
,mkAbsFile
|
,mkAbsFile
|
||||||
,mkRelFile
|
,mkRelFile
|
||||||
|
-- * Operations
|
||||||
|
,(</>)
|
||||||
|
,stripDir
|
||||||
|
,isParentOf
|
||||||
|
,parentAbs
|
||||||
|
,filename
|
||||||
-- * Conversion
|
-- * Conversion
|
||||||
,toFilePath
|
,toFilePath
|
||||||
)
|
)
|
||||||
@ -32,6 +38,7 @@ import Control.Exception (Exception)
|
|||||||
import Control.Monad.Catch (MonadThrow(..))
|
import Control.Monad.Catch (MonadThrow(..))
|
||||||
import Data.Data
|
import Data.Data
|
||||||
import Data.List
|
import Data.List
|
||||||
|
import Data.Maybe
|
||||||
import Language.Haskell.TH
|
import Language.Haskell.TH
|
||||||
import Path.Internal
|
import Path.Internal
|
||||||
import qualified System.FilePath as FilePath
|
import qualified System.FilePath as FilePath
|
||||||
@ -172,6 +179,82 @@ mkRelFile s =
|
|||||||
toFilePath :: Path b t -> FilePath
|
toFilePath :: Path b t -> FilePath
|
||||||
toFilePath (Path l) = l
|
toFilePath (Path l) = l
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Operations
|
||||||
|
|
||||||
|
-- | Append two paths.
|
||||||
|
--
|
||||||
|
-- The following cases are valid and the equalities hold:
|
||||||
|
--
|
||||||
|
-- @$(mkAbsDir x) \<\/> $(mkRelDir y) = $(mkAbsDir (x ++ \"/\" ++ y))@
|
||||||
|
--
|
||||||
|
-- @$(mkAbsDir x) \<\/> $(mkRelFile y) = $(mkAbsFile (x ++ \"/\" ++ y))@
|
||||||
|
--
|
||||||
|
-- @$(mkRelDir x) \<\/> $(mkRelDir y) = $(mkRelDir (x ++ \"/\" ++ y))@
|
||||||
|
--
|
||||||
|
-- @$(mkRelDir x) \<\/> $(mkRelFile y) = $(mkRelFile (x ++ \"/\" ++ y))@
|
||||||
|
--
|
||||||
|
-- The following are proven not possible to express:
|
||||||
|
--
|
||||||
|
-- @$(mkAbsFile …) \<\/> x@
|
||||||
|
--
|
||||||
|
-- @$(mkRelFile …) \<\/> x@
|
||||||
|
--
|
||||||
|
-- @x \<\/> $(mkAbsFile …)@
|
||||||
|
--
|
||||||
|
-- @x \<\/> $(mkAbsDir …)@
|
||||||
|
--
|
||||||
|
(</>) :: Path b Dir -> Path Rel t -> Path b t
|
||||||
|
(</>) (Path a) (Path b) = Path (a ++ b)
|
||||||
|
|
||||||
|
-- | Strip directory from path, making it relative to that directory.
|
||||||
|
-- Returns 'Nothing' if directory is not a parent of the path.
|
||||||
|
--
|
||||||
|
-- The following properties hold:
|
||||||
|
--
|
||||||
|
-- @stripDir parent (parent <\/> child) = child@
|
||||||
|
--
|
||||||
|
-- Cases which are proven not possible:
|
||||||
|
--
|
||||||
|
-- @stripDir (a :: Path Abs …) (b :: Path Rel …)@
|
||||||
|
--
|
||||||
|
-- @stripDir (a :: Path Rel) (b :: Path Abs …)@
|
||||||
|
--
|
||||||
|
-- In other words the bases must match.
|
||||||
|
--
|
||||||
|
stripDir :: Path b Dir -> Path b t -> Maybe (Path Rel t)
|
||||||
|
stripDir (Path p) (Path l) =
|
||||||
|
fmap Path (stripPrefix p l)
|
||||||
|
|
||||||
|
-- | Is p a parent of the given location? Implemented in terms of
|
||||||
|
-- 'stripDir'. The bases must match.
|
||||||
|
isParentOf :: Path b Dir -> Path b t -> Bool
|
||||||
|
isParentOf p l =
|
||||||
|
isJust (stripDir p l)
|
||||||
|
|
||||||
|
-- | Take the absolute parent directory from the absolute path.
|
||||||
|
--
|
||||||
|
-- The following properties hold:
|
||||||
|
--
|
||||||
|
-- @parentAbs (parent \<\/> child) == parent@
|
||||||
|
--
|
||||||
|
-- On the root, getting the parent is idempotent:
|
||||||
|
--
|
||||||
|
-- @parentAbs (parentAbs \"\/\") = \"\/\"@
|
||||||
|
--
|
||||||
|
parentAbs :: Path Abs t -> Path Abs t
|
||||||
|
parentAbs (Path fp) =
|
||||||
|
Path (normalizeDir (FilePath.takeDirectory (FilePath.dropTrailingPathSeparator fp)))
|
||||||
|
|
||||||
|
-- | Extract the relative filename from a given location.
|
||||||
|
--
|
||||||
|
-- The following properties hold:
|
||||||
|
--
|
||||||
|
-- @filename (parent \<\/> filename a) == a@
|
||||||
|
--
|
||||||
|
filename :: Path b File -> Path Rel File
|
||||||
|
filename (Path l) = Path (normalizeFile (FilePath.takeFileName l))
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Internal functions
|
-- Internal functions
|
||||||
|
|
||||||
|
88
test/Main.hs
88
test/Main.hs
@ -1,11 +1,12 @@
|
|||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
-- | Test suite.
|
-- | Test suite.
|
||||||
|
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
|
import Data.Monoid
|
||||||
import Path
|
import Path
|
||||||
import Path.Internal
|
import Path.Internal
|
||||||
|
|
||||||
import Data.Monoid
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
-- | Test suite entry point, returns exit failure if any test fails.
|
-- | Test suite entry point, returns exit failure if any test fails.
|
||||||
@ -14,11 +15,90 @@ main = hspec spec
|
|||||||
|
|
||||||
-- | Test suite.
|
-- | Test suite.
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = do
|
spec =
|
||||||
describe "Parsing: Path Abs Dir" parseAbsDirSpec
|
do describe "Parsing: Path Abs Dir" parseAbsDirSpec
|
||||||
describe "Parsing: Path Rel Dir" parseRelDirSpec
|
describe "Parsing: Path Rel Dir" parseRelDirSpec
|
||||||
describe "Parsing: Path Abs File" parseAbsFileSpec
|
describe "Parsing: Path Abs File" parseAbsFileSpec
|
||||||
describe "Parsing: Path Rel File" parseRelFileSpec
|
describe "Parsing: Path Rel File" parseRelFileSpec
|
||||||
|
describe "Operations: (</>)" operationAppend
|
||||||
|
describe "Operations: stripDir" operationStripDir
|
||||||
|
describe "Operations: isParentOf" operationIsParentOf
|
||||||
|
describe "Operations: parentAbs" operationParentAbs
|
||||||
|
describe "Operations: filename" operationFilename
|
||||||
|
|
||||||
|
-- | The 'filename' operation.
|
||||||
|
operationFilename :: Spec
|
||||||
|
operationFilename =
|
||||||
|
do it "filename ($(mkAbsDir parent) </> filename $(mkRelFile filename)) == $(mkRelFile filename)"
|
||||||
|
(filename ($(mkAbsDir "/home/chris/") </>
|
||||||
|
filename $(mkRelFile "bar.txt")) ==
|
||||||
|
$(mkRelFile "bar.txt"))
|
||||||
|
it "filename ($(mkRelDir parent) </> filename $(mkRelFile filename)) == $(mkRelFile filename)"
|
||||||
|
(filename ($(mkRelDir "home/chris/") </>
|
||||||
|
filename $(mkRelFile "bar.txt")) ==
|
||||||
|
$(mkRelFile "bar.txt"))
|
||||||
|
|
||||||
|
-- | The 'parentAbs' operation.
|
||||||
|
operationParentAbs :: Spec
|
||||||
|
operationParentAbs =
|
||||||
|
do it "parentAbs (parent </> child) == parent"
|
||||||
|
(parentAbs ($(mkAbsDir "/foo") </>
|
||||||
|
$(mkRelDir "bar")) ==
|
||||||
|
$(mkAbsDir "/foo"))
|
||||||
|
it "parentAbs \"\" == \"\""
|
||||||
|
(parentAbs $(mkAbsDir "/") ==
|
||||||
|
$(mkAbsDir "/"))
|
||||||
|
it "parentAbs (parentAbs \"\") == \"\""
|
||||||
|
(parentAbs (parentAbs $(mkAbsDir "/")) ==
|
||||||
|
$(mkAbsDir "/"))
|
||||||
|
|
||||||
|
-- | The 'isParentOf' operation.
|
||||||
|
operationIsParentOf :: Spec
|
||||||
|
operationIsParentOf =
|
||||||
|
do it "isParentOf parent (parent </> child)"
|
||||||
|
(isParentOf
|
||||||
|
$(mkAbsDir "///bar/")
|
||||||
|
($(mkAbsDir "///bar/") </>
|
||||||
|
$(mkRelFile "bar/foo.txt")))
|
||||||
|
it "isParentOf parent (parent </> child)"
|
||||||
|
(isParentOf
|
||||||
|
$(mkRelDir "bar/")
|
||||||
|
($(mkRelDir "bar/") </>
|
||||||
|
$(mkRelFile "bob/foo.txt")))
|
||||||
|
|
||||||
|
-- | The 'stripDir' operation.
|
||||||
|
operationStripDir :: Spec
|
||||||
|
operationStripDir =
|
||||||
|
do it "stripDir parent (parent </> child) = child"
|
||||||
|
(stripDir $(mkAbsDir "///bar/")
|
||||||
|
($(mkAbsDir "///bar/") </>
|
||||||
|
$(mkRelFile "bar/foo.txt")) ==
|
||||||
|
Just $(mkRelFile "bar/foo.txt"))
|
||||||
|
it "stripDir parent (parent </> child) = child"
|
||||||
|
(stripDir $(mkRelDir "bar/")
|
||||||
|
($(mkRelDir "bar/") </>
|
||||||
|
$(mkRelFile "bob/foo.txt")) ==
|
||||||
|
Just $(mkRelFile "bob/foo.txt"))
|
||||||
|
|
||||||
|
-- | The '</>' operation.
|
||||||
|
operationAppend :: Spec
|
||||||
|
operationAppend =
|
||||||
|
do it "AbsDir + RelDir = AbsDir"
|
||||||
|
($(mkAbsDir "/home/") </>
|
||||||
|
$(mkRelDir "chris") ==
|
||||||
|
$(mkAbsDir "/home/chris/"))
|
||||||
|
it "AbsDir + RelFile = AbsFile"
|
||||||
|
($(mkAbsDir "/home/") </>
|
||||||
|
$(mkRelFile "chris/test.txt") ==
|
||||||
|
$(mkAbsFile "/home/chris/test.txt"))
|
||||||
|
it "RelDir + RelDir = RelDir"
|
||||||
|
($(mkRelDir "home/") </>
|
||||||
|
$(mkRelDir "chris") ==
|
||||||
|
$(mkRelDir "home/chris"))
|
||||||
|
it "RelDir + RelFile = RelFile"
|
||||||
|
($(mkRelDir "home/") </>
|
||||||
|
$(mkRelFile "chris/test.txt") ==
|
||||||
|
$(mkRelFile "home/chris/test.txt"))
|
||||||
|
|
||||||
-- | Tests for the tokenizer.
|
-- | Tests for the tokenizer.
|
||||||
parseAbsDirSpec :: Spec
|
parseAbsDirSpec :: Spec
|
||||||
|
Loading…
Reference in New Issue
Block a user