packages feed

cursor-0.3.1.0: src/Cursor/Tree/Insert.hs

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}

module Cursor.Tree.Insert
  ( treeCursorInsert,
    treeCursorInsertAndSelect,
    treeCursorInsertNodeSingleAndSelect,
    treeCursorInsertNodeAndSelect,
    treeCursorAppend,
    treeCursorAppendAndSelect,
    treeCursorAppendNodeSingleAndSelect,
    treeCursorAppendNodeAndSelect,
    treeCursorAddChildAtPos,
    treeCursorAddChildAtStart,
    treeCursorAddChildAtEnd,
    treeCursorAddChildAtPosAndSelect,
    treeCursorAddChildAtStartAndSelect,
    treeCursorAddChildAtEndAndSelect,
    treeCursorAddChildNodeSingleAtPosAndSelect,
    treeCursorAddChildNodeSingleAtStartAndSelect,
    treeCursorAddChildNodeSingleAtEndAndSelect,
    treeCursorAddChildNodeAtPosAndSelect,
    treeCursorAddChildNodeAtStartAndSelect,
    treeCursorAddChildNodeAtEndAndSelect,
  )
where

import Cursor.Tree.Types
import Data.List.NonEmpty ((<|))
import qualified Data.List.NonEmpty as NE
import Data.Tree

treeCursorInsert :: Tree b -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorInsert tree tc@TreeCursor {..} = do
  ta <- treeAbove
  let newTreeAbove = ta {treeAboveLefts = makeCTree tree : treeAboveLefts ta}
  pure tc {treeAbove = Just newTreeAbove}

treeCursorInsertAndSelect ::
  (a -> b) -> (b -> a) -> Tree b -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorInsertAndSelect f g (Node value forest) = treeCursorInsertNodeAndSelect f (g value) (makeCForest forest)

treeCursorInsertNodeSingleAndSelect ::
  (a -> b) -> a -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorInsertNodeSingleAndSelect f a = treeCursorInsertNodeAndSelect f a EmptyCForest

treeCursorInsertNodeAndSelect ::
  (a -> b) -> a -> CForest b -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorInsertNodeAndSelect f value forest tc = do
  ta <- treeAbove tc
  let ta' = ta {treeAboveRights = CNode (f (treeCurrent tc)) (treeBelow tc) : treeAboveRights ta}
      tc' = tc {treeAbove = Just ta', treeCurrent = value, treeBelow = forest}
  pure tc'

treeCursorAppend :: Tree b -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorAppend tree tc@TreeCursor {..} = do
  ta <- treeAbove
  let newTreeAbove = ta {treeAboveRights = makeCTree tree : treeAboveRights ta}
  pure tc {treeAbove = Just newTreeAbove}

treeCursorAppendAndSelect ::
  (a -> b) -> (b -> a) -> Tree b -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorAppendAndSelect f g (Node value forest) = treeCursorAppendNodeAndSelect f (g value) (makeCForest forest)

treeCursorAppendNodeSingleAndSelect ::
  (a -> b) -> a -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorAppendNodeSingleAndSelect f a = treeCursorAppendNodeAndSelect f a EmptyCForest

treeCursorAppendNodeAndSelect ::
  (a -> b) -> a -> CForest b -> TreeCursor a b -> Maybe (TreeCursor a b)
treeCursorAppendNodeAndSelect f value forest tc = do
  ta <- treeAbove tc
  let ta' = ta {treeAboveLefts = CNode (f (treeCurrent tc)) (treeBelow tc) : treeAboveLefts ta}
      tc' = tc {treeAbove = Just ta', treeCurrent = value, treeBelow = forest}
  pure tc'

-- TODO make this fail if the position doesn't make sense
treeCursorAddChildAtPos :: Int -> Tree b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildAtPos i t tc =
  case treeBelow tc of
    EmptyCForest -> tc {treeBelow = openForest [makeCTree t]}
    ClosedForest ts ->
      let (before, after) = splitAt i $ NE.toList ts
       in tc {treeBelow = openForest $ map makeCTree $ before ++ [t] ++ after}
    OpenForest ts ->
      let (before, after) = splitAt i $ NE.toList ts
       in tc {treeBelow = openForest $ before ++ [makeCTree t] ++ after}

