M balkon.cabal => balkon.cabal +2 -1
@@ 141,7 141,8 @@ library balkon-internal
Data.Text.ParagraphLayout.Internal.ProtoFragment,
Data.Text.ParagraphLayout.Internal.ProtoLine,
Data.Text.ParagraphLayout.Internal.ProtoRun,
- Data.Text.ParagraphLayout.Internal.Script
+ Data.Text.ParagraphLayout.Internal.Script,
+ Data.Text.ParagraphLayout.Internal.SplitList
build-depends:
base >=4.12 && < 4.16,
M src/Data/Text/ParagraphLayout/Internal/Layout.hs => src/Data/Text/ParagraphLayout/Internal/Layout.hs +1 -6
@@ 39,6 39,7 @@ import Data.Text.ParagraphLayout.Internal.Rect
import qualified Data.Text.ParagraphLayout.Internal.ResolvedBox as RB
import qualified Data.Text.ParagraphLayout.Internal.ResolvedSpan as RS
import Data.Text.ParagraphLayout.Internal.Run
+import Data.Text.ParagraphLayout.Internal.SplitList
import Data.Text.ParagraphLayout.Internal.TextContainer
import Data.Text.ParagraphLayout.Internal.TextOptions
import Data.Text.ParagraphLayout.Internal.WithSpan
@@ 289,12 290,6 @@ softSplits runs = map (allowSndEmpty . trimFst) splits
-- shortest line break.
cSplits = splitTextsBy (map fst . runCharacterBreaks) runs
-allowFstEmpty :: (NonEmpty a, b) -> ([a], b)
-allowFstEmpty (a, b) = (NonEmpty.toList a, b)
-
-allowSndEmpty :: (a, NonEmpty b) -> (a, [b])
-allowSndEmpty (a, b) = (a, NonEmpty.toList b)
-
-- | The suffix remaining after removing the longest prefix of the list for
-- which the predicate holds, except always including at least the last element
-- of the original list.
A src/Data/Text/ParagraphLayout/Internal/SplitList.hs => src/Data/Text/ParagraphLayout/Internal/SplitList.hs +58 -0
@@ 0,0 1,58 @@
+-- | Utility functions to work with pairs of lists, which may be non-empty.
+module Data.Text.ParagraphLayout.Internal.SplitList
+ ( allowFstEmpty
+ , allowSndEmpty
+ , nonEmptyPairs
+ , nonEmptyFsts
+ , nonEmptySnds
+ )
+where
+
+import Data.List.NonEmpty (NonEmpty, nonEmpty, toList)
+import Data.Maybe (catMaybes)
+
+-- | Generalise the first component of a pair from a non-empty list
+-- to a regular list.
+allowFstEmpty :: (NonEmpty a, b) -> ([a], b)
+allowFstEmpty (a, b) = (toList a, b)
+
+-- | Generalise the second component of a pair from a non-empty list
+-- to a regular list.
+allowSndEmpty :: (a, NonEmpty b) -> (a, [b])
+allowSndEmpty (a, b) = (a, toList b)
+
+-- | Turn pairs of normal lists into pairs of `NonEmpty` lists,
+-- removing pairs in which either list is empty.
+nonEmptyPairs :: [([a], [b])] -> [(NonEmpty a, NonEmpty b)]
+nonEmptyPairs = catMaybes . map nonEmptyPair
+
+-- | Turn a pair of normal lists into `Just` a pair of `NonEmpty` lists,
+-- or `Nothing` if either list is empty.
+nonEmptyPair :: ([a], [b]) -> Maybe (NonEmpty a, NonEmpty b)
+nonEmptyPair (xs, ys) = case (nonEmpty xs, nonEmpty ys) of
+ (Just xs1, Just ys1) -> Just (xs1, ys1)
+ (_, _) -> Nothing
+
+-- | Turn pairs of normal lists into pairs where the first list is `NonEmpty`,
+-- removing pairs in which the first list is empty.
+nonEmptyFsts :: [([a], [b])] -> [(NonEmpty a, [b])]
+nonEmptyFsts = catMaybes . map nonEmptyFst
+
+-- | Turn a pair of normal lists into `Just` a pair where the first list is
+-- `NonEmpty`, or `Nothing` if the first list is empty.
+nonEmptyFst :: ([a], [b]) -> Maybe (NonEmpty a, [b])
+nonEmptyFst (xs, ys) = case nonEmpty xs of
+ Just xs1 -> Just (xs1, ys)
+ Nothing -> Nothing
+
+-- | Turn pairs of normal lists into pairs where the second list is `NonEmpty`,
+-- removing pairs in which the second list is empty.
+nonEmptySnds :: [([a], [b])] -> [([a], NonEmpty b)]
+nonEmptySnds = catMaybes . map nonEmptySnd
+
+-- | Turn a pair of normal lists into `Just` a pair where the second list is
+-- `NonEmpty`, or `Nothing` if the second list is empty.
+nonEmptySnd :: ([a], [b]) -> Maybe ([a], NonEmpty b)
+nonEmptySnd (xs, ys) = case nonEmpty ys of
+ Just ys1 -> Just (xs, ys1)
+ Nothing -> Nothing
M src/Data/Text/ParagraphLayout/Internal/TextContainer.hs => src/Data/Text/ParagraphLayout/Internal/TextContainer.hs +2 -13
@@ 16,11 16,12 @@ where
import Data.Foldable (toList)
import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
-import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Text.Foreign (dropWord8, takeWord8)
+import Data.Text.ParagraphLayout.Internal.SplitList
+
-- | Class of data types containing `Text` that can be accessed.
class TextContainer a where
-- | Extract a `Text` from its container.
@@ 80,18 81,6 @@ splitTextsBy' breakFunc closed (tc : tcs) =
tcSplits = map (\ i -> splitTextAt8 i tc) tcBreakOffsets
tcBreakOffsets = breakFunc tc
--- | Turn pairs of normal lists into pairs of `NonEmpty` lists,
--- removing pairs in which either list is empty.
-nonEmptyPairs :: [([a], [b])] -> [(NonEmpty a, NonEmpty b)]
-nonEmptyPairs = catMaybes . map nonEmptyPair
-
--- | Turn a pair of normal lists into `Just` a pair of `NonEmpty` lists,
--- or `Nothing` if either list is empty.
-nonEmptyPair :: ([a], [b]) -> Maybe (NonEmpty a, NonEmpty b)
-nonEmptyPair (xs, ys) = case (nonEmpty xs, nonEmpty ys) of
- (Just xs1, Just ys1) -> Just (xs1, ys1)
- (_, _) -> Nothing
-
-- | If the first container in the list is empty, remove it.
collapse :: SeparableTextContainer a => NonEmpty a -> [a]
collapse (tc :| tcs)