packages feed

kit-0.4.1: Kit/Util.hs

{-# LANGUAGE TypeSynonymInstances #-}

module Kit.Util(
  module Kit.Util,
  module Control.Applicative,
  module System.FilePath.Posix,
  module System.Directory
  ) where
  import System.FilePath.Posix
  import System.Process
  import System.Directory
  import Data.Maybe
  import Data.List
  import qualified Data.Traversable as T
  import Data.Foldable
  import Control.Applicative
  import Control.Monad
  import Data.Monoid
  import Control.Monad.Trans

--  ma |> f = fmap f ma

  maybeRead :: Read a => String -> Maybe a
  maybeRead = fmap fst . listToMaybe . reads

  justTrue :: Bool -> a -> Maybe a
  justTrue True a = Just a
  justTrue False _ = Nothing

  maybeToRight :: b -> Maybe a -> Either b a
  maybeToRight _ (Just a) = Right a
  maybeToRight b Nothing = Left b

  maybeToLeft :: b -> Maybe a -> Either a b
  maybeToLeft _ (Just a) = Left a
  maybeToLeft b Nothing = Right b

  instance Foldable (Either c) where
    foldr f z (Left c) = z
    foldr f z (Right a) = f a z

  instance T.Traversable (Either c) where
    sequenceA = either (pure . Left) (Right <$>)

  type KitError = String

  data KitIO a = KitIO { unKitIO :: (IO (Either [KitError] a)) }

  kitError :: KitError -> KitIO a
  kitError e = KitIO . return $ Left [e]

  maybeToKitIO msg = maybe (kitError msg) return

  instance Monad KitIO where
    (KitIO ioE) >>= f = KitIO $ ioE >>= g
      where g l@(Left v) = return (Left v)
            g (Right v) = unKitIO $ f v

    return = KitIO . return . Right

  instance Functor KitIO where
    fmap f kio = kio >>= (return . f)

  instance MonadIO KitIO where
    liftIO v = KitIO (fmap Right v)

  instance Applicative KitIO where
    pure = return
    mf <*> ma = do
      f <- mf
      a <- ma
      return $ f a

  mkdir_p :: FilePath -> IO ()
  mkdir_p = createDirectoryIfMissing True

  cleanOrCreate :: FilePath -> IO ()
  cleanOrCreate directory = do
    exists <- doesDirectoryExist directory
    when exists $ removeDirectoryRecursive directory
    mkdir_p directory

  inDirectory :: FilePath -> IO a -> IO a
  inDirectory dir actions = do
    cwd <- getCurrentDirectory
    setCurrentDirectory dir
    v <- actions
    setCurrentDirectory cwd
    return v

  glob :: String -> IO [String]
  glob pattern = fmap lines (readProcess "ruby" ["-e", "puts Dir.glob(\"" ++ pattern ++ "\")"] [])

  stringJoin :: Monoid a => a -> [a] -> a
  stringJoin x = mconcat . intersperse x