-- | Provides a dynamic effect for the readable portion of "System.Directory"'s
-- interface.
--
-- @since 0.1
module Effectful.FileSystem.PathReader.Dynamic
  ( -- * Effect
    PathReader (..),

    -- ** Functions
    listDirectory,
    getDirectoryContents,
    getCurrentDirectory,
    getHomeDirectory,
    getXdgDirectory,
    getXdgDirectoryList,
    getAppUserDataDirectory,
    getUserDocumentsDirectory,
    getTemporaryDirectory,
    getFileSize,
    canonicalizePath,
    makeAbsolute,
    makeRelativeToCurrentDirectory,
    doesPathExist,
    doesFileExist,
    doesDirectoryExist,
    findExecutable,
    findExecutables,
    findExecutablesInDirectories,
    findFileWith,
    findFilesWith,
    pathIsSymbolicLink,
    getSymbolicLinkTarget,
    getPermissions,
    getAccessTime,
    getModificationTime,

    -- ** Handlers
    runPathReader,

    -- * Functions
    findFile,
    findFiles,

    -- ** XDG Utils
    getXdgData,
    getXdgConfig,
    getXdgCache,
    getXdgState,

    -- * Path Types
    PathType (..),

    -- ** Functions
    PathType.displayPathType,
    getPathType,
    isPathType,
    throwIfWrongPathType,

    -- * Tilde expansion
    expandTilde,
    forExpandedTilde,
    onExpandedTilde,

    -- * Misc
    listDirectoryRecursive,
    listDirectoryRecursiveSymbolicLink,
    doesSymbolicLinkExist,
    pathIsSymbolicDirectoryLink,
    pathIsSymbolicFileLink,

    -- * Re-exports
    OsPath,
    Permissions,
    UTCTime (..),
    XdgDirectory (..),
    XdgDirectoryList (..),
  )
where

import Control.Category ((>>>))
import Control.Monad (unless, (>=>))
import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.Time (UTCTime (UTCTime, utctDay, utctDayTime))
import Effectful
  ( Dispatch (Dynamic),
    DispatchOf,
    Eff,
    Effect,
    IOE,
    type (:>),
  )
import Effectful.Dispatch.Dynamic (HasCallStack, localSeqUnlift, reinterpret, send)
import Effectful.Dynamic.Utils (ShowEffect (showEffectCons))
import Effectful.Exception (catchIO)
import Effectful.FileSystem.PathReader.Static qualified as Static
import FileSystem.IO qualified as IO
import FileSystem.OsPath
  ( OsPath,
    OsPathOrEmpty (OsPathEmpty, OsPathNonEmpty),
    TildePrefixState
      ( TildePrefixStateNone,
        TildePrefixStateStripped
      ),
    (</>),
  )
import FileSystem.OsPath qualified as OsP
import FileSystem.PathType
  ( PathType
      ( PathTypeDirectory,
        PathTypeFile,
        PathTypeOther,
        PathTypeSymbolicLink
      ),
  )
import FileSystem.PathType qualified as PathType
import GHC.IO.Exception (IOErrorType (InappropriateType))
import System.Directory
  ( Permissions,
    XdgDirectory (XdgCache, XdgConfig, XdgData, XdgState),
    XdgDirectoryList (XdgConfigDirs, XdgDataDirs),
  )
import System.Directory.OsPath qualified as Dir
import System.IO.Error qualified as IO.Error

-- | Dynamic effect for reading paths.
--
-- @since 0.1
data PathReader :: Effect where
  ListDirectory :: OsPath -> PathReader m [OsPath]
  GetDirectoryContents :: OsPath -> PathReader m [OsPath]
  GetCurrentDirectory :: PathReader m OsPath
  GetHomeDirectory :: PathReader m OsPath
  GetXdgDirectory :: XdgDirectory -> OsPath -> PathReader m OsPath
  GetXdgDirectoryList :: XdgDirectoryList -> PathReader m [OsPath]
  GetAppUserDataDirectory :: OsPath -> PathReader m OsPath
  GetUserDocumentsDirectory :: PathReader m OsPath
  GetTemporaryDirectory :: PathReader m OsPath
  GetFileSize :: OsPath -> PathReader m Integer
  CanonicalizePath :: OsPath -> PathReader m OsPath
  MakeAbsolute :: OsPath -> PathReader m OsPath
  MakeRelativeToCurrentDirectory :: OsPath -> PathReader m OsPath
  DoesPathExist :: OsPath -> PathReader m Bool
  DoesFileExist :: OsPath -> PathReader m Bool
  DoesDirectoryExist :: OsPath -> PathReader m Bool
  FindExecutable :: OsPath -> PathReader m (Maybe OsPath)
  FindExecutables :: OsPath -> PathReader m [OsPath]
  FindExecutablesInDirectories ::
    [OsPath] ->
    OsPath ->
    PathReader m [OsPath]
  FindFile :: [OsPath] -> OsPath -> PathReader m (Maybe OsPath)
  FindFiles :: [OsPath] -> OsPath -> PathReader m [OsPath]
  FindFileWith ::
    (OsPath -> m Bool) ->
    [OsPath] ->
    OsPath ->
    PathReader m (Maybe OsPath)
  FindFilesWith ::
    (OsPath -> m Bool) ->
    [OsPath] ->
    OsPath ->
    PathReader m [OsPath]
  PathIsSymbolicLink :: OsPath -> PathReader m Bool
  GetSymbolicLinkTarget :: OsPath -> PathReader m OsPath
  GetPermissions :: OsPath -> PathReader m Permissions
  GetAccessTime :: OsPath -> PathReader m UTCTime
  GetModificationTime :: OsPath -> PathReader m UTCTime

-- | @since 0.1
type instance DispatchOf PathReader = Dynamic

-- | @since 0.1
instance ShowEffect PathReader where
  showEffectCons :: forall (m :: * -> *) a. PathReader m a -> String
showEffectCons = \case
    ListDirectory OsPath
_ -> String
"ListDirectory"
    GetDirectoryContents OsPath
_ -> String
"GetDirectoryContents"
    PathReader m a
