{-# LANGUAGE FlexibleInstances, NamedFieldPuns, OverloadedStrings #-} module Text.Editor ( Editable(..) , (<>.) , apply , fileFilter , xargs ) where import Control.Monad.IO.Class (MonadIO(..)) import Data.ByteString.Lazy as BS (ByteString, pack, unpack) import Data.Text as Text (Text, intercalate, lines, pack, unpack) import Data.Text.IO as Text (readFile, writeFile) import System.FilePath (replaceDirectory, replaceExtension) class Editable a where enter :: Text -> a leave :: a -> Text instance Editable [Text] where enter = Text.lines leave = Text.intercalate "\n" instance Editable String where enter = Text.unpack leave = Text.pack type Editor m = FilePath -> FilePath -> m () fileFilter :: (Editable a, Editable b, MonadIO m) => (FilePath -> FilePath) -> (a -> m b) -> Editor m fileFilter fixFormat transform target input = liftIO (Text.readFile input) >>= transform . enter >>= liftIO . Text.writeFile output . leave where output = fixFormat $ replaceDirectory input target (<>.) :: (Editable a, Editable b, MonadIO m) => (a -> m b) -> String -> Editor m (<>.) transform extension = fileFilter (`replaceExtension` extension) transform apply :: (Editable a, Editable b, MonadIO m) => (a -> m b) -> Editor m apply = fileFilter id xargs :: (Editable a, Editable b, MonadIO m) => (a -> m b) -> FilePath -> m () xargs transform target = Prelude.lines <$> liftIO getContents >>= mapM_ (apply transform target)