{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DeriveFunctor #-} module Cursor.List ( ListCursor(..) , emptyListCursor , makeListCursor , makeListCursorWithSelection , rebuildListCursor , listCursorNull , listCursorLength , listCursorIndex , listCursorSelectPrev , listCursorSelectNext , listCursorSelectIndex , listCursorSelectStart , listCursorSelectEnd , listCursorPrevItem , listCursorNextItem , listCursorInsert , listCursorAppend , listCursorRemove , listCursorDelete , listCursorSplit , listCursorCombine , traverseListCursor , foldListCursor ) where import GHC.Generics (Generic) import Data.Validity import Control.DeepSeq import Cursor.Types data ListCursor a = ListCursor { listCursorPrev :: [a] -- ^ In reverse order , listCursorNext :: [a] } deriving (Show, Eq, Generic, Functor) instance Validity a => Validity (ListCursor a) instance NFData a => NFData (ListCursor a) emptyListCursor :: ListCursor a emptyListCursor = ListCursor {listCursorPrev = [], listCursorNext = []} makeListCursor :: [a] -> ListCursor a makeListCursor as = ListCursor {listCursorPrev = [], listCursorNext = as} makeListCursorWithSelection :: Int -> [a] -> Maybe (ListCursor a) makeListCursorWithSelection i as | i < 0 = Nothing | i > length as = Nothing | otherwise = Just ListCursor {listCursorPrev = reverse $ take i as, listCursorNext = drop i as} rebuildListCursor :: ListCursor a -> [a] rebuildListCursor ListCursor {..} = reverse listCursorPrev ++ listCursorNext listCursorNull :: ListCursor a -> Bool listCursorNull ListCursor {..} = null listCursorPrev && null listCursorNext listCursorLength :: ListCursor a -> Int listCursorLength = length . rebuildListCursor listCursorIndex :: ListCursor a -> Int listCursorIndex = length . listCursorPrev listCursorSelectPrev :: ListCursor a -> Maybe (ListCursor a) listCursorSelectPrev tc = case listCursorPrev tc of [] -> Nothing (c:cs) -> Just ListCursor {listCursorPrev = cs, listCursorNext = c : listCursorNext tc} listCursorSelectNext :: ListCursor a -> Maybe (ListCursor a) listCursorSelectNext tc = case listCursorNext tc of [] -> Nothing (c:cs) -> Just ListCursor {listCursorPrev = c : listCursorPrev tc, listCursorNext = cs} listCursorSelectIndex :: Int -> ListCursor a -> ListCursor a listCursorSelectIndex ix_ lc = let ls = rebuildListCursor lc in case splitAt ix_ ls of (l, r) -> ListCursor {listCursorPrev = reverse l, listCursorNext = r} listCursorSelectStart :: ListCursor a -> ListCursor a listCursorSelectStart tc = case listCursorSelectPrev tc of Nothing -> tc Just tc' -> listCursorSelectStart tc' listCursorSelectEnd :: ListCursor a -> ListCursor a listCursorSelectEnd tc = case listCursorSelectNext tc of Nothing -> tc Just tc' -> listCursorSelectEnd tc' listCursorPrevItem :: ListCursor a -> Maybe a listCursorPrevItem lc = case listCursorPrev lc of [] -> Nothing (c:_) -> Just c listCursorNextItem :: ListCursor a -> Maybe a listCursorNextItem lc = case listCursorNext lc of [] -> Nothing (c:_) -> Just c listCursorInsert :: a -> ListCursor a -> ListCursor a listCursorInsert c lc = lc {listCursorPrev = c : listCursorPrev lc} listCursorAppend :: a -> ListCursor a -> ListCursor a listCursorAppend c lc = lc {listCursorNext = c : listCursorNext lc} listCursorRemove :: ListCursor a -> Maybe (DeleteOrUpdate (ListCursor a)) listCursorRemove tc = case listCursorPrev tc of [] -> case listCursorNext tc of [] -> Just Deleted _ -> Nothing (_:prev) -> Just $ Updated $ tc {listCursorPrev = prev} listCursorDelete :: ListCursor a -> Maybe (DeleteOrUpdate (ListCursor a)) listCursorDelete tc = case listCursorNext tc of [] -> case listCursorPrev tc of [] -> Just Deleted _ -> Nothing (_:next) -> Just $ Updated $ tc {listCursorNext = next} listCursorSplit :: ListCursor a -> (ListCursor a, ListCursor a) listCursorSplit ListCursor {..} = ( ListCursor {listCursorPrev = listCursorPrev, listCursorNext = []} , ListCursor {listCursorPrev = [], listCursorNext = listCursorNext}) listCursorCombine :: ListCursor a -> ListCursor a -> ListCursor a listCursorCombine lc1 lc2 = ListCursor {listCursorPrev = reverse $ rebuildListCursor lc1, listCursorNext = rebuildListCursor lc2} traverseListCursor :: ([a] -> [a] -> f b) -> ListCursor a -> f b traverseListCursor = foldListCursor foldListCursor :: ([a] -> [a] -> b) -> ListCursor a -> b foldListCursor func ListCursor {..} = func (reverse listCursorPrev) listCursorNext