GetCurrentDirectory -> String
"GetCurrentDirectory"
    PathReader m a
GetHomeDirectory -> String
"GetHomeDirectory"
    GetXdgDirectory XdgDirectory
_ OsPath
_ -> String
"GetXdgDirectory"
    GetXdgDirectoryList XdgDirectoryList
_ -> String
"GetXdgDirectoryList"
    GetAppUserDataDirectory OsPath
_ -> String
"GetAppUserDataDirectory"
    PathReader m a
GetUserDocumentsDirectory -> String
"GetUserDocumentsDirectory"
    PathReader m a
GetTemporaryDirectory -> String
"GetTemporaryDirectory"
    GetFileSize OsPath
_ -> String
"GetFileSize"
    CanonicalizePath OsPath
_ -> String
"CanonicalizePath"
    MakeAbsolute OsPath
_ -> String
"MakeAbsolute"
    MakeRelativeToCurrentDirectory OsPath
_ -> String
"MakeRelativeToCurrentDirectory"
    DoesPathExist OsPath
_ -> String
"DoesPathExist"
    DoesFileExist OsPath
_ -> String
"DoesFileExist"
    DoesDirectoryExist OsPath
_ -> String
"DoesDirectoryExist"
    FindExecutable OsPath
_ -> String
"FindExecutable"
    FindExecutables OsPath
_ -> String
"FindExecutables"
    FindExecutablesInDirectories [OsPath]
_ OsPath
_ -> String
"FindExecutablesInDirectories"
    FindFile [OsPath]
_ OsPath
_ -> String
"FindFile"
    FindFiles [OsPath]
_ OsPath
_ -> String
"FindFiles"
    FindFileWith OsPath -> m Bool
_ [OsPath]
_ OsPath
_ -> String
"FindFileWith"
    FindFilesWith OsPath -> m Bool
_ [OsPath]
_ OsPath
_ -> String
"FindFilesWith"
    PathIsSymbolicLink OsPath
_ -> String
"PathIsSymbolicLink"
    GetSymbolicLinkTarget OsPath
_ -> String
"GetSymbolicLinkTarget"
    GetPermissions OsPath
_ -> String
"GetPermissions"
    GetAccessTime OsPath
_ -> String
"GetAccessTime"
    GetModificationTime OsPath
_ -> String
"GetModificationTime"

-- | Runs 'PathReader' in 'IO'.
--
-- @since 0.1
runPathReader ::
  ( HasCallStack,
    IOE :> es
  ) =>
  Eff (PathReader : es) a ->
  Eff es a
runPathReader :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, IOE :> es) =>
Eff (PathReader : es) a -> Eff es a
runPathReader = (Eff (PathReader : es) a -> Eff es a)
-> EffectHandler PathReader (PathReader : es)
-> Eff (PathReader : es) a
-> Eff es a
forall (e :: (* -> *) -> * -> *)
       (handlerEs :: [(* -> *) -> * -> *]) a (es :: [(* -> *) -> * -> *])
       b.
(HasCallStack, DispatchOf e ~ 'Dynamic) =>
(Eff handlerEs a -> Eff es b)
-> EffectHandler e handlerEs -> Eff (e : es) a -> Eff es b
reinterpret Eff (PathReader : es) a -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, IOE :> es) =>
Eff (PathReader : es) a -> Eff es a
Static.runPathReader (EffectHandler PathReader (PathReader : es)
 -> Eff (PathReader : es) a -> Eff es a)
-> EffectHandler PathReader (PathReader : es)
-> Eff (PathReader : es) a
-> Eff es a
forall a b. (a -> b) -> a -> b
$ \LocalEnv localEs (PathReader : es)
env -> \case
  ListDirectory OsPath
p -> OsPath -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
Static.listDirectory OsPath
p
  GetDirectoryContents OsPath
p -> OsPath -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
Static.getDirectoryContents OsPath
p
  PathReader (Eff localEs) a
GetCurrentDirectory -> IO a -> Eff (PathReader : es) a
forall a. IO a -> Eff (PathReader : es) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
IO OsPath
Dir.getCurrentDirectory
  PathReader (Eff localEs) a
GetHomeDirectory -> IO a -> Eff (PathReader : es) a
forall a. IO a -> Eff (PathReader : es) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
IO OsPath
Dir.getHomeDirectory
  GetXdgDirectory XdgDirectory
xdg OsPath
p -> XdgDirectory -> OsPath -> Eff (PathReader : es) OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectory -> OsPath -> Eff es OsPath
Static.getXdgDirectory XdgDirectory
xdg OsPath
p
  GetXdgDirectoryList XdgDirectoryList
xdg -> XdgDirectoryList -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectoryList -> Eff es [OsPath]
Static.getXdgDirectoryList XdgDirectoryList
xdg
  GetAppUserDataDirectory OsPath
p -> OsPath -> Eff (PathReader : es) OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
Static.getAppUserDataDirectory OsPath
p
  PathReader (Eff localEs) a
GetUserDocumentsDirectory -> IO a -> Eff (PathReader : es) a
forall a. IO a -> Eff (PathReader : es) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
IO OsPath
Dir.getUserDocumentsDirectory
  PathReader (Eff localEs) a
GetTemporaryDirectory -> IO a -> Eff (PathReader : es) a
forall a. IO a -> Eff (PathReader : es) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
IO OsPath
Dir.getTemporaryDirectory
  GetFileSize OsPath
p -> OsPath -> Eff (PathReader : es) Integer
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Integer
Static.getFileSize OsPath
p
  CanonicalizePath OsPath
p -> OsPath -> Eff (PathReader : es) OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
Static.canonicalizePath OsPath
p
  MakeAbsolute OsPath
p -> OsPath -> Eff (PathReader : es) OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
Static.makeAbsolute OsPath
p
  MakeRelativeToCurrentDirectory OsPath
p -> OsPath -> Eff (PathReader : es) OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
Static.makeRelativeToCurrentDirectory OsPath
p
  DoesPathExist OsPath
p -> OsPath -> Eff (PathReader : es) Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
Static.doesPathExist OsPath
p
  DoesFileExist OsPath
