Nothing
# <http://www.gnu.org/software/diffutils/manual/diffutils.html#Detailed-Normal>
#
# * `lar`: Add the lines in range `r` of the second file
# after line `l` of the first file.
# * `fct`: Replace the lines in range `f` of the first file
# with lines in range `t` of the second file.
# * `rdl`: Delete the lines in range `r` from the first file; line `l` is
# where they would have appeared in the second file had they not been deleted.
ses <- function(x, y) {
attributes(x) <- NULL
attributes(y) <- NULL
if (is.character(x)) {
x <- enc2utf8(x)
y <- enc2utf8(y)
}
out <- diffobj::ses(x, y, warn = FALSE, max.diffs = 100)
out <- re_match(out, paste0(
"(?:(?<x1>\\d+),)?(?<x2>\\d+)",
"(?<t>[acd])",
"(?:(?<y1>\\d+),)?(?<y2>\\d+)"
))[1:5]
out$x1 <- ifelse(out$x1 == "", out$x2, out$x1)
out$y1 <- ifelse(out$y1 == "", out$y2, out$y1)
out$x1 <- as.integer(out$x1)
out$x2 <- as.integer(out$x2)
out$y1 <- as.integer(out$y1)
out$y2 <- as.integer(out$y2)
out
}
ses_elementwise <- function(x, y) {
n_x <- length(x)
n_y <- length(y)
n <- min(n_x, n_y)
id <- seq_len(n)
same <- (is.na(x[id]) & is.na(y[id])) | x[id] == y[id]
same[is.na(same)] <- FALSE
neq <- id[!same]
if (length(neq) == 0) {
n_x <- length(x)
n_y <- length(y)
if (length(x) > length(y)) {
return(ses_df(n_y + 1, n_x, "d", n_y, n_y))
} else if (length(x) < length(y)) {
return(ses_df(n_x, n_x, "a", n_x + 1, n_y))
} else {
return(ses_df(integer(), integer(), character(), integer(), integer()))
}
}
new_group <- c(TRUE, neq[-1] - 1 != neq[-length(neq)])
group_id <- cumsum(new_group)
diffs <- unname(split(neq, group_id))
x1 <- y1 <- vapply(diffs, function(x) x[[1]], integer(1))
x2 <- y2 <- vapply(diffs, function(x) x[[length(x)]], integer(1))
t <- rep("c", length(diffs))
if (length(y) > length(x)) {
y2[[length(diffs)]] <- n_y
} else if (length(x) > length(y)) {
x2[[length(diffs)]] <- n_x
}
ses_df(x1, x2, t, y1, y2)
}
ses_shortest <- function(x, y, size = 3) {
ses1 <- ses(x, y)
if (nrow(ses1) == 0) {
return(list())
}
ses2 <- ses_elementwise(x, y)
context1 <- ses_chunks(ses1, length(x), length(y), size = size)
context2 <- ses_chunks(ses2, length(x), length(y), size = size)
diff_length <- function(ses) ses$x2[nrow(ses)] - ses$x1[[1]] + 1
diff1 <- sum(vapply(context1, diff_length, double(1)), na.rm = TRUE)
diff2 <- sum(vapply(context2, diff_length, double(1)))
if (diff1 == diff2) {
# If contextual diffs are same length, break tie using total
# number of changes
if (diff_length(ses1) < diff_length(ses2)) {
context1
} else {
context2
}
} else if (diff1 < diff2) {
context1
} else {
context2
}
}
ses_chunks <- function(diff, n_x, n_y, size = 3) {
# Compute context around each individual diff
diff$x_start <- pmax(diff$x1 - size, 1)
diff$x_end <- pmin(diff$x2 + size, n_x)
diff$y_start <- pmax(diff$y1 - size, 1)
diff$y_end <- pmin(diff$y2 + size, n_y)
# Split up into non-contiguous chunks
new_group <- c(TRUE, diff$x_start[-1] > diff$x_end[-nrow(diff)])
group_id <- cumsum(new_group)
diffs <- unname(split(diff, group_id))
# Fill in rows that are the same in x and y
lapply(diffs, diff_complete)
}
diff_complete <- function(diff) {
n <- nrow(diff)
diff$pos <- 1:n
ctxt <- data.frame(
pos = 1:(n + 1) - 0.5,
x1 = c(diff$x_start[[1]], diff$x2 + 1),
x2 = c(diff$x1 - 1, diff$x_end[[n]]),
t = "x",
y1 = c(diff$y_start[[1]], diff$y2 + 1),
y2 = c(diff$y1 - 1, diff$y_end[[n]])
)
out <- rbind(diff[names(ctxt)], ctxt)
# Interleave in correct order
out <- out[order(out$pos), , drop = FALSE]
out$pos <- NULL
# Drop rows with no data
needed <- (out$x2 - out$x1) >= 0 | (out$y2 - out$y1) >= 0
out[needed, , drop = FALSE]
}
ses_df <- function(x1, x2, t, y1, y2) {
data.frame(x1 = x1, x2 = x2, t = t, y1 = y1, y2 = y2)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.