src/Importify/Environment.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
-- | This module contains enrinment for @importify cache@ command
-- which is running inside @ReaderT env IO@ monad.
module Importify.Environment
( -- * Base monad for @importify cache@ command
RIO (..)
-- * Environment for @importify cache@ command
, CacheEnvironment (..)
, HasGhcIncludeDir
, HasPathToImportify
, HasSaveSources
, ghcIncludeDir
, pathToImportify
, pathToSymbols
, saveSources
-- * Runner for cache commend
, runCache
) where
import Universum
import Lens.Micro.Platform (SimpleGetter, makeLensesWith, to)
import Path (Abs, Dir, Path, (</>))
import Path.IO (getCurrentDir)
import Extended.Lens.TH (fieldsVerboseLensRules)
import Importify.Path (doInsideDir, importifyPath, symbolsPath)
import Importify.Stack (ghcIncludePath, stackProjectRoot)
-- | 'ReaderT' + 'IO' monad described here:
-- https://www.fpcomplete.com/blog/2017/07/the-rio-monad
newtype RIO env a = RIO
{ runRIO :: ReaderT env IO a
} deriving ( Functor, Applicative, Monad, MonadIO
, MonadReader env, MonadThrow, MonadCatch, MonadMask)
-- | Environment for @importify cache@ command.
data CacheEnvironment = CacheEnvironment
{ -- | Path to local @.importify@ folder
_pathToImportify :: !(Path Abs Dir)
-- | Path to GHC .h files
, _ghcIncludeDir :: !(Maybe (Path Abs Dir))
-- | 'True' if unpacked sources should be stored locally as well
, _saveSources :: !Bool
}
makeLensesWith fieldsVerboseLensRules ''CacheEnvironment
type HasPathToImportify env = HasPolyPathToImportify env (Path Abs Dir)
type HasGhcIncludeDir env = HasPolyGhcIncludeDir env (Maybe (Path Abs Dir))
type HasSaveSources env = HasPolySaveSources env Bool
-- | Getter of @~\/path\/to\/project\/.importify\/symbols@ folder.
pathToSymbols :: HasPathToImportify env => SimpleGetter env (Path Abs Dir)
pathToSymbols = pathToImportify.to (</> symbolsPath)
-- | Run @importify cache@ command. This function takes current
-- project directory and searches for ghc include path.
runCache :: Bool -> RIO CacheEnvironment () -> IO ()
runCache _saveSources cacheAction = do
projectRoot <- runMaybeT stackProjectRoot
case projectRoot of
Nothing -> return () -- error is reported inside 'stackProjectRoot'
Just projectRootPath -> doInsideDir projectRootPath cacheRunner
where
cacheRunner :: IO ()
cacheRunner = do
projectPath <- getCurrentDir
let _pathToImportify = projectPath </> importifyPath
_ghcIncludeDir <- runMaybeT ghcIncludePath
usingReaderT CacheEnvironment{..} $ runRIO cacheAction