p -> OsPath -> Eff (PathReader : es) Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
Static.doesFileExist OsPath
p
  DoesDirectoryExist OsPath
p -> OsPath -> Eff (PathReader : es) Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
Static.doesDirectoryExist OsPath
p
  FindExecutable OsPath
p -> OsPath -> Eff (PathReader : es) (Maybe OsPath)
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es (Maybe OsPath)
Static.findExecutable OsPath
p
  FindExecutables OsPath
p -> OsPath -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
Static.findExecutables OsPath
p
  FindExecutablesInDirectories [OsPath]
ps OsPath
str ->
    [OsPath] -> OsPath -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
[OsPath] -> OsPath -> Eff es [OsPath]
Static.findExecutablesInDirectories [OsPath]
ps OsPath
str
  FindFile [OsPath]
xs OsPath
p -> [OsPath] -> OsPath -> Eff (PathReader : es) (Maybe OsPath)
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
[OsPath] -> OsPath -> Eff es (Maybe OsPath)
Static.findFile [OsPath]
xs OsPath
p
  FindFiles [OsPath]
xs OsPath
p -> [OsPath] -> OsPath -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
[OsPath] -> OsPath -> Eff es [OsPath]
Static.findFiles [OsPath]
xs OsPath
p
  FindFileWith OsPath -> Eff localEs Bool
f [OsPath]
ps OsPath
str -> LocalEnv localEs (PathReader : es)
-> ((forall r. Eff localEs r -> Eff (PathReader : es) r)
    -> Eff (PathReader : es) a)
-> Eff (PathReader : es) a
forall (es :: [(* -> *) -> * -> *])
       (handlerEs :: [(* -> *) -> * -> *])
       (localEs :: [(* -> *) -> * -> *]) a.
(HasCallStack, SharedSuffix es handlerEs) =>
LocalEnv localEs handlerEs
-> ((forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a
localSeqUnlift LocalEnv localEs (PathReader : es)
env (((forall r. Eff localEs r -> Eff (PathReader : es) r)
  -> Eff (PathReader : es) a)
 -> Eff (PathReader : es) a)
-> ((forall r. Eff localEs r -> Eff (PathReader : es) r)
    -> Eff (PathReader : es) a)
-> Eff (PathReader : es) a
forall a b. (a -> b) -> a -> b
$ \forall r. Eff localEs r -> Eff (PathReader : es) r
runInStatic ->
    (OsPath -> Eff (PathReader : es) Bool)
-> [OsPath] -> OsPath -> Eff (PathReader : es) (Maybe OsPath)
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es Bool)
-> [OsPath] -> OsPath -> Eff es (Maybe OsPath)
Static.findFileWith (Eff localEs Bool -> Eff (PathReader : es) Bool
forall r. Eff localEs r -> Eff (PathReader : es) r
runInStatic (Eff localEs Bool -> Eff (PathReader : es) Bool)
-> (OsPath -> Eff localEs Bool)
-> OsPath
-> Eff (PathReader : es) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> Eff localEs Bool
f) [OsPath]
ps OsPath
str
  FindFilesWith OsPath -> Eff localEs Bool
f [OsPath]
ps OsPath
str -> LocalEnv localEs (PathReader : es)
-> ((forall r. Eff localEs r -> Eff (PathReader : es) r)
    -> Eff (PathReader : es) a)
-> Eff (PathReader : es) a
forall (es :: [(* -> *) -> * -> *])
       (handlerEs :: [(* -> *) -> * -> *])
       (localEs :: [(* -> *) -> * -> *]) a.
(HasCallStack, SharedSuffix es handlerEs) =>
LocalEnv localEs handlerEs
-> ((forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a
localSeqUnlift LocalEnv localEs (PathReader : es)
env (((forall r. Eff localEs r -> Eff (PathReader : es) r)
  -> Eff (PathReader : es) a)
 -> Eff (PathReader : es) a)
-> ((forall r. Eff localEs r -> Eff (PathReader : es) r)
    -> Eff (PathReader : es) a)
-> Eff (PathReader : es) a
forall a b. (a -> b) -> a -> b
$ \forall r. Eff localEs r -> Eff (PathReader : es) r
runInStatic ->
    (OsPath -> Eff (PathReader : es) Bool)
-> [OsPath] -> OsPath -> Eff (PathReader : es) [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es Bool) -> [OsPath] -> OsPath -> Eff es [OsPath]
Static.findFilesWith (Eff localEs Bool -> Eff (PathReader : es) Bool
forall r. Eff localEs r -> Eff (PathReader : es) r
runInStatic (Eff localEs Bool -> Eff (PathReader : es) Bool)
-> (OsPath -> Eff localEs Bool)
-> OsPath
-> Eff (PathReader : es) Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> Eff localEs Bool
f) [OsPath]
ps OsPath
str
  PathIsSymbolicLink OsPath
p -> OsPath -> Eff (PathReader : es) Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
Static.pathIsSymbolicLink OsPath
p
  GetSymbolicLinkTarget OsPath
p -> OsPath -> Eff (PathReader : es) OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
Static.getSymbolicLinkTarget OsPath
p
  GetPermissions OsPath
p -> OsPath -> Eff (PathReader : es) Permissions
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Permissions
Static.getPermissions OsPath
p
  GetAccessTime OsPath
p -> OsPath -> Eff (PathReader : es) UTCTime
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es UTCTime
Static.getAccessTime OsPath
p
  GetModificationTime OsPath
p -> OsPath -> Eff (PathReader : es) UTCTime
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es UTCTime
Static.getModificationTime OsPath
p

-- | Search through the given list of directories for the given file.
--
-- The behavior is equivalent to 'findFileWith', returning only the first
-- occurrence. Details can be found in the documentation of 'findFileWith'.
--
-- @since 0.1
findFile ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  [OsPath] ->
  OsPath ->
  Eff es (Maybe OsPath)
findFile :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
[OsPath] -> OsPath -> Eff es (Maybe OsPath)
findFile [OsPath]
xs = PathReader (Eff es) (Maybe OsPath) -> Eff es (Maybe OsPath)
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) (Maybe OsPath) -> Eff es (Maybe OsPath))
-> (OsPath -> PathReader (Eff es) (Maybe OsPath))
-> OsPath
-> Eff es (Maybe OsPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OsPath] -> OsPath -> PathReader (Eff es) (Maybe OsPath)
forall (m :: * -> *).
[OsPath] -> OsPath -> PathReader m (Maybe OsPath)
FindFile [OsPath]
xs

-- | Search through the given list of directories for the given file and
-- returns all paths where the given file exists.
--
-- The behavior is equivalent to 'findFilesWith'. Details can be found in the
-- documentation of 'findFilesWith'.
--
-- @since 0.1
findFiles ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  [OsPath] ->
  OsPath ->
  Eff es [OsPath]
findFiles :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
[OsPath] -> OsPath -> Eff es [OsPath]
findFiles [OsPath]
xs = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (OsPath -> PathReader (Eff es) [OsPath])
-> OsPath
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OsPath] -> OsPath -> PathReader (Eff es) [OsPath]
forall (m :: * -> *). [OsPath] -> OsPath -> PathReader m [OsPath]
FindFiles [OsPath]
xs

