Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix an issue where the cursor tag is not used for an empty string in displayLineWithAlignment #78

Merged
merged 4 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -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*:
Expand Down
2 changes: 1 addition & 1 deletion reflex-vty.cabal
Original file line number Diff line number Diff line change
@@ -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 (<https://reflex-frp.org>).
Expand Down
21 changes: 10 additions & 11 deletions src/Data/Text/Zipper.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 ""]])
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the only real change in this PR

apologies for the other minor formatting changes.
I'm maintaining a separate version of this file and I use a different linter or something like that.

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
Expand Down
12 changes: 12 additions & 0 deletions test/Data/Text/ZipperSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 ""]]




Expand Down
Loading