- 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) |     public function __construct($diff, $path_strip_level = 0) | ||||||
|     { |     { | ||||||
|         $this->path_strip_level = $path_strip_level; |         $this->path_strip_level = $path_strip_level; | ||||||
|         $this->lines = self::splitIntoLines($diff); |         $this->lines = IDF_FileUtil::splitIntoLines($diff, true); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 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; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function parse() |     public function parse() | ||||||
| @@ -192,7 +170,7 @@ class IDF_Diff | |||||||
|  |  | ||||||
|                     $offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right); |                     $offsets[] = sprintf('<td>%s</td><td>%s</td>', $left, $right); | ||||||
|                     $content = Pluf_esc($content); |                     $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); |                     $contents[] = sprintf('<td class="%s%s mono">%s</td>', $class, $pretty, $content); | ||||||
|                 } |                 } | ||||||
|                 if (count($file['chunks']) > $cc) { |                 if (count($file['chunks']) > $cc) { | ||||||
| @@ -245,33 +223,6 @@ class IDF_Diff | |||||||
|         return Pluf_Template::markSafe($out); |         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. |      * Review patch. | ||||||
|      * |      * | ||||||
| @@ -299,7 +250,7 @@ class IDF_Diff | |||||||
|         return $this->renderCompared($new_chunks, $filename); |         return $this->renderCompared($new_chunks, $filename); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function mergeChunks($orig_lines, $chunks, $context=10) |     private function mergeChunks($orig_lines, $chunks, $context=10) | ||||||
|     { |     { | ||||||
|         $spans = array(); |         $spans = array(); | ||||||
|         $new_chunks = array(); |         $new_chunks = array(); | ||||||
| @@ -396,7 +347,7 @@ class IDF_Diff | |||||||
|         return $nnew_chunks; |         return $nnew_chunks; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function renderCompared($chunks, $filename) |     private function renderCompared($chunks, $filename) | ||||||
|     { |     { | ||||||
|         $fileinfo = IDF_FileUtil::getMimeType($filename); |         $fileinfo = IDF_FileUtil::getMimeType($filename); | ||||||
|         $pretty = ''; |         $pretty = ''; | ||||||
|   | |||||||
| @@ -65,9 +65,9 @@ class IDF_FileUtil | |||||||
|         } |         } | ||||||
|         $table = array(); |         $table = array(); | ||||||
|         $i = 1; |         $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>' |             $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++; |             $i++; | ||||||
|         } |         } | ||||||
|         return Pluf_Template::markSafe(implode("\n", $table)); |         return Pluf_Template::markSafe(implode("\n", $table)); | ||||||
| @@ -143,6 +143,56 @@ class IDF_FileUtil | |||||||
|         return $res; |         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. |      * Find if a given mime type is a text file. | ||||||
|      * This uses the output of the self::getMimeType function. |      * 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.'); |         parent::__construct('Test the diff parser.'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function testBinaryDiff() |     // | ||||||
|     { |     // IDF_Diff::mergeChunks() is now private, so this test needs to be rewritten | ||||||
|         $diff_content = file_get_contents(dirname(__FILE__).'/test-diff.diff'); |     // | ||||||
|         $orig = file_get_contents(dirname(__FILE__).'/test-diff-view.html'); |     //public function testBinaryDiff() | ||||||
|         $diff = new IDF_Diff($diff_content); |     //{ | ||||||
|         $diff->parse(); |     //    $diff_content = file_get_contents(dirname(__FILE__).'/test-diff.diff'); | ||||||
|         $def = $diff->files['src/IDF/templates/idf/issues/view.html']; |     //    $orig = file_get_contents(dirname(__FILE__).'/test-diff-view.html'); | ||||||
|  |     //    $diff = new IDF_Diff($diff_content); | ||||||
|         $orig_lines = preg_split("/\015\012|\015|\012/", $orig); |     //    $diff->parse(); | ||||||
|         $merged = $diff->mergeChunks($orig_lines, $def, 10); |     //    $def = $diff->files['src/IDF/templates/idf/issues/view.html']; | ||||||
|         $lchunk = end($merged); |     // | ||||||
|         $lline = end($lchunk); |     //    $orig_lines = preg_split("/\015\012|\015|\012/", $orig); | ||||||
|         $this->assertEqual(array('', '166', '{/if}{/block}'), |     //    $merged = $diff->mergeChunks($orig_lines, $def, 10); | ||||||
|                            $lline); |     //    $lchunk = end($merged); | ||||||
|     } |     //    $lline = end($lchunk); | ||||||
|  |     //    $this->assertEqual(array('', '166', '{/if}{/block}'), | ||||||
|  |     //                       $lline); | ||||||
|  |     //} | ||||||
|  |  | ||||||
|     public function testDiffWithHeaders() |     public function testDiffWithHeaders() | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -571,6 +571,19 @@ table.commit table.changes table.properties td.removed { | |||||||
| /** | /** | ||||||
|  * syntax highlighting of diffs |  * 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 { | table.diff { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   table-layout: fixed; |   table-layout: fixed; | ||||||
| @@ -658,40 +671,24 @@ table.diff-contents td.removed { | |||||||
|   background-color: #fdd; |   background-color: #fdd; | ||||||
| } | } | ||||||
|  |  | ||||||
| table.diff-contents td > span.non-printable { | table.diff-contents td > span.ctrl-char { | ||||||
|   visibility: hidden; |   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; |   visibility: visible; | ||||||
| } | } | ||||||
|  |  | ||||||
| table.diff-contents td.added > span.non-printable { | table.diff-contents td.added > span.ctrl-char { | ||||||
|   background: #0A0;    |   background: #0A0;    | ||||||
| } | } | ||||||
|  |  | ||||||
| table.diff-contents td.removed > span.non-printable { | table.diff-contents td.removed > span.ctrl-char { | ||||||
|   background: #A00; |   background: #A00; | ||||||
| } | } | ||||||
|  |  | ||||||
| table.diff-contents td.context > span.non-printable { |  | ||||||
|   background: black; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* override prettify css rule */ | /* override prettify css rule */ | ||||||
| table.diff-contents td > span.non-printable > * { | table.diff-contents td > span.ctrl-char > * { | ||||||
|   color: white; |   color: white; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -737,6 +734,14 @@ table.code td.code { | |||||||
|   padding-left: 5px; |   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 { | table.code td.code-lc { | ||||||
|   text-align: right; |   text-align: right; | ||||||
|   padding: 1px 5px; |   padding: 1px 5px; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user