-- | Lifted 'Dir.listDirectory'.
--
-- @since 0.1
listDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es [OsPath]
listDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
listDirectory = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (OsPath -> PathReader (Eff es) [OsPath])
-> OsPath
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) [OsPath]
forall (m :: * -> *). OsPath -> PathReader m [OsPath]
ListDirectory

-- | Lifted 'Dir.getDirectoryContents'.
--
-- @since 0.1
getDirectoryContents ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es [OsPath]
getDirectoryContents :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
getDirectoryContents = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (OsPath -> PathReader (Eff es) [OsPath])
-> OsPath
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) [OsPath]
forall (m :: * -> *). OsPath -> PathReader m [OsPath]
GetDirectoryContents

-- | Lifted 'Dir.getCurrentDirectory'.
--
-- @since 0.1
getCurrentDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  Eff es OsPath
getCurrentDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
Eff es OsPath
getCurrentDirectory = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send PathReader (Eff es) OsPath
forall (m :: * -> *). PathReader m OsPath
GetCurrentDirectory

-- | Lifted 'Dir.getHomeDirectory'.
--
-- @since 0.1
getHomeDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  Eff es OsPath
getHomeDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
Eff es OsPath
getHomeDirectory = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send PathReader (Eff es) OsPath
forall (m :: * -> *). PathReader m OsPath
GetHomeDirectory

-- | Lifted 'Dir.getXdgDirectory'.
--
-- @since 0.1
getXdgDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  XdgDirectory ->
  OsPath ->
  Eff es OsPath
getXdgDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectory -> OsPath -> Eff es OsPath
getXdgDirectory XdgDirectory
xdg = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) OsPath -> Eff es OsPath)
-> (OsPath -> PathReader (Eff es) OsPath)
-> OsPath
-> Eff es OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XdgDirectory -> OsPath -> PathReader (Eff es) OsPath
forall (m :: * -> *). XdgDirectory -> OsPath -> PathReader m OsPath
GetXdgDirectory XdgDirectory
xdg

-- | Lifted 'Dir.getXdgDirectoryList'.
--
-- @since 0.1
getXdgDirectoryList ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  XdgDirectoryList ->
  Eff es [OsPath]
getXdgDirectoryList :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectoryList -> Eff es [OsPath]
getXdgDirectoryList = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (XdgDirectoryList -> PathReader (Eff es) [OsPath])
-> XdgDirectoryList
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XdgDirectoryList -> PathReader (Eff es) [OsPath]
forall (m :: * -> *). XdgDirectoryList -> PathReader m [OsPath]
GetXdgDirectoryList

-- | Lifted 'Dir.getAppUserDataDirectory'.
--
-- @since 0.1
getAppUserDataDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
getAppUserDataDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getAppUserDataDirectory = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) OsPath -> Eff es OsPath)
-> (OsPath -> PathReader (Eff es) OsPath)
-> OsPath
-> Eff es OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) OsPath
forall (m :: * -> *). OsPath -> PathReader m OsPath
GetAppUserDataDirectory

-- | Lifted 'Dir.getUserDocumentsDirectory'.
--
-- @since 0.1
getUserDocumentsDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  Eff es OsPath
getUserDocumentsDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
Eff es OsPath
getUserDocumentsDirectory = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send PathReader (Eff es) OsPath
forall (m :: * -> *). PathReader m OsPath
GetUserDocumentsDirectory

-- | Lifted 'Dir.getTemporaryDirectory'.
--
-- @since 0.1
getTemporaryDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  Eff es OsPath
getTemporaryDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
Eff es OsPath
getTemporaryDirectory = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send PathReader (Eff es) OsPath
forall (m :: * -> *). PathReader m OsPath
GetTemporaryDirectory

-- | Lifted 'Dir.getFileSize'.
--
-- @since 0.1
getFileSize ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Integer
getFileSize :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Integer
getFileSize = PathReader (Eff es) Integer -> Eff es Integer
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) Integer -> Eff es Integer)
-> (OsPath -> PathReader (Eff es) Integer)
-> OsPath
-> Eff es Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) Integer
forall (m :: * -> *). OsPath -> PathReader m Integer
GetFileSize

-- | Lifted 'Dir.canonicalizePath'.
--
-- @since 0.1
canonicalizePath ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
canonicalizePath :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
canonicalizePath = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) OsPath -> Eff es OsPath)
-> (OsPath -> PathReader (Eff es) OsPath)
-> OsPath
-> Eff es OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) OsPath
forall (m :: * -> *). OsPath -> PathReader m OsPath
CanonicalizePath

-- | Lifted 'Dir.makeAbsolute'.
--
-- @since 0.1
makeAbsolute ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
makeAbsolute :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
makeAbsolute = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) OsPath -> Eff es OsPath)
-> (OsPath -> PathReader (Eff es) OsPath)
-> OsPath
-> Eff es OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) OsPath
forall (m :: * -> *). OsPath -> PathReader m OsPath
MakeAbsolute

