Skip to content
Snippets Groups Projects
Editor.hs 1.64 KiB
Newer Older
{-# 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)