xdiff : side by side support with screen width parameter

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@5062 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2019-03-01 13:30:20 +00:00
parent 38b8b4f5a6
commit ae306d19ba
2 changed files with 158 additions and 1 deletions

View File

@@ -8,7 +8,6 @@
class test_xdiff extends PHPUnit_Framework_TestCase
{
// Declaration of $string1 and $string2
// Taken from
// {{{
private $string1 = "This part of the
document has stayed the
@@ -336,4 +335,48 @@ to this document.
$this->setExpectedException ();
$res = $xdiff->diffFile ("/tmp/test_xdiff1", "/tmp/test_xdiffNOTEXISTS");
}
public function test_diffFile_sideBySide_1 ()
{
file_put_contents ("/tmp/test_xdiff1", $this->string1);
file_put_contents ("/tmp/test_xdiff2", $this->string2);
$xdiff = new xdiff ("sideBySide");
$res = $xdiff->diffFile ("/tmp/test_xdiff1", "/tmp/test_xdiff2");
$this->assertSame ($res,
" > This is an important
> notice! It should
> therefore be located at
> the beginning of this
> document!
>
This part of the This part of the
document has stayed the document has stayed the
same from version to same from version to
version. It shouldn't version. It shouldn't
be shown if it doesn't be shown if it doesn't
change. Otherwise, that change. Otherwise, that
would not be helping to would not be helping to
compress the size of the compress the size of the
changes. changes.
This paragraph contains <
text that is outdated. <
It will be deleted in the <
near future. <
<
It is important to spell It is important to spell
check this dokument. On | check this document. On
the other hand, a the other hand, a
misspelled word isn't misspelled word isn't
the end of the world. the end of the world.
Nothing in the rest of Nothing in the rest of
this paragraph needs to this paragraph needs to
be changed. Things can be changed. Things can
be added after it. be added after it.
>
> This paragraph contains
> important new additions
> to this document.
");
}
}

114
xdiff.php
View File

@@ -29,6 +29,14 @@ class xdiff
*/
private $output = null;
/** Define the size of one column in side by side mode
* 62 chars by default
* The maximum width used on screen is 2*$s2sWidth+2 (134 by default)
* The value must validate $s2sWidth = 8 * X - 2 (with X is integer), like
* 6, 14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102
*/
private $s2sWidth = 62;
/** The constructor allow to choose the output.
* @param string $output The output mode [normal|unified]
*/
@@ -43,6 +51,24 @@ class xdiff
}
// }}}
/** Allow to set the side by side width to the maximum allowed by screenWidth
* @param integer $screenWidth The maximum width of the screen
*/
public function setScreenWidth ($screenWidth)
// {{{
{
for ($x = 20 ; $x > 0 ; $x--)
{
$s2sWidth = 8 * $x - 2;
if (2*$s2sWidth+2 <= $screenWidth)
{
$this->s2sWidth = $s2sWidth;
break;
}
}
}
// }}}
/** Compute the differences between two strings $string1 and $string2
* @param string $string1 The first string to compare
* @param string $string2 The second string to compare
@@ -356,6 +382,94 @@ class xdiff
}
// }}}
/** Return a string like "diff -y" (Side by Side)
* @param array $diffArray The diff array analyzed by diffArray method
* @return string
*/
private function displaySideBySide ($diffArray)
// {{{
{
$d = "";
$i = 0 ;
while ($i < count ($diffArray))
{
$diff = $diffArray[$i];
$i++;
if ($diff["type"] === "Equal")
{
foreach ($diff["chunk"] as $line)
$d .= $this->side ($line, $line);
}
elseif ($diff["type"] === "Append")
{
foreach ($diff["chunk"] as $line)
$d .= $this->side ("", $line, ">");
}
elseif ($diff["type"] === "Delete")
{
foreach ($diff["chunk"] as $line)
$d .= $this->side ($line, "", "<");
}
elseif ($diff["type"] === "Change")
{
$x = 0;
$y = 0;
while (key_exists ($x, $diff["chunk1"]) ||
key_exists ($y, $diff["chunk2"]))
{
$side1 = (key_exists ($x, $diff["chunk1"])) ?
$diff["chunk1"][$x] : "";
$side2 = (key_exists ($y, $diff["chunk2"])) ?
$diff["chunk2"][$y] : "";
$d .= $this->side ($side1, $side2, "|");
if ($side1 !== "")
$x++;
if ($side2 !== "")
$y++;
}
}
}
return $d;
}
// }}}
/** Return a string sideBySide. Used by displaySideBySide for each line
* @param string $side1 The string to be displayed on side1
* @param string $side2 The string to be displayed on side2
* @param string|null $symbol The symbol used to present the diff (<>|)
*/
private function side ($side1, $side2, $symbol = null)
// {{{
{
$d = "";
if (! is_string ($side1))
throw new \Exception ("XDiff : side1 parameter not a string");
if (! is_string ($side2))
throw new \Exception ("XDiff : side2 parameter not a string");
if (trim ($symbol) === "")
$symbol = null;
$side1 = mb_substr (rtrim ($side1), 0, $this->s2sWidth - 1);
$side2 = mb_substr (rtrim ($side2), 0, $this->s2sWidth - 1);
$d .= $side1;
$nbtabs = floor ((1 + $this->s2sWidth - mb_strlen ($side1)) / 8);
if ($symbol !== null || $side2 !== "")
$d .= str_repeat ("\t", $nbtabs);
if ($side1 !== "" && $symbol === null)
$d .= "\t";
elseif ($symbol !== null)
{
if (mb_strlen ($side1) < $this->s2sWidth - 1)
$d .= str_repeat (" ", 5);
$d .= " ".$symbol;
}
if ($symbol !== null && $side2 !== "")
$d .= "\t";
$d .= $side2;
$d .= "\n";
return $d;
}
// }}}
/** This function return the next common part between both arrays starting at
* position $i for $array1 and $j for array2
* Return empty string if no common lines was found