module Language.Haskell.Formatter.Toolkit.Splitter (separate) where
import qualified Control.Applicative as Applicative
import qualified Data.List as List
import qualified Data.Monoid as Monoid
import qualified Language.Haskell.Formatter.Toolkit.ListTool as ListTool
import qualified Language.Haskell.Formatter.Toolkit.Visit as Visit
data Splitter a = Splitter{delimiterPolicy :: DelimiterPolicy,
delimiterQueue :: [[a]]}
deriving (Eq, Ord, Show)
data DelimiterPolicy = Drop
| Separate
| MergeLeft
| MergeRight
deriving (Eq, Ord, Show)
separate :: Eq a => [[a]] -> [a] -> [[a]]
separate = split . createSplitter Drop
where createSplitter rawDelimiterPolicy rawDelimiterQueue
= Splitter{delimiterPolicy = rawDelimiterPolicy,
delimiterQueue = rawDelimiterQueue}
split :: Eq a => Splitter a -> [a] -> [[a]]
split splitter list
= case delimiterPolicy splitter of
Drop -> ListTool.takeEvery period parts
Separate -> parts
MergeLeft -> ListTool.concatenateRuns period parts
MergeRight -> ListTool.concatenateShiftedRuns period shift parts
where shift = 1
where period = 2
parts = rawSplit (delimiterQueue splitter) list
rawSplit :: Eq a => [[a]] -> [a] -> [[a]]
rawSplit delimiters = move [] []
where move parts left [] = Monoid.mappend parts [left]
move parts left right@(first : rest)
= case stripFirstPrefix delimiters right of
Nothing -> move parts (Monoid.mappend left [first]) rest
Just (delimiter, suffix) -> move
(Monoid.mappend parts
[left, delimiter])
[]
suffix
stripFirstPrefix :: Eq a => [[a]] -> [a] -> Maybe ([a], [a])
stripFirstPrefix prefixes list = Visit.findJust strip prefixes
where strip prefix = (,) prefix Applicative.<$> List.stripPrefix prefix list