From ae306d19bae88146ea9e8611405addbdef1e0ec4 Mon Sep 17 00:00:00 2001 From: Dominique Fournier Date: Fri, 1 Mar 2019 13:30:20 +0000 Subject: [PATCH] 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 --- Tests/xdiffTest.php | 45 ++++++++++++++++- xdiff.php | 114 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/Tests/xdiffTest.php b/Tests/xdiffTest.php index 77b1ef7..c1efc7f 100644 --- a/Tests/xdiffTest.php +++ b/Tests/xdiffTest.php @@ -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. +"); + } } diff --git a/xdiff.php b/xdiff.php index a72fdb5..8cd3ed8 100644 --- a/xdiff.php +++ b/xdiff.php @@ -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