-- | Lifted 'Dir.makeRelativeToCurrentDirectory'.
--
-- @since 0.1
makeRelativeToCurrentDirectory ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
makeRelativeToCurrentDirectory :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
makeRelativeToCurrentDirectory = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) OsPath -> Eff es OsPath)
-> (OsPath -> PathReader (Eff es) OsPath)
-> OsPath
-> Eff es OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) OsPath
forall (m :: * -> *). OsPath -> PathReader m OsPath
MakeRelativeToCurrentDirectory

-- | Lifted 'Dir.doesPathExist'.
--
-- @since 0.1
doesPathExist ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
doesPathExist :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesPathExist = PathReader (Eff es) Bool -> Eff es Bool
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) Bool -> Eff es Bool)
-> (OsPath -> PathReader (Eff es) Bool) -> OsPath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) Bool
forall (m :: * -> *). OsPath -> PathReader m Bool
DoesPathExist

-- | Lifted 'Dir.doesFileExist'.
--
-- @since 0.1
doesFileExist ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
doesFileExist :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesFileExist = PathReader (Eff es) Bool -> Eff es Bool
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) Bool -> Eff es Bool)
-> (OsPath -> PathReader (Eff es) Bool) -> OsPath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) Bool
forall (m :: * -> *). OsPath -> PathReader m Bool
DoesFileExist

-- | Lifted 'Dir.doesDirectoryExist'.
--
-- @since 0.1
doesDirectoryExist ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
doesDirectoryExist :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesDirectoryExist = PathReader (Eff es) Bool -> Eff es Bool
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) Bool -> Eff es Bool)
-> (OsPath -> PathReader (Eff es) Bool) -> OsPath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) Bool
forall (m :: * -> *). OsPath -> PathReader m Bool
DoesDirectoryExist

-- | Lifted 'Dir.findExecutable'.
--
-- @since 0.1
findExecutable ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es (Maybe OsPath)
findExecutable :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es (Maybe OsPath)
findExecutable = PathReader (Eff es) (Maybe OsPath) -> Eff es (Maybe OsPath)
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) (Maybe OsPath) -> Eff es (Maybe OsPath))
-> (OsPath -> PathReader (Eff es) (Maybe OsPath))
-> OsPath
-> Eff es (Maybe OsPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) (Maybe OsPath)
forall (m :: * -> *). OsPath -> PathReader m (Maybe OsPath)
FindExecutable

-- | Lifted 'Dir.findExecutables'.
--
-- @since 0.1
findExecutables ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es [OsPath]
findExecutables :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
findExecutables = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (OsPath -> PathReader (Eff es) [OsPath])
-> OsPath
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) [OsPath]
forall (m :: * -> *). OsPath -> PathReader m [OsPath]
FindExecutables

-- | Lifted 'Dir.findExecutablesInDirectories'.
--
-- @since 0.1
findExecutablesInDirectories ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  [OsPath] ->
  OsPath ->
  Eff es [OsPath]
findExecutablesInDirectories :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
[OsPath] -> OsPath -> Eff es [OsPath]
findExecutablesInDirectories [OsPath]
ps = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (OsPath -> PathReader (Eff es) [OsPath])
-> OsPath
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OsPath] -> OsPath -> PathReader (Eff es) [OsPath]
forall (m :: * -> *). [OsPath] -> OsPath -> PathReader m [OsPath]
FindExecutablesInDirectories [OsPath]
ps

-- | Lifted 'Dir.findFileWith'.
--
-- @since 0.1
findFileWith ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  (OsPath -> Eff es Bool) ->
  [OsPath] ->
  OsPath ->
  Eff es (Maybe OsPath)
findFileWith :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es Bool)
-> [OsPath] -> OsPath -> Eff es (Maybe OsPath)
findFileWith OsPath -> Eff es Bool
f [OsPath]
ps = PathReader (Eff es) (Maybe OsPath) -> Eff es (Maybe OsPath)
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) (Maybe OsPath) -> Eff es (Maybe OsPath))
-> (OsPath -> PathReader (Eff es) (Maybe OsPath))
-> OsPath
-> Eff es (Maybe OsPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OsPath -> Eff es Bool)
-> [OsPath] -> OsPath -> PathReader (Eff es) (Maybe OsPath)
forall (m :: * -> *).
(OsPath -> m Bool)
-> [OsPath] -> OsPath -> PathReader m (Maybe OsPath)
FindFileWith OsPath -> Eff es Bool
f [OsPath]
ps

-- | Lifted 'Dir.findFilesWith'.
--
-- @since 0.1
findFilesWith ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  (OsPath -> Eff es Bool) ->
  [OsPath] ->
  OsPath ->
  Eff es [OsPath]
findFilesWith :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es Bool) -> [OsPath] -> OsPath -> Eff es [OsPath]
findFilesWith OsPath -> Eff es Bool
f [OsPath]
ps = PathReader (Eff es) [OsPath] -> Eff es [OsPath]
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) [OsPath] -> Eff es [OsPath])
-> (OsPath -> PathReader (Eff es) [OsPath])
-> OsPath
-> Eff es [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OsPath -> Eff es Bool)
-> [OsPath] -> OsPath -> PathReader (Eff es) [OsPath]
forall (m :: * -> *).
(OsPath -> m Bool) -> [OsPath] -> OsPath -> PathReader m [OsPath]
FindFilesWith OsPath -> Eff es Bool
f [OsPath]
ps

-- | Lifted 'Dir.pathIsSymbolicLink'.
--
-- @since 0.1
pathIsSymbolicLink ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
pathIsSymbolicLink :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
pathIsSymbolicLink = PathReader (Eff es) Bool -> Eff es Bool
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) Bool -> Eff es Bool)
-> (OsPath -> PathReader (Eff es) Bool) -> OsPath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) Bool
forall (m :: * -> *). OsPath -> PathReader m Bool
PathIsSymbolicLink

-- | Lifted 'Dir.getSymbolicLinkTarget'.
--
-- @since 0.1
getSymbolicLinkTarget ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
getSymbolicLinkTarget :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getSymbolicLinkTarget = PathReader (Eff es) OsPath -> Eff es OsPath
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) OsPath -> Eff es OsPath)
-> (OsPath -> PathReader (Eff es) OsPath)
-> OsPath
-> Eff es OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) OsPath
forall (m :: * -> *). OsPath -> PathReader m OsPath
GetSymbolicLinkTarget

