From: Chuck Hagenbuch Date: Mon, 29 Nov 2010 02:39:57 +0000 (-0500) Subject: Add line numbers to side-by-side diffs X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=9d4b6832532c6df8df3d7bb551ef8532966f12c6;p=horde.git Add line numbers to side-by-side diffs --- diff --git a/chora/app/helpers/Diff.php b/chora/app/helpers/Diff.php index ae2d6ca10..0e04ab628 100644 --- a/chora/app/helpers/Diff.php +++ b/chora/app/helpers/Diff.php @@ -11,9 +11,23 @@ class Chora_Diff_Helper extends Horde_View_Helper_Base { /** - * @var string + * @var array */ - protected $_context = ''; + protected $_context = array(); + + /** + * @var array + */ + protected $_leftLines = array(); + protected $_rightLines = array(); + protected $_leftNumbers = array(); + protected $_rightNumbers = array(); + + /** + * @var integer + */ + protected $_leftLine = 0; + protected $_rightLine = 0; public function diff(Horde_Vcs_File $file, $r1, $r2, $id = null) { @@ -23,40 +37,122 @@ class Chora_Diff_Helper extends Horde_View_Helper_Base return '

' . sprintf(_("There was an error generating the diff: %s"), $e->getMessage()) . '

'; } - return $this->render('app/views/diff/diff.html.php', array('diff' => $diff, 'file' => $file, 'r1' => $r1, 'r2' => $r2, 'id' => $id)); + $this->_leftLines = array(); + $this->_rightLines = array(); + $this->_leftNumbers = array(); + $this->_rightNumbers = array(); + + $firstSection = true; + foreach ($diff as $section) { + if (!$firstSection) { + $this->_leftLines[] = array('type' => 'separator', 'lines' => array('')); + $this->_rightLines[] = array('type' => 'separator', 'lines' => array('')); + $this->_leftNumbers[] = '…'; + $this->_rightNumbers[] = '…'; + } + $firstSection = false; + + $this->_leftLine = (int)$section['oldline']; + $this->_rightLine = (int)$section['newline']; + + foreach ($section['contents'] as $change) { + if ($this->hasContext() && $change['type'] != 'empty') { + $this->diffContext(); + } + + $method = 'diff' . ucfirst($change['type']); + $this->$method($change); + } + + if ($this->hasContext()) { + $this->diffContext(); + } + } + + return $this->render('app/views/diff/diff.html.php', array( + 'leftLines' => $this->_leftLines, + 'rightLines' => $this->_rightLines, + 'leftNumbers' => $this->_leftNumbers, + 'rightNumbers' => $this->_rightNumbers, + 'file' => $file, + 'r1' => $r1, + 'r2' => $r2, + 'id' => $id, + )); } public function diffAdd($change) { + $leftSection = array(); + $rightSection = array(); + foreach ($change['lines'] as $addedLine) { + $leftSection[] = ''; + $rightSection[] = $addedLine; + $this->_leftNumbers[] = ''; + $this->_rightNumbers[] = $this->_rightLine++; + } + $this->_leftLines[] = array('type' => 'added-empty', 'lines' => $leftSection); + $this->_rightLines[] = array('type' => 'added', 'lines' => $rightSection); + /* return $this->render('app/views/diff/added.html.php', array( 'lines' => $change['lines'], )); + */ } public function diffRemove($change) { + $leftSection = array(); + $rightSection = array(); + foreach ($change['lines'] as $removedLine) { + $leftSection[] = $removedLine; + $rightSection[] = ''; + $this->_leftNumbers[] = $this->_leftLine++; + $this->_rightNumbers[] = ''; + } + $this->_leftLines[] = array('type' => 'removed', 'lines' => $leftSection); + $this->_rightLines[] = array('type' => 'removed-empty', 'lines' => $rightSection); + /* return $this->render('app/views/diff/removed.html.php', array( 'lines' => $change['lines'], )); + */ } public function diffEmpty($change) { - $this->_context .= $this->escape($change['line']) . '
'; + $this->_context[] = array('left' => $this->_leftLine++, 'right' => $this->_rightLine++, 'text' => $change['line']); return ''; } public function diffChange($change) { + $leftSection = array(); + $rightSection = array(); + // Pop the old/new stacks one by one, until both are empty. $oldsize = count($change['old']); $newsize = count($change['new']); - $left = $right = ''; for ($row = 0, $rowMax = max($oldsize, $newsize); $row < $rowMax; ++$row) { - $left .= (isset($change['old'][$row]) ? $this->escape($change['old'][$row]) : '') . '
'; - $right .= (isset($change['new'][$row]) ? $this->escape($change['new'][$row]) : '') . '
'; - } + if (isset($change['old'][$row])) { + $leftSection[] = $change['old'][$row]; + $this->_leftNumbers[] = $this->_leftLine++; + } else { + $leftSection[] = ''; + $this->_leftNumbers[] = ''; + } + if (isset($change['new'][$row])) { + $rightSection[] = $change['new'][$row]; + $this->_rightNumbers[] = $this->_rightLine++; + } else { + $rightSection[] = ''; + $this->_rightNumbers[] = ''; + } + } + $this->_leftLines[] = array('type' => 'modified', 'lines' => $leftSection); + $this->_rightLines[] = array('type' => 'modified', 'lines' => $rightSection); + /* return $this->render('app/views/diff/change.html.php', array( 'left' => $left, 'right' => $right, @@ -64,6 +160,7 @@ class Chora_Diff_Helper extends Horde_View_Helper_Base 'newsize' => $newsize, 'row' => $row, )); + */ } public function hasContext() @@ -74,11 +171,23 @@ class Chora_Diff_Helper extends Horde_View_Helper_Base public function diffContext() { $context = $this->_context; - $this->_context = ''; + $this->_context = array(); + $leftSection = array(); + $rightSection = array(); + foreach ($context as $contextLine) { + $leftSection[] = $contextLine['text']; + $rightSection[] = $contextLine['text']; + $this->_leftNumbers[] = $contextLine['left']; + $this->_rightNumbers[] = $contextLine['right']; + } + $this->_leftLines[] = array('type' => 'unmodified', 'lines' => $leftSection); + $this->_rightLines[] = array('type' => 'unmodified', 'lines' => $rightSection); + /* return $this->render('app/views/diff/context.html.php', array( 'context' => $context, )); + */ } public function diffCaption() diff --git a/chora/app/views/diff/added.html.php b/chora/app/views/diff/added.html.php deleted file mode 100644 index 6180f9c1d..000000000 --- a/chora/app/views/diff/added.html.php +++ /dev/null @@ -1,4 +0,0 @@ -
-
-
escape($l) . '
' ?>
-
diff --git a/chora/app/views/diff/change.html.php b/chora/app/views/diff/change.html.php deleted file mode 100644 index c73cab465..000000000 --- a/chora/app/views/diff/change.html.php +++ /dev/null @@ -1,17 +0,0 @@ -
- -
- -
 
- -
 
- - - -
- -
 
- -
 
- -
diff --git a/chora/app/views/diff/context.html.php b/chora/app/views/diff/context.html.php deleted file mode 100644 index cd92d044c..000000000 --- a/chora/app/views/diff/context.html.php +++ /dev/null @@ -1,4 +0,0 @@ -
-
-
-
diff --git a/chora/app/views/diff/diff.html.php b/chora/app/views/diff/diff.html.php index 1ca1cebee..506752472 100644 --- a/chora/app/views/diff/diff.html.php +++ b/chora/app/views/diff/diff.html.php @@ -1,24 +1,47 @@
> - - -
-

-

-
-hasContext() && $change['type'] != 'empty') { - echo $this->diffContext(); - } + + + +
+
+
+
    + +
  1. + +
+
- $method = 'diff' . ucfirst($change['type']); - echo $this->$method($change); -} +
+ +
escape($ll) : ' ') . "\n";
+      endforeach ?>
+ +
+
-if ($this->hasContext()) { - echo $this->diffContext(); -} +
+
+
    + +
  1. + +
