better
This commit is contained in:
parent
64b5ca7ea7
commit
b58b58ec61
88
src/Diff.hs
88
src/Diff.hs
|
@ -21,10 +21,11 @@ import qualified Data.Vector as V
|
|||
import qualified Data.Vector.Unboxed.Mutable as M
|
||||
|
||||
type Tok = (Bool, (Int, Int))
|
||||
|
||||
type Diff= [(Op,Tok)]
|
||||
type Hunk = ((Int, Int), [(Op, Tok)])
|
||||
|
||||
type BS = B.ByteString
|
||||
type TV = V.Vector Tok
|
||||
|
||||
data Op
|
||||
= Remove
|
||||
|
@ -36,8 +37,8 @@ data DiffEnv =
|
|||
DiffEnv
|
||||
{ deD1 :: BS
|
||||
, deD2 :: BS
|
||||
, deT1 :: V.Vector Tok
|
||||
, deT2 :: V.Vector Tok
|
||||
, deT1 :: TV
|
||||
, deT2 :: TV
|
||||
, deS :: Int
|
||||
, deE :: Int
|
||||
, deL :: Int
|
||||
|
@ -53,31 +54,43 @@ data DiffEnv =
|
|||
substr b e = B.take (e - b) . B.drop b
|
||||
|
||||
toksMatch x y DiffEnv {deT1 = t1, deT2 = t2, deD1 = d1, deD2 = d2} =
|
||||
toksMatch' x y d1 d2 t1 t2
|
||||
|
||||
toksMatch' x y d1 d2 t1 t2 =
|
||||
let (isTok1, (b1, e1)) = t1 V.! x
|
||||
(isTok2, (b2, e2)) = t2 V.! y
|
||||
in isTok1 == isTok2 && substr b1 e1 d1 == substr b2 e2 d2
|
||||
|
||||
stripEqToks :: DiffEnv -> (Int, Int, Int)
|
||||
stripEqToks de@DiffEnv {deT1 = t1, deT2 = t2} = (b, l1 - e, l2 - e)
|
||||
stripEqToks :: BS -> BS -> TV -> TV -> (Diff, Diff, TV, TV)
|
||||
stripEqToks d1 d2 t1 t2 = (pre, post, t1', t2')
|
||||
where
|
||||
l1 = V.length t1
|
||||
l2 = V.length t2
|
||||
firstDiff i
|
||||
| i < l1 && i < l2 && toksMatch i i de = firstDiff (i + 1)
|
||||
| i < l1 && i < l2 && toksMatch' i i d1 d2 t1 t2 = firstDiff (i + 1)
|
||||
| otherwise = i
|
||||
b = firstDiff 0
|
||||
lastDiff i
|
||||
| l1 - i - 1 >= b &&
|
||||
l2 - i - 1 >= b && toksMatch (l1 - i - 1) (l2 - i - 1) de =
|
||||
l2 - i - 1 >= b && toksMatch' (l1 - i - 1) (l2 - i - 1) d1 d2 t1 t2 =
|
||||
lastDiff (i + 1)
|
||||
| otherwise = i
|
||||
e = lastDiff 0
|
||||
pre = map (\t -> (Keep,t)) . V.toList . V.take b $ t1
|
||||
post = map (\t -> (Keep,t)) . V.toList . V.drop (l1-e) $ t1
|
||||
t1' = V.slice b (l1-e-b) t1
|
||||
t2' = V.slice b (l2-e-b) t2
|
||||
|
||||
diffToks :: BS -> BS -> V.Vector Tok -> V.Vector Tok -> [(Op, Tok)]
|
||||
diffToks d1 d2 t1 t2 =
|
||||
diffToks :: BS -> BS -> TV -> TV -> Diff
|
||||
diffToks d1 d2 t1' t2' = pre ++ res ++ post
|
||||
where
|
||||
(pre, post, t1, t2) = stripEqToks d1 d2 t1' t2'
|
||||
res
|
||||
| V.null t1 = map (\t -> (Add,t)) (V.toList t2)
|
||||
| V.null t2 = map (\t -> (Remove,t)) (V.toList t1)
|
||||
| V.length t1 >= V.length t2 =
|
||||
diffToks' $
|
||||
if V.length t1 >= V.length t2
|
||||
then DiffEnv
|
||||
DiffEnv
|
||||
{ deD1 = d1
|
||||
, deD2 = d2
|
||||
, deT1 = t1
|
||||
|
@ -92,7 +105,9 @@ diffToks d1 d2 t1 t2 =
|
|||
, deVE = V.fromList $ reverse [0 .. V.length t2]
|
||||
, deTrans = False
|
||||
}
|
||||
else DiffEnv
|
||||
| otherwise =
|
||||
diffToks' $
|
||||
DiffEnv
|
||||
{ deD1 = d2
|
||||
, deD2 = d1
|
||||
, deT1 = t2
|
||||
|
@ -124,7 +139,7 @@ minIndexRev =
|
|||
else GT --picks the last minimum
|
||||
)
|
||||
|
||||
diffToks' :: DiffEnv -> [(Op, Tok)]
|
||||
diffToks' :: DiffEnv -> Diff
|
||||
diffToks' de@DiffEnv {deS = s, deE = e, deA = a, deB = b, deTrans = trans} =
|
||||
diff
|
||||
where
|
||||
|
@ -263,50 +278,7 @@ diffToks' de@DiffEnv {deS = s, deE = e, deA = a, deB = b, deTrans = trans} =
|
|||
diffToks' de {deE = mid, deVE = vecEmid, deB = opt} ++
|
||||
diffToks' de {deS = mid, deVS = vecSmid, deA = opt}
|
||||
|
||||
{-
|
||||
diffToksXX :: BS -> BS -> V.Vector Tok -> V.Vector Tok -> IO [(Op, Tok)]
|
||||
diffToksXX d1 d2 t1 t2 = do
|
||||
let (b, e1, e2) = stripEqToks d1 d2 t1 t2
|
||||
ms1 = e1 - b
|
||||
ms2 = e2 - b
|
||||
mtx <- M.new ((ms1 + 1) * (ms2 + 1))
|
||||
let idx x y = (ms2 + 1) * x + y
|
||||
forM_ [0 .. ms1] $ \i -> M.write mtx (idx i 0) i
|
||||
forM_ [0 .. ms2] $ \i -> M.write mtx (idx 0 i) i
|
||||
let toksMatch' x y = toksMatch d1 d2 t1 t2 (b + x) (b + y)
|
||||
forM_ [1 .. ms1] $ \i ->
|
||||
forM [1 .. ms2] $ \j -> do
|
||||
up <- M.read mtx (idx i (j - 1))
|
||||
left <- M.read mtx (idx (i - 1) j)
|
||||
upleft <- M.read mtx (idx (i - 1) (j - 1))
|
||||
M.write mtx (idx i j) $
|
||||
minimum $
|
||||
[up + 1, left + 1] ++
|
||||
(if toksMatch' (i - 1) (j - 1)
|
||||
then [upleft]
|
||||
else [])
|
||||
let doAdd i j = (:) (Add, t2 V.! (b + j - 1)) <$> backtrack i (j - 1)
|
||||
doRem i j = (:) (Remove, t1 V.! (b + i - 1)) <$> backtrack (i - 1) j
|
||||
doKeep i j = (:) (Keep, t1 V.! (b + i - 1)) <$> backtrack (i - 1) (j - 1)
|
||||
backtrack :: Int -> Int -> IO [(Op, Tok)]
|
||||
backtrack 0 0 = pure []
|
||||
backtrack i 0 = doRem i 0
|
||||
backtrack 0 j = doAdd 0 j
|
||||
backtrack i j = do
|
||||
add <- M.read mtx (idx i (j - 1))
|
||||
rem <- M.read mtx (idx (i - 1) j)
|
||||
keep <- M.read mtx (idx (i - 1) (j - 1))
|
||||
if toksMatch' (i - 1) (j - 1) && keep <= min add rem
|
||||
then doKeep i j
|
||||
else if add <= rem
|
||||
then doAdd i j
|
||||
else doRem i j
|
||||
diff <- reverse <$> backtrack ms1 ms2
|
||||
return $
|
||||
map ((,) Keep) (take b $ V.toList t1) ++
|
||||
diff ++ map ((,) Keep) (drop e1 $ V.toList t1)
|
||||
-}
|
||||
pprDiff :: BS -> BS -> [(Op, Tok)] -> [BS]
|
||||
pprDiff :: BS -> BS -> Diff -> [BS]
|
||||
pprDiff d1 d2 = map (pprDiff1 d1 d2)
|
||||
|
||||
pprDiff1 d1 d2 (op, (tok, (i, j))) =
|
||||
|
@ -333,7 +305,7 @@ escNewlines' s
|
|||
| B.head s == BI.c2w '\\' = BB.stringUtf8 "\\\\" <> escNewlines' (B.tail s)
|
||||
| otherwise = BB.word8 (B.head s) <> escNewlines' (B.tail s)
|
||||
|
||||
hunks :: Int -> [(Op, Tok)] -> [Hunk]
|
||||
hunks :: Int -> Diff -> [Hunk]
|
||||
hunks ctxt = go 0 0 0 0 [] . groupBy ((==) `on` fst)
|
||||
where
|
||||
go _ _ bi bj backlog [] =
|
||||
|
|
Loading…
Reference in a new issue