-- | Lifted 'Dir.getPermissions'.
--
-- @since 0.1
getPermissions ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Permissions
getPermissions :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Permissions
getPermissions = PathReader (Eff es) Permissions -> Eff es Permissions
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) Permissions -> Eff es Permissions)
-> (OsPath -> PathReader (Eff es) Permissions)
-> OsPath
-> Eff es Permissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) Permissions
forall (m :: * -> *). OsPath -> PathReader m Permissions
GetPermissions

-- | Lifted 'Dir.getAccessTime'.
--
-- @since 0.1
getAccessTime ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es UTCTime
getAccessTime :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es UTCTime
getAccessTime = PathReader (Eff es) UTCTime -> Eff es UTCTime
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) UTCTime -> Eff es UTCTime)
-> (OsPath -> PathReader (Eff es) UTCTime)
-> OsPath
-> Eff es UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) UTCTime
forall (m :: * -> *). OsPath -> PathReader m UTCTime
GetAccessTime

-- | Lifted 'Dir.getModificationTime'.
--
-- @since 0.1
getModificationTime ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es UTCTime
getModificationTime :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es UTCTime
getModificationTime = PathReader (Eff es) UTCTime -> Eff es UTCTime
forall (e :: (* -> *) -> * -> *) (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (PathReader (Eff es) UTCTime -> Eff es UTCTime)
-> (OsPath -> PathReader (Eff es) UTCTime)
-> OsPath
-> Eff es UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> PathReader (Eff es) UTCTime
forall (m :: * -> *). OsPath -> PathReader m UTCTime
GetModificationTime

-- | Retrieves the XDG data directory e.g. @~/.local\/share@.
--
-- @since 0.1
getXdgData ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
getXdgData :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getXdgData = XdgDirectory -> OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectory -> OsPath -> Eff es OsPath
getXdgDirectory XdgDirectory
XdgData

-- | Retrieves the XDG config directory e.g. @~/.config@.
--
-- @since 0.1
getXdgConfig ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
getXdgConfig :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getXdgConfig = XdgDirectory -> OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectory -> OsPath -> Eff es OsPath
getXdgDirectory XdgDirectory
XdgConfig

-- | Retrieves the XDG cache directory e.g. @~/.cache@.
--
-- @since 0.1
getXdgCache ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
getXdgCache :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getXdgCache = XdgDirectory -> OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectory -> OsPath -> Eff es OsPath
getXdgDirectory XdgDirectory
XdgCache

-- | Retrieves the XDG state directory e.g. @~/.local\/state@.
--
-- @since 0.1
getXdgState ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es OsPath
getXdgState :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getXdgState = XdgDirectory -> OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
XdgDirectory -> OsPath -> Eff es OsPath
getXdgDirectory XdgDirectory
XdgState

-- | Returns true if the path is a symbolic link. Does not traverse the link.
--
-- @since 0.1
doesSymbolicLinkExist ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
doesSymbolicLinkExist :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesSymbolicLinkExist OsPath
p =
  -- pathIsSymbolicLink throws an exception if the path does not exist,
  -- so we need to handle this. Note that the obvious alternative, prefacing
  -- the call with doesPathExist does not work, as that operates on the link
  -- target. doesFileExist also behaves this way.
  OsPath -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
pathIsSymbolicLink OsPath
p Eff es Bool -> (IOException -> Eff es Bool) -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]) a.
Eff es a -> (IOException -> Eff es a) -> Eff es a
`catchIO` \IOException
_ -> Bool -> Eff es Bool
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False

-- | Retrieves the recursive directory contents; splits the sub folders and
-- directories apart.
--
-- @since 0.1
listDirectoryRecursive ::
  forall es.
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | Root path.
  OsPath ->
  -- | (files, directories)
  Eff es ([OsPath], [OsPath])
listDirectoryRecursive :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es ([OsPath], [OsPath])
listDirectoryRecursive OsPath
root = [OsPath] -> Eff es ([OsPath], [OsPath])
recurseDirs [OsPath
emptyPath]
  where
    recurseDirs :: [OsPath] -> Eff es ([OsPath], [OsPath])
    recurseDirs :: [OsPath] -> Eff es ([OsPath], [OsPath])
recurseDirs [] = ([OsPath], [OsPath]) -> Eff es ([OsPath], [OsPath])
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], [])
    recurseDirs (OsPath
d : [OsPath]
ds) = do
      (files, dirs) <- OsPath
-> OsPath
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath])
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath
-> OsPath
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath])
splitPaths OsPath
root OsPath
d [] [] ([OsPath] -> Eff es ([OsPath], [OsPath]))
-> Eff es [OsPath] -> Eff es ([OsPath], [OsPath])
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< OsPath -> Eff es [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
listDirectory (OsPath
root OsPath -> OsPath -> OsPath
</> OsPath
d)
      (files', dirs') <- recurseDirs (dirs ++ ds)
      pure (files ++ files', dirs ++ dirs')
    emptyPath :: OsPath
emptyPath = OsPath
forall a. Monoid a => a
mempty

-- | Like 'listDirectoryRecursive' except symbolic links are not traversed
-- i.e. they are returned separately.
--
-- @since 0.1
listDirectoryRecursiveSymbolicLink ::
  forall es.
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | Root path.
  OsPath ->
  -- | (files, directories, symbolic links)
  Eff es ([OsPath], [OsPath], [OsPath])
listDirectoryRecursiveSymbolicLink :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es ([OsPath], [OsPath], [OsPath])
listDirectoryRecursiveSymbolicLink OsPath
root = [OsPath] -> Eff es ([OsPath], [OsPath], [OsPath])
recurseDirs [OsPath
emptyPath]
  where
    recurseDirs :: [OsPath] -> Eff es ([OsPath], [OsPath], [OsPath])
    recurseDirs :: [OsPath] -> Eff es ([OsPath], [OsPath], [OsPath])
recurseDirs [] = ([OsPath], [OsPath], [OsPath])
-> Eff es ([OsPath], [OsPath], [OsPath])
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], [], [])
    recurseDirs (OsPath
d : [OsPath]
ds) = do
      (files, dirs, symlinks) <-
        OsPath