+
-endforeach; -?> +
+ +
escape($rl) : ' ') . "\n";
+      endforeach ?>
+ +
+
+
diff --git a/chora/app/views/diff/removed.html.php b/chora/app/views/diff/removed.html.php deleted file mode 100644 index f8090efbf..000000000 --- a/chora/app/views/diff/removed.html.php +++ /dev/null @@ -1,4 +0,0 @@ -
-
escape($l) . '
' ?>
-
-
diff --git a/chora/themes/default/screen.css b/chora/themes/default/screen.css index 6f019cedb..1b4383774 100644 --- a/chora/themes/default/screen.css +++ b/chora/themes/default/screen.css @@ -286,9 +286,6 @@ div.diff-header h4 { font-family: Menlo,Consolas,"Lucida Console","DejaVu Sans Mono",monospace; font-size: 110%; } -div.diff-section { - margin-top: 1em; -} div.diff-container:after { content: "."; display: block; @@ -296,19 +293,14 @@ div.diff-container:after { clear: both; visibility: hidden; } -div.diff-container h3 { - font-weight: bold; -} div.diff-left { float: left; width: 50%; - overflow-y: auto; } div.diff-right { float: right; width: 50%; - overflow-y: auto; } .diff-unmodified { @@ -334,6 +326,34 @@ div.diff-right { background: -webkit-gradient(linear, right top, left top, from(#fff), to(#fcc), color-stop(0.5, #fcc)); background: -moz-linear-gradient(right, #fff, #fcc 50%); } +.diff-separator { + background: #eee; +} + +div.diff-linenumbers { + float: left; + font-family: Menlo,Consolas,"Lucida Console","DejaVu Sans Mono",monospace; + text-align: right; + padding: 0 .5em 0 .1em; + width: 4em; + color: #333; + background: #eee; + border-right: thin solid #ddd; +} +div.diff-linenumbers ol { + list-style: none; +} +div.diff-right div.diff-linenumbers { + border-left: thin solid #ddd; +} + +div.diff-listing { + font-family: Menlo,Consolas,"Lucida Console","DejaVu Sans Mono",monospace; + overflow-y: auto; +} +div.diff-listing pre { + padding-left: .3em; +} .diff-caption { text-align: left;