packages feed

hpath 0.11.0 → 0.12.0

raw patch · 4 files changed

+64/−25 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- HPath: instance Language.Haskell.TH.Syntax.Lift (HPath.Internal.Path a)
+ HPath: instance Data.Typeable.Internal.Typeable a => Language.Haskell.TH.Syntax.Lift (HPath.Internal.Path a)
+ HPath: isPwdPath :: Path Rel -> Bool
+ HPath: pwdPath :: Path Rel

Files

CHANGELOG view
@@ -1,3 +1,6 @@+0.12.0+	* Type-safe quasi-quoters wrt [MR #39](https://github.com/hasufell/hpath/pull/39)+	* Allow "." as relative dir wrt #36 0.11.0 	* Many API breaking changes 	* Remove RelC and Fn, because they complicate API/break semantics (see #29)
README.md view
@@ -4,7 +4,11 @@  Support for well-typed paths in Haskell. -This package is part of the HPath suite, also check out [hpath-filepath](https://hackage.haskell.org/package/hpath-filepath) and [hpath-io](https://hackage.haskell.org/package/hpath-io).+This package is part of the HPath suite, also check out:++* [hpath-directory](https://hackage.haskell.org/package/hpath-directory)+* [hpath-filepath](https://hackage.haskell.org/package/hpath-filepath)+* [hpath-io](https://hackage.haskell.org/package/hpath-io)  ## Motivation 
hpath.cabal view
@@ -1,5 +1,5 @@ name:                hpath-version:             0.11.0+version:             0.12.0 synopsis:            Support for well-typed paths description:         Support for well-typed paths, utilizing ByteString under the hood. license:             BSD3
src/HPath.hs view
@@ -18,6 +18,7 @@ #endif {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ScopedTypeVariables #-}  module HPath   (@@ -36,6 +37,7 @@   ,parseRel   ,parseAny   ,rootPath+  ,pwdPath   -- * Path Conversion   ,fromAbs   ,fromRel@@ -52,6 +54,7 @@   -- * Path Examination   ,isParentOf   ,isRootPath+  ,isPwdPath   -- * Path IO helpers   ,withAbsPath   ,withRelPath@@ -61,6 +64,7 @@   )   where +import           Control.Applicative ((<|>)) import           Control.Exception (Exception) import           Control.Monad.Catch (MonadThrow(..)) #if MIN_VERSION_bytestring(0,10,8)@@ -76,7 +80,8 @@ import           Data.Word8 import           HPath.Internal import           Language.Haskell.TH-import           Language.Haskell.TH.Syntax (Exp(..), Lift(..), lift)+import           Language.Haskell.TH.Syntax (Lift(..), lift)+import qualified Language.Haskell.TH.Syntax as TH import           Language.Haskell.TH.Quote (QuasiQuoter(..)) import           Prelude hiding (abs, any) import           System.Posix.FilePath hiding ((</>))@@ -150,8 +155,8 @@ -- | Get a location for a relative path. Produces a normalised -- path. ----- Note that @filepath@ may contain any number of @./@ but may not consist--- solely of @./@.  It also may not contain a single @..@ anywhere.+-- Note that @filepath@ may contain any number of @./@.+-- It also may not contain a single @..@ anywhere. -- -- Throws: 'PathParseException' --@@ -170,14 +175,17 @@ -- >>> parseRel "abc/../foo" :: Maybe (Path Rel) -- Nothing -- >>> parseRel "."          :: Maybe (Path Rel)--- Nothing+-- Just "."+-- >>> parseRel "././././."  :: Maybe (Path Rel)+-- Just "."+-- >>> parseRel "./..."      :: Maybe (Path Rel)+-- Just "..." -- >>> parseRel ".."         :: Maybe (Path Rel) -- Nothing parseRel :: MonadThrow m          => ByteString -> m (Path Rel) parseRel filepath =   if not (isAbsolute filepath) &&-     filepath /= BS.singleton _period &&      filepath /= BS.pack [_period, _period] &&      not (hasParentDir filepath) &&      isValid filepath@@ -186,11 +194,8 @@   --- | Parses a path, whether it's relative or absolute. Will lose--- information on whether it's relative or absolute. If you need to know,--- reparse it.+-- | Parses a path, whether it's relative or absolute. ----- Filenames must not contain slashes. -- Excludes '.' and '..'. -- -- Throws: 'PathParseException'@@ -210,7 +215,7 @@ -- >>> parseAny "abc/../foo" :: Maybe (Either (Path Abs) (Path Rel)) -- Nothing -- >>> parseAny "."          :: Maybe (Either (Path Abs) (Path Rel))--- Nothing+-- Just (Right ".") -- >>> parseAny ".."         :: Maybe (Either (Path Abs) (Path Rel)) -- Nothing parseAny :: MonadThrow m => ByteString -> m (Either (Path Abs) (Path Rel))@@ -224,7 +229,10 @@ rootPath :: Path Abs rootPath = (MkPath (BS.singleton _slash)) +pwdPath :: Path Rel+pwdPath = (MkPath (BS.singleton _period)) + -------------------------------------------------------------------------------- -- Path Conversion @@ -262,14 +270,15 @@ -- "/path/to/file" -- >>> (MkPath "/")        </> (MkPath "file/lal" :: Path Rel) -- "/file/lal"--- >>> (MkPath "/")        </> (MkPath "file"    :: Path Rel)+-- >>> (MkPath "/")        </> (MkPath "file/"    :: Path Rel) -- "/file"+-- >>> (MkPath "/")        </> (MkPath "."        :: Path Rel)+-- "/"+-- >>> (MkPath ".")        </> (MkPath "."        :: Path Rel)+-- "." (</>) :: Path b -> Path Rel -> Path b-(</>) (MkPath a) (MkPath b) = MkPath (a' `BS.append` b)-  where-    a' = if hasTrailingPathSeparator a-            then a-            else addTrailingPathSeparator a+(</>) (MkPath a) (MkPath b) =+  MkPath (dropTrailingPathSeparator $ normalise (addTrailingPathSeparator a `BS.append` b))   -- | Strip directory from path, making it relative to that directory.@@ -282,18 +291,20 @@ -- >>> (MkPath "lal/lad")      `stripDir` (MkPath "lal/lad/fad")  :: Maybe (Path Rel) -- Just "fad" -- >>> (MkPath "/")            `stripDir` (MkPath "/")            :: Maybe (Path Rel)--- Nothing+-- Just "." -- >>> (MkPath "/lal/lad/fad") `stripDir` (MkPath "/lal/lad")     :: Maybe (Path Rel) -- Nothing--- >>> (MkPath "fad")          `stripDir` (MkPath "fad")          :: Maybe (Path Rel)+-- >>> (MkPath "/abs")         `stripDir` (MkPath "/lal/lad")     :: Maybe (Path Rel) -- Nothing+-- >>> (MkPath "fad")          `stripDir` (MkPath "fad")          :: Maybe (Path Rel)+-- Just "." stripDir :: MonadThrow m          => Path b -> Path b -> m (Path Rel) stripDir (MkPath p) (MkPath l) =-  case stripPrefix p' l of+  case stripPrefix p' l <|> stripPrefix p l of     Nothing -> throwM (Couldn'tStripPrefixTPS p' l)     Just ok -> if BS.null ok-                 then throwM (Couldn'tStripPrefixTPS p' l)+                 then return (MkPath $ BS.singleton _period)                  else return (MkPath ok)   where     p' = addTrailingPathSeparator p@@ -359,6 +370,8 @@ -- Just "dod" -- >>> basename (MkPath "dod")          :: Maybe (Path Rel) -- Just "dod"+-- >>> basename (MkPath ".")            :: Maybe (Path Rel)+-- Just "." -- >>> basename (MkPath "/")            :: Maybe (Path Rel) -- Nothing basename :: MonadThrow m => Path b -> m (Path Rel)@@ -387,7 +400,11 @@ -- >>> (MkPath "fad")          `isParentOf` (MkPath "fad") -- False isParentOf :: Path b -> Path b -> Bool-isParentOf p l = isJust (stripDir p l :: Maybe (Path Rel))+isParentOf p l = case stripDir p l :: Maybe (Path Rel) of+  Nothing -> False+  Just ok+    | isPwdPath ok -> False+    | otherwise -> True   -- | Check whether the given Path is the root "/" path.@@ -399,7 +416,16 @@ isRootPath :: Path Abs -> Bool isRootPath = (== rootPath) +-- | Check whether the given Path is the pwd "." path.+--+-- >>> isPwdPath (MkPath "/lal/lad")+-- False+-- >>> isPwdPath (MkPath ".")+-- True+isPwdPath :: Path Rel -> Bool+isPwdPath = (== pwdPath) + -------------------------------------------------------------------------------- -- Path IO helpers @@ -426,8 +452,14 @@ ------------------------ -- QuasiQuoters -instance Lift (Path a) where-  lift (MkPath bs) = AppE <$> [| MkPath . BS.pack |] <*> lift (BS.unpack bs)+instance Typeable a => Lift (Path a) where+  lift (MkPath bs) = [| MkPath (BS.pack $(lift $ BS.unpack bs)) :: Path $(pure a) |]+    where+      a = TH.ConT $ TH.Name occ flav+        where+        tc   = typeRepTyCon (typeRep (Proxy :: Proxy a))+        occ  = TH.OccName (tyConName tc)+        flav = TH.NameG TH.TcClsName (TH.PkgName (tyConPackage tc)) (TH.ModName (tyConModule tc))   qq :: (ByteString -> Q Exp) -> QuasiQuoter