40 lines
1.1 KiB
Haskell
40 lines
1.1 KiB
Haskell
module Profold.LineNode
|
|
( LineNode(..)
|
|
, newLineNode
|
|
, Path
|
|
, flatten
|
|
, modify
|
|
) where
|
|
|
|
import qualified Data.Text as T
|
|
import qualified Data.Vector as V
|
|
|
|
data LineNode = LineNode
|
|
{ lineText :: T.Text
|
|
, lineChildren :: V.Vector LineNode
|
|
, lineFolded :: Bool
|
|
} deriving (Show)
|
|
|
|
newLineNode :: T.Text -> [LineNode] -> LineNode
|
|
newLineNode text children = LineNode text (V.fromList children) True
|
|
|
|
type Path = [Int]
|
|
|
|
flatten :: LineNode -> V.Vector (Path, LineNode)
|
|
flatten ln
|
|
| lineFolded ln = V.singleton ([], ln)
|
|
| otherwise =
|
|
V.cons ([], ln) $
|
|
V.concat $ V.toList $ V.imap flattenChild $ lineChildren ln
|
|
where
|
|
flattenChild :: Int -> LineNode -> V.Vector (Path, LineNode)
|
|
flattenChild i c = V.map (\(is, n) -> (i : is, n)) $ flatten c
|
|
|
|
modifyAtIndex :: Int -> (a -> a) -> V.Vector a -> V.Vector a
|
|
-- Yes, this function looks ugly, but it's short enough that I don't care.
|
|
modifyAtIndex i f v = maybe v (\a -> v V.// [(i, f a)]) (v V.!? i)
|
|
|
|
modify :: (LineNode -> LineNode) -> Path -> LineNode -> LineNode
|
|
modify f [] ln = f ln
|
|
modify f (i:is) ln =
|
|
ln {lineChildren = modifyAtIndex i (modify f is) $ lineChildren ln}
|