    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Data.Algorithm.DiffContext
    -- Copyright   :  (c) David Fox (2015)
    -- License     :  BSD 3 Clause
    -- Maintainer  :  s.clover@gmail.com
    -- Stability   :  experimental
    -- Portability :  portable
    -- Author      :  David Fox (ddssff at the email service from google)
    --
    -- Generates a grouped diff with merged runs, and outputs them in the manner of diff -u
    -----------------------------------------------------------------------------
    module Data.Algorithm.DiffContext
        ( ContextDiff, Hunk
        , getContextDiff
        , prettyContextDiff
        , prettyContextDiffOld
        , getContextDiffNumbered
        , Numbered(Numbered), numbered, unnumber
        , unNumberContextDiff
        , groupBy'
        ) where

    import Data.Algorithm.Diff (PolyDiff(..), Diff, getGroupedDiff)
    -- import Data.List (groupBy)
    import Data.Bifunctor
    import Text.PrettyPrint (Doc, text, empty, hcat)

    type ContextDiff c = [Hunk c]
    type Hunk c = [Diff [c]]

    -- | A version of 'groupBy' that does not assume the argument function
    -- is transitive.  This is used to partition the 'Diff' list into
    -- segments that begin and end with matching ('Both') text, with and
    -- have non-matching ('First' and 'Second') text in the middle.
    --
    --     > let notBoth1 a b = not (a == 1 || b == 1) in
    --     >
    --     > groupBy' notBoth1 [1,1,2,3,1,1,4,5,6,1]
    --     > [[1],[1,2,3,1],[1,4,5,6,1]]
    --     >
    --     > groupBy notBoth1 [1,1,2,3,1,1,4,5,6,1]
    --     > [[1],[1,2,3],[1],[1,4,5,6],[1]]
    --
    -- In the first result the list is split anywhere there are two
    -- adjacent ones, as desired.
    groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
    groupBy' :: forall a. (a -> a -> Bool) -> [a] -> [[a]]
    groupBy' a -> a -> Bool
    _ [] = []
    groupBy' a -> a -> Bool
    eq (a
    x0 : [a]
    xs0) = [a] -> [a] -> [[a]]
    go [a
    x0] [a]
    xs0
        where
          go :: [a] -> [a] -> [[a]]
    go (a
    x : [a]
    xs) (a
    y : [a]
    zs) | a -> a -> Bool
    eq a
    x a
    y = [a] -> [a] -> [[a]]
    go (a
    y a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    xs) [a]
    zs
          go [a]
    g (a
    y : [a]
    zs) = [a] -> [a]
    forall a. [a] -> [a]
    reverse [a]
    g [a] -> [[a]] -> [[a]]
    forall a. a -> [a] -> [a]
    : [a] -> [a] -> [[a]]
    go [a
    y] [a]
    zs
          go [a]
    g [] = [[a] -> [a]
    forall a. [a] -> [a]
    reverse [a]
    g]

    data Numbered a = Numbered Int a deriving Int -> Numbered a -> ShowS
    [Numbered a] -> ShowS
    Numbered a -> String
    (Int -> Numbered a -> ShowS)
    -> (Numbered a -> String)
    -> ([Numbered a] -> ShowS)
    -> Show (Numbered a)
    forall a. Show a => Int -> Numbered a -> ShowS
    forall a. Show a => [Numbered a] -> ShowS
    forall a. Show a => Numbered a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> Numbered a -> ShowS
    showsPrec :: Int -> Numbered a -> ShowS
    $cshow :: forall a. Show a => Numbered a -> String
    show :: Numbered a -> String
    $cshowList :: forall a. Show a => [Numbered a] -> ShowS
    showList :: [Numbered a] -> ShowS
    Show
    instance Eq a => Eq (Numbered a) where
      Numbered Int
    _ a
    a == :: Numbered a -> Numbered a -> Bool
    == Numbered Int
    _ a
    b = a
    a a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    b
    instance Ord a => Ord (Numbered a) where
      compare :: Numbered a -> Numbered a -> Ordering
    compare (Numbered Int
    _ a
    a) (Numbered Int
    _ a
    b) = a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare a
    a a
    b

    numbered :: [a] -> [Numbered a]
    numbered :: forall a. [a] -> [Numbered a]
    numbered [a]
    xs = ((Int, a) -> Numbered a) -> [(Int, a)] -> [Numbered a]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Int -> a -> Numbered a) -> (Int, a) -> Numbered a
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Int -> a -> Numbered a
    forall a. Int -> a -> Numbered a
    Numbered) ([Int] -> [a] -> [(Int, a)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [Int
    1..] [a]
    xs)

    unnumber :: Numbered a -> a
    unnumber :: forall a. Numbered a -> a
    unnumber (Numbered Int
    _ a
    a) = a
    a

    -- |
    -- > > let textA = ["a","b","c","d","e","f","g","h","i","j","k"]
    -- > > let textB = ["a","b","d","e","f","g","h","i","j"]
    -- > > let diff = getContextDiff (Just 2) textA textB
    -- > > prettyContextDiff (text "file1") (text "file2") (text . unnumber) diff
    -- > --- file1
    -- > +++ file2
    -- > @@ -1,5 +1,4 @@
    -- >  a
    -- >  b
    -- > -c
    -- >  d
    -- >  e
    -- > @@ -9,3 +8,2 @@
    -- >  i
    -- >  j
    -- > -k
    getContextDiff ::
      Eq a
      => Maybe Int -- ^ Number of context elements, Nothing means infinite
      -> [a]
      -> [a]
      -> ContextDiff (Numbered a)
    getContextDiff :: forall a.
    Eq a =>
    Maybe Int -> [a] -> [a] -> ContextDiff (Numbered a)
    getContextDiff Maybe Int
    context [a]
    a [a]
    b =
      Maybe Int
    -> [Numbered a] -> [Numbered a] -> ContextDiff (Numbered a)
    forall a.
    Eq a =>
    Maybe Int
    -> [Numbered a] -> [Numbered a] -> ContextDiff (Numbered a)
    getContextDiffNumbered Maybe Int
    context ([a] -> [Numbered a]
    forall a. [a] -> [Numbered a]
    numbered [a]
    a) ([a] -> [Numbered a]
    forall a. [a] -> [Numbered a]
    numbered [a]
    b)

    -- | If for some reason you need the line numbers stripped from the
    -- result of getContextDiff for backwards compatibility.
    unNumberContextDiff :: ContextDiff (Numbered a) -> ContextDiff a
    unNumberContextDiff :: forall a. ContextDiff (Numbered a) -> ContextDiff a
    unNumberContextDiff = (Hunk (Numbered a) -> Hunk a) -> [Hunk (Numbered a)] -> [Hunk a]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Diff [Numbered a] -> Diff [a]) -> Hunk (Numbered a) -> Hunk a
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([Numbered a] -> [a])
    -> ([Numbered a] -> [a]) -> Diff [Numbered a] -> Diff [a]
    forall a b c d.
    (a -> b) -> (c -> d) -> PolyDiff a c -> PolyDiff b d
    forall (p :: * -> * -> *) a b c d.
    Bifunctor p =>
    (a -> b) -> (c -> d) -> p a c -> p b d
    bimap ((Numbered a -> a) -> [Numbered a] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Numbered a -> a
    forall a. Numbered a -> a
    unnumber) ((Numbered a -> a) -> [Numbered a] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Numbered a -> a
    forall a. Numbered a -> a
    unnumber)))

    getContextDiffNumbered ::
      Eq a
      => Maybe Int -- ^ Number of context elements, Nothing means infinite
      -> [Numbered a]
      -> [Numbered a]
      -> ContextDiff (Numbered a)
    getContextDiffNumbered :: forall a.
    Eq a =>
    Maybe Int
    -> [Numbered a] -> [Numbered a] -> ContextDiff (Numbered a)
    getContextDiffNumbered Maybe Int
    context [Numbered a]
    a0 [Numbered a]
    b0 =
        (Diff [Numbered a] -> Diff [Numbered a] -> Bool)
    -> [Diff [Numbered a]] -> [[Diff [Numbered a]]]
    forall a. (a -> a -> Bool) -> [a] -> [[a]]
    groupBy' (\Diff [Numbered a]
    a Diff [Numbered a]
    b -> Bool -> Bool
    not (Diff [Numbered a] -> Bool
    forall {a} {b}. PolyDiff a b -> Bool
    isBoth Diff [Numbered a]
    a Bool -> Bool -> Bool
    && Diff [Numbered a] -> Bool
    forall {a} {b}. PolyDiff a b -> Bool
    isBoth Diff [Numbered a]
    b)) ([Diff [Numbered a]] -> [[Diff [Numbered a]]])
    -> [Diff [Numbered a]] -> [[Diff [Numbered a]]]
    forall a b. (a -> b) -> a -> b
    $ [Diff [Numbered a]] -> [Diff [Numbered a]]
    forall {a} {a}. [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doPrefix ([Diff [Numbered a]] -> [Diff [Numbered a]])
    -> [Diff [Numbered a]] -> [Diff [Numbered a]]
    forall a b. (a -> b) -> a -> b
    $ [Numbered a] -> [Numbered a] -> [Diff [Numbered a]]
    forall a. Eq a => [a] -> [a] -> [Diff [a]]
    getGroupedDiff [Numbered a]
    a0 [Numbered a]
    b0
        where
          isBoth :: PolyDiff a b -> Bool
    isBoth (Both a
    _ b
    _) = Bool
    True
          isBoth PolyDiff a b
    _ = Bool
    False
          -- Handle the common text leading up to a diff.
          doPrefix :: [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doPrefix [] = []
          doPrefix [Both [a]
    _ [a]
    _] = []
          doPrefix (Both [a]
    xs [a]
    ys : [PolyDiff [a] [a]]
    more) =
              [a] -> [a] -> PolyDiff [a] [a]
    forall a b. a -> b -> PolyDiff a b
    Both ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    xs (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop (Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    0 ([a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    xs Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    n)) [a]
    xs) Maybe Int
    context)
                   ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    ys (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop (Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    0 ([a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    ys Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    n)) [a]
    ys) Maybe Int
    context) PolyDiff [a] [a] -> [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    forall a. a -> [a] -> [a]
    : [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doSuffix [PolyDiff [a] [a]]
    more
          -- Prefix finished, do the diff then the following suffix
          doPrefix (PolyDiff [a] [a]
    d : [PolyDiff [a] [a]]
    ds) = [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doSuffix (PolyDiff [a] [a]
    d PolyDiff [a] [a] -> [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    forall a. a -> [a] -> [a]
    : [PolyDiff [a] [a]]
    ds)
          -- Handle the common text following a diff.
          doSuffix :: [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doSuffix [] = []
          doSuffix [Both [a]
    xs [a]
    ys] = [[a] -> [a] -> PolyDiff [a] [a]
    forall a b. a -> b -> PolyDiff a b
    Both ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    xs (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n [a]
    xs) Maybe Int
    context) ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    ys (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n [a]
    ys) Maybe Int
    context)]
          doSuffix (Both [a]
    xs [a]
    ys : [PolyDiff [a] [a]]
    more)
              | Bool -> (Int -> Bool) -> Maybe Int -> Bool
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Bool
    True (\Int
    n -> [a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    xs Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    2) Maybe Int
    context =
                  [a] -> [a] -> PolyDiff [a] [a]
    forall a b. a -> b -> PolyDiff a b
    Both [a]
    xs [a]
    ys PolyDiff [a] [a] -> [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    forall a. a -> [a] -> [a]
    : [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doPrefix [PolyDiff [a] [a]]
    more
          doSuffix (Both [a]
    xs [a]
    ys : [PolyDiff [a] [a]]
    more) =
              [a] -> [a] -> PolyDiff [a] [a]
    forall a b. a -> b -> PolyDiff a b
    Both ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    xs (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n [a]
    xs) Maybe Int
    context) ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    ys (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n [a]
    ys) Maybe Int
    context)
                       PolyDiff [a] [a] -> [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    forall a. a -> [a] -> [a]
    : [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doPrefix ([a] -> [a] -> PolyDiff [a] [a]
    forall a b. a -> b -> PolyDiff a b
    Both ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    forall a. Monoid a => a
    mempty (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    n [a]
    xs) Maybe Int
    context) ([a] -> (Int -> [a]) -> Maybe Int -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [a]
    forall a. Monoid a => a
    mempty (\Int
    n -> Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    n [a]
    ys) Maybe Int
    context) PolyDiff [a] [a] -> [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    forall a. a -> [a] -> [a]
    : [PolyDiff [a] [a]]
    more)
          doSuffix (PolyDiff [a] [a]
    d : [PolyDiff [a] [a]]
    ds) = PolyDiff [a] [a]
    d PolyDiff [a] [a] -> [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    forall a. a -> [a] -> [a]
    : [PolyDiff [a] [a]] -> [PolyDiff [a] [a]]
    doSuffix [PolyDiff [a] [a]]
    ds

    -- | Pretty print a ContextDiff in the manner of diff -u.
    prettyContextDiff ::
           Doc            -- ^ Document 1 name
        -> Doc            -- ^ Document 2 name
        -> (Numbered c -> Doc)     -- ^ Element pretty printer
        -> ContextDiff (Numbered c)
        -> Doc
    prettyContextDiff :: forall c.
    Doc
    -> Doc -> (Numbered c -> Doc) -> ContextDiff (Numbered c) -> Doc
    prettyContextDiff Doc
    _ Doc
    _ Numbered c -> Doc
    _ [] = Doc
    empty
    prettyContextDiff Doc
    old Doc
    new Numbered c -> Doc
    prettyElem [Hunk (Numbered c)]
    hunks =
        [Doc] -> Doc
    hcat ([Doc] -> Doc) -> ([Doc] -> [Doc]) -> [Doc] -> Doc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Doc -> Doc) -> [Doc] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> String -> Doc
    text String
    "\n") ([Doc] -> Doc) -> [Doc] -> Doc
    forall a b. (a -> b) -> a -> b
    $ (String -> Doc
    text String
    "--- " Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    old Doc -> [Doc] -> [Doc]
    forall a. a -> [a] -> [a]
    :
                                     String -> Doc
    text String
    "+++ " Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    new Doc -> [Doc] -> [Doc]
    forall a. a -> [a] -> [a]
    :
                                     (Hunk (Numbered c) -> [Doc]) -> [Hunk (Numbered c)] -> [Doc]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Hunk (Numbered c) -> [Doc]
    prettyRun [Hunk (Numbered c)]
    hunks)
        where
          -- Pretty print a run of adjacent changes
          prettyRun :: Hunk (Numbered c) -> [Doc]
    prettyRun Hunk (Numbered c)
    hunk =
            String -> Doc
    text (String
    "@@ " String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> Hunk (Numbered c) -> String
    forall {a} {a}. [PolyDiff [Numbered a] [Numbered a]] -> String
    formatHunk Hunk (Numbered c)
    hunk String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    " @@") Doc -> [Doc] -> [Doc]
    forall a. a -> [a] -> [a]
    : (PolyDiff [Numbered c] [Numbered c] -> [Doc])
    -> Hunk (Numbered c) -> [Doc]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap PolyDiff [Numbered c] [Numbered c] -> [Doc]
    prettyChange Hunk (Numbered c)
    hunk

          -- Pretty print a single change (e.g. one line of a text file)
          prettyChange :: PolyDiff [Numbered c] [Numbered c] -> [Doc]
    prettyChange (Both [Numbered c]
    ts [Numbered c]
    _) = (Numbered c -> Doc) -> [Numbered c] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ Numbered c
    l -> String -> Doc
    text String
    " " Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Numbered c -> Doc
    prettyElem Numbered c
    l) [Numbered c]
    ts
          prettyChange (First [Numbered c]
    ts)  = (Numbered c -> Doc) -> [Numbered c] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ Numbered c
    l -> String -> Doc
    text String
    "-" Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Numbered c -> Doc
    prettyElem Numbered c
    l) [Numbered c]
    ts
          prettyChange (Second [Numbered c]
    ts) = (Numbered c -> Doc) -> [Numbered c] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ Numbered c
    l -> String -> Doc
    text String
    "+" Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Numbered c -> Doc
    prettyElem Numbered c
    l) [Numbered c]
    ts

          formatHunk :: [PolyDiff [Numbered a] [Numbered a]] -> String
    formatHunk [PolyDiff [Numbered a] [Numbered a]]
    hunk = String
    "-" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> [Int] -> String
    formatRun ([PolyDiff [Numbered a] [Numbered a]] -> [Int]
    forall {a} {b}. [PolyDiff [Numbered a] b] -> [Int]
    firsts [PolyDiff [Numbered a] [Numbered a]]
    hunk) String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    " +" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> [Int] -> String
    formatRun ([PolyDiff [Numbered a] [Numbered a]] -> [Int]
    forall {a} {a}. [PolyDiff a [Numbered a]] -> [Int]
    seconds [PolyDiff [Numbered a] [Numbered a]]
    hunk)

          formatRun :: [Int] -> String
          formatRun :: [Int] -> String
    formatRun [] = String
    "-0,0"
          formatRun [Int
    n] = Int -> String
    forall a. Show a => a -> String
    show Int
    n
          formatRun ns :: [Int]
    ns@(Int
    n : [Int]
    _) = Int -> String
    forall a. Show a => a -> String
    show Int
    n String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "," String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show ([Int] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [Int]
    ns)

          firsts :: [PolyDiff [Numbered a] b] -> [Int]
    firsts (Both [Numbered a]
    ns b
    _ : [PolyDiff [Numbered a] b]
    more) = (Numbered a -> Int) -> [Numbered a] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\(Numbered Int
    n a
    _) -> Int
    n) [Numbered a]
    ns [Int] -> [Int] -> [Int]
    forall a. Semigroup a => a -> a -> a
    <> [PolyDiff [Numbered a] b] -> [Int]
    firsts [PolyDiff [Numbered a] b]
    more
          firsts (First [Numbered a]
    ns : [PolyDiff [Numbered a] b]
    more) = (Numbered a -> Int) -> [Numbered a] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\(Numbered Int
    n a
    _) -> Int
    n) [Numbered a]
    ns [Int] -> [Int] -> [Int]
    forall a. Semigroup a => a -> a -> a
    <> [PolyDiff [Numbered a] b] -> [Int]
    firsts [PolyDiff [Numbered a] b]
    more
          firsts (Second b
    _ : [PolyDiff [Numbered a] b]
    more) = [PolyDiff [Numbered a] b] -> [Int]
    firsts [PolyDiff [Numbered a] b]
    more
          firsts [] = []

          seconds :: [PolyDiff a [Numbered a]] -> [Int]
    seconds (Both a
    _ [Numbered a]
    ns : [PolyDiff a [Numbered a]]
    more) = (Numbered a -> Int) -> [Numbered a] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\(Numbered Int
    n a
    _) -> Int
    n) [Numbered a]
    ns [Int] -> [Int] -> [Int]
    forall a. Semigroup a => a -> a -> a
    <> [PolyDiff a [Numbered a]] -> [Int]
    seconds [PolyDiff a [Numbered a]]
    more
          seconds (First a
    _ : [PolyDiff a [Numbered a]]
    more) = [PolyDiff a [Numbered a]] -> [Int]
    seconds [PolyDiff a [Numbered a]]
    more
          seconds (Second [Numbered a]
    ns : [PolyDiff a [Numbered a]]
    more) = (Numbered a -> Int) -> [Numbered a] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\(Numbered Int
    n a
    _) -> Int
    n) [Numbered a]
    ns [Int] -> [Int] -> [Int]
    forall a. Semigroup a => a -> a -> a
    <> [PolyDiff a [Numbered a]] -> [Int]
    seconds [PolyDiff a [Numbered a]]
    more
          seconds [] = []

    -- | Pretty print without line numbers.
    prettyContextDiffOld ::
           Doc            -- ^ Document 1 name
        -> Doc            -- ^ Document 2 name
        -> (c -> Doc)     -- ^ Element pretty printer
        -> ContextDiff c
        -> Doc
    prettyContextDiffOld :: forall c. Doc -> Doc -> (c -> Doc) -> ContextDiff c -> Doc
    prettyContextDiffOld Doc
    _ Doc
    _ c -> Doc
    _ [] = Doc
    empty
    prettyContextDiffOld Doc
    old Doc
    new c -> Doc
    prettyElem [Hunk c]
    hunks =
        [Doc] -> Doc
    hcat ([Doc] -> Doc) -> ([Doc] -> [Doc]) -> [Doc] -> Doc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Doc -> Doc) -> [Doc] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> String -> Doc
    text String
    "\n") ([Doc] -> Doc) -> [Doc] -> Doc
    forall a b. (a -> b) -> a -> b
    $ (String -> Doc
    text String
    "--- " Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    old Doc -> [Doc] -> [Doc]
    forall a. a -> [a] -> [a]
    :
                                     String -> Doc
    text String
    "+++ " Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    new Doc -> [Doc] -> [Doc]
    forall a. a -> [a] -> [a]
    :
                                     (Hunk c -> [Doc]) -> [Hunk c] -> [Doc]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Hunk c -> [Doc]
    forall {t :: * -> *}. Foldable t => t (PolyDiff [c] [c]) -> [Doc]
    prettyRun [Hunk c]
    hunks)
        where
          -- Pretty print a run of adjacent changes
          prettyRun :: t (PolyDiff [c] [c]) -> [Doc]
    prettyRun t (PolyDiff [c] [c])
    hunk =
              String -> Doc
    text String
    "@@" Doc -> [Doc] -> [Doc]
    forall a. a -> [a] -> [a]
    : (PolyDiff [c] [c] -> [Doc]) -> t (PolyDiff [c] [c]) -> [Doc]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap PolyDiff [c] [c] -> [Doc]
    prettyChange t (PolyDiff [c] [c])
    hunk

          -- Pretty print a single change (e.g. one line of a text file)
          prettyChange :: PolyDiff [c] [c] -> [Doc]
    prettyChange (Both [c]
    ts [c]
    _) = (c -> Doc) -> [c] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ c
    l -> String -> Doc
    text String
    " " Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> c -> Doc
    prettyElem c
    l) [c]
    ts
          prettyChange (First [c]
    ts)  = (c -> Doc) -> [c] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ c
    l -> String -> Doc
    text String
    "-" Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> c -> Doc
    prettyElem c
    l) [c]
    ts
          prettyChange (Second [c]
    ts) = (c -> Doc) -> [c] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ c
    l -> String -> Doc
    text String
    "+" Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> c -> Doc
    prettyElem c
    l) [c]
    ts