- Move common static methods out of IDF_Diff and into IDF_FileUtil.
- Make stuff that should be private in IDF_Diff really private and comment out a test that was the only call path for a previously public method. - Apply the whitespace emphasizing on the normal file view as well and get finally rid of padLine()
This commit is contained in:
		| @@ -35,29 +35,7 @@ class IDF_Diff | ||||
|     public function __construct($diff, $path_strip_level = 0) | ||||
|     { | ||||
|         $this->path_strip_level = $path_strip_level; | ||||
|         $this->lines = self::splitIntoLines($diff); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Splits a diff into separate lines while retaining the individual | ||||
|      * line ending character for every line | ||||
|      */ | ||||
|     private static function splitIntoLines($diff) | ||||
|     { | ||||
|         // this works because in unified diff format even empty lines are | ||||
|         // either prefixed with a '+', '-' or ' ' | ||||
|         $splitted = preg_split("/\r\n|\n/", $diff, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); | ||||
|  | ||||
|         $last_off = -1; | ||||
|         $lines = array(); | ||||
|         while (($split = array_shift($splitted)) !== null) { | ||||
|             if ($last_off != -1) { | ||||
|                 $lines[] .= substr($diff, $last_off, $split[1] - $last_off); | ||||
|             } | ||||
|             $last_off = $split[1]; | ||||
|         } | ||||
|         $lines[] = substr($diff, $last_off); | ||||
|         return $lines; | ||||
|         $this->lines = IDF_FileUtil::splitIntoLines($diff, true); | ||||
|     } | ||||
|  | ||||
|     public function parse() | ||||
| @@ -192,7 +170,7 @@ class IDF_Diff | ||||
|  | ||||
|                     $offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right); | ||||
|                     $content = Pluf_esc($content); | ||||
|                     $content = self::makeNonPrintableCharsVisible($content); | ||||
|                     $content = IDF_FileUtil::emphasizeControlCharacters($content); | ||||
|                     $contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content); | ||||
|                 } | ||||
|                 if (count($file['chunks']) > $cc) { | ||||
| @@ -245,33 +223,6 @@ class IDF_Diff | ||||
|         return Pluf_Template::markSafe($out); | ||||
|     } | ||||
|  | ||||
|     private static function makeNonPrintableCharsVisible($line) | ||||
|     { | ||||
|         // This translates most of the C0 ASCII control characters into | ||||
|         // their visual counterparts in the 0x24## unicode plane | ||||
|         // (http://en.wikipedia.org/wiki/C0_and_C1_control_codes). | ||||
|         // We could add DEL (0x7F) to this set, but unfortunately this | ||||
|         // is not nicely mapped to 0x247F in the control plane, but 0x2421 | ||||
|         // and adding an if expression below just for this is a little bit | ||||
|         // of a hassle. And of course, the more esoteric ones from C1 are | ||||
|         // missing as well... | ||||
|         return preg_replace('/([\x00-\x1F])/ue', | ||||
|                             '"<span class=\"non-printable\" title=\"0x".bin2hex("\\1")."\">$".bin2hex("\\1")."</span>"', | ||||
|                             $line); | ||||
|     } | ||||
|  | ||||
|     public static function padLine($line) | ||||
|     { | ||||
|         $line = str_replace("\t", '    ', $line); | ||||
|         $n = strlen($line); | ||||
|         for ($i=0;$i<$n;$i++) { | ||||
|             if (substr($line, $i, 1) != ' ') { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         return str_repeat(' ', $i).substr($line, $i); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Review patch. | ||||
|      * | ||||
| @@ -299,7 +250,7 @@ class IDF_Diff | ||||
|         return $this->renderCompared($new_chunks, $filename); | ||||
|     } | ||||
|  | ||||
|     public function mergeChunks($orig_lines, $chunks, $context=10) | ||||
|     private function mergeChunks($orig_lines, $chunks, $context=10) | ||||
|     { | ||||
|         $spans = array(); | ||||
|         $new_chunks = array(); | ||||
| @@ -396,7 +347,7 @@ class IDF_Diff | ||||
|         return $nnew_chunks; | ||||
|     } | ||||
|  | ||||
|     public function renderCompared($chunks, $filename) | ||||
|     private function renderCompared($chunks, $filename) | ||||
|     { | ||||
|         $fileinfo = IDF_FileUtil::getMimeType($filename); | ||||
|         $pretty = ''; | ||||
|   | ||||
| @@ -65,9 +65,9 @@ class IDF_FileUtil | ||||
|         } | ||||
|         $table = array(); | ||||
|         $i = 1; | ||||
|         foreach (preg_split("/\015\012|\015|\012/", $content) as $line) { | ||||
|         foreach (self::splitIntoLines($content) as $line) { | ||||
|             $table[] = '<tr class="c-line"><td class="code-lc" id="L'.$i.'"><a href="#L'.$i.'">'.$i.'</a></td>' | ||||
|                 .'<td class="code mono'.$pretty.'">'.IDF_Diff::padLine(Pluf_esc($line)).'</td></tr>'; | ||||
|                 .'<td class="code mono'.$pretty.'">'.self::emphasizeControlCharacters(Pluf_esc($line)).'</td></tr>'; | ||||
|             $i++; | ||||
|         } | ||||
|         return Pluf_Template::markSafe(implode("\n", $table)); | ||||
| @@ -143,6 +143,56 @@ class IDF_FileUtil | ||||
|         return $res; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Splits a string into separate lines while retaining the individual | ||||
|      * line ending character for every line. | ||||
|      * | ||||
|      * OS9 line endings are not supported. | ||||
|      * | ||||
|      * @param string content | ||||
|      * @param boolean if true, skip completely empty lines | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function splitIntoLines($content, $skipEmpty = false) | ||||
|     { | ||||
|         $flags = PREG_SPLIT_OFFSET_CAPTURE; | ||||
|         if ($skipEmpty) $flags |= PREG_SPLIT_NO_EMPTY; | ||||
|         $splitted = preg_split("/\r\n|\n/", $content, -1, $flags); | ||||
|  | ||||
|         $last_off = -1; | ||||
|         $lines = array(); | ||||
|         while (($split = array_shift($splitted)) !== null) { | ||||
|             if ($last_off != -1) { | ||||
|                 $lines[] .= substr($content, $last_off, $split[1] - $last_off); | ||||
|             } | ||||
|             $last_off = $split[1]; | ||||
|         } | ||||
|         $lines[] = substr($content, $last_off); | ||||
|         return $lines; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This translates most of the C0 ASCII control characters into | ||||
|      * their visual counterparts in the 0x24## unicode plane | ||||
|      * (http://en.wikipedia.org/wiki/C0_and_C1_control_codes). | ||||
|      * | ||||
|      * We could add DEL (0x7F) to this set, but unfortunately this | ||||
|      * is not nicely mapped to 0x247F in the control plane, but 0x2421 | ||||
|      * and adding an if expression below just for this is a little bit | ||||
|      * of a hassle. And of course, the more esoteric ones from C1 are | ||||
|      * missing as well... | ||||
|      * | ||||
|      * @param string $content | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function emphasizeControlCharacters($content) | ||||
|     { | ||||
|         return preg_replace( | ||||
|             '/([\x00-\x1F])/ue', | ||||
|             '"<span class=\"ctrl-char\" title=\"0x".bin2hex("\\1")."\">$".bin2hex("\\1")."</span>"', | ||||
|             $content); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find if a given mime type is a text file. | ||||
|      * This uses the output of the self::getMimeType function. | ||||
|   | ||||
| @@ -32,21 +32,24 @@ class IDF_Tests_TestDiff extends UnitTestCase | ||||
|         parent::__construct('Test the diff parser.'); | ||||
|     } | ||||
|  | ||||
|     public function testBinaryDiff() | ||||
|     { | ||||
|         $diff_content = file_get_contents(dirname(__FILE__).'/test-diff.diff'); | ||||
|         $orig = file_get_contents(dirname(__FILE__).'/test-diff-view.html'); | ||||
|         $diff = new IDF_Diff($diff_content); | ||||
|         $diff->parse(); | ||||
|         $def = $diff->files['src/IDF/templates/idf/issues/view.html']; | ||||
|  | ||||
|         $orig_lines = preg_split("/\015\012|\015|\012/", $orig); | ||||
|         $merged = $diff->mergeChunks($orig_lines, $def, 10); | ||||
|         $lchunk = end($merged); | ||||
|         $lline = end($lchunk); | ||||
|         $this->assertEqual(array('', '166', '{/if}{/block}'), | ||||
|                            $lline); | ||||
|     } | ||||
|     // | ||||
|     // IDF_Diff::mergeChunks() is now private, so this test needs to be rewritten | ||||
|     // | ||||
|     //public function testBinaryDiff() | ||||
|     //{ | ||||
|     //    $diff_content = file_get_contents(dirname(__FILE__).'/test-diff.diff'); | ||||
|     //    $orig = file_get_contents(dirname(__FILE__).'/test-diff-view.html'); | ||||
|     //    $diff = new IDF_Diff($diff_content); | ||||
|     //    $diff->parse(); | ||||
|     //    $def = $diff->files['src/IDF/templates/idf/issues/view.html']; | ||||
|     // | ||||
|     //    $orig_lines = preg_split("/\015\012|\015|\012/", $orig); | ||||
|     //    $merged = $diff->mergeChunks($orig_lines, $def, 10); | ||||
|     //    $lchunk = end($merged); | ||||
|     //    $lline = end($lchunk); | ||||
|     //    $this->assertEqual(array('', '166', '{/if}{/block}'), | ||||
|     //                       $lline); | ||||
|     //} | ||||
|  | ||||
|     public function testDiffWithHeaders() | ||||
|     { | ||||
|   | ||||
| @@ -571,6 +571,19 @@ table.commit table.changes table.properties td.removed { | ||||
| /** | ||||
|  * syntax highlighting of diffs | ||||
|  */ | ||||
| span.ctrl-char { | ||||
|   color: white; | ||||
|   background: black; | ||||
|   text-align: center; | ||||
|   display: inline-block; | ||||
|   padding: 1px 1px 0px 1px; | ||||
|   margin-left: 1px; | ||||
|   margin-right: 1px; | ||||
|   -moz-border-radius: 2px; | ||||
|   -webkit-border-radius: 2px; | ||||
|   cursor: default; | ||||
| } | ||||
|  | ||||
| table.diff { | ||||
|   width: 100%; | ||||
|   table-layout: fixed; | ||||
| @@ -658,40 +671,24 @@ table.diff-contents td.removed { | ||||
|   background-color: #fdd; | ||||
| } | ||||
|  | ||||
| table.diff-contents td > span.non-printable { | ||||
| table.diff-contents td > span.ctrl-char { | ||||
|   visibility: hidden; | ||||
|   color: white; | ||||
|   text-transform: uppercase; | ||||
|   float: none; | ||||
|   text-align: center; | ||||
|   display: inline-block; | ||||
|   padding: 1px 1px 0px 1px; | ||||
|   margin-left: 1px; | ||||
|   margin-right: 1px; | ||||
|   -moz-border-radius: 2px; | ||||
|   -webkit-border-radius: 2px; | ||||
|   cursor: default; | ||||
|   vertical-align: 10%; | ||||
| } | ||||
|  | ||||
| table.diff-contents td:hover > span.non-printable { | ||||
| table.diff-contents td:hover > span.ctrl-char { | ||||
|   visibility: visible; | ||||
| } | ||||
|  | ||||
| table.diff-contents td.added > span.non-printable { | ||||
| table.diff-contents td.added > span.ctrl-char { | ||||
|   background: #0A0;    | ||||
| } | ||||
|  | ||||
| table.diff-contents td.removed > span.non-printable { | ||||
| table.diff-contents td.removed > span.ctrl-char { | ||||
|   background: #A00; | ||||
| } | ||||
|  | ||||
| table.diff-contents td.context > span.non-printable { | ||||
|   background: black; | ||||
| } | ||||
|  | ||||
| /* override prettify css rule */ | ||||
| table.diff-contents td > span.non-printable > * { | ||||
| table.diff-contents td > span.ctrl-char > * { | ||||
|   color: white; | ||||
| } | ||||
|  | ||||
| @@ -737,6 +734,14 @@ table.code td.code { | ||||
|   padding-left: 5px; | ||||
| } | ||||
|  | ||||
| table.code td.code span.ctrl-char { | ||||
|   visibility: hidden; | ||||
| } | ||||
|  | ||||
| table.code td.code:hover span.ctrl-char { | ||||
|   visibility: visible; | ||||
| } | ||||
|  | ||||
| table.code td.code-lc { | ||||
|   text-align: right; | ||||
|   padding: 1px 5px; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user