Completed
Pull Request — master (#9)
by Harry
02:43
created

ConsoleDiff::lines()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 10
nc 4
nop 2
1
<?php
2
/**
3
 * This file is part of graze/console-diff-renderer.
4
 *
5
 * Copyright (c) 2017 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/console-diff-renderer/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/console-diff-renderer
12
 */
13
14
namespace Graze\DiffRenderer\Diff;
15
16
use Graze\DiffRenderer\Terminal\ANSI;
17
use Graze\DiffRenderer\Terminal\CursorInterface;
18
19
class ConsoleDiff extends FirstDiff
20
{
21
    const REPLACEMENT_CHAR = "\6";
22
23
    /** @var CursorInterface */
24
    private $cursor;
25
    /** @var string */
26
    private $regex;
27
28
    /**
29
     * ConsoleDiff constructor.
30
     *
31
     * @param CursorInterface|null $cursor The cursor used to move around the screen
32
     */
33
    public function __construct(CursorInterface $cursor = null)
34
    {
35
        $this->cursor = $cursor ?: new ANSI();
36
37
        if ($this->cursor instanceof ANSI) {
38
            $this->regex = "/\e\\[(?:[1-9][0-9;]*)m.+?\e\\[(?:0|29|39|49)m/i";
39
        }
40
    }
41
42
    /**
43
     * Loop through each line, and produce a difference report of what to write out to the terminal
44
     *
45
     * Assumes the beginning of old and new are the same line
46
     *
47
     * @param string[] $old
48
     * @param string[] $new
49
     *
50
     * @return array [[:col, :str]]
51
     */
52
    public function lines(array $old, array $new)
53
    {
54
        $diff = parent::lines($old, $new);
55
56
        $len = count($new);
57
        for ($i = 0; $i < $len; $i++) {
58
            if (isset($diff[$i]) && !is_null($new[$i]) && $diff[$i]['col'] > 0) {
59
                $styling = $this->cursor->getCurrentFormatting(mb_substr($new[$i], 0, $diff[$i]['col']));
60
                $diff[$i]['col'] = mb_strlen($this->cursor->filter(mb_substr($new[$i], 0, $diff[$i]['col'])));
61
                if (mb_strlen($styling) > 0) {
62
                    $diff[$i]['str'] = $styling . $diff[$i]['str'];
63
                }
64
            }
65
        }
66
67
        return $diff;
68
    }
69
70
    /**
71
     * Looks through a line to find the character to of the first difference between the 2 strings.
72
     *
73
     * If no difference is found, returns -1
74
     *
75
     * @param string $old
76
     * @param string $new
77
     *
78
     * @return int
79
     */
80
    public function firstDifference($old, $new)
81
    {
82
        // loop through old and new character by character and compare
83
        $oldLen = mb_strlen($old);
84
        $newLen = mb_strlen($new);
85
86
        if ($oldLen === 0) {
87
            return 0;
88
        }
89
90
        $oldStripped = $this->cursor->filter($old, static::REPLACEMENT_CHAR);
91
        $newStripped = $this->cursor->filter($new, static::REPLACEMENT_CHAR);
92
        $lastReal = 0;
93
94
        for ($i = 0; $i < $oldLen && $i < $newLen; $i++) {
95
            if (mb_substr($old, $i, 1) !== mb_substr($new, $i, 1)) {
96
                if (($i > 0)
97
                    && ((mb_substr($oldStripped, $i - 1, 1) === static::REPLACEMENT_CHAR)
98
                        || (mb_substr($newStripped, $i - 1, 1) === static::REPLACEMENT_CHAR)
99
                    )
100
                ) {
101
                    return $lastReal > 0 ? $lastReal + 1 : 0;
102
                }
103
                return $i;
104
            } elseif (mb_substr($oldStripped, $i, 1) !== static::REPLACEMENT_CHAR) {
105
                $lastReal = $i;
106
            }
107
        }
108
        if ($i < $oldLen || $i < $newLen) {
109
            return $i;
110
        }
111
        return -1;
112
    }
113
}
114