@@ -1416,14 +1416,94 @@ test diffCharsToLines {
14161416 try tmp_vector .append ("beta\n " );
14171417 try diffCharsToLines (arena .allocator (), diffs .items , tmp_vector .items );
14181418
1419- try std .testing .expectEqualDeep ([_ ]Diff {
1419+ try std .testing .expectEqualDeep (@as ([] const Diff , & [_ ]Diff {
14201420 Diff { .operation = .equal , .text = "alpha\n beta\n alpha\n " },
14211421 Diff { .operation = .insert , .text = "beta\n alpha\n beta\n " },
1422- }, diffs .items [0 .. 2] .* );
1422+ }) , diffs .items );
14231423
14241424 // TODO: Implement exhaustive tests
14251425}
14261426
1427+ test diffCleanupMerge {
1428+ var arena = std .heap .ArenaAllocator .init (testing .allocator );
1429+ defer arena .deinit ();
1430+
1431+ // Cleanup a messy diff.
1432+ var diffs = std .ArrayListUnmanaged (Diff ){};
1433+ try std .testing .expectEqualDeep (@as ([]const Diff , &[0 ]Diff {}), diffs .items ); // Null case
1434+
1435+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff { .{ .operation = .equal , .text = "a" }, .{ .operation = .delete , .text = "b" }, .{ .operation = .insert , .text = "c" } });
1436+ try diffCleanupMerge (arena .allocator (), & diffs );
1437+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff { .{ .operation = .equal , .text = "a" }, .{ .operation = .delete , .text = "b" }, .{ .operation = .insert , .text = "c" } }), diffs .items ); // No change case
1438+
1439+ diffs .items .len = 0 ;
1440+
1441+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff { .{ .operation = .equal , .text = "a" }, .{ .operation = .equal , .text = "b" }, .{ .operation = .equal , .text = "c" } });
1442+ try diffCleanupMerge (arena .allocator (), & diffs );
1443+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff {.{ .operation = .equal , .text = "abc" }}), diffs .items ); // Merge equalities
1444+
1445+ diffs .items .len = 0 ;
1446+
1447+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff { .{ .operation = .delete , .text = "a" }, .{ .operation = .delete , .text = "b" }, .{ .operation = .delete , .text = "c" } });
1448+ try diffCleanupMerge (arena .allocator (), & diffs );
1449+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff {.{ .operation = .delete , .text = "abc" }}), diffs .items ); // Merge deletions
1450+
1451+ diffs .items .len = 0 ;
1452+
1453+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff { .{ .operation = .insert , .text = "a" }, .{ .operation = .insert , .text = "b" }, .{ .operation = .insert , .text = "c" } });
1454+ try diffCleanupMerge (arena .allocator (), & diffs );
1455+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff {.{ .operation = .insert , .text = "abc" }}), diffs .items ); // Merge insertions
1456+
1457+ diffs .items .len = 0 ;
1458+
1459+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff {
1460+ .{ .operation = .delete , .text = "a" },
1461+ .{ .operation = .insert , .text = "b" },
1462+ .{ .operation = .delete , .text = "c" },
1463+ .{ .operation = .insert , .text = "d" },
1464+ .{ .operation = .equal , .text = "e" },
1465+ .{ .operation = .equal , .text = "f" },
1466+ });
1467+ try diffCleanupMerge (arena .allocator (), & diffs );
1468+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff {
1469+ .{ .operation = .delete , .text = "ac" },
1470+ .{ .operation = .insert , .text = "bd" },
1471+ .{ .operation = .equal , .text = "ef" },
1472+ }), diffs .items ); // Merge interweave
1473+
1474+ diffs .items .len = 0 ;
1475+
1476+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff {
1477+ .{ .operation = .delete , .text = "a" },
1478+ .{ .operation = .insert , .text = "abc" },
1479+ .{ .operation = .delete , .text = "dc" },
1480+ });
1481+ try diffCleanupMerge (arena .allocator (), & diffs );
1482+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff {
1483+ .{ .operation = .equal , .text = "a" },
1484+ .{ .operation = .delete , .text = "d" },
1485+ .{ .operation = .insert , .text = "b" },
1486+ .{ .operation = .equal , .text = "c" },
1487+ }), diffs .items ); // Prefix and suffix detection
1488+
1489+ diffs .items .len = 0 ;
1490+
1491+ try diffs .appendSlice (arena .allocator (), &[_ ]Diff {
1492+ .{ .operation = .equal , .text = "x" },
1493+ .{ .operation = .delete , .text = "a" },
1494+ .{ .operation = .insert , .text = "abc" },
1495+ .{ .operation = .delete , .text = "dc" },
1496+ .{ .operation = .equal , .text = "y" },
1497+ });
1498+ try diffCleanupMerge (arena .allocator (), & diffs );
1499+ try std .testing .expectEqualDeep (@as ([]const Diff , &[_ ]Diff {
1500+ .{ .operation = .equal , .text = "xa" },
1501+ .{ .operation = .delete , .text = "d" },
1502+ .{ .operation = .insert , .text = "b" },
1503+ .{ .operation = .equal , .text = "cy" },
1504+ }), diffs .items ); // Prefix and suffix detection with equalities
1505+ }
1506+
14271507fn rebuildtexts (allocator : std.mem.Allocator , diffs : std .ArrayListUnmanaged (Diff )) ! [2 ][]const u8 {
14281508 var text = [2 ]std .ArrayList (u8 ){
14291509 std .ArrayList (u8 ).init (allocator ),
0 commit comments