-> OsPath
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath], [OsPath])
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath
-> OsPath
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath], [OsPath])
splitPathsSymboliclink OsPath
root OsPath
d [] [] [] ([OsPath] -> Eff es ([OsPath], [OsPath], [OsPath]))
-> Eff es [OsPath] -> Eff es ([OsPath], [OsPath], [OsPath])
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< OsPath -> Eff es [OsPath]
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es [OsPath]
listDirectory (OsPath
root OsPath -> OsPath -> OsPath
</> OsPath
d)
      (files', dirs', symlinks') <- recurseDirs (dirs ++ ds)
      pure (files ++ files', dirs ++ dirs', symlinks ++ symlinks')
    emptyPath :: OsPath
emptyPath = OsPath
forall a. Monoid a => a
mempty

splitPaths ::
  forall es.
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  OsPath ->
  [OsPath] ->
  [OsPath] ->
  [OsPath] ->
  Eff es ([OsPath], [OsPath])
splitPaths :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath
-> OsPath
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath])
splitPaths OsPath
root OsPath
d = [OsPath] -> [OsPath] -> [OsPath] -> Eff es ([OsPath], [OsPath])
go
  where
    go :: [OsPath] -> [OsPath] -> [OsPath] -> Eff es ([OsPath], [OsPath])
    go :: [OsPath] -> [OsPath] -> [OsPath] -> Eff es ([OsPath], [OsPath])
go [OsPath]
files [OsPath]
dirs [] = ([OsPath], [OsPath]) -> Eff es ([OsPath], [OsPath])
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([OsPath] -> [OsPath]
forall a. [a] -> [a]
reverse [OsPath]
files, [OsPath] -> [OsPath]
forall a. [a] -> [a]
reverse [OsPath]
dirs)
    go [OsPath]
files [OsPath]
dirs (OsPath
p : [OsPath]
ps) = do
      let dirEntry :: OsPath
dirEntry = OsPath
d OsPath -> OsPath -> OsPath
</> OsPath
p
      isDir <- OsPath -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesDirectoryExist (OsPath
root OsPath -> OsPath -> OsPath
</> OsPath
dirEntry)
      if isDir
        then go files (dirEntry : dirs) ps
        else go (dirEntry : files) dirs ps

splitPathsSymboliclink ::
  forall es.
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  OsPath ->
  [OsPath] ->
  [OsPath] ->
  [OsPath] ->
  [OsPath] ->
  Eff es ([OsPath], [OsPath], [OsPath])
splitPathsSymboliclink :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath
-> OsPath
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath], [OsPath])
splitPathsSymboliclink OsPath
root OsPath
d = [OsPath]
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath], [OsPath])
go
  where
    go :: [OsPath] -> [OsPath] -> [OsPath] -> [OsPath] -> Eff es ([OsPath], [OsPath], [OsPath])
    go :: [OsPath]
-> [OsPath]
-> [OsPath]
-> [OsPath]
-> Eff es ([OsPath], [OsPath], [OsPath])
go [OsPath]
files [OsPath]
dirs [OsPath]
symlinks [] = ([OsPath], [OsPath], [OsPath])
-> Eff es ([OsPath], [OsPath], [OsPath])
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([OsPath] -> [OsPath]
forall a. [a] -> [a]
reverse [OsPath]
files, [OsPath] -> [OsPath]
forall a. [a] -> [a]
reverse [OsPath]
dirs, [OsPath]
symlinks)
    go [OsPath]
files [OsPath]
dirs [OsPath]
symlinks (OsPath
p : [OsPath]
ps) = do
      let dirEntry :: OsPath
dirEntry = OsPath
d OsPath -> OsPath -> OsPath
</> OsPath
p
          fullPath :: OsPath
fullPath = OsPath
root OsPath -> OsPath -> OsPath
</> OsPath
dirEntry

      isSymlink <- OsPath -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesSymbolicLinkExist OsPath
fullPath
      if isSymlink
        then go files dirs (dirEntry : symlinks) ps
        else do
          isDir <- doesDirectoryExist fullPath
          if isDir
            then go files (dirEntry : dirs) symlinks ps
            else go (dirEntry : files) dirs symlinks ps

-- | Like 'pathIsSymbolicDirectoryLink' but for files.
--
-- @since 0.1
pathIsSymbolicFileLink ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
pathIsSymbolicFileLink :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
pathIsSymbolicFileLink = OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getSymbolicLinkTarget (OsPath -> Eff es OsPath)
-> (OsPath -> Eff es Bool) -> OsPath -> Eff es Bool
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> OsPath -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesFileExist

-- | Returns true if @p@ is a symbolic link and it points to an extant
-- directory. Throws an exception if the path is not a symbolic link or the
-- target does not exist.
--
-- This function and 'pathIsSymbolicFileLink' are intended to distinguish file
-- and directory links on Windows. This matters for knowing when to use:
--
--     - @createFileLink@ vs. @createDirectoryLink@
--     - @removeFile@ vs. @removeDirectoryLink@
--
-- Suppose we want to copy an arbitrary path @p@. We first determine that
-- @p@ is a symlink via 'doesSymbolicLinkExist'. If
-- 'pathIsSymbolicDirectoryLink' returns true then we know we should use
-- "Effects.FileSystem.PathWriter"'s @createDirectoryLink@. Otherwise we can
-- fall back to @createFileLink@.
--
-- Because this relies on the symlink's target, this is best effort, and it is
-- possible 'pathIsSymbolicDirectoryLink' and 'pathIsSymbolicFileLink' both
-- return false.
--
-- Note that Posix makes no distinction between file and directory symbolic
-- links. Thus if your system only has to work on Posix, you probably don't
-- need this function.
--
-- @since 0.1
pathIsSymbolicDirectoryLink ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es Bool
pathIsSymbolicDirectoryLink :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
pathIsSymbolicDirectoryLink = OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
getSymbolicLinkTarget (OsPath -> Eff es OsPath)
-> (OsPath -> Eff es Bool) -> OsPath -> Eff es Bool
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> OsPath -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesDirectoryExist

