{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE RecordWildCards #-}
module Ormolu.Diff.Text
( TextDiff,
diffText,
selectSpans,
printTextDiff,
)
where
import Control.Monad (unless, when)
import Data.Algorithm.Diff qualified as D
import Data.Foldable (for_)
import Data.IntSet (IntSet)
import Data.IntSet qualified as IntSet
import Data.List (foldl')
import Data.Maybe (listToMaybe)
import Data.Text (Text)
import Data.Text qualified as T
import GHC.Types.SrcLoc
import Ormolu.Terminal
import Ormolu.Terminal.QualifiedDo qualified as Term
data TextDiff = TextDiff
{
TextDiff -> FilePath
textDiffPath :: FilePath,
TextDiff -> DiffList
textDiffDiffList :: DiffList,
TextDiff -> IntSet
textDiffSelectedLines :: IntSet
}
deriving (TextDiff -> TextDiff -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TextDiff -> TextDiff -> Bool
$c/= :: TextDiff -> TextDiff -> Bool
== :: TextDiff -> TextDiff -> Bool
$c== :: TextDiff -> TextDiff -> Bool
Eq, Int -> TextDiff -> ShowS
[TextDiff] -> ShowS
TextDiff -> FilePath
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [TextDiff] -> ShowS
$cshowList :: [TextDiff] -> ShowS
show :: TextDiff -> FilePath
$cshow :: TextDiff -> FilePath
showsPrec :: Int -> TextDiff -> ShowS
$cshowsPrec :: Int -> TextDiff -> ShowS
Show)
type DiffList = [D.Diff [Text]]
type DiffList' = [D.Diff [(Int, Int, Text)]]
data Hunk = Hunk
{ Hunk -> Int
hunkFirstStartLine :: Int,
Hunk -> Int
hunkFirstLength :: Int,
Hunk -> Int
hunkSecondStartLine :: Int,
Hunk -> Int
hunkSecondLength :: Int,
Hunk -> DiffList
hunkDiff :: DiffList
}
deriving (Int -> Hunk -> ShowS
[Hunk] -> ShowS
Hunk -> FilePath
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [Hunk] -> ShowS
$cshowList :: [Hunk] -> ShowS
show :: Hunk -> FilePath
$cshow :: Hunk -> FilePath
showsPrec :: Int -> Hunk -> ShowS
$cshowsPrec :: Int -> Hunk -> ShowS
Show)
diffText ::
Text ->
Text ->
FilePath ->
Maybe TextDiff
diffText :: Text -> Text -> FilePath -> Maybe TextDiff
diffText Text
a Text
b FilePath
path =
if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall {a} {b}. PolyDiff a b -> Bool
isBoth DiffList
xs
then forall a. Maybe a
Nothing
else
forall a. a -> Maybe a
Just
TextDiff
{ textDiffPath :: FilePath
textDiffPath = FilePath
path,
textDiffDiffList :: DiffList
textDiffDiffList = DiffList
xs,
textDiffSelectedLines :: IntSet
textDiffSelectedLines = IntSet
IntSet.empty
}
where
xs :: DiffList
xs = forall a. Eq a => [a] -> [a] -> [Diff [a]]
D.getGroupedDiff (Text -> [Text]
lines' Text
a) (Text -> [Text]
lines' Text
b)
isBoth :: PolyDiff a b -> Bool
isBoth = \case
D.Both a
_ b
_ -> Bool
True
D.First a
_ -> Bool
False
D.Second b
_ -> Bool
False
lines' :: Text -> [Text]
lines' = HasCallStack => Text -> Text -> [Text]
T.splitOn Text
"\n"
selectSpans :: [RealSrcSpan] -> TextDiff -> TextDiff
selectSpans :: [RealSrcSpan] -> TextDiff -> TextDiff
selectSpans [RealSrcSpan]
ss TextDiff
textDiff = TextDiff
textDiff {textDiffSelectedLines :: IntSet
textDiffSelectedLines = IntSet
xs}
where
xs :: IntSet
xs = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' IntSet -> RealSrcSpan -> IntSet
addOneSpan (TextDiff -> IntSet
textDiffSelectedLines TextDiff
textDiff) [RealSrcSpan]
ss
addOneSpan :: IntSet -> RealSrcSpan -> IntSet
addOneSpan IntSet
linesSoFar RealSrcSpan
s =
let start :: Int
start = RealSrcSpan -> Int
srcSpanStartLine RealSrcSpan
s
end :: Int
end = RealSrcSpan -> Int
srcSpanEndLine RealSrcSpan
s
in IntSet -> IntSet -> IntSet
IntSet.union
IntSet
linesSoFar
([Int] -> IntSet
IntSet.fromAscList [Int
start .. Int
end])
printTextDiff :: TextDiff -> Term
printTextDiff :: TextDiff -> Term
printTextDiff TextDiff {FilePath
DiffList
IntSet
textDiffSelectedLines :: IntSet
textDiffDiffList :: DiffList
textDiffPath :: FilePath
textDiffSelectedLines :: TextDiff -> IntSet
textDiffDiffList :: TextDiff -> DiffList
textDiffPath :: TextDiff -> FilePath
..} = Term.do
(Term -> Term
bold forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Term
put forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack) FilePath
textDiffPath
Term
newline
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (DiffList' -> [Hunk]
toHunks (DiffList -> DiffList'
assignLines DiffList
textDiffDiffList)) forall a b. (a -> b) -> a -> b
$ \hunk :: Hunk
hunk@Hunk {Int
DiffList
hunkDiff :: DiffList
hunkSecondLength :: Int
hunkSecondStartLine :: Int
hunkFirstLength :: Int
hunkFirstStartLine :: Int
hunkDiff :: Hunk -> DiffList
hunkSecondLength :: Hunk -> Int
hunkSecondStartLine :: Hunk -> Int
hunkFirstLength :: Hunk -> Int
hunkFirstStartLine :: Hunk -> Int
..} ->
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (IntSet -> Hunk -> Bool
isSelectedLine IntSet
textDiffSelectedLines Hunk
hunk) forall a b. (a -> b) -> a -> b
$ Term.do
Term -> Term
cyan forall a b. (a -> b) -> a -> b
$ Term.do
Text -> Term
put Text
"@@ -"
forall a. Show a => a -> Term
putShow Int
hunkFirstStartLine
Text -> Term
put Text
","
forall a. Show a => a -> Term
putShow Int
hunkFirstLength
Text -> Term
put Text
" +"
forall a. Show a => a -> Term
putShow Int
hunkSecondStartLine
Text -> Term
put Text
","
forall a. Show a => a -> Term
putShow Int
hunkSecondLength
Text -> Term
put Text
" @@"
Term
newline
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ DiffList
hunkDiff forall a b. (a -> b) -> a -> b
$ \case
D.Both [Text]
ys [Text]
_ ->
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Text]
ys forall a b. (a -> b) -> a -> b
$ \Text
y -> Term.do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
T.null Text
y) forall a b. (a -> b) -> a -> b
$
Text -> Term
put Text
" "
Text -> Term
put Text
y
Term
newline
D.First [Text]
ys ->
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Text]
ys forall a b. (a -> b) -> a -> b
$ \Text
y -> Term -> Term
red forall a b. (a -> b) -> a -> b
$ Term.do
Text -> Term
put Text
"-"
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
T.null Text
y) forall a b. (a -> b) -> a -> b
$
Text -> Term
put Text
" "
Text -> Term
put Text
y
Term
newline
D.Second [Text]
ys ->
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Text]
ys forall a b. (a -> b) -> a -> b
$ \Text
y -> Term -> Term
green forall a b. (a -> b) -> a -> b
$ Term.do
Text -> Term
put Text
"+"
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
T.null Text
y) forall a b. (a -> b) -> a -> b
$
Text -> Term
put Text
" "
Text -> Term
put Text
y
Term
newline
assignLines :: DiffList -> DiffList'
assignLines :: DiffList -> DiffList'
assignLines = forall {c} {c}.
Int
-> Int
-> ([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c)
-> [PolyDiff [c] [c]]
-> c
go Int
1 Int
1 forall a. a -> a
id
where
go :: Int
-> Int
-> ([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c)
-> [PolyDiff [c] [c]]
-> c
go Int
_ Int
_ [PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c
acc [] = [PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c
acc []
go !Int
firstLine !Int
secondLine [PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c
acc (PolyDiff [c] [c]
x : [PolyDiff [c] [c]]
xs) =
case PolyDiff [c] [c]
x of
D.Both [c]
a [c]
b ->
let firstInc :: Int
firstInc = forall (t :: * -> *) a. Foldable t => t a -> Int
length [c]
a
secondInc :: Int
secondInc = forall (t :: * -> *) a. Foldable t => t a -> Int
length [c]
b
a' :: [(Int, Int, c)]
a' =
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3
(forall a. (a -> a) -> a -> [a]
iterate (forall a. Num a => a -> a -> a
+ Int
1) Int
firstLine)
(forall a. (a -> a) -> a -> [a]
iterate (forall a. Num a => a -> a -> a
+ Int
1) Int
secondLine)
[c]
a
in Int
-> Int
-> ([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c)
-> [PolyDiff [c] [c]]
-> c
go
(Int
firstLine forall a. Num a => a -> a -> a
+ Int
firstInc)
(Int
secondLine forall a. Num a => a -> a -> a
+ Int
secondInc)
([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. a -> b -> PolyDiff a b
D.Both [(Int, Int, c)]
a' [(Int, Int, c)]
a' :))
[PolyDiff [c] [c]]
xs
D.First [c]
a ->
let firstInc :: Int
firstInc = forall (t :: * -> *) a. Foldable t => t a -> Int
length [c]
a
a' :: [(Int, Int, c)]
a' =
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3
(forall a. (a -> a) -> a -> [a]
iterate (forall a. Num a => a -> a -> a
+ Int
1) Int
firstLine)
(forall a. a -> [a]
repeat Int
secondLine)
[c]
a
in Int
-> Int
-> ([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c)
-> [PolyDiff [c] [c]]
-> c
go
(Int
firstLine forall a. Num a => a -> a -> a
+ Int
firstInc)
Int
secondLine
([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. a -> PolyDiff a b
D.First [(Int, Int, c)]
a' :))
[PolyDiff [c] [c]]
xs
D.Second [c]
b ->
let secondInc :: Int
secondInc = forall (t :: * -> *) a. Foldable t => t a -> Int
length [c]
b
b' :: [(Int, Int, c)]
b' =
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3
(forall a. a -> [a]
repeat Int
firstLine)
(forall a. (a -> a) -> a -> [a]
iterate (forall a. Num a => a -> a -> a
+ Int
1) Int
secondLine)
[c]
b
in Int
-> Int
-> ([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c)
-> [PolyDiff [c] [c]]
-> c
go
Int
firstLine
(Int
secondLine forall a. Num a => a -> a -> a
+ Int
secondInc)
([PolyDiff [(Int, Int, c)] [(Int, Int, c)]] -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. b -> PolyDiff a b
D.Second [(Int, Int, c)]
b' :))
[PolyDiff [c] [c]]
xs
toHunks :: DiffList' -> [Hunk]
toHunks :: DiffList' -> [Hunk]
toHunks = Int
-> Bool
-> ([Hunk] -> [Hunk])
-> (DiffList' -> DiffList')
-> [(Int, Int, Text)]
-> DiffList'
-> [Hunk]
go Int
0 Bool
False forall a. a -> a
id forall a. a -> a
id []
where
margin :: Int
margin = Int
3
go ::
Int ->
Bool ->
([Hunk] -> [Hunk]) ->
(DiffList' -> DiffList') ->
[(Int, Int, Text)] ->
DiffList' ->
[Hunk]
go :: Int
-> Bool
-> ([Hunk] -> [Hunk])
-> (DiffList' -> DiffList')
-> [(Int, Int, Text)]
-> DiffList'
-> [Hunk]
go !Int
n Bool
gotChanges [Hunk] -> [Hunk]
hunksAcc DiffList' -> DiffList'
currentAcc [(Int, Int, Text)]
bothHistory = \case
[] ->
if Bool
gotChanges
then
let currentAcc' :: DiffList' -> DiffList'
currentAcc' = forall {a} {c}.
[a] -> ([PolyDiff [a] [a]] -> c) -> [PolyDiff [a] [a]] -> c
addBothAfter [(Int, Int, Text)]
p DiffList' -> DiffList'
currentAcc
p :: [(Int, Int, Text)]
p = forall a. Int -> [a] -> [a]
take Int
margin (forall a. [a] -> [a]
reverse [(Int, Int, Text)]
bothHistory)
in case DiffList' -> Maybe Hunk
formHunk (DiffList' -> DiffList'
currentAcc' []) of
Maybe Hunk
Nothing -> [Hunk] -> [Hunk]
hunksAcc []
Just Hunk
hunk -> [Hunk] -> [Hunk]
hunksAcc [Hunk
hunk]
else [Hunk] -> [Hunk]
hunksAcc []
(Diff [(Int, Int, Text)]
x : DiffList'
xs) ->
case Diff [(Int, Int, Text)]
x of
D.Both [(Int, Int, Text)]
a [(Int, Int, Text)]
_ ->
let currentAcc' :: DiffList' -> DiffList'
currentAcc' = forall {a} {c}.
[a] -> ([PolyDiff [a] [a]] -> c) -> [PolyDiff [a] [a]] -> c
addBothAfter [(Int, Int, Text)]
p DiffList' -> DiffList'
currentAcc
p :: [(Int, Int, Text)]
p = forall a. [a] -> [a]
reverse (forall a. Int -> [a] -> [a]
drop (Int
n' forall a. Num a => a -> a -> a
- Int
margin) [(Int, Int, Text)]
bothHistory')
hunksAcc' :: [Hunk] -> [Hunk]
hunksAcc' =
case DiffList' -> Maybe Hunk
formHunk (DiffList' -> DiffList'
currentAcc' []) of
Maybe Hunk
Nothing -> [Hunk] -> [Hunk]
hunksAcc
Just Hunk
hunk -> [Hunk] -> [Hunk]
hunksAcc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Hunk
hunk :)
bothHistory' :: [(Int, Int, Text)]
bothHistory' = forall a. [a] -> [a]
reverse [(Int, Int, Text)]
a forall a. [a] -> [a] -> [a]
++ [(Int, Int, Text)]
bothHistory
lena :: Int
lena = forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, Int, Text)]
a
n' :: Int
n' = Int
n forall a. Num a => a -> a -> a
+ Int
lena
in if Bool
gotChanges Bool -> Bool -> Bool
&& Int
n' forall a. Ord a => a -> a -> Bool
> Int
margin forall a. Num a => a -> a -> a
* Int
2
then Int
-> Bool
-> ([Hunk] -> [Hunk])
-> (DiffList' -> DiffList')
-> [(Int, Int, Text)]
-> DiffList'
-> [Hunk]
go Int
0 Bool
False [Hunk] -> [Hunk]
hunksAcc' forall a. a -> a
id [(Int, Int, Text)]
bothHistory' DiffList'
xs
else Int
-> Bool
-> ([Hunk] -> [Hunk])
-> (DiffList' -> DiffList')
-> [(Int, Int, Text)]
-> DiffList'
-> [Hunk]
go Int
n' Bool
gotChanges [Hunk] -> [Hunk]
hunksAcc DiffList' -> DiffList'
currentAcc [(Int, Int, Text)]
bothHistory' DiffList'
xs
Diff [(Int, Int, Text)]
piece ->
if Bool
gotChanges
then
let currentAcc' :: DiffList' -> DiffList'
currentAcc' = DiffList' -> DiffList'
currentAcc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a} {a}.
[a] -> (a -> [PolyDiff [a] [a]]) -> a -> [PolyDiff [a] [a]]
addBothBefore [(Int, Int, Text)]
p (Diff [(Int, Int, Text)]
piece :)
p :: [(Int, Int, Text)]
p = forall a. [a] -> [a]
reverse [(Int, Int, Text)]
bothHistory
in Int
-> Bool
-> ([Hunk] -> [Hunk])
-> (DiffList' -> DiffList')
-> [(Int, Int, Text)]
-> DiffList'
-> [Hunk]
go Int
0 Bool
True [Hunk] -> [Hunk]
hunksAcc DiffList' -> DiffList'
currentAcc' [] DiffList'
xs
else
let currentAcc' :: DiffList' -> DiffList'
currentAcc' = forall {a} {a}.
[a] -> (a -> [PolyDiff [a] [a]]) -> a -> [PolyDiff [a] [a]]
addBothBefore [(Int, Int, Text)]
p (Diff [(Int, Int, Text)]
piece :)
p :: [(Int, Int, Text)]
p = forall a. [a] -> [a]
reverse (forall a. Int -> [a] -> [a]
take Int
margin [(Int, Int, Text)]
bothHistory)
in Int
-> Bool
-> ([Hunk] -> [Hunk])
-> (DiffList' -> DiffList')
-> [(Int, Int, Text)]
-> DiffList'
-> [Hunk]
go Int
0 Bool
True [Hunk] -> [Hunk]
hunksAcc DiffList' -> DiffList'
currentAcc' [] DiffList'
xs
addBothBefore :: [a] -> (a -> [PolyDiff [a] [a]]) -> a -> [PolyDiff [a] [a]]
addBothBefore [] a -> [PolyDiff [a] [a]]
acc = a -> [PolyDiff [a] [a]]
acc
addBothBefore [a]
p a -> [PolyDiff [a] [a]]
acc = (forall a b. a -> b -> PolyDiff a b
D.Both [a]
p [a]
p :) forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [PolyDiff [a] [a]]
acc
addBothAfter :: [a] -> ([PolyDiff [a] [a]] -> c) -> [PolyDiff [a] [a]] -> c
addBothAfter [] [PolyDiff [a] [a]] -> c
acc = [PolyDiff [a] [a]] -> c
acc
addBothAfter [a]
p [PolyDiff [a] [a]] -> c
acc = [PolyDiff [a] [a]] -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. a -> b -> PolyDiff a b
D.Both [a]
p [a]
p :)
formHunk :: DiffList' -> Maybe Hunk
formHunk :: DiffList' -> Maybe Hunk
formHunk DiffList'
xsRaw = do
let xs :: DiffList'
xs = DiffList' -> DiffList'
trimEmpty DiffList'
xsRaw
Int
hunkFirstStartLine <- forall a. [a] -> Maybe a
listToMaybe DiffList'
xs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. Diff [(Int, Int, a)] -> Maybe Int
firstStartLine
let hunkFirstLength :: Int
hunkFirstLength = forall a. [Diff [(Int, Int, a)]] -> Int
firstLength DiffList'
xs
Int
hunkSecondStartLine <- forall a. [a] -> Maybe a
listToMaybe DiffList'
xs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. Diff [(Int, Int, a)] -> Maybe Int
secondStartLine
let hunkSecondLength :: Int
hunkSecondLength = forall a. [Diff [(Int, Int, a)]] -> Int
secondLength DiffList'
xs
hunkDiff :: DiffList
hunkDiff = forall a b. (a -> b) -> [Diff a] -> [Diff b]
mapDiff (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, Int, Text) -> Text
third) DiffList'
xs
forall (m :: * -> *) a. Monad m => a -> m a
return Hunk {Int
DiffList
hunkDiff :: DiffList
hunkSecondLength :: Int
hunkSecondStartLine :: Int
hunkFirstLength :: Int
hunkFirstStartLine :: Int
hunkDiff :: DiffList
hunkSecondLength :: Int
hunkSecondStartLine :: Int
hunkFirstLength :: Int
hunkFirstStartLine :: Int
..}
trimEmpty :: DiffList' -> DiffList'
trimEmpty :: DiffList' -> DiffList'
trimEmpty = forall {c}. Bool -> (DiffList' -> c) -> DiffList' -> c
go Bool
True forall a. a -> a
id
where
go :: Bool -> (DiffList' -> c) -> DiffList' -> c
go Bool
isFirst DiffList' -> c
acc = \case
[] -> DiffList' -> c
acc []
[D.Both [(Int, Int, Text)]
x [(Int, Int, Text)]
_] ->
let x' :: [(Int, Int, Text)]
x' = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Text -> Bool
T.null forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int, Text) -> Text
third) (forall a. [a] -> [a]
reverse [(Int, Int, Text)]
x)
in Bool -> (DiffList' -> c) -> DiffList' -> c
go Bool
False (DiffList' -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. a -> b -> PolyDiff a b
D.Both [(Int, Int, Text)]
x' [(Int, Int, Text)]
x' :)) []
(D.Both [(Int, Int, Text)]
x [(Int, Int, Text)]
_ : DiffList'
xs) ->
let x' :: [(Int, Int, Text)]
x' = forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Text -> Bool
T.null forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int, Text) -> Text
third) [(Int, Int, Text)]
x
in if Bool
isFirst
then Bool -> (DiffList' -> c) -> DiffList' -> c
go Bool
False (DiffList' -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. a -> b -> PolyDiff a b
D.Both [(Int, Int, Text)]
x' [(Int, Int, Text)]
x' :)) DiffList'
xs
else Bool -> (DiffList' -> c) -> DiffList' -> c
go Bool
False (DiffList' -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. a -> b -> PolyDiff a b
D.Both [(Int, Int, Text)]
x [(Int, Int, Text)]
x :)) DiffList'
xs
(Diff [(Int, Int, Text)]
x : DiffList'
xs) ->
Bool -> (DiffList' -> c) -> DiffList' -> c
go Bool
False (DiffList' -> c
acc forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Diff [(Int, Int, Text)]
x :)) DiffList'
xs
firstStartLine :: D.Diff [(Int, Int, a)] -> Maybe Int
firstStartLine :: forall a. Diff [(Int, Int, a)] -> Maybe Int
firstStartLine = \case
D.Both ((Int
x, Int
_, a
_) : [(Int, Int, a)]
_) [(Int, Int, a)]
_ -> forall a. a -> Maybe a
Just Int
x
D.First ((Int
x, Int
_, a
_) : [(Int, Int, a)]
_) -> forall a. a -> Maybe a
Just Int
x
D.Second ((Int
x, Int
_, a
_) : [(Int, Int, a)]
_) -> forall a. a -> Maybe a
Just Int
x
Diff [(Int, Int, a)]
_ -> forall a. Maybe a
Nothing
firstLength :: [D.Diff [(Int, Int, a)]] -> Int
firstLength :: forall a. [Diff [(Int, Int, a)]] -> Int
firstLength = forall {t :: * -> *} {a} {b}.
Foldable t =>
Int -> [PolyDiff (t a) b] -> Int
go Int
0
where
go :: Int -> [PolyDiff (t a) b] -> Int
go Int
n [] = Int
n
go !Int
n (PolyDiff (t a) b
x : [PolyDiff (t a) b]
xs) = case PolyDiff (t a) b
x of
D.Both t a
as b
_ -> Int -> [PolyDiff (t a) b] -> Int
go (Int
n forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
as) [PolyDiff (t a) b]
xs
D.First t a
as -> Int -> [PolyDiff (t a) b] -> Int
go (Int
n forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
as) [PolyDiff (t a) b]
xs
D.Second b
_ -> Int -> [PolyDiff (t a) b] -> Int
go Int
n [PolyDiff (t a) b]
xs
secondStartLine :: D.Diff [(Int, Int, a)] -> Maybe Int
secondStartLine :: forall a. Diff [(Int, Int, a)] -> Maybe Int
secondStartLine = \case
D.Both ((Int
_, Int
x, a
_) : [(Int, Int, a)]
_) [(Int, Int, a)]
_ -> forall a. a -> Maybe a
Just Int
x
D.First ((Int
_, Int
x, a
_) : [(Int, Int, a)]
_) -> forall a. a -> Maybe a
Just Int
x
D.Second ((Int
_, Int
x, a
_) : [(Int, Int, a)]
_) -> forall a. a -> Maybe a
Just Int
x
Diff [(Int, Int, a)]
_ -> forall a. Maybe a
Nothing
secondLength :: [D.Diff [(Int, Int, a)]] -> Int
secondLength :: forall a. [Diff [(Int, Int, a)]] -> Int
secondLength = forall {t :: * -> *} {t :: * -> *} {a} {a}.
(Foldable t, Foldable t) =>
Int -> [PolyDiff (t a) (t a)] -> Int
go Int
0
where
go :: Int -> [PolyDiff (t a) (t a)] -> Int
go Int
n [] = Int
n
go !Int
n (PolyDiff (t a) (t a)
x : [PolyDiff (t a) (t a)]
xs) = case PolyDiff (t a) (t a)
x of
D.Both t a
as t a
_ -> Int -> [PolyDiff (t a) (t a)] -> Int
go (Int
n forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
as) [PolyDiff (t a) (t a)]
xs
D.First t a
_ -> Int -> [PolyDiff (t a) (t a)] -> Int
go Int
n [PolyDiff (t a) (t a)]
xs
D.Second t a
as -> Int -> [PolyDiff (t a) (t a)] -> Int
go (Int
n forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
as) [PolyDiff (t a) (t a)]
xs
mapDiff :: (a -> b) -> [D.Diff a] -> [D.Diff b]
mapDiff :: forall a b. (a -> b) -> [Diff a] -> [Diff b]
mapDiff a -> b
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a -> b) -> a -> b
$ \case
D.Both a
a a
b -> forall a b. a -> b -> PolyDiff a b
D.Both (a -> b
f a
a) (a -> b
f a
b)
D.First a
a -> forall a b. a -> PolyDiff a b
D.First (a -> b
f a
a)
D.Second a
b -> forall a b. b -> PolyDiff a b
D.Second (a -> b
f a
b)
third :: (Int, Int, Text) -> Text
third :: (Int, Int, Text) -> Text
third (Int
_, Int
_, Text
x) = Text
x
isSelectedLine :: IntSet -> Hunk -> Bool
isSelectedLine :: IntSet -> Hunk -> Bool
isSelectedLine IntSet
selected Hunk {Int
DiffList
hunkDiff :: DiffList
hunkSecondLength :: Int
hunkSecondStartLine :: Int
hunkFirstLength :: Int
hunkFirstStartLine :: Int
hunkDiff :: Hunk -> DiffList
hunkSecondLength :: Hunk -> Int
hunkSecondStartLine :: Hunk -> Int
hunkFirstLength :: Hunk -> Int
hunkFirstStartLine :: Hunk -> Int
..} =
IntSet -> Bool
IntSet.null IntSet
selected
Bool -> Bool -> Bool
|| Bool -> Bool
not (IntSet -> IntSet -> Bool
IntSet.disjoint IntSet
selected IntSet
hunkOriginalLines)
where
hunkOriginalLines :: IntSet
hunkOriginalLines =
[Int] -> IntSet
IntSet.fromAscList (forall a. Int -> [a] -> [a]
take Int
hunkFirstLength [Int
hunkFirstStartLine ..])