treeCursorAddChildAtStart :: Tree b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildAtStart t tc =
  case treeBelow tc of
    EmptyCForest -> tc {treeBelow = openForest [makeCTree t]}
    ClosedForest ts -> tc {treeBelow = OpenForest $ NE.map makeCTree $ t <| ts}
    OpenForest ts -> tc {treeBelow = OpenForest $ makeCTree t <| ts}

treeCursorAddChildAtEnd :: Tree b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildAtEnd t tc =
  case treeBelow tc of
    EmptyCForest -> tc {treeBelow = openForest [makeCTree t]}
    ClosedForest ts -> tc {treeBelow = openForest $ map makeCTree $ NE.toList ts ++ [t]}
    OpenForest ts -> tc {treeBelow = openForest $ NE.toList ts ++ [makeCTree t]}

treeCursorAddChildAtPosAndSelect ::
  (a -> b) -> (b -> a) -> Int -> Tree b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildAtPosAndSelect f g i (Node t ts) = treeCursorAddChildNodeAtPosAndSelect f i (g t) ts

treeCursorAddChildAtStartAndSelect ::
  (a -> b) -> (b -> a) -> Tree b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildAtStartAndSelect f g (Node t ts) = treeCursorAddChildNodeAtStartAndSelect f (g t) ts

treeCursorAddChildAtEndAndSelect ::
  (a -> b) -> (b -> a) -> Tree b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildAtEndAndSelect f g (Node t ts) = treeCursorAddChildNodeAtEndAndSelect f (g t) ts

treeCursorAddChildNodeSingleAtPosAndSelect ::
  (a -> b) -> Int -> a -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildNodeSingleAtPosAndSelect f i a = treeCursorAddChildNodeAtPosAndSelect f i a []

treeCursorAddChildNodeSingleAtStartAndSelect ::
  (a -> b) -> a -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildNodeSingleAtStartAndSelect f a = treeCursorAddChildNodeAtStartAndSelect f a []

treeCursorAddChildNodeSingleAtEndAndSelect ::
  (a -> b) -> a -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildNodeSingleAtEndAndSelect f a = treeCursorAddChildNodeAtEndAndSelect f a []

treeCursorAddChildNodeAtPosAndSelect ::
  (a -> b) -> Int -> a -> Forest b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildNodeAtPosAndSelect f i t ts tc =
  let (before, after) = splitAt i $ unpackCForest $ treeBelow tc
   in TreeCursor
        { treeAbove =
            Just
              TreeAbove
                { treeAboveLefts = reverse before,
                  treeAboveAbove = treeAbove tc,
                  treeAboveNode = f (treeCurrent tc),
                  treeAboveRights = after
                },
          treeCurrent = t,
          treeBelow = makeCForest ts
        }

treeCursorAddChildNodeAtStartAndSelect ::
  (a -> b) -> a -> Forest b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildNodeAtStartAndSelect f t ts tc =
  TreeCursor
    { treeAbove =
        Just
          TreeAbove
            { treeAboveLefts = [],
              treeAboveAbove = treeAbove tc,
              treeAboveNode = f (treeCurrent tc),
              treeAboveRights = unpackCForest $ treeBelow tc
            },
      treeCurrent = t,
      treeBelow = makeCForest ts
    }

treeCursorAddChildNodeAtEndAndSelect ::
  (a -> b) -> a -> Forest b -> TreeCursor a b -> TreeCursor a b
treeCursorAddChildNodeAtEndAndSelect f t ts tc =
  TreeCursor
    { treeAbove =
        Just
          TreeAbove
            { treeAboveLefts = reverse $ unpackCForest $ treeBelow tc,
              treeAboveAbove = treeAbove tc,
              treeAboveNode = f (treeCurrent tc),
              treeAboveRights = []
            },
      treeCurrent = t,
      treeBelow = makeCForest ts
    }