Newer
Older
Alice Brenon
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{-# 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)