~jaro/balkon

0975c99f8e8fc2f33c968daa8968444bb0c026c5 — Jaro 10 months ago cb613a6
Refactor lineNumbers into a common module.
M balkon.cabal => balkon.cabal +1 -0
@@ 137,6 137,7 @@ library balkon-internal
    -- Modules used purely internally and not in any tests.
    other-modules:
        Data.Text.ParagraphLayout.Internal.Layout,
        Data.Text.ParagraphLayout.Internal.LineNumbers,
        Data.Text.ParagraphLayout.Internal.ParagraphExtents,
        Data.Text.ParagraphLayout.Internal.ParagraphLine,
        Data.Text.ParagraphLayout.Internal.ProtoFragment,

A src/Data/Text/ParagraphLayout/Internal/LineNumbers.hs => src/Data/Text/ParagraphLayout/Internal/LineNumbers.hs +23 -0
@@ 0,0 1,23 @@
module Data.Text.ParagraphLayout.Internal.LineNumbers
    ( LineNumbers
    , lineNumbers
    , lineNumbersWithDuplication
    )
where

import qualified Data.List.NonEmpty as NonEmpty

-- | Data types that contain numbered lines.
class LineNumbers ml where

    -- | A list of all line numbers in ascending order,
    -- with possible duplicates.
    lineNumbersWithDuplication :: ml -> [Int]

-- | A list of all unique line numbers, in ascending order.
lineNumbers :: (LineNumbers ml) => ml -> [Int]
lineNumbers ml = dedupe $ lineNumbersWithDuplication ml

-- | Remove duplicates from a sorted list.
dedupe :: Eq a => [a] -> [a]
dedupe xs = map NonEmpty.head $ NonEmpty.group xs

M src/Data/Text/ParagraphLayout/Internal/Paginable.hs => src/Data/Text/ParagraphLayout/Internal/Paginable.hs +2 -1
@@ 8,6 8,7 @@ where

import Data.Int (Int32)

import Data.Text.ParagraphLayout.Internal.LineNumbers
import Data.Text.ParagraphLayout.Internal.LinePagination
import Data.Text.ParagraphLayout.Internal.ParagraphLine
import qualified Data.Text.ParagraphLayout.Internal.Plain.ParagraphLayout


@@ 86,7 87,7 @@ instance Paginable (Plain.ParagraphLayout d) where
instance Paginable (Rich.ParagraphLayout d) where
    paginate = paginateLayout

paginateLayout :: (Line a, GenericLayout a) =>
paginateLayout :: (Line a, LineNumbers a, GenericLayout a) =>
   PageOptions -> a -> (PageContinuity, a, Maybe a)
paginateLayout opts pl =
    case paginate opts (cutLines pl) of

M src/Data/Text/ParagraphLayout/Internal/ParagraphLine.hs => src/Data/Text/ParagraphLayout/Internal/ParagraphLine.hs +2 -14
@@ 7,9 7,9 @@ module Data.Text.ParagraphLayout.Internal.ParagraphLine
where

import Data.Int (Int32)
import qualified Data.List.NonEmpty as NonEmpty

import Data.Text.ParagraphLayout.Internal.Fragment
import Data.Text.ParagraphLayout.Internal.LineNumbers
import qualified Data.Text.ParagraphLayout.Internal.Plain.ParagraphLayout as P
import qualified Data.Text.ParagraphLayout.Internal.Rich.ParagraphLayout as R
import Data.Text.ParagraphLayout.Internal.Rect


@@ 25,9 25,6 @@ class GenericLayout pl where
    -- | Actual distance between the paragraph origin and the nearest fragment.
    topDistance :: pl -> Int32

    -- | A list of all unique line numbers that have laid out content.
    lineNumbers :: pl -> [Int]

    -- | Keep only fragments with the given line number.
    limitFragments :: Int -> pl -> pl



