module System.Path.Internal
(
  -- * The main filepath (& dirpath) abstract type
  Path, -- kept abstract

  -- * Type Synonyms
  AbsFile,
  RelFile,
  AbsDir,
  RelDir,
  AbsRelFile,
  AbsRelDir,
  AbsFileDir,
  RelFileDir,
  AbsRelFileDir,

  AbsPath,     Abs,
  RelPath,     Rel,
  FilePath,    File,
  DirPath,     Dir,
  AbsRelPath,  AbsRel,
  FileDirPath, FileDir,

  -- * Decisions on path types
  withAbsRel, withFileDir,

  -- * Path to String conversion
  toString,
  getPathString,

  -- * Constants
  rootDir,
  currentDir,
  emptyFile,

  -- * Parsing Functions
  maybePath, maybe,
  parsePath, parse,

  -- * Checked Construction Functions
  path,
  relFile,
  relDir,
  absFile,
  absDir,
  relPath,    rel,
  absPath,    abs,
  filePath,   file,
  dirPath,    dir,
  absRel,     fileDir,

  idAbsRel, idAbs, idRel,
  idFileDir, idFile, idDir,

  -- * Unchecked Construction Functions
  asPath,
  asRelFile,
  asRelDir,
  asAbsFile,
  asAbsDir,
  asRelPath,
  asAbsPath,
  asFilePath,
  asDirPath,

  -- * Checked Construction Functions
  mkPathAbsOrRel,
  mkPathFileOrDir,
  mkAbsPath,
  mkAbsPathFromCwd,

  -- * Basic Manipulation Functions
  (</>),
  (<.>),
  (<++>),
  addExtension,
  combine,
  dropExtension,
  dropExtensions,
  dropFileName,
  replaceExtension,
  replaceBaseName,
  replaceDirectory,
  replaceFileName,
  splitExtension,
  splitExtensions,
  splitFileName,
  splitDirName,
  takeBaseName,
  takeDirectory,
  takeSuperDirectory,
  takeExtension,
  takeExtensions,
  takeFileName,
  takeDirName,
  mapFileName,
  mapFileNameF,

  -- * Auxillary Manipulation Functions
  equalFilePath,
  joinPath,
  normalise,
  splitPath,
  makeRelative,
  makeRelativeMaybe,
  makeAbsolute,
  makeAbsoluteFromCwd,
  dynamicMakeAbsolute,
  dynamicMakeAbsoluteFromCwd,
  genericMakeAbsolute,
  genericMakeAbsoluteFromCwd,
  pathMap,
  dirFromFile,
  fileFromDir,
  toFileDir,
  fromFileDir,
  fileFromFileDir,
  dirFromFileDir,
  toAbsRel,
  fromAbsRel,

  -- * Path Predicates
  isAbsolute,
  isRelative,
  isAbsoluteString,
  isRelativeString,
  hasAnExtension,
  hasExtension,

  -- * Separators
  System(..),
  extSeparator,
  searchPathSeparator,
  isExtSeparator,
  isSearchPathSeparator,

  -- * Generic Manipulation Functions
  genericAddExtension,
  genericDropExtension,
  genericDropExtensions,
  genericSplitExtension,
  genericSplitExtensions,
  genericTakeExtension,
  genericTakeExtensions,

  -- * Tests
  testAll,
  isValid,
)

where

import qualified System.Path.Internal.PartClass as Class
import qualified System.Path.Internal.Part as Part
import System.Path.Internal.PartClass as Class
        (WrapFileDir(WrapFileDir), WrapAbsRel(WrapAbsRel), FuncArg(..), fdMap)
import System.Path.Internal.Part
        (PathComponent(PathComponent), GenComponent, System(..),
         absPC, emptyPC, retagPC, untagPC, pcMap)

import qualified System.Directory as SD

import qualified Control.Monad.Trans.Class as MT
import qualified Control.Monad.Trans.State as MS
import Control.Monad (MonadPlus, guard, liftM2, mplus, mzero)
import Control.Applicative (Const(Const), liftA2, (<$>), (<$))
import Control.DeepSeq (NFData(rnf))

import qualified Data.Monoid.HT as MonHT
import qualified Data.List.HT as ListHT
import Data.Tagged (Tagged(Tagged), untag)
import Data.Functor.Compose (Compose(Compose), getCompose)
import Data.List (isSuffixOf, isPrefixOf, stripPrefix, intersperse)
import Data.String (IsString(fromString))
import Data.Maybe.HT (toMaybe)
import Data.Maybe (fromMaybe, maybeToList)
import Data.Tuple.HT (mapFst, mapSnd)
import Data.Monoid (Monoid(mempty, mappend, mconcat), Endo(Endo), appEndo)
import Data.Semigroup (Semigroup(sconcat, (<>)), )
import Data.Char (isSpace)
import Data.Ord.HT (comparing)
import Data.Eq.HT (equating)

import Text.Show.HT (concatS)
import Text.Printf (printf)

import qualified Test.DocTest.Driver as DocTest
import qualified Test.QuickCheck as QC
import Test.QuickCheck
          (Gen, Property, property, Arbitrary(arbitrary), frequency)

import qualified Prelude as P
import Prelude hiding (FilePath, maybe, abs)


{- $setup
>>> :set -XTypeFamilies
>>>
>>> :set -fno-warn-warnings-deprecations
>>> import qualified System.Path.PartClass as Class
>>> import qualified System.Path.Generic as Path
>>> import qualified System.Path.Posix as Posix
>>> import qualified System.Path.Windows as Windows
>>> import System.Path.Generic ((</>), (<.>), relFile, relDir, absFile, absDir)
>>> import Data.List (isSuffixOf, isPrefixOf)
>>> import Data.Char (toLower)
>>> import qualified Test.QuickCheck as QC
>>> forAllAbsRel :: (Class.FileDir fd, QC.Testable prop) => (Default.AbsRel fd -> prop) -> QC.Property
>>> forAllAbsRel = QC.forAll QC.arbitrary
-}


------------------------------------------------------------------------
-- Types

-- | This is the main filepath abstract datatype
data Path os ar fd = Path ar [PathComponent os] fd

instance
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
        Eq (Path os ar fd) where
    == :: Path os ar fd -> Path os ar fd -> Bool
(==)  =  forall b a. Eq b => (a -> b) -> a -> a -> Bool
equating forall os ar fd.
Path os ar fd
-> (WrapAbsRel os ar, [PathComponent os], WrapFileDir os fd)
inspectPath

instance
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
        Ord (Path os ar fd) where
    compare :: Path os ar fd -> Path os ar fd -> Ordering
compare  =  forall b a. Ord b => (a -> b) -> a -> a -> Ordering
comparing forall os ar fd.
Path os ar fd
-> (WrapAbsRel os ar, [PathComponent os], WrapFileDir os fd)
inspectPath

inspectPath ::
    Path os ar fd -> (WrapAbsRel os ar, [PathComponent os], WrapFileDir os fd)
inspectPath :: forall os ar fd.
Path os ar fd
-> (WrapAbsRel os ar, [PathComponent os], WrapFileDir os fd)
inspectPath (Path ar
ar [PathComponent os]
pcs fd
fd) = (forall os ar. ar -> WrapAbsRel os ar
WrapAbsRel ar
ar, [PathComponent os]
pcs, forall os fd. fd -> WrapFileDir os fd
WrapFileDir fd
fd)


selTag :: Path os ar fd -> Tagged os a -> a
selTag :: forall os ar fd a. Path os ar fd -> Tagged os a -> a
selTag Path os ar fd
_ = forall {k} (s :: k) b. Tagged s b -> b
untag


type AbsFile os = Path os Part.Abs Part.File
type RelFile os = Path os Part.Rel Part.File
type AbsDir  os = Path os Part.Abs Part.Dir
type RelDir  os = Path os Part.Rel Part.Dir
type AbsRelFile os = Path os Part.AbsRel Part.File
type AbsRelDir  os = Path os Part.AbsRel Part.Dir
type AbsFileDir os = Path os Part.Abs Part.FileDir
type RelFileDir os = Path os Part.Rel Part.FileDir
type AbsRelFileDir os = Path os Part.AbsRel Part.FileDir

type Abs  os fd = Path os Part.Abs fd
type Rel  os fd = Path os Part.Rel fd
type File os ar = Path os ar Part.File
type Dir  os ar = Path os ar Part.Dir
type AbsRel  os fd = Path os Part.AbsRel fd
type FileDir os ar = Path os ar Part.FileDir

