diff --git a/ChangeLog.md b/ChangeLog.md index 9356762..3861e15 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,10 +1,15 @@ # Revision history for reflex-vty +## Unreleased 0.5.1.1 + +* Fix an issue where the cursor tag is not used for an empty string in `displayLineWithAlignment` + ## 0.5.1.0 * Change `inputInFocusedRegion` to filter mouse scroll wheel input based on if the region under than the mouse rather than using mouse drag tracking * Add MonadCatch, MonadThrow, and MonadMask instances (relies on reflex-0.9.2.0 or greater) + ## 0.5.0.0 * *Breaking change*: diff --git a/reflex-vty.cabal b/reflex-vty.cabal index 841cb9c..8b941d5 100644 --- a/reflex-vty.cabal +++ b/reflex-vty.cabal @@ -1,5 +1,5 @@ name: reflex-vty -version: 0.5.1.0 +version: 0.5.1.1 synopsis: Reflex FRP host and widgets for VTY applications description: Build terminal applications using functional reactive programming (FRP) with Reflex FRP (). diff --git a/src/Data/Text/Zipper.hs b/src/Data/Text/Zipper.hs index d97c602..969b542 100644 --- a/src/Data/Text/Zipper.hs +++ b/src/Data/Text/Zipper.hs @@ -404,9 +404,11 @@ wrapWithOffsetAndAlignment alignment maxWidth n txt = assert (n <= maxWidth) r w -- | converts deleted eol spaces into logical lines eolSpacesToLogicalLines :: [[WrappedLine]] -> [[(Text, Int)]] -eolSpacesToLogicalLines = fmap (fmap (\(WrappedLine a _ c) -> (a,c))) . ((L.groupBy (\(WrappedLine _ b _) _ -> not b)) =<<) +eolSpacesToLogicalLines = fmap (fmap (\(WrappedLine a _ c) -> (a,c))) . concatMap (L.groupBy (\(WrappedLine _ b _) _ -> not b)) + +offsetMapWithAlignmentInternal :: [[WrappedLine]] -> OffsetMapWithAlignment +offsetMapWithAlignmentInternal = offsetMapWithAlignment . eolSpacesToLogicalLines --- | Convert logical lines to a map of displayed rows of aligned text offsetMapWithAlignment :: [[(Text, Int)]] -- ^ The outer list represents logical lines, inner list represents wrapped lines -> OffsetMapWithAlignment @@ -423,9 +425,6 @@ offsetMapWithAlignment ts = evalState (offsetMap' ts) (0, 0) -- add additional offset to last line in wrapped lines (for newline char) return $ Map.adjust (\(align,_)->(align,o+1)) dl $ Map.unions maps --- | Convert logical lines to a map of displayed rows of aligned text -offsetMapWithAlignmentInternal :: [[WrappedLine]] -> OffsetMapWithAlignment -offsetMapWithAlignmentInternal = offsetMapWithAlignment . eolSpacesToLogicalLines -- | Given a width and a 'TextZipper', produce a list of display lines -- (i.e., lines of wrapped text) with special attributes applied to @@ -469,7 +468,7 @@ displayLinesWithAlignment alignment width tag cursorTag (TextZipper lb b a la) = -- map to spans and highlight the cursor -- accumulator type (accumulated text length, Either (current y position) (cursor y and x position)) --mapaccumlfn :: (Int, Either Int (Int, Int)) -> WrappedLine -> ((Int, Either Int (Int, Int)), [Span tag]) - mapaccumlfn (acclength, ecpos') (WrappedLine t dwseol xoff) = r where + mapaccumlfn (acclength, ecpos) (WrappedLine t dwseol xoff) = r where tlength = T.length t -- how many words we've gone through nextacclength = acclength + tlength + if dwseol then 1 else 0 @@ -478,7 +477,7 @@ displayLinesWithAlignment alignment width tag cursorTag (TextZipper lb b a la) = charsbeforecursor = blength-acclength ctlength = textWidth $ T.take charsbeforecursor t cursorx = xoff + ctlength - nextecpos = case ecpos' of + nextecpos = case ecpos of Left y -> if cursoroncurspan then if ctlength == width -- cursor wraps to next line case @@ -496,15 +495,15 @@ displayLinesWithAlignment alignment width tag cursorTag (TextZipper lb b a la) = r = if cursoroncurspan then (nextacc, cursorspans) else (nextacc, [Span tag t]) - ((_, ecpos), curlinespans) = if T.null curlinetext + ((_, ecpos_out), curlinespans) = if T.null curlinetext -- manually handle empty case because mapaccumlfn doesn't handle it - then ((0, Right (0, alignmentOffset alignment width "")), [[Span tag ""]]) + then ((0, Right (0, alignmentOffset alignment width "")), [[Span cursorTag ""]]) else L.mapAccumL mapaccumlfn (0, Left 0) curwrappedlines - (cursorY', cursorX) = case ecpos of + (cursorY', cursorX) = case ecpos_out of Right (y,x) -> (y,x) -- if we never hit the cursor position, this means it's at the beginning of the next line - Left y -> (y+1, alignmentOffset alignment width "") + Left y -> (y+1, alignmentOffset alignment width "") cursorY = cursorY' + length spansBefore in DisplayLines diff --git a/test/Data/Text/ZipperSpec.hs b/test/Data/Text/ZipperSpec.hs index 0177c02..3bd3b9d 100644 --- a/test/Data/Text/ZipperSpec.hs +++ b/test/Data/Text/ZipperSpec.hs @@ -83,6 +83,8 @@ spec = dl1 = displayLinesWithAlignment TextAlignment_Right 10 () () (fromText "aoeu\n\n\naoeu") dl2 = displayLinesWithAlignment TextAlignment_Right 10 () () (fromText "\n\n\naoeu") dl3 = displayLinesWithAlignment TextAlignment_Right 10 () () (fromText "aoeu\n\n\n") + dl4 = displayLinesWithAlignment TextAlignment_Right 10 () () (empty) + insertcharnewlinesentence `shouldBe` fromText newlineSentence @@ -91,6 +93,16 @@ spec = _displayLines_spans dl1 `shouldBe` makespans [["aoeu"],[""],[""],["aoeu", ""]] _displayLines_spans dl2 `shouldBe` makespans [[""],[""],[""],["aoeu", ""]] _displayLines_spans dl3 `shouldBe` makespans [["aoeu"],[""],[""],[""]] + _displayLines_spans dl4 `shouldBe` makespans [[""]] + + + it "displayLinesWithAlignment - cursor tag" $ do + let + dl0 = displayLinesWithAlignment TextAlignment_Right 10 0 1 (fromText "abc") + dl1 = displayLinesWithAlignment TextAlignment_Right 10 0 1 empty + _displayLines_spans dl0 `shouldBe` [[Span 0 "abc", Span 1 ""]] + _displayLines_spans dl1 `shouldBe` [[Span 1 ""]] +