@@ 42,7 39,6 @@ instance GenericLayout (P.ParagraphLayout d) where
    empty = P.emptyParagraphLayout
    rect = P.paragraphRect
    topDistance pl = topFragmentOrigin $ P.paragraphFragments pl
    lineNumbers pl = uniqueFragmentLines $ P.paragraphFragments pl
    limitFragments n = P.filterFragments (fragmentIsOnLine n)
    shiftFragments dy = P.mapFragments (shiftFragment dy)
    appendFragments = P.appendFragments


@@ 51,13 47,12 @@ instance GenericLayout (R.ParagraphLayout d) where
    empty = R.emptyParagraphLayout
    rect = R.paragraphRect
    topDistance pl = topFragmentOrigin $ R.paragraphFragments pl
    lineNumbers pl = uniqueFragmentLines $ R.paragraphFragments pl
    limitFragments n = R.filterFragments (fragmentIsOnLine n)
    shiftFragments dy = R.mapFragments (shiftFragment dy)
    appendFragments = R.appendFragments

-- | Split the given paragraph layout into single-line layouts.
cutLines :: GenericLayout pl => pl -> [pl]
cutLines :: (GenericLayout pl, LineNumbers pl) => pl -> [pl]
cutLines pl = map (\ n -> cutLine n pl) (lineNumbers pl)

-- | Reduce the given paragraph layout to fragments with the given line number.


@@ 71,13 66,6 @@ trimTop pl = shiftFragments (-topDistance pl) pl
topFragmentOrigin :: [Fragment d] -> Int32
topFragmentOrigin frags = maximum $ map (y_origin . fragmentRect) frags

uniqueFragmentLines :: [Fragment d] -> [Int]
uniqueFragmentLines frags = dedupe $ map fragmentLine frags

-- | Remove duplicates from a sorted list.
dedupe :: Eq a => [a] -> [a]
dedupe xs = map NonEmpty.head $ NonEmpty.group xs

-- | Put the given paragraph layouts together as a vertically contiguous
-- sequence.
mergeLines :: GenericLayout pl => [pl] -> pl

M src/Data/Text/ParagraphLayout/Internal/Plain/ParagraphLayout.hs => src/Data/Text/ParagraphLayout/Internal/Plain/ParagraphLayout.hs +4 -0
@@ 13,6 13,7 @@ where
import Data.Int (Int32)

import Data.Text.ParagraphLayout.Internal.Fragment
import Data.Text.ParagraphLayout.Internal.LineNumbers
import Data.Text.ParagraphLayout.Internal.LinePagination
import Data.Text.ParagraphLayout.Internal.ParagraphExtents
import Data.Text.ParagraphLayout.Internal.Rect


@@ 26,6 27,9 @@ data ParagraphLayout d = ParagraphLayout
    }
    deriving (Eq, Read, Show)

instance LineNumbers (ParagraphLayout d) where
    lineNumbersWithDuplication pl = map fragmentLine $ paragraphFragments pl

instance Line (ParagraphLayout d) where
    lineHeight pl = height $ paragraphRect pl


M src/Data/Text/ParagraphLayout/Internal/Rich/ParagraphLayout.hs => src/Data/Text/ParagraphLayout/Internal/Rich/ParagraphLayout.hs +4 -0
@@ 14,6 14,7 @@ where
import Data.Int (Int32)

import Data.Text.ParagraphLayout.Internal.Fragment
import Data.Text.ParagraphLayout.Internal.LineNumbers
import Data.Text.ParagraphLayout.Internal.LinePagination
import Data.Text.ParagraphLayout.Internal.ParagraphExtents
import Data.Text.ParagraphLayout.Internal.Rect


@@ 29,6 30,9 @@ data ParagraphLayout d = ParagraphLayout
    }
    deriving (Eq, Read, Show)

instance LineNumbers (ParagraphLayout d) where
    lineNumbersWithDuplication pl = map fragmentLine $ paragraphFragments pl

instance Line (ParagraphLayout d) where
    lineHeight pl = height $ paragraphRect pl