{-# DEPRECATED RelPath     "Use Path.Rel instead." #-}
{-# DEPRECATED AbsPath     "Use Path.Abs instead." #-}
{-# DEPRECATED AbsRelPath  "Use Path.AbsRel instead." #-}
{-# DEPRECATED FilePath    "Use Path.File instead." #-}
{-# DEPRECATED DirPath     "Use Path.Dir instead." #-}
{-# DEPRECATED FileDirPath "Use Path.FileDir instead." #-}

type AbsPath  os fd = Path os Part.Abs fd
type RelPath  os fd = Path os Part.Rel fd
type FilePath os ar = Path os ar Part.File
type DirPath  os ar = Path os ar Part.Dir
type AbsRelPath  os fd = Path os Part.AbsRel fd
type FileDirPath os ar = Path os ar Part.FileDir

instance (Class.AbsRel ar, Class.FileDir fd) => NFData (Path os ar fd) where
    rnf :: Path os ar fd -> ()
rnf (Path ar
ar [PathComponent os]
pcs fd
fd) =
        forall a. NFData a => a -> ()
rnf (forall ar a. AbsRel ar => ([Char] -> a) -> a -> ar -> a
Class.withAbsRel forall a. NFData a => a -> ()
rnf () ar
ar, [PathComponent os]
pcs, forall fd a. FileDir fd => (GenComponent -> a) -> a -> a -> fd -> a
Class.withFileDir forall a. NFData a => a -> ()
rnf () () fd
fd)

-- I don't think this basic type of fold is appropriate for a nested datatype
-- pathFold :: a -> (a -> String -> a) -> Path ar fd -> a
-- pathFold pr f PathRoot = pr
-- pathFold pr f (FileDir d pc) = f (pathFold pr f d) (unPathComponent pc)

-- | Map over the components of the path.
--
-- prop> Path.pathMap (map toLower) (absDir "/tmp/Reports/SpreadSheets") == Posix.absDir "/tmp/reports/spreadsheets"
pathMap ::
    (Class.FileDir fd) => (String -> String) -> Path os ar fd -> Path os ar fd
pathMap :: forall fd os ar.
FileDir fd =>
([Char] -> [Char]) -> Path os ar fd -> Path os ar fd
pathMap [Char] -> [Char]
f (Path ar
ar [PathComponent os]
pcs fd
fd) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar (forall a b. (a -> b) -> [a] -> [b]
map (forall os.
([Char] -> [Char]) -> PathComponent os -> PathComponent os
pcMap [Char] -> [Char]
f) [PathComponent os]
pcs) (forall fd. FileDir fd => ([Char] -> [Char]) -> fd -> fd
fdMap [Char] -> [Char]
f fd
fd)


mapFilePart ::
    (GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar
mapFilePart :: forall os ar.
(GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar
mapFilePart GenComponent -> GenComponent
f (Path ar
ar [PathComponent os]
pcs (Part.File GenComponent
fd)) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs forall a b. (a -> b) -> a -> b
$ GenComponent -> File
Part.File forall a b. (a -> b) -> a -> b
$ GenComponent -> GenComponent
f GenComponent
fd

mapFilePartF ::
    (Functor f) =>
    (GenComponent -> f GenComponent) -> FilePath os ar -> f (FilePath os ar)
mapFilePartF :: forall (f :: * -> *) os ar.
Functor f =>
(GenComponent -> f GenComponent)
-> FilePath os ar -> f (FilePath os ar)
mapFilePartF GenComponent -> f GenComponent
f (Path ar
ar [PathComponent os]
pcs (Part.File GenComponent
fd)) =
    forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenComponent -> File
Part.File forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenComponent -> f GenComponent
f GenComponent
fd

splitFilePart ::
    (GenComponent -> (GenComponent, a)) -> FilePath os ar -> (FilePath os ar, a)
splitFilePart :: forall a os ar.
(GenComponent -> (GenComponent, a))
-> FilePath os ar -> (FilePath os ar, a)
splitFilePart GenComponent -> (GenComponent, a)
f (Path ar
ar [PathComponent os]
pcs (Part.File GenComponent
fd)) = forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenComponent -> File
Part.File) forall a b. (a -> b) -> a -> b
$ GenComponent -> (GenComponent, a)
f GenComponent
fd

mapPathDirs ::
    ([PathComponent os] -> [PathComponent os]) -> Path os ar fd -> Path os ar fd
mapPathDirs :: forall os ar fd.
([PathComponent os] -> [PathComponent os])
-> Path os ar fd -> Path os ar fd
mapPathDirs [PathComponent os] -> [PathComponent os]
f ~(Path ar
ar [PathComponent os]
pcs fd
fd) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar ([PathComponent os] -> [PathComponent os]
f [PathComponent os]
pcs) fd
fd


withAbsRel ::
    (Class.AbsRel ar) =>
    (AbsPath os fd -> a) -> (RelPath os fd -> a) -> Path os ar fd -> a
withAbsRel :: forall ar os fd a.
AbsRel ar =>
(AbsPath os fd -> a) -> (RelPath os fd -> a) -> Path os ar fd -> a
withAbsRel AbsPath os fd -> a
fAbs RelPath os fd -> a
fRel (Path ar
ar [PathComponent os]
pcs fd
fd) =
    forall ar a. AbsRel ar => ([Char] -> a) -> a -> ar -> a
Class.withAbsRel
        (\[Char]
drive -> AbsPath os fd -> a
fAbs forall a b. (a -> b) -> a -> b
$ forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path (GenComponent -> Abs
Part.Abs (forall os. [Char] -> PathComponent os
PathComponent [Char]
drive)) [PathComponent os]
pcs fd
fd)
        (RelPath os fd -> a
fRel forall a b. (a -> b) -> a -> b
$ forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path Rel
Part.Rel [PathComponent os]
pcs fd
fd)
        ar
ar

switchFileDir ::
    (Class.FileDir fd) =>
    f (FilePath os ar) -> f (DirPath os ar) -> f (FileDirPath os ar) ->
    f (Path os ar fd)
switchFileDir :: forall fd (f :: * -> *) os ar.
FileDir fd =>
f (FilePath os ar)
-> f (DirPath os ar) -> f (FileDirPath os ar) -> f (Path os ar fd)
switchFileDir f (FilePath os ar)
f f (DirPath os ar)
d f (FileDirPath os ar)
fd =
    forall {k1} {k2} (f :: k1 -> *) (g :: k2 -> k1) (a :: k2).
Compose f g a -> f (g a)
getCompose forall a b. (a -> b) -> a -> b
$ forall fd (f :: * -> *).
FileDir fd =>
f File -> f Dir -> f FileDir -> f fd
Class.switchFileDir (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose f (FilePath os ar)
f) (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose f (DirPath os ar)
d) (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose f (FileDirPath os ar)
fd)

switchFileOrDir ::
    (Class.FileOrDir fd) =>
    f (FilePath os ar) -> f (DirPath os ar) -> f (Path os ar fd)
switchFileOrDir :: forall fd (f :: * -> *) os ar.
FileOrDir fd =>
f (FilePath os ar) -> f (DirPath os ar) -> f (Path os ar fd)
switchFileOrDir f (FilePath os ar)
f f (DirPath os ar)
d =
    forall {k1} {k2} (f :: k1 -> *) (g :: k2 -> k1) (a :: k2).
Compose f g a -> f (g a)
getCompose forall a b. (a -> b) -> a -> b
$ forall fd (f :: * -> *). FileOrDir fd => f File -> f Dir -> f fd
Class.switchFileOrDir (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose f (FilePath os ar)
f) (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose f (DirPath os ar)
d)

withFileDir ::
    (Class.FileOrDir fd) =>
    (FilePath os ar -> a) -> (DirPath os ar -> a) -> Path os ar fd -> a
withFileDir :: forall fd os ar a.
FileOrDir fd =>
(FilePath os ar -> a) -> (DirPath os ar -> a) -> Path os ar fd -> a
withFileDir FilePath os ar -> a
f DirPath os ar -> a
g = forall b a. FuncArg b a -> a -> b
runFuncArg forall a b. (a -> b) -> a -> b
$ forall fd (f :: * -> *) os ar.
FileOrDir fd =>
f (FilePath os ar) -> f (DirPath os ar) -> f (Path os ar fd)
switchFileOrDir (forall b a. (a -> b) -> FuncArg b a
FuncArg FilePath os ar -> a
f) (forall b a. (a -> b) -> FuncArg b a
FuncArg DirPath os ar -> a
g)


-- | Currently not exported
eitherFromAbsRel ::
    Class.AbsRel ar => Path os ar fd -> Either (AbsPath os fd) (RelPath os fd)
eitherFromAbsRel :: forall ar os fd.
AbsRel ar =>
Path os ar fd -> Either (AbsPath os fd) (RelPath os fd)
eitherFromAbsRel = forall ar os fd a.
AbsRel ar =>
(AbsPath os fd -> a) -> (RelPath os fd -> a) -> Path os ar fd -> a
withAbsRel forall a b. a -> Either a b
Left forall a b. b -> Either a b
Right

-- | Currently not exported
_eitherFromFileDir ::
    Class.FileOrDir fd => Path os ar fd -> Either (FilePath os ar) (DirPath os ar)
_eitherFromFileDir :: forall fd os ar.
FileOrDir fd =>
Path os ar fd -> Either (FilePath os ar) (DirPath os ar)
_eitherFromFileDir = forall fd os ar a.
FileOrDir fd =>
(FilePath os ar -> a) -> (DirPath os ar -> a) -> Path os ar fd -> a
withFileDir forall a b. a -> Either a b
Left forall a b. b -> Either a b
Right

------------------------------------------------------------------------
-- Read & Show instances

{- |
We show and parse file path components
using the rather generic 'relPath' smart constructor
instead of 'relFile', 'relDir' and @relPath str :: FileDirPath ar@.
Otherwise handling of all cases of 'Part.File', 'Part.Dir' and 'Part.FileDir' types
becomes pretty complicated.

>>> Posix.rootDir </> relDir "bla" </> relFile "blub"
rootDir </> relPath "bla" </> relPath "blub"
>>> Just (Posix.rootDir </> relDir "bla" </> relFile "blub")
Just (rootDir </> relPath "bla" </> relPath "blub")
>>> Posix.currentDir </> relDir "bla" </> relFile "blub"
currentDir </> relPath "bla" </> relPath "blub"
>>> Just (Posix.currentDir </> relDir "bla" </> relFile "blub")
Just (currentDir </> relPath "bla" </> relPath "blub")
>>> Windows.absDir "c:" </> relDir "bla" </> relFile "blub"
absDir "c:" </> relPath "bla" </> relPath "blub"
>>> Just (Windows.absDir "c:\\" </> relDir "bla" </> relFile "blub")
Just (absDir "c:\\" </> relPath "bla" </> relPath "blub")
-}
instance
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
        Show (Path os ar fd) where
    showsPrec :: Int -> Path os ar fd -> [Char] -> [Char]
showsPrec = forall {k} (s :: k) b. Tagged s b -> b
untag forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Tagged os (Int -> Path os ar fd -> [Char] -> [Char])
showsPrecTagged

showsPrecTagged ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    Tagged os (Int -> Path os ar fd -> ShowS)
showsPrecTagged :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Tagged os (Int -> Path os ar fd -> [Char] -> [Char])
showsPrecTagged =
    forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os. System os => Tagged os [Char]
rootStringTagged forall a b. (a -> b) -> a -> b
$ \[Char]
root Int
d Path os ar fd
x ->
        case forall fd os ar.
FileDir fd =>
Path os ar fd -> (ar, [PathComponent os])
pathComponents Path os ar fd
x of
            (ar
ar, [PathComponent os]
pcs) ->
                Bool -> ([Char] -> [Char]) -> [Char] -> [Char]
showParen (Int
dforall a. Ord a => a -> a -> Bool
>Int
5) forall a b. (a -> b) -> a -> b
$ [[Char] -> [Char]] -> [Char] -> [Char]
concatS forall a b. (a -> b) -> a -> b
$
                forall a. a -> [a] -> [a]
intersperse
                    (Char -> [Char] -> [Char]
showChar Char
' ' forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [Char]
showString [Char]
combineOperator forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> [Char] -> [Char]
showChar Char
' ') forall a b. (a -> b) -> a -> b
$
                forall ar a. AbsRel ar => ([Char] -> a) -> a -> ar -> a
Class.withAbsRel
                    (\[Char]
drive ->
                        if [Char]
drive forall a. Eq a => a -> a -> Bool
== [Char]
root
                          then [Char] -> [Char] -> [Char]
showString [Char]
rootName
                          else forall a. Show a => [Char] -> a -> [Char] -> [Char]
showsCons [Char]
absDirName [Char]
drive)
                    ([Char] -> [Char] -> [Char]
showString [Char]
currentName)
                    ar
ar forall a. a -> [a] -> [a]
:
                forall a b. (a -> b) -> [a] -> [b]
map (\(PathComponent [Char]
pc) -> forall a. Show a => [Char] -> a -> [Char] -> [Char]
showsCons [Char]
relPathName [Char]
pc) [PathComponent os]
pcs

showsCons :: Show a => String -> a -> ShowS
showsCons :: forall a. Show a => [Char] -> a -> [Char] -> [Char]
showsCons [Char]
name a
arg  =  [Char] -> [Char] -> [Char]
showString [Char]
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> [Char] -> [Char]
showChar Char
' ' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => Int -> a -> [Char] -> [Char]
showsPrec Int
11 a
arg

{- |
Currently it also parses Part.AbsRel and Part.FileDir paths,
although these cannot be composed with the accepted combinators.
-}
-- prop> read "rootDir" == Posix.rootDir
-- prop> read "rootDir" == Windows.rootDir
-- prop> read "currentDir" == Posix.currentDir
-- prop> read "currentDir" == Windows.currentDir
-- prop> let path = Posix.rootDir </> relDir "bla" </> relFile "blub" in read (show path) == path
-- prop> let path = Just (Posix.rootDir </> relDir "bla" </> relFile "blub") in read (show path) == path
-- prop> let path = Posix.currentDir </> relDir "bla" </> relFile "blub" in read (show path) == path
-- prop> let path = Just (Posix.currentDir </> relDir "bla" </> relFile "blub") in read (show path) == path
-- prop> let path = Windows.rootDir </> relDir "bla" </> relFile "blub" in read (show path) == path
-- prop> let path = Just (Windows.rootDir </> relDir "bla" </> relFile "blub") in read (show path) == path
-- prop> let path = Windows.absDir "c:" </> relDir "bla" </> relFile "blub" in read (show path) == path
instance
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
        Read (Path os ar fd) where
    readsPrec :: Int -> ReadS (Path os ar fd)
readsPrec Int
d = forall a. Bool -> ReadS a -> ReadS a
readParen (Int
dforall a. Ord a => a -> a -> Bool
>Int
5) forall a b. (a -> b) -> a -> b
$ forall {k} (s :: k) b. Tagged s b -> b
untag forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Tagged os (ReadS (Path os ar fd))
readsPrecTagged

readsPrecTagged ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    Tagged os (ReadS (Path os ar fd))
readsPrecTagged :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Tagged os (ReadS (Path os ar fd))
readsPrecTagged =
    forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os ar.
(System os, AbsRel ar) =>
Tagged os (StateT [Char] [] ar)
readsSplitDrive forall a b. (a -> b) -> a -> b
$ \StateT [Char] [] ar
readsSplDrv ->
        let go :: StateT [Char] [] [PathComponent os]
go =
                forall s (m :: * -> *) a.
StateT s Maybe () -> StateT s m a -> StateT s m a -> StateT s m a
handleMismatch
                    (forall (m :: * -> *). Monad m => StateT [Char] m ()
skipSpaces forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *). MonadPlus m => [Char] -> StateT [Char] m ()
matchString [Char]
combineOperator)
                    (forall (m :: * -> *) a. Monad m => a -> m a
return [])
                    (forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (:) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os. [Char] -> PathComponent os
PathComponent forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> StateT [Char] [] a
readsCons [Char]
relPathName) StateT [Char] [] [PathComponent os]
go)
        in  forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
MS.runStateT forall a b. (a -> b) -> a -> b
$ do
                forall (m :: * -> *). Monad m => StateT [Char] m ()
skipSpaces
                forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
MT.lift forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Maybe a -> [a]
maybeToList forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<
                    forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 forall fd ar os.
FileDir fd =>
ar -> [PathComponent os] -> Maybe (Path os ar fd)
maybePathFromComponents StateT [Char] [] ar
readsSplDrv forall {os}. StateT [Char] [] [PathComponent os]
go

skipSpaces :: (Monad m) => MS.StateT String m ()
skipSpaces :: forall (m :: * -> *). Monad m => StateT [Char] m ()
skipSpaces = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
MS.modify forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace

readsCons :: (Read a) => String -> MS.StateT String [] a
readsCons :: forall a. Read a => [Char] -> StateT [Char] [] a
readsCons [Char]
name = do
    forall (m :: * -> *). Monad m => StateT [Char] m ()
skipSpaces
    forall (m :: * -> *). MonadPlus m => [Char] -> StateT [Char] m ()
matchString [Char]
name
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
MS.StateT forall a b. (a -> b) -> a -> b
$ forall a. Read a => Int -> ReadS a
readsPrec Int
11

handleMismatch ::
    MS.StateT s Maybe () ->
    MS.StateT s m a -> MS.StateT s m a -> MS.StateT s m a
handleMismatch :: forall s (m :: * -> *) a.
StateT s Maybe () -> StateT s m a -> StateT s m a -> StateT s m a
handleMismatch StateT s Maybe ()
act StateT s m a
err StateT s m a
success =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
MS.StateT forall a b. (a -> b) -> a -> b
$ \s
s0 ->
        case forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m s
MS.execStateT StateT s Maybe ()
act s
s0 of
           Maybe s
Nothing -> forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
MS.runStateT StateT s m a
err s
s0
           Just s
s1 -> forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
MS.runStateT StateT s m a
success s
s1

matchString :: (MonadPlus m) => String -> MS.StateT String m ()
matchString :: forall (m :: * -> *). MonadPlus m => [Char] -> StateT [Char] m ()
matchString [Char]
prefix =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
MS.StateT forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
P.maybe forall (m :: * -> *) a. MonadPlus m => m a
mzero (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) ()) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix [Char]
prefix

readsSplitDrive ::
    (System os, Class.AbsRel ar) => Tagged os (MS.StateT String [] ar)
readsSplitDrive :: forall os ar.
(System os, AbsRel ar) =>
Tagged os (StateT [Char] [] ar)
readsSplitDrive =
    forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os. System os => Tagged os (StateT [Char] [] Abs)
readsSplitDriveAbs forall a b. (a -> b) -> a -> b
$ \StateT [Char] [] Abs
readsSplDrvAbs ->
        forall ar (f :: * -> *).
AbsRel ar =>
f Abs -> f Rel -> f AbsRel -> f ar
Class.switchAbsRel
            StateT [Char] [] Abs
readsSplDrvAbs
            forall (m :: * -> *). MonadPlus m => StateT [Char] m Rel
readsSplitDriveRel
            (forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus
                (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Part.Abs GenComponent
drive) -> GenComponent -> AbsRel
Part.AbsO GenComponent
drive) StateT [Char] [] Abs
readsSplDrvAbs)
                (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Rel
Part.Rel -> AbsRel
Part.RelO) forall (m :: * -> *). MonadPlus m => StateT [Char] m Rel
readsSplitDriveRel))

readsSplitDriveAbs :: (System os) => Tagged os (MS.StateT String [] Part.Abs)
readsSplitDriveAbs :: forall os. System os => Tagged os (StateT [Char] [] Abs)
readsSplitDriveAbs =
    forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os. System os => Tagged os [Char]
rootStringTagged forall a b. (a -> b) -> a -> b
$ \[Char]
root ->
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Char] -> Abs
absPC forall a b. (a -> b) -> a -> b
$
            ([Char]
root forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *). MonadPlus m => [Char] -> StateT [Char] m ()
matchString [Char]
rootName)
            forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus`
            forall a. Read a => [Char] -> StateT [Char] [] a
readsCons [Char]
absDirName

readsSplitDriveRel :: (MonadPlus m) => MS.StateT String m Part.Rel
readsSplitDriveRel :: forall (m :: * -> *). MonadPlus m => StateT [Char] m Rel
readsSplitDriveRel = forall (m :: * -> *). MonadPlus m => [Char] -> StateT [Char] m ()
matchString [Char]
currentName forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return Rel
Part.Rel


-- | Convert the 'Path' into a plain 'String' as required for OS calls.
--
-- prop> \p -> Path.asPath (Path.toString p) == (p::Default.AbsFile)
toString ::
    (System os, Class.AbsRel ar, Class.FileDir fd) => Path os ar fd -> String
toString :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
toString = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char] -> [Char]
toStringS [Char]
""

{-# DEPRECATED getPathString "Use Path.toString instead." #-}

-- | Synonym of 'toString' intended for unqualified use.
getPathString ::
    (System os, Class.AbsRel ar, Class.FileDir fd) => Path os ar fd -> String
getPathString :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
getPathString = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
toString

toStringS ::
    (System os, Class.AbsRel ar, Class.FileDir fd) => Path os ar fd -> ShowS
toStringS :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char] -> [Char]
toStringS Path os ar fd
x =
    case forall fd os ar.
FileDir fd =>
Path os ar fd -> (ar, [PathComponent os])
pathComponents Path os ar fd
x of
        (ar
ar, []) ->
            forall ar a. AbsRel ar => ([Char] -> a) -> a -> ar -> a
Class.withAbsRel [Char] -> [Char] -> [Char]
showString ([Char] -> [Char] -> [Char]
showString [Char]
currentDirComponent) ar
ar
        (ar
ar, [PathComponent os]
pcs) ->
            [[Char] -> [Char]] -> [Char] -> [Char]
concatS forall a b. (a -> b) -> a -> b
$
            forall ar a. AbsRel ar => ([Char] -> a) -> a -> ar -> a
Class.withAbsRel (\[Char]
drive -> ([Char] -> [Char] -> [Char]
showString [Char]
drive forall a. a -> [a] -> [a]
:)) forall a. a -> a
id ar
ar forall a b. (a -> b) -> a -> b
$
            forall a. a -> [a] -> [a]
intersperse (Char -> [Char] -> [Char]
showChar (forall os ar fd a. Path os ar fd -> Tagged os a -> a
selTag Path os ar fd
x forall os. System os => Tagged os Char
pathSeparator)) forall a b. (a -> b) -> a -> b
$
            forall a b. (a -> b) -> [a] -> [b]
map (\(PathComponent [Char]
pc) -> [Char] -> [Char] -> [Char]
showString [Char]
pc) [PathComponent os]
pcs


------------------------------------------------------------------------
-- Constants

-- prop> Posix.toString Path.rootDir == "/"
-- prop> Windows.toString Path.rootDir == "\\"
rootDir :: (System os) => AbsDir os
rootDir :: forall os. System os => AbsDir os
rootDir = forall {k} (s :: k) b. Tagged s b -> b
untag forall os. System os => Tagged os (AbsDir os)
rootDirTagged

rootDirTagged :: (System os) => Tagged os (AbsDir os)
rootDirTagged :: forall os. System os => Tagged os (AbsDir os)
rootDirTagged = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\[Char]
root -> forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ([Char] -> Abs
absPC [Char]
root) [] Dir
Part.Dir) forall os. System os => Tagged os [Char]
rootStringTagged

rootStringTagged :: (System os) => Tagged os String
rootStringTagged :: forall os. System os => Tagged os [Char]
rootStringTagged = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Char
sep -> [Char
sep]) forall os. System os => Tagged os Char
pathSeparator

-- prop> Posix.toString Path.currentDir == "."
-- prop> Windows.toString Path.currentDir == "."
currentDir :: (System os) => RelDir os
currentDir :: forall os. System os => RelDir os
currentDir = forall a. Monoid a => a
mempty

{- |
This is a file with path @\"\"@.
You will not be able to create a file with this name.
We also forbid parsing @\"\"@ by 'relFile'.
You might only need this file path as intermediate step
when manipulating extensions of files like @\".bashrc\"@.
-}
emptyFile :: (System os) => RelFile os
emptyFile :: forall os. System os => RelFile os
emptyFile = forall os. File -> RelFile os
atomicFile forall a b. (a -> b) -> a -> b
$ GenComponent -> File
Part.File forall os. PathComponent os
emptyPC

atomicFile :: Part.File -> RelFile os
atomicFile :: forall os. File -> RelFile os
atomicFile = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path Rel
Part.Rel []

rootName :: String
rootName :: [Char]
rootName = [Char]
"rootDir"

currentName :: String
currentName :: [Char]
currentName = [Char]
"currentDir"

currentDirComponent :: String
currentDirComponent :: [Char]
currentDirComponent = [Char]
"."

absDirName :: String
absDirName :: [Char]
absDirName = [Char]
"absDir"

relPathName :: String
relPathName :: [Char]
relPathName = [Char]
"relPath"


------------------------------------------------------------------------
-- Parsing Functions

{-# DEPRECATED maybePath "Use Path.maybe instead." #-}
{-# DEPRECATED parsePath "Use Path.parse instead." #-}

-- | This function is intended for checking and parsing paths
--   provided as user input.
--
-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsDir) == Just "/"
-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsFile) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelDir) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelFile) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsDir) == Just "/tmp"
-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsFile) == Just "/tmp"
-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelDir) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelFile) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsDir) == Just "/tmp"
-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsFile) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelDir) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelFile) == Nothing
-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"
-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"
-- prop> fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.RelFile) == Just "file.txt"
-- prop> fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.AbsFile) == Nothing
-- prop> fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.AbsDir) == Just "\\tmp"
-- prop> fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.AbsDir) == Just "a:\\tmp"
-- prop> fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.AbsDir) == Just "a:tmp"
-- prop> fmap Windows.toString (Windows.maybePath "a:\\" :: Maybe Windows.AbsDir) == Just "a:\\"
-- prop> fmap Windows.toString (Windows.maybePath "a:" :: Maybe Windows.AbsDir) == Just "a:"
-- prop> fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.RelDir) == Just "tmp"
-- prop> fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.RelDir) == Nothing
-- prop> fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.RelDir) == Nothing
-- prop> fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.RelDir) == Nothing
-- prop> fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.AbsDir) == Nothing
maybe, maybePath ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    String -> Maybe (Path os ar fd)
maybe :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Maybe (Path os ar fd)
maybe [Char]
str = do
    let (AbsRel
ar0, [PathComponent os]
pcs0, Either FileDir Dir
fd0) = forall {k} (s :: k) b. Tagged s b -> b
untag forall os.
System os =>
Tagged
  os ([Char] -> (AbsRel, [PathComponent os], Either FileDir Dir))
makePathComponents [Char]
str
    ar
ar <- forall ar. AbsRel ar => AbsRel -> Maybe ar
Class.fromAbsRel AbsRel
ar0
    ([PathComponent os]
pcs, fd
fd) <-
        case Either FileDir Dir
fd0 of
            Left FileDir
Part.FileDir -> forall fd os.
FileDir fd =>
[PathComponent os] -> Maybe ([PathComponent os], fd)
arrangeComponents [PathComponent os]
pcs0
            Right Dir
Part.Dir ->
                forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((,) [PathComponent os]
pcs0) forall a b. (a -> b) -> a -> b
$
                forall fd (f :: * -> *).
FileDir fd =>
f File -> f Dir -> f FileDir -> f fd
Class.switchFileDir forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just Dir
Part.Dir) (forall a. a -> Maybe a
Just FileDir
Part.FileDir)
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs fd
fd

maybePath :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Maybe (Path os ar fd)
maybePath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Maybe (Path os ar fd)
maybe

parse, parsePath ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    String -> Either String (Path os ar fd)
parse :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Either [Char] (Path os ar fd)
parse = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Const [Char] ar
-> Const [Char] fd -> [Char] -> Either [Char] (Path os ar fd)
pathWithNames forall ar. AbsRel ar => Const [Char] ar
arName forall fd. FileDir fd => Const [Char] fd
fdName
parsePath :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Either [Char] (Path os ar fd)
parsePath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Either [Char] (Path os ar fd)
parse

pathWithNames ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    Const String ar -> Const String fd ->
    String -> Either String (Path os ar fd)
pathWithNames :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Const [Char] ar
-> Const [Char] fd -> [Char] -> Either [Char] (Path os ar fd)
pathWithNames (Const [Char]
ar) (Const [Char]
fd) [Char]
str =
    forall b a. b -> (a -> b) -> Maybe a -> b
P.maybe (forall a b. a -> Either a b
Left (forall r. PrintfType r => [Char] -> r
printf [Char]
"\"%s\" is not a valid %s%spath" [Char]
str [Char]
ar [Char]
fd)) forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$
    forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Maybe (Path os ar fd)
maybePath [Char]
str

arName :: (Class.AbsRel ar) => Const String ar
arName :: forall ar. AbsRel ar => Const [Char] ar
arName = forall ar (f :: * -> *).
AbsRel ar =>
f Abs -> f Rel -> f AbsRel -> f ar
Class.switchAbsRel (forall {k} a (b :: k). a -> Const a b
Const [Char]
"absolute ") (forall {k} a (b :: k). a -> Const a b
Const [Char]
"relative ") (forall {k} a (b :: k). a -> Const a b
Const [Char]
"")

fdName :: (Class.FileDir fd) => Const String fd
fdName :: forall fd. FileDir fd => Const [Char] fd
fdName = forall fd (f :: * -> *).
FileDir fd =>
f File -> f Dir -> f FileDir -> f fd
Class.switchFileDir (forall {k} a (b :: k). a -> Const a b
Const [Char]
"file ") (forall {k} a (b :: k). a -> Const a b
Const [Char]
"directory ") (forall {k} a (b :: k). a -> Const a b
Const [Char]
"")

------------------------------------------------------------------------
-- Checked Construction Functions

-- | This function is intended for converting path strings
--   with known content, e.g. string literals, to the 'Path' type.
path ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    String -> Path os ar fd
path :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. HasCallStack => [Char] -> a
error forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Either [Char] (Path os ar fd)
parsePath

-- | Construct a 'RelFile' from a 'String'.
--
-- prop> Posix.toString (Posix.relFile "file.txt") == "file.txt"
-- prop> Posix.toString (Posix.relFile "tmp") == "tmp"
relFile :: (System os) => String -> RelFile os
relFile :: forall os. System os => [Char] -> RelFile os
relFile = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'RelDir' from a 'String'.
--
-- prop> Posix.toString (Posix.relDir ".") == "."
-- prop> Posix.toString (Posix.relDir "file.txt") == "file.txt"
-- prop> Posix.toString (Posix.relDir "tmp") == "tmp"
relDir :: (System os) => String -> RelDir os
relDir :: forall os. System os => [Char] -> RelDir os
relDir = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct an 'AbsFile' from a 'String'.
--
-- prop> Posix.toString (Posix.absFile "/file.txt") == "/file.txt"
-- prop> Posix.toString (Posix.absFile "/tmp") == "/tmp"
absFile :: (System os) => String -> AbsFile os
absFile :: forall os. System os => [Char] -> AbsFile os
absFile = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct an 'AbsDir' from a 'String'.
--
-- prop> Posix.toString (Posix.absDir "/file.txt") == "/file.txt"
-- prop> Posix.toString (Posix.absDir "/tmp") == "/tmp"
absDir :: (System os) => String -> AbsDir os
absDir :: forall os. System os => [Char] -> AbsDir os
absDir = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'Rel fd' from a 'String'.
rel :: (System os, Class.FileDir fd) => String -> Rel os fd
rel :: forall os fd. (System os, FileDir fd) => [Char] -> Rel os fd
rel = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct an 'Abs fd' from a 'String'.
abs :: (System os, Class.FileDir fd) => String -> Abs os fd
abs :: forall os fd. (System os, FileDir fd) => [Char] -> Abs os fd
abs = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct an 'AbsRel fd' from a 'String'.
absRel :: (System os, Class.FileDir fd) => String -> AbsRel os fd
absRel :: forall os fd. (System os, FileDir fd) => [Char] -> AbsRel os fd
absRel = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'File ar' from a 'String'.
file :: (System os, Class.AbsRel ar) => String -> File os ar
file :: forall os ar. (System os, AbsRel ar) => [Char] -> File os ar
file = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'Dir ar' from a 'String'.
dir :: (System os, Class.AbsRel ar) => String -> Dir os ar
dir :: forall os ar. (System os, AbsRel ar) => [Char] -> Dir os ar
dir = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'FileDir ar' from a 'String'.
fileDir :: (System os, Class.AbsRel ar) => String -> FileDir os ar
fileDir :: forall os ar. (System os, AbsRel ar) => [Char] -> FileDir os ar
fileDir = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path


{-# DEPRECATED relPath    "Use Path.rel instead." #-}
{-# DEPRECATED absPath    "Use Path.abs instead." #-}
{-# DEPRECATED filePath   "Use Path.file instead." #-}
{-# DEPRECATED dirPath    "Use Path.dir instead." #-}

-- | Construct a 'RelPath fd' from a 'String'.
relPath :: (System os, Class.FileDir fd) => String -> RelPath os fd
relPath :: forall os fd. (System os, FileDir fd) => [Char] -> Rel os fd
relPath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct an 'AbsPath fd' from a 'String'.
absPath :: (System os, Class.FileDir fd) => String -> AbsPath os fd
absPath :: forall os fd. (System os, FileDir fd) => [Char] -> Abs os fd
absPath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'FilePath ar' from a 'String'.
filePath :: (System os, Class.AbsRel ar) => String -> FilePath os ar
filePath :: forall os ar. (System os, AbsRel ar) => [Char] -> File os ar
filePath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path

-- | Construct a 'DirPath ar' from a 'String'.
dirPath :: (System os, Class.AbsRel ar) => String -> DirPath os ar
dirPath :: forall os ar. (System os, AbsRel ar) => [Char] -> Dir os ar
dirPath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path



idAbsRel :: AbsRelPath os fd -> AbsRelPath os fd
idAbsRel :: forall os fd. AbsRelPath os fd -> AbsRelPath os fd
idAbsRel = forall a. a -> a
id

idAbs :: AbsPath os fd -> AbsPath os fd
idAbs :: forall os fd. AbsPath os fd -> AbsPath os fd
idAbs = forall a. a -> a
id

idRel :: RelPath os fd -> RelPath os fd
idRel :: forall os fd. RelPath os fd -> RelPath os fd
idRel = forall a. a -> a
id


idFileDir :: FileDirPath os fd -> FileDirPath os fd
idFileDir :: forall os fd. FileDirPath os fd -> FileDirPath os fd
idFileDir = forall a. a -> a
id

idFile :: FilePath os fd -> FilePath os fd
idFile :: forall os fd. FilePath os fd -> FilePath os fd
idFile = forall a. a -> a
id

idDir :: DirPath os fd -> DirPath os fd
idDir :: forall os fd. DirPath os fd -> DirPath os fd
idDir = forall a. a -> a
id


{-# DEPRECATED asPath "Use 'maybePath', 'parsePath' or 'path' instead." #-}
{-# DEPRECATED asRelFile "Use 'relFile' instead." #-}
{-# DEPRECATED asRelDir "Use 'relDir' instead." #-}
{-# DEPRECATED asAbsFile "Use 'absFile' instead." #-}
{-# DEPRECATED asAbsDir "Use 'absDir' instead." #-}
{-# DEPRECATED asRelPath "Use 'relPath' instead." #-}
{-# DEPRECATED asAbsPath "Use 'absPath' instead." #-}
{-# DEPRECATED asFilePath "Use 'filePath' instead." #-}
{-# DEPRECATED asDirPath "Use 'dirPath' instead." #-}

------------------------------------------------------------------------
-- Unchecked Construction Functions
-- NB - these construction functions are non-IO and do no checking!!

-- | Use a 'String' as a 'Path' whose type is determined by its context.
--   You should not use this and other @as*@ functions,
--   since they may silently turn a relative path to an absolute one,
--   or vice versa, or they may accept a path as file path
--   although it ends on a slash.
--   If you are certain about the string content
--   then you should use 'path'.
--   If you got the string as user input then use 'maybePath' or 'parsePath'.
--
-- prop> Posix.asPath "/tmp" == Posix.absDir "/tmp"
-- prop> Posix.asPath "file.txt" == Posix.relFile "file.txt"
-- prop> Path.isAbsolute (Posix.asAbsDir "/tmp")
-- prop> Path.isRelative (Posix.asRelDir "/tmp")
-- prop> Posix.toString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp"
-- prop> Posix.toString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp"
-- prop> Windows.toString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp"
-- prop> Windows.toString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp"
-- prop> Windows.toString (Windows.asPath "a:tmp" :: Windows.AbsDir) == "a:tmp"
-- prop> Windows.toString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp"
asPath ::
    (System os, Class.AbsRel ar, Class.FileDir fd) => String -> Path os ar fd
asPath :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall fd ar os.
FileDir fd =>
ar -> [PathComponent os] -> Path os ar fd
mkPathFromComponents forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (s :: k) b. Tagged s b -> b
untag forall os ar.
(System os, AbsRel ar) =>
Tagged os ([Char] -> (ar, [PathComponent os]))
mkPathComponents


-- | Use a 'String' as a 'RelFile'. No checking is done.
--
-- prop> Posix.toString (Posix.asRelFile "file.txt") == "file.txt"
-- prop> Posix.toString (Posix.asRelFile "/file.txt") == "file.txt"
-- prop> Posix.toString (Posix.asRelFile "tmp") == "tmp"
-- prop> Posix.toString (Posix.asRelFile "/tmp") == "tmp"
asRelFile :: (System os) => String -> RelFile os
asRelFile :: forall os. System os => [Char] -> RelFile os
asRelFile = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as a 'RelDir'. No checking is done.
--
-- prop> Posix.toString (Posix.asRelDir ".") == "."
-- prop> Posix.toString (Posix.asRelDir "file.txt") == "file.txt"
-- prop> Posix.toString (Posix.asRelDir "/file.txt") == "file.txt"
-- prop> Posix.toString (Posix.asRelDir "tmp") == "tmp"
-- prop> Posix.toString (Posix.asRelDir "/tmp") == "tmp"
asRelDir :: (System os) => String -> RelDir os
asRelDir :: forall os. System os => [Char] -> RelDir os
asRelDir = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as an 'AbsFile'. No checking is done.
--
-- prop> Posix.toString (Posix.asAbsFile "/file.txt") == "/file.txt"
-- prop> Posix.toString (Posix.asAbsFile "/tmp") == "/tmp"
asAbsFile :: (System os) => String -> AbsFile os
asAbsFile :: forall os. System os => [Char] -> AbsFile os
asAbsFile = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as an 'AbsDir'. No checking is done.
--
-- prop> Posix.toString (Posix.asAbsDir "/file.txt") == "/file.txt"
-- prop> Posix.toString (Posix.asAbsDir "/tmp") == "/tmp"
asAbsDir :: (System os) => String -> AbsDir os
asAbsDir :: forall os. System os => [Char] -> AbsDir os
asAbsDir = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as a 'RelPath fd'. No checking is done.
asRelPath :: (System os, Class.FileDir fd) => String -> RelPath os fd
asRelPath :: forall os fd. (System os, FileDir fd) => [Char] -> Rel os fd
asRelPath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as an 'AbsPath fd'. No checking is done.
asAbsPath :: (System os, Class.FileDir fd) => String -> AbsPath os fd
asAbsPath :: forall os fd. (System os, FileDir fd) => [Char] -> Abs os fd
asAbsPath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as a 'FilePath ar'. No checking is done.
asFilePath :: (System os, Class.AbsRel ar) => String -> FilePath os ar
asFilePath :: forall os ar. (System os, AbsRel ar) => [Char] -> File os ar
asFilePath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Use a 'String' as a 'DirPath ar'. No checking is done.
asDirPath :: (System os, Class.AbsRel ar) => String -> DirPath os ar
asDirPath :: forall os ar. (System os, AbsRel ar) => [Char] -> Dir os ar
asDirPath = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
asPath

-- | Forbid use of OverloadedStrings and prevent custom orphan instances
instance
    (ForbiddenSystem os, ForbiddenAbsRel ar, ForbiddenFileDir fd) =>
        IsString (Path os ar fd) where fromString :: [Char] -> Path os ar fd
fromString = forall os ar fd. ForbiddenSystem os => [Char] -> Path os ar fd
forbiddenFromString

class System os => ForbiddenSystem os where
    forbiddenFromString :: String -> Path os ar fd

class Class.AbsRel ar => ForbiddenAbsRel ar where
class Class.FileDir fd => ForbiddenFileDir fd where

------------------------------------------------------------------------
-- Checked Construction Functions

{-# DEPRECATED mkPathAbsOrRel "Use Path.absRel instead." #-}

-- | Examines the supplied string and constructs an absolute or
-- relative path as appropriate.
--
-- prop> Path.mkPathAbsOrRel "/tmp" == Left (Posix.absDir "/tmp")
-- prop> Path.mkPathAbsOrRel  "tmp" == Right (Posix.relDir "tmp")
-- prop> Path.mkPathAbsOrRel "\\tmp" == Left (Windows.absDir "\\tmp")
-- prop> Path.mkPathAbsOrRel "d:\\tmp" == Left (Windows.absDir "d:\\tmp")
-- prop> Path.mkPathAbsOrRel "d:tmp" == Left (Windows.absDir "d:tmp")
-- prop> Path.mkPathAbsOrRel "tmp" == Right (Windows.relDir "tmp")
mkPathAbsOrRel, mkPathAbsOrRelPriv ::
    (System os, Class.FileDir fd) =>
    String -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRel :: forall os fd.
(System os, FileDir fd) =>
[Char] -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRel = forall os fd.
(System os, FileDir fd) =>
[Char] -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRelPriv
mkPathAbsOrRelPriv :: forall os fd.
(System os, FileDir fd) =>
[Char] -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRelPriv = forall ar os fd.
AbsRel ar =>
Path os ar fd -> Either (AbsPath os fd) (RelPath os fd)
eitherFromAbsRel forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os fd. (System os, FileDir fd) => [Char] -> AbsRel os fd
absRel

{-# DEPRECATED mkPathFileOrDir "Don't let the path type depend on current file system content. Instead choose the path type according to the needed disk object type." #-}

-- | Searches for a file or directory with the supplied path string
--   and returns a 'Part.File' or 'Part.Dir' path as appropriate. If neither exists
--   at the supplied path, 'Nothing' is returned.
mkPathFileOrDir ::
    (System os, Class.AbsRel ar) =>
    String -> IO (Maybe (Either (FilePath os ar) (DirPath os ar)))
mkPathFileOrDir :: forall os ar.
(System os, AbsRel ar) =>
[Char] -> IO (Maybe (Either (FilePath os ar) (DirPath os ar)))
mkPathFileOrDir [Char]
s = do
  Bool
isfile <- [Char] -> IO Bool
SD.doesFileExist [Char]
s
  Bool
isdir <- [Char] -> IO Bool
SD.doesDirectoryExist [Char]
s
  case (Bool
isfile, Bool
isdir) of
    (Bool
False, Bool
False) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
    (Bool
True,  Bool
False) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path [Char]
s
    (Bool
False, Bool
True ) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
[Char] -> Path os ar fd
path [Char]
s
    (Bool
True,  Bool
True ) -> forall a. IOError -> IO a
ioError forall a b. (a -> b) -> a -> b
$ [Char] -> IOError
userError [Char]
"mkPathFileOrDir - object type changed while checking"

{-# DEPRECATED mkAbsPath "Use Path.dynamicMakeAbsolute instead." #-}

-- | Convert a 'String' into an 'AbsPath' by interpreting it as
--   relative to the supplied directory if necessary.
--
-- prop> Path.mkAbsPath (absDir "/tmp") "foo.txt" == Posix.absFile "/tmp/foo.txt"
-- prop> Path.mkAbsPath (absDir "/tmp") "/etc/foo.txt" == Posix.absFile "/etc/foo.txt"
mkAbsPath ::
    (System os, Class.FileDir fd) => AbsDir os -> String -> AbsPath os fd
mkAbsPath :: forall os fd.
(System os, FileDir fd) =>
AbsDir os -> [Char] -> AbsPath os fd
mkAbsPath AbsDir os
d = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. a -> a
id (forall os fd.
System os =>
AbsDir os -> RelPath os fd -> AbsPath os fd
makeAbsolute AbsDir os
d) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os fd.
(System os, FileDir fd) =>
[Char] -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRelPriv

{-# DEPRECATED mkAbsPathFromCwd "Use Path.dynamicMakeAbsoluteFromCwd instead." #-}

-- | Convert a 'String' into an 'AbsPath' by interpreting it as
--   relative to the cwd if necessary.
mkAbsPathFromCwd ::
    (System os, Class.FileDir fd) => String -> IO (AbsPath os fd)
mkAbsPathFromCwd :: forall os fd.
(System os, FileDir fd) =>
[Char] -> IO (AbsPath os fd)
mkAbsPathFromCwd = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (m :: * -> *) a. Monad m => a -> m a
return forall os fd. System os => RelPath os fd -> IO (AbsPath os fd)
makeAbsoluteFromCwd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os fd.
(System os, FileDir fd) =>
[Char] -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRelPriv


------------------------------------------------------------------------
-- Internal Functions for GenComponent manipulation

mkPathFromComponents ::
    (Class.FileDir fd) => ar -> [PathComponent os] -> Path os ar fd
mkPathFromComponents :: forall fd ar os.
FileDir fd =>
ar -> [PathComponent os] -> Path os ar fd
mkPathFromComponents ar
ar [PathComponent os]
pcs =
    forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar) forall a b. (a -> b) -> a -> b
$
    forall fd (f :: * -> *).
FileDir fd =>
f File -> f Dir -> f FileDir -> f fd
Class.switchFileDir
        (forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd GenComponent -> File
Part.File forall a b. (a -> b) -> a -> b
$
         forall b a. b -> ([a] -> a -> b) -> [a] -> b
ListHT.switchR ([], forall os. PathComponent os
emptyPC) (forall a b c. ((a, b) -> c) -> a -> b -> c
curry forall a b. (a -> b) -> a -> b
$ forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd forall os. PathComponent os -> GenComponent
untagPC) [PathComponent os]
pcs)
        ([PathComponent os]
pcs, Dir
Part.Dir)
        ([PathComponent os]
pcs, FileDir
Part.FileDir)

maybePathFromComponents ::
    (Class.FileDir fd) => ar -> [PathComponent os] -> Maybe (Path os ar fd)
maybePathFromComponents :: forall fd ar os.
FileDir fd =>
ar -> [PathComponent os] -> Maybe (Path os ar fd)
maybePathFromComponents ar
ar [PathComponent os]
pcs =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a b. (a -> b) -> a -> b
$ forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar) forall a b. (a -> b) -> a -> b
$ forall fd os.
FileDir fd =>
[PathComponent os] -> Maybe ([PathComponent os], fd)
arrangeComponents [PathComponent os]
pcs

arrangeComponents ::
    (Class.FileDir fd) => [PathComponent os] -> Maybe ([PathComponent os], fd)
arrangeComponents :: forall fd os.
FileDir fd =>
[PathComponent os] -> Maybe ([PathComponent os], fd)
arrangeComponents [PathComponent os]
pcs =
    forall {k1} {k2} (f :: k1 -> *) (g :: k2 -> k1) (a :: k2).
Compose f g a -> f (g a)
getCompose forall a b. (a -> b) -> a -> b
$
    forall fd (f :: * -> *).
FileDir fd =>
f File -> f Dir -> f FileDir -> f fd
Class.switchFileDir
        (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd (GenComponent -> File
Part.File forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. PathComponent os -> GenComponent
untagPC)) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Maybe ([a], a)
ListHT.viewR [PathComponent os]
pcs)
        (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just ([PathComponent os]
pcs, Dir
Part.Dir))
        (forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just ([PathComponent os]
pcs, FileDir
Part.FileDir))

mkPathComponents ::
    (System os, Class.AbsRel ar) =>
    Tagged os (String -> (ar, [PathComponent os]))
mkPathComponents :: forall os ar.
(System os, AbsRel ar) =>
Tagged os ([Char] -> (ar, [PathComponent os]))
mkPathComponents =
    forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2
        (\Char -> Bool
isSep State [Char] ar
splDriveOS ->
            forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd (forall os. [[Char]] -> [PathComponent os]
nonEmptyComponents forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [[a]]
ListHT.chop Char -> Bool
isSep)
             forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. State s a -> s -> (a, s)
MS.runState State [Char] ar
splDriveOS)
        forall os. System os => Tagged os (Char -> Bool)
isPathSeparator forall os ar. (System os, AbsRel ar) => Tagged os (State [Char] ar)
splitDriveOS

{- |
Parse path string independent from expectations
expressed by the type parameters.
-}
makePathComponents ::
    (System os) =>
    Tagged os (String -> (Part.AbsRel, [PathComponent os], Either Part.FileDir Part.Dir))
makePathComponents :: forall os.
System os =>
Tagged
  os ([Char] -> (AbsRel, [PathComponent os], Either FileDir Dir))
makePathComponents =
    forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2
        (\Char -> Bool
isSep State [Char] AbsRel
splAbsolute [Char]
str ->
            let (AbsRel
ar, [[Char]]
pct) =
                    forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd (forall a. (a -> Bool) -> [a] -> [[a]]
ListHT.chop Char -> Bool
isSep) forall a b. (a -> b) -> a -> b
$
                    forall s a. State s a -> s -> (a, s)
MS.runState State [Char] AbsRel
splAbsolute [Char]
str
                ([[Char]]
pcs1, Either FileDir Dir
fd) =
                    case forall a. [a] -> Maybe ([a], a)
ListHT.viewR [[Char]]
pct of
                        Maybe ([[Char]], [Char])
Nothing -> ([], forall a b. b -> Either a b
Right Dir
Part.Dir)
                        Just ([[Char]]
pcs, [Char]
pc) ->
                            if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
pc -- caused by trailing slash
                              then ([[Char]]
pcs, forall a b. b -> Either a b
Right Dir
Part.Dir)
                              else ([[Char]]
pct, forall a b. a -> Either a b
Left FileDir
Part.FileDir)
            in  (AbsRel
ar, forall os. [[Char]] -> [PathComponent os]
nonEmptyComponents [[Char]]
pcs1, Either FileDir Dir
fd))
        forall os. System os => Tagged os (Char -> Bool)
isPathSeparator forall os. System os => Tagged os (State [Char] AbsRel)
splitAbsoluteO

nonEmptyComponents :: [String] -> [PathComponent os]
nonEmptyComponents :: forall os. [[Char]] -> [PathComponent os]
nonEmptyComponents = forall a b. (a -> b) -> [a] -> [b]
map forall os. [Char] -> PathComponent os
PathComponent forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null)

splitDriveOS ::
    (System os, Class.AbsRel ar) => Tagged os (MS.State String ar)
splitDriveOS :: forall os ar. (System os, AbsRel ar) => Tagged os (State [Char] ar)
splitDriveOS =
    forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2
        (\StateT [Char] Identity [Char]
splDrive State [Char] AbsRel
splAbsolute ->
            forall ar (f :: * -> *).
AbsRel ar =>
f Abs -> f Rel -> f AbsRel -> f ar
Class.switchAbsRel (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Char] -> Abs
absPC StateT [Char] Identity [Char]
splDrive) (forall (m :: * -> *) a. Monad m => a -> m a
return Rel
Part.Rel) State [Char] AbsRel
splAbsolute)
        forall os. System os => Tagged os (StateT [Char] Identity [Char])
splitDriveAbs forall os. System os => Tagged os (State [Char] AbsRel)
splitAbsoluteO

splitDriveAbs :: (System os) => Tagged os (MS.State String String)
splitDriveAbs :: forall os. System os => Tagged os (StateT [Char] Identity [Char])
splitDriveAbs =
    forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2
        (\Char -> Bool
isSep StateT [Char] Identity [Char]
splDrive -> do
            [Char]
drive <- StateT [Char] Identity [Char]
splDrive
            [Char]
xt <- forall (m :: * -> *) s. Monad m => StateT s m s
MS.get
            case [Char]
xt of
                [] -> forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
drive
                Char
x:[Char]
xs ->
                    if Char -> Bool
isSep Char
x
                      then forall (m :: * -> *) s. Monad m => s -> StateT s m ()
MS.put [Char]
xs forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return ([Char]
driveforall a. [a] -> [a] -> [a]
++[Char
x])
                      else forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
drive)
        forall os. System os => Tagged os (Char -> Bool)
isPathSeparator forall os. System os => Tagged os (StateT [Char] Identity [Char])
splitDrive

splitAbsoluteO :: (System os) => Tagged os (MS.State String Part.AbsRel)
splitAbsoluteO :: forall os. System os => Tagged os (State [Char] AbsRel)
splitAbsoluteO =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\[Char]
drive -> if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
drive then AbsRel
Part.RelO else GenComponent -> AbsRel
Part.AbsO forall a b. (a -> b) -> a -> b
$ forall os. [Char] -> PathComponent os
PathComponent [Char]
drive)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
    forall os. System os => Tagged os (StateT [Char] Identity [Char])
splitAbsolute

-- | > \p -> uncurry Path.mkPathFromComponents (Path.pathComponents p) == (p::Default.AbsDir)
pathComponents ::
    (Class.FileDir fd) => Path os ar fd -> (ar, [PathComponent os])
pathComponents :: forall fd os ar.
FileDir fd =>
Path os ar fd -> (ar, [PathComponent os])
pathComponents (Path ar
ar [PathComponent os]
pcs fd
fd) =
    (ar
ar, [PathComponent os]
pcs forall a. [a] -> [a] -> [a]
++ forall fd a. FileDir fd => (GenComponent -> a) -> a -> a -> fd -> a
Class.withFileDir ((forall a. a -> [a] -> [a]
:[]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. GenComponent -> PathComponent os
retagPC) [] [] fd
fd)

prop_mkPathFromComponents_pathComponents :: (System os) => AbsDir os -> Property
prop_mkPathFromComponents_pathComponents :: forall os. System os => AbsDir os -> Property
prop_mkPathFromComponents_pathComponents Path os Abs Dir
p =
    forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall fd ar os.
FileDir fd =>
ar -> [PathComponent os] -> Path os ar fd
mkPathFromComponents (forall fd os ar.
FileDir fd =>
Path os ar fd -> (ar, [PathComponent os])
pathComponents Path os Abs Dir
p) forall a. Eq a => a -> a -> Bool
== Path os Abs Dir
p



------------------------------------------------------------------------
-- Basic Manipulation Functions

combineOperator :: String
combineOperator :: [Char]
combineOperator = [Char]
"</>"


instance (Class.Rel ar, Class.Dir fd) => Semigroup (Path os ar fd) where
    Path ar
r [PathComponent os]
pcs0 fd
_dir <> :: Path os ar fd -> Path os ar fd -> Path os ar fd
<> Path ar
_rel [PathComponent os]
pcs1 fd
d = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
r ([PathComponent os]
pcs0 forall a. [a] -> [a] -> [a]
++ [PathComponent os]
pcs1) fd
d
    sconcat :: NonEmpty (Path os ar fd) -> Path os ar fd
sconcat NonEmpty (Path os ar fd)
paths =
        forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path forall ar. Rel ar => ar
Class.relVar
            (forall a. Semigroup a => NonEmpty a -> a
sconcat forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Path ar
_rel [PathComponent os]
pcs fd
_dir) -> [PathComponent os]
pcs) NonEmpty (Path os ar fd)
paths) forall fd. Dir fd => fd
Class.dirVar

instance (Class.Rel ar, Class.Dir fd) => Monoid (Path os ar fd) where
    mempty :: Path os ar fd
mempty = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path forall ar. Rel ar => ar
Class.relVar [] forall fd. Dir fd => fd
Class.dirVar
    mappend :: Path os ar fd -> Path os ar fd -> Path os ar fd
mappend (Path ar
r [PathComponent os]
pcs0 fd
_dir) (Path ar
_rel [PathComponent os]
pcs1 fd
d) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
r ([PathComponent os]
pcs0 forall a. [a] -> [a] -> [a]
++ [PathComponent os]
pcs1) fd
d
    mconcat :: [Path os ar fd] -> Path os ar fd
mconcat [Path os ar fd]
paths =
        forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path forall ar. Rel ar => ar
Class.relVar
            (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Path ar
_rel [PathComponent os]
pcs fd
_dir) -> [PathComponent os]
pcs) [Path os ar fd]
paths) forall fd. Dir fd => fd
Class.dirVar


-- | Infix variant of 'combine'.
--
-- prop> Posix.toString (Posix.absDir "/tmp" </> Posix.relFile "file.txt") == "/tmp/file.txt"
-- prop> Posix.toString (Posix.absDir "/tmp" </> Posix.relDir "dir" </> Posix.relFile "file.txt") == "/tmp/dir/file.txt"
-- prop> Posix.toString (Posix.relDir "dir" </> Posix.relFile "file.txt") == "dir/file.txt"
-- prop> Windows.toString (Windows.absDir "\\tmp" </> Windows.relFile "file.txt") == "\\tmp\\file.txt"
-- prop> Windows.toString (Windows.absDir "c:\\tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"
-- prop> Windows.toString (Windows.absDir "c:tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"
-- prop> Windows.toString (Windows.absDir "c:\\" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"
-- prop> Windows.toString (Windows.absDir "c:" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"
-- prop> Windows.toString (Windows.relDir "dir" </> Windows.relFile "file.txt") == "dir\\file.txt"
(</>) :: DirPath os ar -> RelPath os fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs0 Dir
Part.Dir  </> :: forall os ar fd. DirPath os ar -> RelPath os fd -> Path os ar fd
</>  Path Rel
Part.Rel [PathComponent os]
pcs1 fd
fd  =  forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar ([PathComponent os]
pcs0 forall a. [a] -> [a] -> [a]
++ [PathComponent os]
pcs1) fd
fd

infixr 5  </>

-- | Infix variant of 'addExtension'.
--   We only allow files (and not directories) to have extensions added
--   by this function. This is because it's the vastly common case and
--   an attempt to add one to a directory will - more often than not -
--   represent an error.
--   We don't however want to prevent the corresponding operation on
--   directories, and so we provide a function that is more flexible:
--   'genericAddExtension'.
(<.>) :: FilePath os ar -> String -> FilePath os ar
FilePath os ar
p <.> :: forall os ar. FilePath os ar -> [Char] -> FilePath os ar
<.> [Char]
ext = forall os ar.
(GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar
mapFilePart (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall os. PathComponent os -> [Char] -> PathComponent os
addExtensionPC [Char]
ext) FilePath os ar
p

infixl 7  <.>

(<++>) :: FilePath os ar -> String -> FilePath os ar
FilePath os ar
p <++> :: forall os ar. FilePath os ar -> [Char] -> FilePath os ar
<++> [Char]
str = forall os ar.
([Char] -> [Char]) -> FilePath os ar -> FilePath os ar
mapFileName (forall a. [a] -> [a] -> [a]
++[Char]
str) FilePath os ar
p

infixl 7  <++>

-- | Add an extension, even if there is already one there.
--   E.g. @addExtension \"foo.txt\" \"bat\" -> \"foo.txt.bat\"@.
--
-- prop> Path.addExtension (relFile "file.txt") "bib" == Posix.relFile "file.txt.bib"
-- prop> Path.addExtension (relFile "file.") ".bib" == Posix.relFile "file..bib"
-- prop> Path.addExtension (relFile "file") ".bib" == Posix.relFile "file.bib"
-- prop> Path.addExtension Path.emptyFile "bib" == Posix.relFile ".bib"
-- prop> Path.addExtension Path.emptyFile ".bib" == Posix.relFile ".bib"
-- prop> Path.takeFileName (Path.addExtension Path.emptyFile "ext") == Posix.relFile ".ext"
addExtension :: FilePath os ar -> String -> FilePath os ar
addExtension :: forall os ar. FilePath os ar -> [Char] -> FilePath os ar
addExtension = forall os ar. FilePath os ar -> [Char] -> FilePath os ar
(<.>)

-- | Join an (absolute or relative) directory path with a relative
--   (file or directory) path to form a new path.
--
-- prop> \p -> Path.combine Path.currentDir p == (p::Default.RelDir)
combine :: DirPath os ar -> RelPath os fd -> Path os ar fd
combine :: forall os ar fd. DirPath os ar -> RelPath os fd -> Path os ar fd
combine = forall os ar fd. DirPath os ar -> RelPath os fd -> Path os ar fd
(</>)


-- | Remove last extension, and the \".\" preceding it.
--
-- prop> forAllAbsRel $ \x -> Path.dropExtension x == fst (Path.splitExtension x)
dropExtension :: FilePath os ar -> FilePath os ar
dropExtension :: forall os fd. FilePath os fd -> FilePath os fd
dropExtension = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtension

-- | Drop all extensions
--
-- prop> forAllAbsRel $ \x -> not $ Path.hasAnExtension (Path.dropExtensions x)
dropExtensions :: FilePath os ar -> FilePath os ar
dropExtensions :: forall os fd. FilePath os fd -> FilePath os fd
dropExtensions = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtensions

-- | Synonym for 'takeDirectory'
dropFileName :: FilePath os ar -> DirPath os ar
dropFileName :: forall os ar. FilePath os ar -> DirPath os ar
dropFileName = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (DirPath os ar, RelFile os)
splitFileName


-- | Set the extension of a file, overwriting one if already present.
--
-- prop> Path.replaceExtension (relFile "file.txt") ".bob" == Posix.relFile "file.bob"
-- prop> Path.replaceExtension (relFile "file.txt") "bob" == Posix.relFile "file.bob"
-- prop> Path.replaceExtension (relFile "file") ".bob" == Posix.relFile "file.bob"
-- prop> Path.replaceExtension (relFile "file.txt") "" == Posix.relFile "file"
-- prop> Path.replaceExtension (relFile "file.fred.bob") "txt" == Posix.relFile "file.fred.txt"
replaceExtension :: FilePath os ar -> String -> FilePath os ar
replaceExtension :: forall os ar. FilePath os ar -> [Char] -> FilePath os ar
replaceExtension FilePath os ar
p [Char]
ext = forall os fd. FilePath os fd -> FilePath os fd
dropExtension FilePath os ar
p forall os ar. FilePath os ar -> [Char] -> FilePath os ar
<.> [Char]
ext

replaceBaseName :: FilePath os ar -> String -> FilePath os ar
replaceBaseName :: forall os ar. FilePath os ar -> [Char] -> FilePath os ar
replaceBaseName FilePath os ar
p [Char]
bn =
    forall os ar.
(GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar
mapFilePart (forall os. PathComponent os -> [Char] -> PathComponent os
addExtensionPC (forall os. [Char] -> PathComponent os
PathComponent [Char]
bn) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionPC) FilePath os ar
p

replaceDirectory :: FilePath os ar1 -> DirPath os ar2 -> FilePath os ar2
replaceDirectory :: forall os ar1 ar2.
FilePath os ar1 -> DirPath os ar2 -> FilePath os ar2
replaceDirectory (Path ar1
_ [PathComponent os]
_ File
fd) (Path ar2
ar [PathComponent os]
pcs Dir
_) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar2
ar [PathComponent os]
pcs File
fd

replaceFileName :: FilePath os ar -> String -> FilePath os ar
replaceFileName :: forall os ar. FilePath os ar -> [Char] -> FilePath os ar
replaceFileName FilePath os ar
p [Char]
fn = forall os ar.
(GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar
mapFilePart (forall a b. a -> b -> a
const (forall os. [Char] -> PathComponent os
PathComponent [Char]
fn)) FilePath os ar
p


-- | Split on the extension. 'addExtension' is the inverse.
--
-- prop> forAllAbsRel $ \x -> uncurry (<.>) (Path.splitExtension x) == x
-- prop> forAllAbsRel $ \x -> uncurry Path.addExtension (Path.splitExtension x) == x
-- prop> Path.splitExtension (relFile "file.txt") == (Posix.relFile "file",".txt")
-- prop> Path.splitExtension (relFile ".bashrc") == (Posix.emptyFile, ".bashrc")
-- prop> Path.splitExtension (relFile "file") == (Posix.relFile "file","")
-- prop> Path.splitExtension (relFile "file/file.txt") == (Posix.relFile "file/file",".txt")
-- prop> Path.splitExtension (relFile "file.txt/boris") == (Posix.relFile "file.txt/boris","")
-- prop> Path.splitExtension (relFile "file.txt/boris.ext") == (Posix.relFile "file.txt/boris",".ext")
-- prop> Path.splitExtension (relFile "file/path.txt.bob.fred") == (Posix.relFile "file/path.txt.bob",".fred")
splitExtension :: FilePath os ar -> (FilePath os ar, String)
splitExtension :: forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtension = forall a os ar.
(GenComponent -> (GenComponent, a))
-> FilePath os ar -> (FilePath os ar, a)
splitFilePart forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionPC

-- | Split on all extensions
--
-- prop> Path.splitExtensions (relFile "file.tar.gz") == (Posix.relFile "file",".tar.gz")
-- prop> \p -> uncurry (<.>) (Path.splitExtension p) == (p::Default.AbsFile)
splitExtensions :: FilePath os ar -> (FilePath os ar, String)
splitExtensions :: forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtensions = forall a os ar.
(GenComponent -> (GenComponent, a))
-> FilePath os ar -> (FilePath os ar, a)
splitFilePart forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionsPC

-- | prop> \p -> uncurry Path.combine (Path.splitFileName p) == (p::Default.AbsFile)
splitFileName :: FilePath os ar -> (DirPath os ar, RelFile os)
splitFileName :: forall os ar. FilePath os ar -> (DirPath os ar, RelFile os)
splitFileName (Path ar
ar [PathComponent os]
pcs File
fd) = (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs Dir
Part.Dir, forall os. File -> RelFile os
atomicFile File
fd)

-- | > \p -> (uncurry Path.combine <$> Path.splitDirName p) == toMaybe (not $ Default.isDrive p) (p::Default.AbsDir)
splitDirName :: DirPath os ar -> Maybe (DirPath os ar, RelDir os)
splitDirName :: forall os ar. DirPath os ar -> Maybe (DirPath os ar, RelDir os)
splitDirName = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd forall os ar. FilePath os ar -> DirPath os ar
dirFromFile forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (DirPath os ar, RelFile os)
splitFileName) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. DirPath os ar -> Maybe (FilePath os ar)
fileFromDir

prop_splitDir_combine :: (System os) => AbsDir os -> Property
prop_splitDir_combine :: forall os. System os => AbsDir os -> Property
prop_splitDir_combine Path os Abs Dir
p =
    forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$
    (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall os ar fd. DirPath os ar -> RelPath os fd -> Path os ar fd
combine forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall os ar. DirPath os ar -> Maybe (DirPath os ar, RelDir os)
splitDirName Path os Abs Dir
p) forall a. Eq a => a -> a -> Bool
== forall a. Bool -> a -> Maybe a
toMaybe (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall os. AbsDir os -> Bool
isDrive Path os Abs Dir
p) Path os Abs Dir
p


-- | Get the basename of a file
--
-- prop> Path.takeBaseName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile"
-- prop> Path.takeBaseName (relFile "./myfile.txt") == Posix.relFile "myfile"
-- prop> Path.takeBaseName (relFile "myfile.txt") == Posix.relFile "myfile"
takeBaseName :: FilePath os ar -> RelFile os
takeBaseName :: forall os ar. FilePath os ar -> RelFile os
takeBaseName = forall os ar. FilePath os ar -> RelFile os
takeFileName forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os fd. FilePath os fd -> FilePath os fd
dropExtension

takeDirectory :: FilePath os ar -> DirPath os ar
takeDirectory :: forall os ar. FilePath os ar -> DirPath os ar
takeDirectory = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (DirPath os ar, RelFile os)
splitFileName

-- prop> Path.takeSuperDirectory (Posix.absDir "/tmp/somedir") == Just (absDir "/tmp")
-- prop> Path.takeSuperDirectory (Posix.absDir "/tmp/") == Just (absDir "/")
-- prop> Path.takeSuperDirectory (Posix.absDir "/") == Nothing
-- prop> Path.takeSuperDirectory (Posix.relDir "tmp/somedir") == Just (relDir "tmp")
-- prop> Path.takeSuperDirectory (Posix.relDir "./somedir") == Just (relDir ".")
-- prop> Path.takeSuperDirectory (Posix.relDir "somedir") == Just Path.currentDir
-- prop> Path.takeSuperDirectory (Posix.relDir "") == Nothing
takeSuperDirectory :: DirPath os ar -> Maybe (DirPath os ar)
takeSuperDirectory :: forall os ar. DirPath os ar -> Maybe (DirPath os ar)
takeSuperDirectory = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os ar. FilePath os ar -> DirPath os ar
takeDirectory forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. DirPath os ar -> Maybe (FilePath os ar)
fileFromDir

-- | Get the extension of a file, returns @\"\"@ for no extension, @.ext@ otherwise.
--
-- prop> forAllAbsRel $ \x -> Path.takeExtension x == snd (Path.splitExtension x)
-- prop> forAllAbsRel $ \x -> Path.takeExtension (Path.addExtension x "ext") == ".ext"
-- prop> forAllAbsRel $ \x -> Path.takeExtension (Path.replaceExtension x "ext") == ".ext"
takeExtension :: FilePath os ar -> String
takeExtension :: forall os ar. FilePath os ar -> [Char]
takeExtension = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtension

-- | Get all extensions
--
-- prop> Path.takeExtensions (Posix.relFile "file.tar.gz") == ".tar.gz"
takeExtensions :: FilePath os ar -> String
takeExtensions :: forall os ar. FilePath os ar -> [Char]
takeExtensions = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtensions

-- | Get the filename component of a file path (ie stripping all parent dirs)
--
-- prop> Path.takeFileName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile.txt"
-- prop> Path.takeFileName (relFile "./myfile.txt") == Posix.relFile "myfile.txt"
-- prop> Path.takeFileName (relFile "myfile.txt") == Posix.relFile "myfile.txt"
-- prop> \p -> Path.toString (Path.takeFileName p) `isSuffixOf` Path.toString (p::Default.AbsFile)
takeFileName :: FilePath os ar -> RelFile os
takeFileName :: forall os ar. FilePath os ar -> RelFile os
takeFileName (Path ar
_ [PathComponent os]
_ File
fd) = forall os. File -> RelFile os
atomicFile File
fd

-- | > \p -> fmap (\d -> toString d `isSuffixOf` toString p) (takeDirName p) == toMaybe (not $ isDrive p) True
takeDirName :: DirPath os ar -> Maybe (RelDir os)
takeDirName :: forall os ar. DirPath os ar -> Maybe (RelDir os)
takeDirName = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. DirPath os ar -> Maybe (DirPath os ar, RelDir os)
splitDirName

prop_takeDirName_end :: (System os) => AbsDir os -> Property
prop_takeDirName_end :: forall os. System os => AbsDir os -> Property
prop_takeDirName_end AbsDir os
p =
    forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Path os Rel Dir
d -> forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
toString Path os Rel Dir
d forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
toString AbsDir os
p) (forall os ar. DirPath os ar -> Maybe (RelDir os)
takeDirName AbsDir os
p)
    forall a. Eq a => a -> a -> Bool
==
    forall a. Bool -> a -> Maybe a
toMaybe (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall os. AbsDir os -> Bool
isDrive AbsDir os
p) Bool
True

mapFileName :: (String -> String) -> FilePath os ar -> FilePath os ar
mapFileName :: forall os ar.
([Char] -> [Char]) -> FilePath os ar -> FilePath os ar
mapFileName = forall os ar.
(GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar
mapFilePart forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os.
([Char] -> [Char]) -> PathComponent os -> PathComponent os
pcMap

mapFileNameF ::
    (Functor f) =>
    (String -> f String) -> FilePath os ar -> f (FilePath os ar)
mapFileNameF :: forall (f :: * -> *) os ar.
Functor f =>
([Char] -> f [Char]) -> FilePath os ar -> f (FilePath os ar)
mapFileNameF = forall (f :: * -> *) os ar.
Functor f =>
(GenComponent -> f GenComponent)
-> FilePath os ar -> f (FilePath os ar)
mapFilePartF forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) os.
Functor f =>
([Char] -> f [Char]) -> PathComponent os -> f (PathComponent os)
Part.pcMapF


------------------------------------------------------------------------
-- Auxillary Manipulation Functions

-- | Check whether two strings are equal as file paths.
--
-- prop>       Posix.equalFilePath "abc/def" "abc/def"
-- prop>       Posix.equalFilePath "abc/def" "abc//def"
-- prop>       Posix.equalFilePath "/tmp/" "/tmp"
-- prop>       Posix.equalFilePath "/tmp" "//tmp"
-- prop>       Posix.equalFilePath "/tmp" "///tmp"
-- prop> not $ Posix.equalFilePath "abc" "def"
-- prop> not $ Posix.equalFilePath "/tmp" "tmp"
-- prop>       Windows.equalFilePath "abc\\def" "abc\\def"
-- prop>       Windows.equalFilePath "abc\\def" "abc\\\\def"
-- prop>       Windows.equalFilePath "file" "File"
-- prop>       Windows.equalFilePath "\\file" "\\\\file"
-- prop>       Windows.equalFilePath "\\file" "\\\\\\file"
-- prop> not $ Windows.equalFilePath "abc" "def"
-- prop> not $ Windows.equalFilePath "file" "dir"
equalFilePath :: (System os) => Tagged os (String -> String -> Bool)
equalFilePath :: forall os. System os => Tagged os ([Char] -> [Char] -> Bool)
equalFilePath = forall b a. Eq b => (a -> b) -> a -> a -> Bool
equating forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall os.
System os =>
Tagged os ([Char] -> Either (AbsFileDir os) (RelFileDir os))
mkPathAbsOrRelTagged

mkPathAbsOrRelTagged ::
    (System os) =>
    Tagged os (String -> Either (AbsFileDir os) (RelFileDir os))
mkPathAbsOrRelTagged :: forall os.
System os =>
Tagged os ([Char] -> Either (AbsFileDir os) (RelFileDir os))
mkPathAbsOrRelTagged = forall {k} (s :: k) b. b -> Tagged s b
Tagged forall os fd.
(System os, FileDir fd) =>
[Char] -> Either (AbsPath os fd) (RelPath os fd)
mkPathAbsOrRelPriv

-- | Constructs a 'RelPath' from a list of components.
--   It is an unchecked error if the path components contain path separators.
--   It is an unchecked error if a 'RelFile' path is empty.
--
-- prop> Path.joinPath ["tmp","someDir","dir"] == Posix.relDir "tmp/someDir/dir"
-- prop> Path.joinPath ["tmp","someDir","file.txt"] == Posix.relFile "tmp/someDir/file.txt"
joinPath :: (Class.FileDir fd) => [String] -> RelPath os fd
joinPath :: forall fd os. FileDir fd => [[Char]] -> RelPath os fd
joinPath = forall fd ar os.
FileDir fd =>
ar -> [PathComponent os] -> Path os ar fd
mkPathFromComponents Rel
Part.Rel forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall os. [Char] -> PathComponent os
PathComponent

-- | Currently just transforms:
--
-- prop> Path.normalise (absFile "/tmp/fred/./jim/./file") == Posix.absFile "/tmp/fred/jim/file"
normalise :: (System os) => Path os ar fd -> Path os ar fd
normalise :: forall os ar fd. System os => Path os ar fd -> Path os ar fd
normalise = forall os ar fd.
([PathComponent os] -> [PathComponent os])
-> Path os ar fd -> Path os ar fd
mapPathDirs (forall a. (a -> Bool) -> [a] -> [a]
filter (forall os. [Char] -> PathComponent os
PathComponent [Char]
currentDirComponent forall a. Eq a => a -> a -> Bool
/=))

-- | Deconstructs a path into its components.
--
-- prop> Path.splitPath (Posix.absDir "/tmp/someDir/mydir.dir") == (True, map relDir ["tmp","someDir","mydir.dir"], Nothing)
-- prop> Path.splitPath (Posix.absFile "/tmp/someDir/myfile.txt") == (True, map relDir ["tmp","someDir"], Just $ relFile "myfile.txt")
splitPath ::
    (Class.AbsRel ar, Class.FileOrDir fd) =>
    Path os ar fd -> (Bool, [RelDir os], Maybe (RelFile os))
splitPath :: forall ar fd os.
(AbsRel ar, FileOrDir fd) =>
Path os ar fd -> (Bool, [RelDir os], Maybe (RelFile os))
splitPath (Path ar
ar [PathComponent os]
pcs fd
fd) =
    (forall ar. AbsRel ar => ar -> Bool
Class.isAbsolute ar
ar,
     forall a b. (a -> b) -> [a] -> [b]
map (\PathComponent os
pc -> forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path Rel
Part.Rel [PathComponent os
pc] Dir
Part.Dir) [PathComponent os]
pcs,
     forall fd os. FileOrDir fd => fd -> Maybe (RelFile os)
maybeFileDir fd
fd)

maybeFileDir :: (Class.FileOrDir fd) => fd -> Maybe (RelFile os)
maybeFileDir :: forall fd os. FileOrDir fd => fd -> Maybe (RelFile os)
maybeFileDir = forall fd a. FileOrDir fd => (GenComponent -> a) -> a -> fd -> a
Class.withFileOrDir (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. File -> RelFile os
atomicFile forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenComponent -> File
Part.File) forall a. Maybe a
Nothing

-- | This function can be used to construct a relative path by removing
--   the supplied 'AbsDir' from the front. It is a runtime 'error' if the
--   supplied 'AbsPath' doesn't start with the 'AbsDir'.
--
-- prop> Path.makeRelative (absDir "/tmp/somedir") (absFile "/tmp/somedir/anotherdir/file.txt") == Posix.relFile "anotherdir/file.txt"
-- prop> Path.makeRelative (absDir "/tmp/somedir") (absDir "/tmp/somedir/anotherdir/dir") == Posix.relDir "anotherdir/dir"
-- prop> Path.makeRelative (absDir "c:\\tmp\\somedir") (absFile "C:\\Tmp\\SomeDir\\AnotherDir\\File.txt") == Windows.relFile "AnotherDir\\File.txt"
-- prop> Path.makeRelative (absDir "c:\\tmp\\somedir") (absDir "c:\\tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"
-- prop> Path.makeRelative (absDir "c:tmp\\somedir") (absDir "c:tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"
makeRelative ::
    (System os, Class.FileDir fd) =>
    AbsDir os -> AbsPath os fd -> RelPath os fd
makeRelative :: forall os fd.
(System os, FileDir fd) =>
AbsDir os -> AbsPath os fd -> RelPath os fd
makeRelative AbsDir os
relTo AbsPath os fd
orig =
    forall a. a -> Maybe a -> a
fromMaybe
        (forall a. HasCallStack => [Char] -> a
error forall a b. (a -> b) -> a -> b
$
            forall r. PrintfType r => [Char] -> r
printf [Char]
"System.Path can't make (%s) relative to (%s)"
                (forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
toString AbsPath os fd
orig) (forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> [Char]
toString AbsDir os
relTo)) forall a b. (a -> b) -> a -> b
$
    forall os fd.
(System os, FileDir fd) =>
AbsDir os -> AbsPath os fd -> Maybe (RelPath os fd)
makeRelativeMaybe AbsDir os
relTo AbsPath os fd
orig

-- prop> Path.makeRelativeMaybe (Posix.absDir "/tmp/somedir") (absFile "/tmp/anotherdir/file.txt") == Nothing
-- prop> Path.makeRelativeMaybe (Posix.absDir "/Tmp") (absFile "/tmp/anotherdir/file.txt") == Nothing
-- prop> Path.makeRelativeMaybe (Windows.absDir "\\Tmp") (absFile "\\tmp\\anotherdir\\file.txt") == Just (relFile "anotherdir\\file.txt")
makeRelativeMaybe ::
    (System os, Class.FileDir fd) =>
    AbsDir os -> AbsPath os fd -> Maybe (RelPath os fd)
makeRelativeMaybe :: forall os fd.
(System os, FileDir fd) =>
AbsDir os -> AbsPath os fd -> Maybe (RelPath os fd)
makeRelativeMaybe AbsDir os
relTo AbsPath os fd
orig =
    case (forall os ar fd.
Path os ar fd
-> (WrapAbsRel os ar, [PathComponent os], WrapFileDir os fd)
inspectPath AbsDir os
relTo, forall os ar fd.
Path os ar fd
-> (WrapAbsRel os ar, [PathComponent os], WrapFileDir os fd)
inspectPath AbsPath os fd
orig) of
        ((WrapAbsRel os Abs
relToAR, [PathComponent os]
relToPCs, WrapFileDir Dir
Part.Dir),
         (WrapAbsRel os Abs
origAR, [PathComponent os]
origPCs, WrapFileDir fd
fd)) ->
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path Rel
Part.Rel) fd
fd) forall a b. (a -> b) -> a -> b
$
                forall (f :: * -> *). Alternative f => Bool -> f ()
guard (WrapAbsRel os Abs
relToAR forall a. Eq a => a -> a -> Bool
== WrapAbsRel os Abs
origAR) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix [PathComponent os]
relToPCs [PathComponent os]
origPCs

-- | Joins an absolute directory with a relative path to construct a
--   new absolute path.
--
-- prop> Path.makeAbsolute (absDir "/tmp") (relFile "file.txt")      == Posix.absFile "/tmp/file.txt"
-- prop> Path.makeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"
-- prop> Path.makeAbsolute (absDir "/tmp") (relDir  "adir/dir")      == Posix.absDir "/tmp/adir/dir"
-- prop> \base p -> Default.toString p `isSuffixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))
-- prop> \base p -> Default.toString base `isPrefixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))
makeAbsolute :: (System os) => AbsDir os -> RelPath os fd -> AbsPath os fd
makeAbsolute :: forall os fd.
System os =>
AbsDir os -> RelPath os fd -> AbsPath os fd
makeAbsolute = forall os ar fd.
(System os, AbsRel ar) =>
AbsDir os -> Path os ar fd -> AbsPath os fd
genericMakeAbsolute

-- | Converts a relative path into an absolute one by
--   prepending the current working directory.
makeAbsoluteFromCwd :: (System os) => RelPath os fd -> IO (AbsPath os fd)
makeAbsoluteFromCwd :: forall os fd. System os => RelPath os fd -> IO (AbsPath os fd)
makeAbsoluteFromCwd = forall os ar fd.
(System os, AbsRel ar) =>
Path os ar fd -> IO (AbsPath os fd)
genericMakeAbsoluteFromCwd

dynamicMakeAbsolute ::
    (System os) => AbsDir os -> AbsRelPath os fd -> AbsPath os fd
dynamicMakeAbsolute :: forall os fd.
System os =>
AbsDir os -> AbsRelPath os fd -> AbsPath os fd
dynamicMakeAbsolute = forall os ar fd.
(System os, AbsRel ar) =>
AbsDir os -> Path os ar fd -> AbsPath os fd
genericMakeAbsolute

dynamicMakeAbsoluteFromCwd ::
    (System os) => AbsRelPath os fd -> IO (AbsPath os fd)
dynamicMakeAbsoluteFromCwd :: forall os fd. System os => AbsRelPath os fd -> IO (AbsPath os fd)
dynamicMakeAbsoluteFromCwd = forall os ar fd.
(System os, AbsRel ar) =>
Path os ar fd -> IO (AbsPath os fd)
genericMakeAbsoluteFromCwd

-- | As for 'makeAbsolute', but for use when the path may already be
--   absolute (in which case it is left unchanged).
--   You should avoid the use of 'genericMakeAbsolute'-type functions,
--   because then you avoid to absolutize a path that was already absolutized.
--
-- prop> Path.genericMakeAbsolute (absDir "/tmp") (relFile "file.txt")       == Posix.absFile "/tmp/file.txt"
-- prop> Path.genericMakeAbsolute (absDir "/tmp") (relFile "adir/file.txt")  == Posix.absFile "/tmp/adir/file.txt"
-- prop> Path.genericMakeAbsolute (absDir "/tmp") (absFile "/adir/file.txt") == Posix.absFile "/adir/file.txt"
genericMakeAbsolute ::
    (System os, Class.AbsRel ar) => AbsDir os -> Path os ar fd -> AbsPath os fd
genericMakeAbsolute :: forall os ar fd.
(System os, AbsRel ar) =>
AbsDir os -> Path os ar fd -> AbsPath os fd
genericMakeAbsolute AbsDir os
base Path os ar fd
p = forall ar os fd a.
AbsRel ar =>
(AbsPath os fd -> a) -> (RelPath os fd -> a) -> Path os ar fd -> a
withAbsRel forall a. a -> a
id (AbsDir os
base forall os ar fd. DirPath os ar -> RelPath os fd -> Path os ar fd
</>) Path os ar fd
p

-- | As for 'makeAbsoluteFromCwd', but for use when the path may already be
--   absolute (in which case it is left unchanged).
genericMakeAbsoluteFromCwd ::
    (System os, Class.AbsRel ar) => Path os ar fd -> IO (AbsPath os fd)
genericMakeAbsoluteFromCwd :: forall os ar fd.
(System os, AbsRel ar) =>
Path os ar fd -> IO (AbsPath os fd)
genericMakeAbsoluteFromCwd Path os ar fd
p = do
  [Char]
cwdString <- IO [Char]
SD.getCurrentDirectory -- we don't use System.Path.Directory impl here to avoid module cycle
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall os ar fd.
(System os, AbsRel ar) =>
AbsDir os -> Path os ar fd -> AbsPath os fd
genericMakeAbsolute (forall os. System os => [Char] -> AbsDir os
asAbsDir [Char]
cwdString) Path os ar fd
p

-- prop_makeAbsoluteFromDir_startSameAbs :: AbsDir os -> AbsFile -> Property
-- prop_makeAbsoluteFromDir_startSameAbs base p = property $ show base `isPrefixOf` show (makeAbsolute base p)


-- | Convert a file to a directory path.
--   Obviously, the corresponding disk object won't change accordingly.
--   The purpose of this function is to be an intermediate step
--   when deriving a directory name from a file name.
dirFromFile :: FilePath os ar -> DirPath os ar
dirFromFile :: forall os ar. FilePath os ar -> DirPath os ar
dirFromFile FilePath os ar
p = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path (forall fd os ar.
FileDir fd =>
Path os ar fd -> (ar, [PathComponent os])
pathComponents FilePath os ar
p) Dir
Part.Dir

-- | Convert a directory to a file path.
--   The function returns 'Nothing' if the directory path is empty.
--   The purpose of this function is to be an intermediate step
--   when deriving a file name from a directory name.
fileFromDir :: DirPath os ar -> Maybe (FilePath os ar)
fileFromDir :: forall os ar. DirPath os ar -> Maybe (FilePath os ar)
fileFromDir = forall os ar fd. Path os ar fd -> Maybe (FilePath os ar)
fileFromAny

toFileDir :: (Class.FileDir fd) => Path os ar fd -> FileDirPath os ar
toFileDir :: forall fd os ar. FileDir fd => Path os ar fd -> FileDirPath os ar
toFileDir Path os ar fd
p = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path (forall fd os ar.
FileDir fd =>
Path os ar fd -> (ar, [PathComponent os])
pathComponents Path os ar fd
p) FileDir
Part.FileDir

fromFileDir ::
    (Class.FileDir fd) => FileDirPath os ar -> Maybe (Path os ar fd)
fromFileDir :: forall fd os ar.
FileDir fd =>
FileDirPath os ar -> Maybe (Path os ar fd)
fromFileDir FileDirPath os ar
p =
    forall fd (f :: * -> *) os ar.
FileDir fd =>
f (FilePath os ar)
-> f (DirPath os ar) -> f (FileDirPath os ar) -> f (Path os ar fd)
switchFileDir
        (forall os ar. FileDirPath os ar -> Maybe (FilePath os ar)
fileFromFileDir FileDirPath os ar
p)
        (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall os ar. FileDirPath os ar -> DirPath os ar
dirFromFileDir FileDirPath os ar
p)
        (forall a. a -> Maybe a
Just FileDirPath os ar
p)

fileFromFileDir :: FileDirPath os ar -> Maybe (FilePath os ar)
fileFromFileDir :: forall os ar. FileDirPath os ar -> Maybe (FilePath os ar)
fileFromFileDir = forall os ar fd. Path os ar fd -> Maybe (FilePath os ar)
fileFromAny

fileFromAny :: Path os ar fd -> Maybe (FilePath os ar)
fileFromAny :: forall os ar fd. Path os ar fd -> Maybe (FilePath os ar)
fileFromAny (Path ar
ar [PathComponent os]
pcs fd
_) =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b c a. (b -> c) -> (a, b) -> (a, c)
mapSnd (GenComponent -> File
Part.File forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. PathComponent os -> GenComponent
untagPC)) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Maybe ([a], a)
ListHT.viewR [PathComponent os]
pcs

dirFromFileDir :: FileDirPath os ar -> DirPath os ar
dirFromFileDir :: forall os ar. FileDirPath os ar -> DirPath os ar
dirFromFileDir (Path ar
ar [PathComponent os]
pcs FileDir
Part.FileDir) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs Dir
Part.Dir


toAbsRel :: (Class.AbsRel ar) => Path os ar fd -> AbsRelPath os fd
toAbsRel :: forall ar os fd. AbsRel ar => Path os ar fd -> AbsRelPath os fd
toAbsRel (Path ar
ar [PathComponent os]
pcs fd
fd) = forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path (forall ar. AbsRel ar => ar -> AbsRel
Class.toAbsRel ar
ar) [PathComponent os]
pcs fd
fd

fromAbsRel :: (Class.AbsRel ar) => AbsRelPath os fd -> Maybe (Path os ar fd)
fromAbsRel :: forall ar os fd.
AbsRel ar =>
AbsRelPath os fd -> Maybe (Path os ar fd)
fromAbsRel (Path AbsRel
ar0 [PathComponent os]
pcs fd
fd) = (\ar
ar -> forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs fd
fd) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall ar. AbsRel ar => AbsRel -> Maybe ar
Class.fromAbsRel AbsRel
ar0


------------------------------------------------------------------------
-- NYI - Not Yet Implemented

{-
splitSearchPath  :: String   -> [String]
getSearchPath    :: IO [String]
splitDrive       :: String   -> (String, String)
joinDrive        :: String   -> String -> String
takeDrive        :: String   -> String
hasDrive         :: String   -> Bool
dropDrive        :: String   -> String
isDrive          :: String   -> Bool
isValid          :: String   -> Bool
makeValid        :: String   -> String
-}

isDrive :: AbsDir os -> Bool
isDrive :: forall os. AbsDir os -> Bool
isDrive (Path Abs
_ [PathComponent os]
pcs Dir
_) = forall (t :: * -> *) a. Foldable t => t a -> Bool
null [PathComponent os]
pcs


------------------------------------------------------------------------
-- Path Predicates

-- | Test whether a @'Path' ar fd@ is absolute.
--
-- prop> Path.isAbsolute (Posix.absFile "/fred")
-- prop> Path.isAbsolute (Windows.absFile "\\fred")
-- prop> Path.isAbsolute (Windows.absFile "c:\\fred")
-- prop> Path.isAbsolute (Windows.absFile "c:fred")
isAbsolute :: Class.AbsRel ar => Path os ar fd -> Bool
isAbsolute :: forall ar os fd. AbsRel ar => Path os ar fd -> Bool
isAbsolute = forall ar os fd a.
AbsRel ar =>
(AbsPath os fd -> a) -> (RelPath os fd -> a) -> Path os ar fd -> a
withAbsRel (forall a b. a -> b -> a
const Bool
True) (forall a b. a -> b -> a
const Bool
False)

-- | Invariant - this should return True iff arg is of type @'Path' Part.Rel _@
--
-- > isRelative = not . isAbsolute
-- prop> Path.isRelative (Posix.relFile "fred")
-- prop> Path.isRelative (Windows.relFile "fred")
isRelative :: Class.AbsRel ar => Path os ar fd -> Bool
isRelative :: forall ar os fd. AbsRel ar => Path os ar fd -> Bool
isRelative = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ar os fd. AbsRel ar => Path os ar fd -> Bool
isAbsolute


{- |
Test whether the 'String' would correspond
to an absolute path if interpreted as a 'Path'.
-}
isAbsoluteString :: (System os) => Tagged os (String -> Bool)
isAbsoluteString :: forall os. System os => Tagged os ([Char] -> Bool)
isAbsoluteString =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\StateT [Char] Identity [Char]
split -> Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. State s a -> s -> a
MS.evalState StateT [Char] Identity [Char]
split) forall os. System os => Tagged os (StateT [Char] Identity [Char])
splitAbsolute

{- |
Test whether the 'String' would correspond
to a relative path if interpreted as a 'Path'.

> isRelativeString = not . isAbsoluteString
-}
isRelativeString :: (System os) => Tagged os (String -> Bool)
isRelativeString :: forall os. System os => Tagged os ([Char] -> Bool)
isRelativeString = (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
.) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall os. System os => Tagged os ([Char] -> Bool)
isAbsoluteString


-- | Does the given filename have an extension?
--
-- prop> forAllAbsRel $ \x -> null (Path.takeExtension x) == not (Path.hasAnExtension x)
hasAnExtension :: FilePath os ar -> Bool
hasAnExtension :: forall os ar. FilePath os ar -> Bool
hasAnExtension = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtension

-- | Does the given filename have the given extension?
--
-- prop> Path.hasExtension ".hs" (Posix.relFile "MyCode.hs")
-- prop> Path.hasExtension ".hs" (Posix.relFile "MyCode.bak.hs")
-- prop> not $ Path.hasExtension ".hs" (Posix.relFile "MyCode.hs.bak")
hasExtension :: String -> FilePath os ar -> Bool
hasExtension :: forall os ar. [Char] -> FilePath os ar -> Bool
hasExtension [Char]
ext = (forall a. Eq a => a -> a -> Bool
==[Char]
ext) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtension


------------------------------------------------------------------------
-- Separators

-- | Part.File extension character
--
-- prop> Posix.extSeparator == '.'
extSeparator :: Char
extSeparator :: Char
extSeparator = Char
'.'

-- | The character that is used to separate the entries in the $PATH environment variable.
--
searchPathSeparator :: Char
searchPathSeparator :: Char
searchPathSeparator = Char
':'

-- | Is the character an extension character?
--
-- prop> \a -> Posix.isExtSeparator a == (a == Posix.extSeparator)
isExtSeparator :: Char -> Bool
isExtSeparator :: Char -> Bool
isExtSeparator = (forall a. Eq a => a -> a -> Bool
== Char
extSeparator)

-- | Is the character a file separator?
--
-- prop> \a -> Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)
isSearchPathSeparator :: Char -> Bool
isSearchPathSeparator :: Char -> Bool
isSearchPathSeparator = (forall a. Eq a => a -> a -> Bool
== Char
searchPathSeparator)


------------------------------------------------------------------------
-- Generic Manipulation Functions

-- These functions support manipulation of extensions on directories
-- as well as files. They have looser types than the corresponding
-- 'Basic Manipulation Functions', but it is expected that the basic
-- functions will be used more frequently as they provide more checks.

-- | This is a more flexible variant of 'addExtension' / '<.>' which can
--   work with files or directories
--
-- prop> Path.genericAddExtension (absDir "/") "x" == Posix.absDir "/.x"
-- prop> Path.genericAddExtension (absDir "/a") "x" == Posix.absDir "/a.x"
-- prop> Path.genericAddExtension Path.emptyFile "x" == Posix.relFile ".x"
-- prop> Path.genericAddExtension Path.emptyFile "" == Posix.emptyFile
genericAddExtension ::
    (Class.FileDir fd) => Path os ar fd -> String -> Path os ar fd
genericAddExtension :: forall fd os ar.
FileDir fd =>
Path os ar fd -> [Char] -> Path os ar fd
genericAddExtension =
    forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> b) -> a -> b
$ \[Char]
ext ->
        forall a. Endo a -> a -> a
appEndo forall a b. (a -> b) -> a -> b
$ forall m. Monoid m => Bool -> m -> m
MonHT.when (Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
ext) forall a b. (a -> b) -> a -> b
$
        forall fd (f :: * -> *) os ar.
FileDir fd =>
f (FilePath os ar)
-> f (DirPath os ar) -> f (FileDirPath os ar) -> f (Path os ar fd)
switchFileDir
            (forall a. (a -> a) -> Endo a
Endo forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip forall os ar. FilePath os ar -> [Char] -> FilePath os ar
addExtension [Char]
ext)
            (forall a. (a -> a) -> Endo a
Endo forall a b. (a -> b) -> a -> b
$ forall os ar fd. [Char] -> Path os ar fd -> Path os ar fd
componentsAddExtension [Char]
ext)
            (forall a. (a -> a) -> Endo a
Endo forall a b. (a -> b) -> a -> b
$ forall os ar fd. [Char] -> Path os ar fd -> Path os ar fd
componentsAddExtension [Char]
ext)

componentsAddExtension :: String -> Path os ar fd -> Path os ar fd
componentsAddExtension :: forall os ar fd. [Char] -> Path os ar fd -> Path os ar fd
componentsAddExtension [Char]
ext (Path ar
ar [PathComponent os]
pcs0 fd
fd) =
    let pcs :: [PathComponent os]
pcs = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [PathComponent os]
pcs0 then [forall os. PathComponent os
emptyPC] else [PathComponent os]
pcs0
    in  forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar (forall a. (a -> a) -> [a] -> [a]
mapLast (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall os. PathComponent os -> [Char] -> PathComponent os
addExtensionPC [Char]
ext) [PathComponent os]
pcs) fd
fd

genericDropExtension :: (Class.FileDir fd) => Path os ar fd -> Path os ar fd
genericDropExtension :: forall fd os ar. FileDir fd => Path os ar fd -> Path os ar fd
genericDropExtension = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall fd os ar.
FileDir fd =>
Path os ar fd -> (Path os ar fd, [Char])
genericSplitExtension

genericDropExtensions :: (Class.FileDir fd) => Path os ar fd -> Path os ar fd
genericDropExtensions :: forall fd os ar. FileDir fd => Path os ar fd -> Path os ar fd
genericDropExtensions = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall fd os ar.
FileDir fd =>
Path os ar fd -> (Path os ar fd, [Char])
genericSplitExtensions

genericSplitExtension ::
    (Class.FileDir fd) => Path os ar fd -> (Path os ar fd, String)
genericSplitExtension :: forall fd os ar.
FileDir fd =>
Path os ar fd -> (Path os ar fd, [Char])
genericSplitExtension =
    forall path. SplitExtension path -> path -> (path, [Char])
runSplitExtension forall a b. (a -> b) -> a -> b
$
    forall fd (f :: * -> *) os ar.
FileDir fd =>
f (FilePath os ar)
-> f (DirPath os ar) -> f (FileDirPath os ar) -> f (Path os ar fd)
switchFileDir
        (forall path. (path -> (path, [Char])) -> SplitExtension path
SplitExtension forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtension)
        (forall path. (path -> (path, [Char])) -> SplitExtension path
SplitExtension forall os ar b. Path os ar b -> (Path os ar b, [Char])
componentsSplitExtension)
        (forall path. (path -> (path, [Char])) -> SplitExtension path
SplitExtension forall os ar b. Path os ar b -> (Path os ar b, [Char])
componentsSplitExtension)

componentsSplitExtension :: Path os ar b -> (Path os ar b, String)
componentsSplitExtension :: forall os ar b. Path os ar b -> (Path os ar b, [Char])
componentsSplitExtension (Path ar
ar [PathComponent os]
pcs b
fd) =
    forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar) b
fd) forall a b. (a -> b) -> a -> b
$
    forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPair
        (forall a. HasCallStack => [Char] -> a
error [Char]
"genericSplitExtension: empty path")
        forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionPC [PathComponent os]
pcs

genericSplitExtensions ::
    (Class.FileDir fd) => Path os ar fd -> (Path os ar fd, String)
genericSplitExtensions :: forall fd os ar.
FileDir fd =>
Path os ar fd -> (Path os ar fd, [Char])
genericSplitExtensions =
    forall path. SplitExtension path -> path -> (path, [Char])
runSplitExtension forall a b. (a -> b) -> a -> b
$
    forall fd (f :: * -> *) os ar.
FileDir fd =>
f (FilePath os ar)
-> f (DirPath os ar) -> f (FileDirPath os ar) -> f (Path os ar fd)
switchFileDir
        (forall path. (path -> (path, [Char])) -> SplitExtension path
SplitExtension forall os ar. FilePath os ar -> (FilePath os ar, [Char])
splitExtensions)
        (forall path. (path -> (path, [Char])) -> SplitExtension path
SplitExtension forall os ar b. Path os ar b -> (Path os ar b, [Char])
componentsSplitExtensions)
        (forall path. (path -> (path, [Char])) -> SplitExtension path
SplitExtension forall os ar b. Path os ar b -> (Path os ar b, [Char])
componentsSplitExtensions)

componentsSplitExtensions :: Path os ar b -> (Path os ar b, String)
componentsSplitExtensions :: forall os ar b. Path os ar b -> (Path os ar b, [Char])
componentsSplitExtensions (Path ar
ar [PathComponent os]
pcs b
fd) =
    forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar) b
fd) forall a b. (a -> b) -> a -> b
$
    forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPair
        (forall a. HasCallStack => [Char] -> a
error [Char]
"genericSplitExtensions: empty path")
        forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionsPC [PathComponent os]
pcs

genericTakeExtension :: (Class.FileDir fd) => Path os ar fd -> String
genericTakeExtension :: forall fd os ar. FileDir fd => Path os ar fd -> [Char]
genericTakeExtension = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall fd os ar.
FileDir fd =>
Path os ar fd -> (Path os ar fd, [Char])
genericSplitExtension

genericTakeExtensions :: (Class.FileDir fd) => Path os ar fd -> String
genericTakeExtensions :: forall fd os ar. FileDir fd => Path os ar fd -> [Char]
genericTakeExtensions = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall fd os ar.
FileDir fd =>
Path os ar fd -> (Path os ar fd, [Char])
genericSplitExtension

newtype
    SplitExtension path =
        SplitExtension {forall path. SplitExtension path -> path -> (path, [Char])
runSplitExtension :: path -> (path, String)}


-- move to utility-ht
mapLast :: (a -> a) -> [a] -> [a]
mapLast :: forall a. (a -> a) -> [a] -> [a]
mapLast a -> a
f [a]
xs = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. a -> a
id (forall a. Int -> [a] -> [a]
drop Int
1 forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b. a -> b -> a
const forall a. a -> a
id) [a]
xs forall a. [a] -> [a] -> [a]
++ [a -> a
f]) [a]
xs

mapLastPair :: b -> (a -> (a,b)) -> [a] -> ([a], b)
mapLastPair :: forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPair b
b a -> (a, b)
f =
    forall b a. b -> ([a] -> a -> b) -> [a] -> b
ListHT.switchR ([], b
b) (\[a]
as a
a -> forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (([a]
asforall a. [a] -> [a] -> [a]
++) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. a -> [a] -> [a]
:[])) forall a b. (a -> b) -> a -> b
$ a -> (a, b)
f a
a)

mapLastPairFoldr :: b -> (a -> (a,b)) -> [a] -> ([a], b)
mapLastPairFoldr :: forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPairFoldr b
b a -> (a, b)
_ [] = ([], b
b)
mapLastPairFoldr b
_ a -> (a, b)
f (a
x:[a]
xs) =
    forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
        (\a
y1 a -> ([a], b)
go a
y0 -> forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (a
y0forall a. a -> [a] -> [a]
:) forall a b. (a -> b) -> a -> b
$ a -> ([a], b)
go a
y1)
        (\a
y -> forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (forall a. a -> [a] -> [a]
:[]) forall a b. (a -> b) -> a -> b
$ a -> (a, b)
f a
y)
        [a]
xs a
x

mapLastPairRec :: b -> (a -> (a,b)) -> [a] -> ([a], b)
mapLastPairRec :: forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPairRec b
b a -> (a, b)
_ [] = ([], b
b)
mapLastPairRec b
_ a -> (a, b)
f (a
x:[a]
xs) =
    let go :: a -> [a] -> ([a], b)
go a
y [] = forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (forall a. a -> [a] -> [a]
:[]) forall a b. (a -> b) -> a -> b
$ a -> (a, b)
f a
y
        go a
y0 (a
y1:[a]
ys) = forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst (a
y0forall a. a -> [a] -> [a]
:) forall a b. (a -> b) -> a -> b
$ a -> [a] -> ([a], b)
go a
y1 [a]
ys
    in  a -> [a] -> ([a], b)
go a
x [a]
xs

mapLastPairRev :: b -> (a -> (a,b)) -> [a] -> ([a], b)
mapLastPairRev :: forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPairRev b
b0 a -> (a, b)
f [a]
xs =
    case forall a. [a] -> [a]
reverse [a]
xs of
        [] -> ([a]
xs, b
b0)
        a
y:[a]
ys ->
            let (a
a, b
b) = a -> (a, b)
f a
y
            in  (forall a. [a] -> [a]
reverse [a]
ys forall a. [a] -> [a] -> [a]
++ [a
a], b
b)

_prop_mapLastPair :: String -> Int -> [String] -> Bool
_prop_mapLastPair :: [Char] -> Int -> [[Char]] -> Bool
_prop_mapLastPair [Char]
b Int
n [[Char]]
strs =
    let f :: [a] -> ([a], [a])
f = forall a. Int -> [a] -> ([a], [a])
splitAt Int
n
    in  forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPair [Char]
b forall {a}. [a] -> ([a], [a])
f [[Char]]
strs forall a. Eq a => a -> a -> Bool
==) forall a b. (a -> b) -> a -> b
$
            forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPairFoldr [Char]
b forall {a}. [a] -> ([a], [a])
f [[Char]]
strs forall a. a -> [a] -> [a]
:
            forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPairRev [Char]
b forall {a}. [a] -> ([a], [a])
f [[Char]]
strs forall a. a -> [a] -> [a]
:
            forall b a. b -> (a -> (a, b)) -> [a] -> ([a], b)
mapLastPairRec [Char]
b forall {a}. [a] -> ([a], [a])
f [[Char]]
strs forall a. a -> [a] -> [a]
:
            []


addExtensionPC :: PathComponent os -> String -> PathComponent os
addExtensionPC :: forall os. PathComponent os -> [Char] -> PathComponent os
addExtensionPC PathComponent os
p [Char]
"" = PathComponent os
p
addExtensionPC (PathComponent [Char]
pc) [Char]
ext =
    forall os. [Char] -> PathComponent os
PathComponent forall a b. (a -> b) -> a -> b
$ [Char]
pc forall a. [a] -> [a] -> [a]
++
        if [Char
extSeparator] forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
ext
          then [Char]
ext
          else Char
extSeparator forall a. a -> [a] -> [a]
: [Char]
ext

splitExtensionPC :: PathComponent os -> (PathComponent os, String)
splitExtensionPC :: forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionPC (PathComponent [Char]
s) =
    forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst forall os. [Char] -> PathComponent os
PathComponent forall a b. (a -> b) -> a -> b
$
    forall b a. b -> (a -> b) -> Maybe a -> b
P.maybe ([Char]
s, [Char]
"") (forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat) forall a b. (a -> b) -> a -> b
$
    ((\p :: ([[Char]], [Char])
p@([[Char]]
pcs,[Char]
_) -> forall a. Bool -> a -> Maybe a
toMaybe (Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
pcs)) ([[Char]], [Char])
p) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Maybe ([a], a)
ListHT.viewR forall a b. (a -> b) -> a -> b
$
    forall a. (a -> Bool) -> [a] -> [[a]]
ListHT.segmentBefore Char -> Bool
isExtSeparator [Char]
s

_splitExtensionPC :: PathComponent os -> (PathComponent os, String)
_splitExtensionPC :: forall os. PathComponent os -> (PathComponent os, [Char])
_splitExtensionPC (PathComponent [Char]
s) =
    forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst forall os. [Char] -> PathComponent os
PathComponent forall a b. (a -> b) -> a -> b
$
    case forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
isExtSeparator forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [Char]
s of
        ([Char]
_, [Char]
"") -> ([Char]
s, [Char]
"")
        ([Char]
rext, Char
dot:[Char]
rstem) -> (forall a. [a] -> [a]
reverse [Char]
rstem, Char
dot forall a. a -> [a] -> [a]
: forall a. [a] -> [a]
reverse [Char]
rext)

splitExtensionsPC :: PathComponent os -> (PathComponent os, String)
splitExtensionsPC :: forall os. PathComponent os -> (PathComponent os, [Char])
splitExtensionsPC (PathComponent [Char]
s) =
    forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst forall os. [Char] -> PathComponent os
PathComponent forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
isExtSeparator [Char]
s



{- |
Check internal integrity of the path data structure.
-}
isValid ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    Path os ar fd -> Bool
isValid :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Path os ar fd -> Bool
isValid = forall {k} (s :: k) b. Tagged s b -> b
untag forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Tagged os (Path os ar fd -> Bool)
isValidTagged

isValidTagged ::
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
    Tagged os (Path os ar fd -> Bool)
isValidTagged :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Tagged os (Path os ar fd -> Bool)
isValidTagged =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        (\PathComponent os -> Bool
isValidPC (Path ar
ar [PathComponent os]
pcs fd
fd) ->
            forall ar a. AbsRel ar => ([Char] -> a) -> a -> ar -> a
Class.withAbsRel [Char] -> Bool
isValidComponent Bool
True ar
ar
            Bool -> Bool -> Bool
&&
            forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all PathComponent os -> Bool
isValidPC [PathComponent os]
pcs
            Bool -> Bool -> Bool
&&
            forall fd a. FileDir fd => (GenComponent -> a) -> a -> a -> fd -> a
Class.withFileDir (PathComponent os -> Bool
isValidPC forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. GenComponent -> PathComponent os
retagPC) Bool
True Bool
True fd
fd)
        forall os. System os => Tagged os (PathComponent os -> Bool)
isValidPathComponent

isValidComponent :: String -> Bool
isValidComponent :: [Char] -> Bool
isValidComponent = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null

isValidPathComponent ::
    (System os) => Tagged os (PathComponent os -> Bool)
isValidPathComponent :: forall os. System os => Tagged os (PathComponent os -> Bool)
isValidPathComponent =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        (\Char -> Bool
isSep (PathComponent [Char]
str) ->
            [Char] -> Bool
isValidComponent [Char]
str  Bool -> Bool -> Bool
&&  Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Char -> Bool
isSep [Char]
str))
        forall os. System os => Tagged os (Char -> Bool)
isPathSeparator

------------------------------------------------------------------------
-- QuickCheck

testAll :: (System os) => os -> [(String, DocTest.T ())]
testAll :: forall os. System os => os -> [([Char], T ())]
testAll os
os =
    ([Char]
"mkPathFromComponents_pathComponents",
        forall prop os fd ar.
(Testable prop, System os, FileDir fd, AbsRel ar) =>
os -> (Path os ar fd -> prop) -> T ()
quickCheck os
os forall os. System os => AbsDir os -> Property
prop_mkPathFromComponents_pathComponents) forall a. a -> [a] -> [a]
:
    ([Char]
"splitDir_combine",
        forall prop os fd ar.
(Testable prop, System os, FileDir fd, AbsRel ar) =>
os -> (Path os ar fd -> prop) -> T ()
quickCheck os
os forall os. System os => AbsDir os -> Property
prop_splitDir_combine) forall a. a -> [a] -> [a]
:
    ([Char]
"takeDirName_end",
        forall prop os fd ar.
(Testable prop, System os, FileDir fd, AbsRel ar) =>
os -> (Path os ar fd -> prop) -> T ()
quickCheck os
os forall os. System os => AbsDir os -> Property
prop_takeDirName_end) forall a. a -> [a] -> [a]
:
    []

quickCheck ::
    (QC.Testable prop, System os, Class.FileDir fd, Class.AbsRel ar) =>
    os -> (Path os ar fd -> prop) -> DocTest.T ()
quickCheck :: forall prop os fd ar.
(Testable prop, System os, FileDir fd, AbsRel ar) =>
os -> (Path os ar fd -> prop) -> T ()
quickCheck os
_ = forall prop. Testable prop => prop -> T ()
DocTest.property

-- test :: Testable a => a -> IO ()
-- test = quickCheck

qcFileComponent :: Gen (PathComponent os)
qcFileComponent :: forall os. Gen (PathComponent os)
qcFileComponent = forall os. [Char] -> PathComponent os
PathComponent forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. [(Int, Gen a)] -> Gen a
frequency [
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"someFile"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"fileWith.ext"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"file.with.multiple.exts"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"file with spcs")
                  ]

qcDirComponent :: Gen (PathComponent os)
qcDirComponent :: forall os. Gen (PathComponent os)
qcDirComponent = forall os. [Char] -> PathComponent os
PathComponent forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. [(Int, Gen a)] -> Gen a
frequency [
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"someDir"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"aDir"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"aFolder"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"a folder"),
                    (Int
1, forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"directory")
                  ]


qcAbsRel :: (System os, Class.AbsRel ar) => Tagged os (Gen ar)
qcAbsRel :: forall os ar. (System os, AbsRel ar) => Tagged os (Gen ar)
qcAbsRel =
    forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall os. System os => Tagged os (Gen [Char])
genDrive forall a b. (a -> b) -> a -> b
$ \Gen [Char]
drive ->
        forall ar (f :: * -> *).
AbsRel ar =>
f Abs -> f Rel -> f AbsRel -> f ar
Class.switchAbsRel (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Char] -> Abs
absPC Gen [Char]
drive) (forall (m :: * -> *) a. Monad m => a -> m a
return Rel
Part.Rel)
            (forall a. [Gen a] -> Gen a
QC.oneof
                [forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (GenComponent -> AbsRel
Part.AbsO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall os. [Char] -> PathComponent os
PathComponent) Gen [Char]
drive, forall (m :: * -> *) a. Monad m => a -> m a
return AbsRel
Part.RelO])

qcGenPath ::
    Tagged os (Gen ar) ->
    (Gen ar -> Gen (Path os ar fd)) ->
    Gen (Path os ar fd)
qcGenPath :: forall os ar fd.
Tagged os (Gen ar)
-> (Gen ar -> Gen (Path os ar fd)) -> Gen (Path os ar fd)
qcGenPath Tagged os (Gen ar)
qcAR Gen ar -> Gen (Path os ar fd)
gen = Gen ar -> Gen (Path os ar fd)
gen forall a b. (a -> b) -> a -> b
$ forall {k} (s :: k) b. Tagged s b -> b
untag Tagged os (Gen ar)
qcAR

qcFilePath :: (System os, Class.AbsRel ar) => Gen (FilePath os ar)
qcFilePath :: forall os ar. (System os, AbsRel ar) => Gen (FilePath os ar)
qcFilePath = forall os ar fd.
Tagged os (Gen ar)
-> (Gen ar -> Gen (Path os ar fd)) -> Gen (Path os ar fd)
qcGenPath forall os ar. (System os, AbsRel ar) => Tagged os (Gen ar)
qcAbsRel forall a b. (a -> b) -> a -> b
$ \Gen ar
qcAR -> do
    ar
ar <- Gen ar
qcAR
    [PathComponent os]
pcs <- forall a. Gen a -> Gen [a]
QC.listOf forall os. Gen (PathComponent os)
qcDirComponent
    GenComponent
pc <- forall os. Gen (PathComponent os)
qcFileComponent
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs forall a b. (a -> b) -> a -> b
$ GenComponent -> File
Part.File GenComponent
pc

qcDirPath :: (System os, Class.AbsRel ar) => fd -> Gen (Path os ar fd)
qcDirPath :: forall os ar fd.
(System os, AbsRel ar) =>
fd -> Gen (Path os ar fd)
qcDirPath fd
fd = forall os ar fd.
Tagged os (Gen ar)
-> (Gen ar -> Gen (Path os ar fd)) -> Gen (Path os ar fd)
qcGenPath forall os ar. (System os, AbsRel ar) => Tagged os (Gen ar)
qcAbsRel forall a b. (a -> b) -> a -> b
$ \Gen ar
qcAR -> do
    ar
ar <- Gen ar
qcAR
    [PathComponent os]
pcs <- forall a. Gen a -> Gen [a]
QC.listOf forall os. Gen (PathComponent os)
qcDirComponent
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall os ar fd. ar -> [PathComponent os] -> fd -> Path os ar fd
Path ar
ar [PathComponent os]
pcs fd
fd

qcPath ::
    (System os, Class.AbsRel ar, Class.FileDir fd) => Gen (Path os ar fd)
qcPath :: forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Gen (Path os ar fd)
qcPath =
    forall fd (f :: * -> *) os ar.
FileDir fd =>
f (FilePath os ar)
-> f (DirPath os ar) -> f (FileDirPath os ar) -> f (Path os ar fd)
switchFileDir forall os ar. (System os, AbsRel ar) => Gen (FilePath os ar)
qcFilePath (forall os ar fd.
(System os, AbsRel ar) =>
fd -> Gen (Path os ar fd)
qcDirPath Dir
Part.Dir) (forall os ar fd.
(System os, AbsRel ar) =>
fd -> Gen (Path os ar fd)
qcDirPath FileDir
Part.FileDir)

instance
    (System os, Class.AbsRel ar, Class.FileDir fd) =>
        Arbitrary (Path os ar fd) where
    arbitrary :: Gen (Path os ar fd)
arbitrary = forall os ar fd.
(System os, AbsRel ar, FileDir fd) =>
Gen (Path os ar fd)
qcPath