-- | Throws 'IOException' if the path does not exist or the expected path type
-- does not match actual.
--
-- @since 0.1
throwIfWrongPathType ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | The location for the thrown exception (e.g. function name)
  String ->
  -- | Expected path type
  PathType ->
  -- | Path
  OsPath ->
  Eff es ()
throwIfWrongPathType :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
String -> PathType -> OsPath -> Eff es ()
throwIfWrongPathType String
location PathType
expected OsPath
path = do
  actual <- OsPath -> Eff es PathType
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es PathType
getPathType OsPath
path

  let err =
        [String] -> String
forall a. Monoid a => [a] -> a
mconcat
          [ String
"Expected path to have type ",
            PathType -> String
forall a. IsString a => PathType -> a
PathType.displayPathType PathType
expected,
            String
", but detected ",
            PathType -> String
forall a. IsString a => PathType -> a
PathType.displayPathType PathType
actual
          ]

  unless (expected == actual) $
    IO.throwPathIOError
      path
      location
      InappropriateType
      err

-- | Checks that the path type matches the expectation. Throws
-- 'IOException' if the path does not exist or the type cannot be detected.
--
-- @since 0.1
isPathType ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | Expected path type.
  PathType ->
  -- Path.
  OsPath ->
  Eff es Bool
isPathType :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
PathType -> OsPath -> Eff es Bool
isPathType PathType
expected = (PathType -> Bool) -> Eff es PathType -> Eff es Bool
forall a b. (a -> b) -> Eff es a -> Eff es b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PathType -> PathType -> Bool
forall a. Eq a => a -> a -> Bool
== PathType
expected) (Eff es PathType -> Eff es Bool)
-> (OsPath -> Eff es PathType) -> OsPath -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> Eff es PathType
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es PathType
getPathType

-- | Returns the type for a given path without following symlinks.
-- Throws 'IOException' if the path does not exist or the type cannot be
-- detected.
--
-- @since 0.1
getPathType ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  OsPath ->
  Eff es PathType
getPathType :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es PathType
getPathType OsPath
path = do
  -- This needs to be first as does(Directory|File|Path)Exist acts on the target.
  symlinkExists <- OsPath -> Eff es Bool
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es Bool
doesSymbolicLinkExist OsPath
path
  if symlinkExists
    then pure PathTypeSymbolicLink
    else do
      dirExists <- doesDirectoryExist path
      if dirExists
        then pure PathTypeDirectory
        else do
          fileExists <- doesFileExist path
          if fileExists
            then pure PathTypeFile
            else do
              pathExists <- doesPathExist path
              if pathExists
                then pure PathTypeOther
                else
                  IO.throwPathIOError
                    path
                    "getPathType"
                    IO.Error.doesNotExistErrorType
                    "path does not exist"

-- | 'onExpandedTilde' that simply returns the expanded path.
--
-- @since 0.1
expandTilde ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | Path to potentially expand.
  OsPath ->
  Eff es OsPath
expandTilde :: forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
OsPath -> Eff es OsPath
expandTilde = (OsPath -> Eff es OsPath) -> OsPath -> Eff es OsPath
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es a) -> OsPath -> Eff es a
onExpandedTilde OsPath -> Eff es OsPath
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | Flipped 'onExpandedTilde'.
--
-- @since 0.1
forExpandedTilde ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | Path to potentially expand.
  OsPath ->
  -- | Action to run on the expanded path.
  (OsPath -> Eff es a) ->
  Eff es a
forExpandedTilde :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, PathReader :> es) =>
OsPath -> (OsPath -> Eff es a) -> Eff es a
forExpandedTilde = ((OsPath -> Eff es a) -> OsPath -> Eff es a)
-> OsPath -> (OsPath -> Eff es a) -> Eff es a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (OsPath -> Eff es a) -> OsPath -> Eff es a
forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es a) -> OsPath -> Eff es a
onExpandedTilde

-- | Expands a "tilde prefix" (~) with the home directory, running the
-- action on the result. Throws an exception if the 'OsPath' contains any
-- other tildes i.e. the only expansions we allow are:
--
-- - @"~/..."@
-- - @"~"@
-- - @"~\\..."@ (windows only)
--
-- If the path contains no tildes, it is handled normally.
--
-- @since 0.1
onExpandedTilde ::
  ( HasCallStack,
    PathReader :> es
  ) =>
  -- | Action to run on the expanded path.
  (OsPath -> Eff es a) ->
  -- | Path to potentially expand.
  OsPath ->
  Eff es a
onExpandedTilde :: forall (es :: [(* -> *) -> * -> *]) a.
(HasCallStack, PathReader :> es) =>
(OsPath -> Eff es a) -> OsPath -> Eff es a
onExpandedTilde OsPath -> Eff es a
onPath =
  OsPath -> TildePrefixState
OsP.toTildePrefixState (OsPath -> TildePrefixState)
-> (TildePrefixState -> Eff es a) -> OsPath -> Eff es a
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> \case
    TildePrefixStateNone OsPath
p -> OsPath -> Eff es a
onPath OsPath
p
    TildePrefixStateStripped OsPathOrEmpty
pne ->
      Eff es OsPath
forall (es :: [(* -> *) -> * -> *]).
(HasCallStack, PathReader :> es) =>
Eff es OsPath
getHomeDirectory Eff es OsPath -> (OsPath -> Eff es a) -> Eff es a
forall a b. Eff es a -> (a -> Eff es b) -> Eff es b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \OsPath
d -> case OsPathOrEmpty
pne of
        OsPathOrEmpty
OsPathEmpty -> OsPath -> Eff es a
onPath OsPath
d
        OsPathNonEmpty OsPath
p -> OsPath -> Eff es a
onPath (OsPath -> Eff es a) -> OsPath -> Eff es a
forall a b. (a -> b) -> a -> b
$ OsPath
d OsPath -> OsPath -> OsPath
</> OsPath
p