diff --git a/packages.dhall b/packages.dhall index 8a9c027..0ccb5e8 100644 --- a/packages.dhall +++ b/packages.dhall @@ -116,10 +116,8 @@ let additions = } ------------------------------- -} - - let upstream = - https://github.com/purescript/package-sets/releases/download/psc-0.13.6-20200309/packages.dhall sha256:9221987b4e7ea99ccd0efbe056f7bebc872cd92e0058efe5baa181d73359e7b3 + https://github.com/purescript/package-sets/releases/download/psc-0.14.5/packages.dhall sha256:7ed6350fe897a93926d16298e37d2324aabbe5eca99810204719dc3632fb555f let overrides = {=} diff --git a/spago.dhall b/spago.dhall index ed2f19a..6590101 100644 --- a/spago.dhall +++ b/spago.dhall @@ -10,6 +10,13 @@ You can edit this file as you like. , "quickcheck-laws" , "spec" , "control" + , "aff" + , "effect" + , "foldable-traversable" + , "gen" + , "maybe" + , "partial" + , "prelude" ] , packages = ./packages.dhall , sources = [ "src/**/*.purs", "test/**/*.purs" ] diff --git a/src/Data/Zipper/ArrayZipper.purs b/src/Data/Zipper/ArrayZipper.purs index 6889bf8..74e61a7 100644 --- a/src/Data/Zipper/ArrayZipper.purs +++ b/src/Data/Zipper/ArrayZipper.purs @@ -10,6 +10,9 @@ module Data.Zipper.ArrayZipper , exposeMaxIndex , exposeFocusIndex + , dropBefore + , dropAfter + , hasPrev , hasNext @@ -41,7 +44,7 @@ import Prelude import Control.Comonad (class Comonad) import Control.Extend (class Extend) import Control.Monad.Gen (chooseInt) -import Data.Array (findIndex, length, mapWithIndex, unsafeIndex) +import Data.Array (findIndex, length, mapWithIndex, unsafeIndex, splitAt) import Data.Array.NonEmpty as NEA import Data.Foldable (class Foldable, foldMapDefaultL, foldl, foldr) import Data.FoldableWithIndex (class FoldableWithIndex, foldMapWithIndex, foldlWithIndex, foldrWithIndex) @@ -258,7 +261,7 @@ shiftFocusByFind f zipper = fromMaybe zipper $ shiftFocusByFind' f zipper -- | If no element matches, `Nothing` is returned. -- | If an element matches, `Just zipper` is returned. shiftFocusByFind' :: forall a. (a -> Boolean) -> ArrayZipper a -> Maybe (ArrayZipper a) -shiftFocusByFind' f zipper@(ArrayZipper r) = do +shiftFocusByFind' f (ArrayZipper r) = do index <- findIndex f r.array pure $ ArrayZipper $ r { focusIndex = index } @@ -299,6 +302,27 @@ setFocus a (ArrayZipper r) = ArrayZipper (r { array = unsafeSetAt r.focusIndex a modifyFocus :: forall a. (a -> a) -> ArrayZipper a -> ArrayZipper a modifyFocus f (ArrayZipper r) = ArrayZipper (r { array = unsafeModifyAt r.focusIndex f r.array }) +-- | Drops all elements after the focused element +dropAfter :: forall a. ArrayZipper a -> ArrayZipper a +dropAfter (ArrayZipper r) = + ArrayZipper ( r { array = before + , maxIndex = length before - 1 + } + ) + where + { before } = splitAt (r.focusIndex + 1) r.array + +-- | Drops all elements before the focused element +dropBefore :: forall a. ArrayZipper a -> ArrayZipper a +dropBefore (ArrayZipper r) = + ArrayZipper ( r { array = after + , focusIndex = 0 + , maxIndex = length after - 1 + } + ) + where + { after } = splitAt r.focusIndex r.array + -- | Inserts an element in front of / to the left of the focus element. `O(n)` pushPrev :: forall a. a -> ArrayZipper a -> ArrayZipper a pushPrev a (ArrayZipper r) = diff --git a/test/Data/Zipper/ArrayZipper.purs b/test/Data/Zipper/ArrayZipper.purs index ff27f18..b641134 100644 --- a/test/Data/Zipper/ArrayZipper.purs +++ b/test/Data/Zipper/ArrayZipper.purs @@ -3,7 +3,7 @@ module Test.Data.Zipper.ArrayZipper where import Prelude import Data.Maybe (Maybe(..), fromJust) -import Data.Zipper.ArrayZipper (ArrayZipper, asArrayZipper, getFocus, modifyFocus, next, prev, pushNextRefocus, pushPrevRefocus, setFocus, shiftFocusBy, shiftFocusBy', shiftFocusByFind, shiftFocusByFind', shiftFocusTo, shiftFocusTo', shiftFocusFirst, shiftFocusLast, toArrayZipperAt, toArrayZipperAt', toArrayZipperFirst, toArrayZipperLast) +import Data.Zipper.ArrayZipper (ArrayZipper, asArrayZipper, dropAfter, dropBefore, getFocus, modifyFocus, next, prev, pushNextRefocus, pushPrevRefocus, setFocus, shiftFocusBy, shiftFocusBy', shiftFocusByFind, shiftFocusByFind', shiftFocusFirst, shiftFocusLast, shiftFocusTo, shiftFocusTo', toArrayZipperAt, toArrayZipperAt', toArrayZipperFirst, toArrayZipperLast) import Effect.Class (liftEffect) import Partial.Unsafe (unsafePartial) import Test.QuickCheck.Laws as Laws @@ -142,6 +142,11 @@ spec = describe "Array Zipper" do it "next with refocus" do pushNextRefocus 10 i0 `shouldEqual` mkZipper 1 [0, 10, 1, 2, 3, 4] pushNextRefocus 10 i4 `shouldEqual` mkZipper 5 [0, 1, 2, 3, 4, 10] + describe "dropping" do + it "drops before focus" do + dropBefore i2 `shouldEqual` mkZipper 0 [2, 3, 4] + it "drops after focus" do + dropAfter i2 `shouldEqual` mkZipper 2 [0, 1, 2] describe "Laws" do it "Eq" do