{-# LANGUAGE CPP #-}
module Diagrams.Util
(
with
, applyAll
, (#)
, (##)
, iterateN
, tau
, findHsFile
, findSandbox
, globalPackage
, foldB
) where
import Control.Applicative
import Control.Lens hiding (( # ))
import Control.Monad
import Control.Monad.Catch
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import Data.Default.Class
import Data.List
import Data.Maybe
import Data.Monoid
import System.Directory
import System.Environment
import System.FilePath
import System.FilePath.Lens
import System.Process
with :: Default d => d
with :: forall d. Default d => d
with = d
forall d. Default d => d
def
applyAll :: [a -> a] -> a -> a
applyAll :: forall a. [a -> a] -> a -> a
applyAll = Endo a -> a -> a
forall a. Endo a -> a -> a
appEndo (Endo a -> a -> a) -> ([a -> a] -> Endo a) -> [a -> a] -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Endo a] -> Endo a
forall a. Monoid a => [a] -> a
mconcat ([Endo a] -> Endo a)
-> ([a -> a] -> [Endo a]) -> [a -> a] -> Endo a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> a) -> Endo a) -> [a -> a] -> [Endo a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a) -> Endo a
forall a. (a -> a) -> Endo a
Endo
infixl 8 #
(#) :: a -> (a -> b) -> b
# :: forall a b. a -> (a -> b) -> b
(#) = ((a -> b) -> a -> b) -> a -> (a -> b) -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
($)
(##) :: AReview t b -> b -> t
## :: forall t b. AReview t b -> b -> t
(##) = AReview t b -> b -> t
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review
{-# INLINE (##) #-}
infixr 8 ##
iterateN :: Int -> (a -> a) -> a -> [a]
iterateN :: forall a. Int -> (a -> a) -> a -> [a]
iterateN Int
n a -> a
f = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
n ([a] -> [a]) -> (a -> [a]) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> a -> [a]
forall a. (a -> a) -> a -> [a]
iterate a -> a
f
tau :: Floating a => a
tau :: forall a. Floating a => a
tau = a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
forall a. Floating a => a
pi
foldB :: (a -> a -> a) -> a -> [a] -> a
foldB :: forall a. (a -> a -> a) -> a -> [a] -> a
foldB a -> a -> a
_ a
z [] = a
z
foldB a -> a -> a
f a
_ [a]
as = [a] -> a
foldB' [a]
as
where foldB' :: [a] -> a
foldB' [a
x] = a
x
foldB' [a]
xs = [a] -> a
foldB' ([a] -> [a]
go [a]
xs)
go :: [a] -> [a]
go [] = []
go [a
x] = [a
x]
go (a
x1:a
x2:[a]
xs) = a -> a -> a
f a
x1 a
x2 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a]
go [a]
xs
findHsFile :: FilePath -> IO (Maybe FilePath)
findHsFile :: String -> IO (Maybe String)
findHsFile String
file = MaybeT IO String -> IO (Maybe String)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT IO String -> IO (Maybe String))
-> MaybeT IO String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ MaybeT IO String
hs MaybeT IO String -> MaybeT IO String -> MaybeT IO String
forall a. MaybeT IO a -> MaybeT IO a -> MaybeT IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> MaybeT IO String
lhs
where
hs :: MaybeT IO String
hs = String -> MaybeT IO String
forall {t :: (* -> *) -> * -> *}.
(Monad (t IO), MonadTrans t, Alternative (t IO)) =>
String -> t IO String
check (String -> String -> String
addExtension String
file String
"hs")
lhs :: MaybeT IO String
lhs = String -> MaybeT IO String
forall {t :: (* -> *) -> * -> *}.
(Monad (t IO), MonadTrans t, Alternative (t IO)) =>
String -> t IO String
check (String -> String -> String
addExtension String
file String
"lhs")
check :: String -> t IO String
check String
f = do
IO Bool -> t IO Bool
forall (m :: * -> *) a. Monad m => m a -> t m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (String -> IO Bool
doesFileExist String
f) t IO Bool -> (Bool -> t IO ()) -> t IO ()
forall a b. t IO a -> (a -> t IO b) -> t IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> t IO ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard
String -> t IO String
forall a. a -> t IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
f
parseConfig :: FilePath -> MaybeT IO FilePath
parseConfig :: String -> MaybeT IO String
parseConfig String
file = do
String
config <- IO String -> MaybeT IO String
forall (m :: * -> *) a.
(MonadCatch m, MonadIO m) =>
IO a -> MaybeT m a
maybeIO (IO String -> MaybeT IO String) -> IO String -> MaybeT IO String
forall a b. (a -> b) -> a -> b
$ String -> IO String
readFile String
file
Maybe String -> MaybeT IO String
forall (m :: * -> *) b. Applicative m => Maybe b -> MaybeT m b
hoistMaybe (Maybe String -> MaybeT IO String)
-> Maybe String -> MaybeT IO String
forall a b. (a -> b) -> a -> b
$ String
config String -> Getting (First String) String String -> Maybe String
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First String) String String
forall (f :: * -> *).
Applicative f =>
IndexedLensLike' Int f String String
IndexedLensLike' Int (Const (First String)) String String
lined Getting (First String) String String
-> Getting (First String) String String
-> Getting (First String) String String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Prism' String String
forall t. Prefixed t => t -> Prism' t t
prefixed String
"package-db: "
configSearch :: FilePath -> MaybeT IO FilePath
configSearch :: String -> MaybeT IO String
configSearch String
p0 = do
String
p0' <- IO String -> MaybeT IO String
forall (m :: * -> *) a.
(MonadCatch m, MonadIO m) =>
IO a -> MaybeT m a
maybeIO (IO String -> MaybeT IO String) -> IO String -> MaybeT IO String
forall a b. (a -> b) -> a -> b
$ String -> IO String
canonicalizePath String
p0
let mkPaths :: String -> [String]
mkPaths String
p
| (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isPathSeparator String
p Bool -> Bool -> Bool
|| String
p String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"."
= []
| Bool
otherwise = (String
p String -> String -> String
</> String
"cabal.sandbox.config")
String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String -> [String]
mkPaths (String
p String -> Getting String String String -> String
forall s a. s -> Getting a s a -> a
^. Getting String String String
Lens' String String
directory)
(String -> MaybeT IO String) -> [String] -> MaybeT IO String
forall (m :: * -> *) a b.
Monad m =>
(a -> MaybeT m b) -> [a] -> MaybeT m b
foldMaybeT String -> MaybeT IO String
parseConfig (String -> [String]
mkPaths String
p0')
isDB :: FilePath -> MaybeT IO FilePath
isDB :: String -> MaybeT IO String
isDB String
path =
if String -> Bool
isConf String
path
then String -> MaybeT IO String
forall a. a -> MaybeT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return String
path
else IO [String] -> MaybeT IO [String]
forall (m :: * -> *) a.
(MonadCatch m, MonadIO m) =>
IO a -> MaybeT m a
maybeIO (String -> IO [String]
getDirectoryContents String
path) MaybeT IO [String]
-> ([String] -> MaybeT IO String) -> MaybeT IO String
forall a b. MaybeT IO a -> (a -> MaybeT IO b) -> MaybeT IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe String -> MaybeT IO String
forall (m :: * -> *) b. Applicative m => Maybe b -> MaybeT m b
hoistMaybe (Maybe String -> MaybeT IO String)
-> ([String] -> Maybe String) -> [String] -> MaybeT IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> [String] -> Maybe String
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find String -> Bool
isConf
where
isConf :: String -> Bool
isConf = String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".conf.d"
findSandbox :: [FilePath] -> IO (Maybe FilePath)
findSandbox :: [String] -> IO (Maybe String)
findSandbox [String]
paths = MaybeT IO String -> IO (Maybe String)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT IO String -> IO (Maybe String))
-> MaybeT IO String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ MaybeT IO String
pathsTest MaybeT IO String -> MaybeT IO String -> MaybeT IO String
forall a. MaybeT IO a -> MaybeT IO a -> MaybeT IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> MaybeT IO String
diaSB MaybeT IO String -> MaybeT IO String -> MaybeT IO String
forall a. MaybeT IO a -> MaybeT IO a -> MaybeT IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> MaybeT IO String
envDB MaybeT IO String -> MaybeT IO String -> MaybeT IO String
forall a. MaybeT IO a -> MaybeT IO a -> MaybeT IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> MaybeT IO String
wdConfig
where
lookEnv :: String -> MaybeT IO String
lookEnv = IO (Maybe String) -> MaybeT IO String
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (IO (Maybe String) -> MaybeT IO String)
-> (String -> IO (Maybe String)) -> String -> MaybeT IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Maybe String -> Maybe String)
-> IO (Maybe String) -> IO (Maybe String)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe String -> Maybe String)
-> IO (Maybe String) -> IO (Maybe String))
-> ((String -> String) -> Maybe String -> Maybe String)
-> (String -> String)
-> IO (Maybe String)
-> IO (Maybe String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> Maybe String -> Maybe String
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) ([String] -> String
forall a. HasCallStack => [a] -> a
head ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
splitSearchPath) (IO (Maybe String) -> IO (Maybe String))
-> (String -> IO (Maybe String)) -> String -> IO (Maybe String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO (Maybe String)
lookupEnv
envDB :: MaybeT IO String
envDB = (String -> MaybeT IO String) -> [String] -> MaybeT IO String
forall (m :: * -> *) a b.
Monad m =>
(a -> MaybeT m b) -> [a] -> MaybeT m b
foldMaybeT String -> MaybeT IO String
lookEnv [String
"GHC_PACKAGE_PATH", String
"HSENV", String
"PACKAGE_DB_FOR_GHC"]
test :: String -> MaybeT IO String
test String
x = String -> MaybeT IO String
isDB String
x MaybeT IO String -> MaybeT IO String -> MaybeT IO String
forall a. MaybeT IO a -> MaybeT IO a -> MaybeT IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> MaybeT IO String
configSearch String
x
pathsTest :: MaybeT IO String
pathsTest = (String -> MaybeT IO String) -> [String] -> MaybeT IO String
forall (m :: * -> *) a b.
Monad m =>
(a -> MaybeT m b) -> [a] -> MaybeT m b
foldMaybeT String -> MaybeT IO String
test [String]
paths
diaSB :: MaybeT IO String
diaSB = String -> MaybeT IO String
lookEnv String
"DIAGRAMS_SANDBOX" MaybeT IO String
-> (String -> MaybeT IO String) -> MaybeT IO String
forall a b. MaybeT IO a -> (a -> MaybeT IO b) -> MaybeT IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> MaybeT IO String
test
wdConfig :: MaybeT IO String
wdConfig = IO String -> MaybeT IO String
forall (m :: * -> *) a.
(MonadCatch m, MonadIO m) =>
IO a -> MaybeT m a
maybeIO IO String
getCurrentDirectory MaybeT IO String
-> (String -> MaybeT IO String) -> MaybeT IO String
forall a b. MaybeT IO a -> (a -> MaybeT IO b) -> MaybeT IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> MaybeT IO String
configSearch
globalPackage :: IO FilePath
globalPackage :: IO String
globalPackage = do
[(String, String)]
info <- String -> [(String, String)]
forall a. Read a => String -> a
read (String -> [(String, String)])
-> IO String -> IO [(String, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> [String] -> String -> IO String
readProcess String
"ghc" [String
"--info"] String
""
String -> IO String
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe (String -> String
forall a. HasCallStack => String -> a
error String
"Unable to parse ghc --info.")
(String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"Global Package DB" [(String, String)]
info)
maybeIO :: (MonadCatch m, MonadIO m) => IO a -> MaybeT m a
maybeIO :: forall (m :: * -> *) a.
(MonadCatch m, MonadIO m) =>
IO a -> MaybeT m a
maybeIO IO a
io = IO a -> MaybeT m a
forall a. IO a -> MaybeT m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
io MaybeT m a -> (SomeException -> MaybeT m a) -> MaybeT m a
forall (m :: * -> *) a.
(HasCallStack, MonadCatch m) =>
m a -> (SomeException -> m a) -> m a
`catchAll` MaybeT m a -> SomeException -> MaybeT m a
forall a b. a -> b -> a
const MaybeT m a
forall a. MaybeT m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
#if MIN_VERSION_transformers(0,6,0)
#else
hoistMaybe :: Monad m => Maybe a -> MaybeT m a
hoistMaybe = MaybeT . return
#endif
foldMaybeT :: Monad m => (a -> MaybeT m b) -> [a] -> MaybeT m b
foldMaybeT :: forall (m :: * -> *) a b.
Monad m =>
(a -> MaybeT m b) -> [a] -> MaybeT m b
foldMaybeT a -> MaybeT m b
_ [] = MaybeT m b
forall a. MaybeT m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
foldMaybeT a -> MaybeT m b
f (a
a:[a]
as) = m (Maybe b) -> MaybeT m b
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe b) -> MaybeT m b) -> m (Maybe b) -> MaybeT m b
forall a b. (a -> b) -> a -> b
$ do
Maybe b
x <- MaybeT m b -> m (Maybe b)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (a -> MaybeT m b
f a
a)
if Maybe b -> Bool
forall a. Maybe a -> Bool
isJust Maybe b
x
then Maybe b -> m (Maybe b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe b
x
else MaybeT m b -> m (Maybe b)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT ((a -> MaybeT m b) -> [a] -> MaybeT m b
forall (m :: * -> *) a b.
Monad m =>
(a -> MaybeT m b) -> [a] -> MaybeT m b
foldMaybeT a -> MaybeT m b
f [a]
as)