packages feed

cursor 0.1.0.1 → 0.2.0.0

raw patch · 5 files changed

+80/−91 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Cursor.Types: isSafeChar :: Char -> Bool
- Cursor.TextField: textFieldCursorAppendChar :: Char -> Maybe TextFieldCursor -> TextFieldCursor
+ Cursor.TextField: textFieldCursorAppendChar :: Char -> Maybe TextFieldCursor -> Maybe TextFieldCursor
- Cursor.TextField: textFieldCursorInsertChar :: Char -> Maybe TextFieldCursor -> TextFieldCursor
+ Cursor.TextField: textFieldCursorInsertChar :: Char -> Maybe TextFieldCursor -> Maybe TextFieldCursor

Files

+ CHANGELOG.md view
@@ -0,0 +1,9 @@+# Changelog++## [Unreleased]++## [0.2.0.0] - 2019-09-23++### Changed++- `textFieldCursorInsertChar` and `textFieldCursorAppendChar` now fail on unsafe characters.
cursor.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.31.1.+-- This file has been generated from package.yaml by hpack version 0.31.2. -- -- see: https://github.com/sol/hpack ----- hash: 8f3a123718c5c3c3ec43456e3311c0955cd17b64bda527bc0e553a10f783d5bf+-- hash: 198732d25b67091588b88dbc6fd99fc8847ea61c7ebadc1ce7a7f313a60a70eb  name:           cursor-version:        0.1.0.1+version:        0.2.0.0 synopsis:       Purely Functional Cursors description:    Purely Functional Cursors for common data structures                 .@@ -20,6 +20,8 @@ license:        MIT license-file:   LICENSE build-type:     Simple+extra-source-files:+    CHANGELOG.md  library   exposed-modules:
src/Cursor/Text.hs view
@@ -49,7 +49,10 @@     mconcat       [ genericValidate lc       , decorateList (rebuildListCursor lc) $ \c ->-          declare "The character is not a newline character" $ c /= '\n'+          mconcat+            [ declare "The character is not a newline character" $ c /= '\n'+            , declare "The character is a safe character" $ isSafeChar c+            ]       ]  emptyTextCursor :: TextCursor@@ -68,10 +71,7 @@ rebuildTextCursor = T.pack . rebuildListCursor . textCursorList  textCursorListCursorL ::-     Functor f-  => (ListCursor Char -> f (ListCursor Char))-  -> TextCursor-  -> f TextCursor+     Functor f => (ListCursor Char -> f (ListCursor Char)) -> TextCursor -> f TextCursor textCursorListCursorL = lens textCursorList (\tc lc -> tc {textCursorList = lc})  textCursorNull :: TextCursor -> Bool@@ -106,19 +106,23 @@  textCursorInsert :: Char -> TextCursor -> Maybe TextCursor textCursorInsert '\n' _ = Nothing-textCursorInsert c tc = Just (tc & textCursorListCursorL %~ listCursorInsert c)+textCursorInsert c tc =+  if isSafeChar c+    then Just (tc & textCursorListCursorL %~ listCursorInsert c)+    else Nothing  textCursorAppend :: Char -> TextCursor -> Maybe TextCursor textCursorAppend '\n' _ = Nothing-textCursorAppend c tc = Just (tc & textCursorListCursorL %~ listCursorAppend c)+textCursorAppend c tc =+  if isSafeChar c+    then Just (tc & textCursorListCursorL %~ listCursorAppend c)+    else Nothing  textCursorRemove :: TextCursor -> Maybe (DeleteOrUpdate TextCursor)-textCursorRemove =-  focusPossibleDeleteOrUpdate textCursorListCursorL listCursorRemove+textCursorRemove = focusPossibleDeleteOrUpdate textCursorListCursorL listCursorRemove  textCursorDelete :: TextCursor -> Maybe (DeleteOrUpdate TextCursor)-textCursorDelete =-  focusPossibleDeleteOrUpdate textCursorListCursorL listCursorDelete+textCursorDelete = focusPossibleDeleteOrUpdate textCursorListCursorL listCursorDelete  textCursorSplit :: TextCursor -> (TextCursor, TextCursor) textCursorSplit tc =
src/Cursor/TextField.hs view
@@ -62,19 +62,8 @@     mconcat       [ genericValidate tfc       , decorate "None of the texts contain newlines" $-        mconcat $-        NE.toList $-        flip-          NE.map-          (NE.zip (fromJust $ NE.nonEmpty [0 ..]) $-           rebuildNonEmptyCursor rebuildTextCursor textFieldCursorNonEmpty) $ \(i, tc) ->-          declare-            (unwords-               [ "The text of the line at index"-               , show (i :: Int)-               , "does not contain any newlines"-               ]) $-          T.all (/= '\n') tc+        decorateList (NE.toList $ rebuildNonEmptyCursor rebuildTextCursor textFieldCursorNonEmpty) $ \tc ->+          declare "The text of this line does not contain any newlines" $ T.all (/= '\n') tc       ]  makeTextFieldCursor :: Text -> TextFieldCursor@@ -82,32 +71,23 @@  makeTextFieldCursorWithSelection :: Int -> Int -> Text -> Maybe TextFieldCursor makeTextFieldCursorWithSelection x y t = do-  let ls-    -- This is safe because 'splitOn' always returns a nonempty list.-       = NE.fromList $ T.split (== '\n') t+  ls <- NE.nonEmpty $ T.split (== '\n') t   guard (x >= 0)   guard (x < NE.length ls)-  nec <--    makeNonEmptyCursorWithSelection-                -- This is safe because we already checked that it would work above-      (makeTextCursorWithSelection y)-      x-      ls+  nec <- makeNonEmptyCursorWithSelection (makeTextCursorWithSelection y) x ls   void $ nonEmptyCursorCurrent nec+  -- This is safe because we already checked that it would work above   pure $ TextFieldCursor (nec & nonEmptyCursorElemL %~ fromJust)  rebuildTextFieldCursorLines :: TextFieldCursor -> NonEmpty Text-rebuildTextFieldCursorLines =-  rebuildNonEmptyCursor rebuildTextCursor . textFieldCursorNonEmpty+rebuildTextFieldCursorLines = rebuildNonEmptyCursor rebuildTextCursor . textFieldCursorNonEmpty  rebuildTextFieldCursor :: TextFieldCursor -> Text-rebuildTextFieldCursor =-  T.intercalate "\n" . NE.toList . rebuildTextFieldCursorLines+rebuildTextFieldCursor = T.intercalate "\n" . NE.toList . rebuildTextFieldCursorLines  emptyTextFieldCursor :: TextFieldCursor emptyTextFieldCursor =-  TextFieldCursor-    {textFieldCursorNonEmpty = singletonNonEmptyCursor emptyTextCursor}+  TextFieldCursor {textFieldCursorNonEmpty = singletonNonEmptyCursor emptyTextCursor}  nullTextFieldCursor :: TextFieldCursor -> Bool nullTextFieldCursor = (== emptyTextFieldCursor)@@ -117,8 +97,7 @@   ( nonEmptyCursorSelection $ textFieldCursorNonEmpty tfc   , textCursorIndex $ textFieldCursorNonEmpty tfc ^. nonEmptyCursorElemL) -textFieldCursorNonEmptyCursorL ::-     Lens' TextFieldCursor (NonEmptyCursor TextCursor Text)+textFieldCursorNonEmptyCursorL :: Lens' TextFieldCursor (NonEmptyCursor TextCursor Text) textFieldCursorNonEmptyCursorL =   lens textFieldCursorNonEmpty $ \tfc lec -> tfc {textFieldCursorNonEmpty = lec} @@ -127,13 +106,11 @@  textFieldCursorSelectPrevLine :: TextFieldCursor -> Maybe TextFieldCursor textFieldCursorSelectPrevLine =-  moveMWhileKeepingSelection $-  nonEmptyCursorSelectPrev rebuildTextCursor unsafeMakeTextCursor+  moveMWhileKeepingSelection $ nonEmptyCursorSelectPrev rebuildTextCursor unsafeMakeTextCursor  textFieldCursorSelectNextLine :: TextFieldCursor -> Maybe TextFieldCursor textFieldCursorSelectNextLine =-  moveMWhileKeepingSelection $-  nonEmptyCursorSelectNext rebuildTextCursor unsafeMakeTextCursor+  moveMWhileKeepingSelection $ nonEmptyCursorSelectNext rebuildTextCursor unsafeMakeTextCursor  moveMWhileKeepingSelection ::      (NonEmptyCursor TextCursor Text -> Maybe (NonEmptyCursor TextCursor Text))@@ -147,13 +124,11 @@  textFieldCursorSelectFirstLine :: TextFieldCursor -> TextFieldCursor textFieldCursorSelectFirstLine =-  moveWhileKeepingSelection $-  nonEmptyCursorSelectFirst rebuildTextCursor unsafeMakeTextCursor+  moveWhileKeepingSelection $ nonEmptyCursorSelectFirst rebuildTextCursor unsafeMakeTextCursor  textFieldCursorSelectLastLine :: TextFieldCursor -> TextFieldCursor textFieldCursorSelectLastLine =-  moveWhileKeepingSelection $-  nonEmptyCursorSelectLast rebuildTextCursor unsafeMakeTextCursor+  moveWhileKeepingSelection $ nonEmptyCursorSelectLast rebuildTextCursor unsafeMakeTextCursor  moveWhileKeepingSelection ::      (NonEmptyCursor TextCursor Text -> NonEmptyCursor TextCursor Text)@@ -172,28 +147,38 @@ textFieldCursorSelectNextChar = textFieldCursorSelectedL textCursorSelectNext  textFieldCursorIndexOnLine :: TextFieldCursor -> Int-textFieldCursorIndexOnLine tfc =-  textCursorIndex $ tfc ^. textFieldCursorSelectedL+textFieldCursorIndexOnLine tfc = textCursorIndex $ tfc ^. textFieldCursorSelectedL  textFieldCursorSelectIndexOnLine :: Int -> TextFieldCursor -> TextFieldCursor-textFieldCursorSelectIndexOnLine ix_ =-  textFieldCursorSelectedL %~ textCursorSelectIndex ix_+textFieldCursorSelectIndexOnLine ix_ = textFieldCursorSelectedL %~ textCursorSelectIndex ix_ -textFieldCursorInsertChar :: Char -> Maybe TextFieldCursor -> TextFieldCursor+-- |+--+-- returns 'Nothing' when given unsafe characters.+textFieldCursorInsertChar :: Char -> Maybe TextFieldCursor -> Maybe TextFieldCursor textFieldCursorInsertChar c mtfc =   case c of-    '\n' -> textFieldCursorInsertNewline mtfc-    _ ->-      (fromMaybe emptyTextFieldCursor mtfc) &-      textFieldCursorSelectedL %~ (fromJust . textCursorInsert c)+    '\n' -> Just $ textFieldCursorInsertNewline mtfc+    _+      | isSafeChar c ->+        Just $+        (fromMaybe emptyTextFieldCursor mtfc) &+        textFieldCursorSelectedL %~ (fromJust . textCursorInsert c)+      | otherwise -> Nothing -textFieldCursorAppendChar :: Char -> Maybe TextFieldCursor -> TextFieldCursor+-- |+--+-- returns 'Nothing' when given unsafe characters.+textFieldCursorAppendChar :: Char -> Maybe TextFieldCursor -> Maybe TextFieldCursor textFieldCursorAppendChar c mtfc =   case c of-    '\n' -> textFieldCursorAppendNewline mtfc-    _ ->-      (fromMaybe emptyTextFieldCursor mtfc) &-      textFieldCursorSelectedL %~ (fromJust . textCursorAppend c)+    '\n' -> Just $ textFieldCursorAppendNewline mtfc+    _+      | isSafeChar c ->+        Just $+        (fromMaybe emptyTextFieldCursor mtfc) &+        textFieldCursorSelectedL %~ (fromJust . textCursorAppend c)+      | otherwise -> Nothing  textFieldCursorInsertNewline :: Maybe TextFieldCursor -> TextFieldCursor textFieldCursorInsertNewline mtfc =@@ -219,8 +204,7 @@                , nonEmptyCursorNext = rebuildTextCursor tc2 : nonEmptyCursorNext                }) -textFieldCursorRemove ::-     TextFieldCursor -> Maybe (DeleteOrUpdate TextFieldCursor)+textFieldCursorRemove :: TextFieldCursor -> Maybe (DeleteOrUpdate TextFieldCursor) textFieldCursorRemove tfc =   if nullTextFieldCursor tfc     then Just Deleted@@ -228,8 +212,7 @@            textFieldCursorNonEmptyCursorL            (\lec@NonEmptyCursor {..} ->               case textCursorRemove nonEmptyCursorCurrent of-                Just (Updated ctc) ->-                  Just $ Updated $ lec & nonEmptyCursorElemL .~ ctc+                Just (Updated ctc) -> Just $ Updated $ lec & nonEmptyCursorElemL .~ ctc                 _ ->                   case nonEmptyCursorPrev of                     [] -> Nothing@@ -239,14 +222,11 @@                       lec                         { nonEmptyCursorPrev = pls                         , nonEmptyCursorCurrent =-                            textCursorCombine-                              (unsafeMakeTextCursor pl)-                              nonEmptyCursorCurrent+                            textCursorCombine (unsafeMakeTextCursor pl) nonEmptyCursorCurrent                         })            tfc -textFieldCursorDelete ::-     TextFieldCursor -> Maybe (DeleteOrUpdate TextFieldCursor)+textFieldCursorDelete :: TextFieldCursor -> Maybe (DeleteOrUpdate TextFieldCursor) textFieldCursorDelete tfc =   if nullTextFieldCursor tfc     then Just Deleted@@ -254,8 +234,7 @@            textFieldCursorNonEmptyCursorL            (\lec@NonEmptyCursor {..} ->               case textCursorDelete nonEmptyCursorCurrent of-                Just (Updated ctc) ->-                  Just $ Updated $ lec & nonEmptyCursorElemL .~ ctc+                Just (Updated ctc) -> Just $ Updated $ lec & nonEmptyCursorElemL .~ ctc                 _ ->                   case nonEmptyCursorNext of                     [] -> Nothing@@ -264,16 +243,13 @@                       Updated $                       lec                         { nonEmptyCursorCurrent =-                            textCursorCombine-                              nonEmptyCursorCurrent-                              (unsafeMakeTextCursor pl)+                            textCursorCombine nonEmptyCursorCurrent (unsafeMakeTextCursor pl)                         , nonEmptyCursorNext = pls                         })            tfc  textFieldCursorSelectStartOfLine :: TextFieldCursor -> TextFieldCursor-textFieldCursorSelectStartOfLine =-  textFieldCursorSelectedL %~ textCursorSelectStart+textFieldCursorSelectStartOfLine = textFieldCursorSelectedL %~ textCursorSelectStart  textFieldCursorSelectEndOfLine :: TextFieldCursor -> TextFieldCursor textFieldCursorSelectEndOfLine = textFieldCursorSelectedL %~ textCursorSelectEnd
src/Cursor/Types.hs view
@@ -5,6 +5,7 @@  import GHC.Generics (Generic) +import qualified Data.Text.Internal as T import Data.Validity  import Data.Functor.Compose@@ -13,6 +14,9 @@  import Lens.Micro +isSafeChar :: Char -> Bool+isSafeChar c = T.safe c == c+ data DeleteOrUpdate a   = Deleted   | Updated a@@ -35,8 +39,7 @@   Updated a <|> _ = Updated a   Deleted <|> doua = doua -joinDeletes ::-     Maybe (DeleteOrUpdate a) -> Maybe (DeleteOrUpdate a) -> DeleteOrUpdate a+joinDeletes :: Maybe (DeleteOrUpdate a) -> Maybe (DeleteOrUpdate a) -> DeleteOrUpdate a joinDeletes m1 m2 =   case (m1, m2) of     (Nothing, Nothing) -> Deleted@@ -56,16 +59,11 @@     (Just a, _, _) -> a  joinPossibleDeletes ::-     Maybe (DeleteOrUpdate a)-  -> Maybe (DeleteOrUpdate a)-  -> Maybe (DeleteOrUpdate a)+     Maybe (DeleteOrUpdate a) -> Maybe (DeleteOrUpdate a) -> Maybe (DeleteOrUpdate a) joinPossibleDeletes d1 d2 = getCompose $ Compose d1 <|> Compose d2  focusPossibleDeleteOrUpdate ::-     Lens' b a-  -> (a -> Maybe (DeleteOrUpdate a))-  -> b-  -> Maybe (DeleteOrUpdate b)+     Lens' b a -> (a -> Maybe (DeleteOrUpdate a)) -> b -> Maybe (DeleteOrUpdate b) focusPossibleDeleteOrUpdate l func = getCompose . l (Compose . func)  dullMDelete :: Maybe (DeleteOrUpdate a) -> Maybe a