Completed
Push — master ( 61e87b...b8e375 )
by Harry
01:35
created

ConsoleDiff::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 1
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
26
    /**
27
     * ConsoleDiff constructor.
28
     *
29
     * @param CursorInterface|null $cursor The cursor used to move around the screen
30
     */
31
    public function __construct(CursorInterface $cursor = null)
32
    {
33
        $this->cursor = $cursor ?: new ANSI();
34
    }
35
36
    /**
37
     * Loop through each line, and produce a difference report of what to write out to the terminal
38
     *
39
     * Assumes the beginning of old and new are the same line
40
     *
41
     * @param string[] $old
42
     * @param string[] $new
43
     *
44
     * @return array [[:col, :str]]
45
     */
46
    public function lines(array $old, array $new)
47
    {
48
        $diff = parent::lines($old, $new);
49
50
        $len = count($new);
51
        for ($i = 0; $i < $len; $i++) {
52
            if (isset($diff[$i]) && !is_null($new[$i]) && $diff[$i]['col'] > 0) {
53
                $styling = $this->cursor->getCurrentFormatting(mb_substr($new[$i], 0, $diff[$i]['col']));
54
                $diff[$i]['col'] = mb_strlen($this->cursor->filter(mb_substr($new[$i], 0, $diff[$i]['col'])));
55
                if (mb_strlen($styling) > 0) {
56
                    $diff[$i]['str'] = $styling . $diff[$i]['str'];
57
                }
58
            }
59
        }
60
61
        return $diff;
62
    }
63
64
    /**
65
     * Looks through a line to find the character to of the first difference between the 2 strings.
66
     *
67
     * If no difference is found, returns -1
68
     *
69
     * @param string $old
70
     * @param string $new
71
     *
72
     * @return int
73
     */
74
    public function firstDifference($old, $new)
75
    {
76
        // loop through old and new character by character and compare
77
        $oldLen = mb_strlen($old);
78
        $newLen = mb_strlen($new);
79
80
        if ($oldLen === 0) {
81
            return 0;
82
        }
83
84
        $oldStripped = $this->cursor->filter($old, static::REPLACEMENT_CHAR);
85
        $newStripped = $this->cursor->filter($new, static::REPLACEMENT_CHAR);
86
        $lastReal = 0;
87
88
        for ($i = 0; $i < $oldLen && $i < $newLen; $i++) {
89
            if (mb_substr($old, $i, 1) !== mb_substr($new, $i, 1)) {
90
                if (($i > 0)
91
                    && ((mb_substr($oldStripped, $i - 1, 1) === static::REPLACEMENT_CHAR)
92
                        || (mb_substr($newStripped, $i - 1, 1) === static::REPLACEMENT_CHAR)
93
                    )
94
                ) {
95
                    return $lastReal > 0 ? $lastReal + 1 : 0;
96
                }
97
                return $i;
98
            } elseif (mb_substr($oldStripped, $i, 1) !== static::REPLACEMENT_CHAR) {
99
                $lastReal = $i;
100
            }
101
        }
102
        if ($i < $oldLen || $i < $newLen) {
103
            return $i;
104
        }
105
        return -1;
106
    }
107
}
108