{-# LANGUAGE FlexibleInstances, OverloadedStrings #-} module Text.Editor ( Editor , edit , editAll , editM , editAllM ) where import Control.Monad.IO.Class (MonadIO(..)) import Data.Text as Text (Text, intercalate, lines, pack, unpack) import Data.Text.IO as Text (readFile, writeFile) import System.FilePath (replaceDirectory) type Editor a = a -> a type EditorM m a = a -> m a 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 -- | Apply an 'Editor' to the content of a file which path is passed as third -- argument. The second argument is the path to the target folder where the -- edited version will be created. editM :: (Editable a, MonadIO m) => EditorM m a -> FilePath -> FilePath -> m () editM editor target input = liftIO (Text.readFile input) >>= editor . enter >>= liftIO . Text.writeFile output . leave where output = replaceDirectory input target -- | A convenient shortcut of 'editM' for pure editors edit :: Editable a => Editor a -> FilePath -> FilePath -> IO () edit editor = editM (pure . editor) -- | Apply an 'Editor' like 'edit' on all the files which paths are expected to -- be read from the input 'String', one per line. editAllM :: (Editable a, MonadIO m) => EditorM m a -> FilePath -> String -> m () editAllM editor target = mapM_ (editM editor target) . Prelude.lines -- | A convenient shortcut of 'editAllM' for pure editors editAll :: Editable a => Editor a -> FilePath -> String -> IO () editAll editor = editAllM (pure . editor)