Completed
Push — master ( 0581d7...c73d91 )
by Craig
01:46
created

Spinner::drawSpinner()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace League\CLImate\TerminalObject\Dynamic;
4
5
use function array_merge;
6
use function count;
7
use function microtime;
8
use function range;
9
use function str_repeat;
10
use function substr;
11
use function trim;
12
13
final class Spinner extends DynamicTerminalObject
14
{
15
    /**
16
     * @var string[] The characters to be used to present progress.
17
     */
18
    private $characters = ["[=---]", "[-=--]", "[--=-]", "[---=]", "[--=-]", "[-=--]"];
19
20
    /**
21
     * @var int The current item of the sequence
22
     */
23
    private $current = 0;
24
25
    /**
26
     * @var bool Flag indicating whether we are writing the bar for the first time.
27
     */
28
    private $firstLine = true;
29
30
    /**
31
     * @var string Current label.
32
     */
33
    private $label;
34
35
    /**
36
     * @var float When the spinner was last drawn.
37
     */
38
    private $lastDrawn;
39
40
    /**
41
     * @var float How long to wait in seconds between drawing each stage.
42
     */
43
    private $timeLimit = 0.1;
44
45
46
    /**
47
     * If they pass in a sequence, set the sequence
48
     *
49
     * @param string $label
50
     * @param string ...$characters
51
     */
52
    public function __construct($label = null, ...$characters)
53
    {
54
        if ($label !== null) {
55
            $this->label = $label;
56
        }
57
58
        if (count($characters) < 1) {
59
            $characters = [];
60
            $size = 5;
61
            $positions = array_merge(range(0, $size - 1), range($size - 2, 1, -1));
62
            foreach ($positions as $pos) {
63
                $line = str_repeat("-", $size);
64
                $characters[] = "[" . substr($line, 0, $pos) . "=" . substr($line, $pos + 1) . "]";
65
            }
66
        }
67
        $this->characters(...$characters);
68
    }
69
70
71
    /**
72
     * Set the length of time to wait between drawing each stage.
73
     *
74
     * @param float $timeLimit
75
     *
76
     * @return Spinner
77
     */
78
    public function timeLimit($timeLimit)
79
    {
80
        $this->timeLimit = (float) $timeLimit;
81
82
        return $this;
83
    }
84
85
86
    /**
87
     * Set the character to loop around.
88
     *
89
     * @param string $characters
90
     *
91
     * @return Spinner
92
     */
93
    public function characters(...$characters)
94
    {
95
        if (count($characters) < 1) {
96
            throw new \UnexpectedValueException("You must specify the characters to use");
97
        }
98
99
        $this->characters = $characters;
100
101
        return $this;
102
    }
103
104
105
    /**
106
     * Re-writes the spinner
107
     *
108
     * @param string $label
109
     *
110
     * @return void
111
     */
112
    public function advance($label = null)
113
    {
114
        if ($label === null) {
115
            $label = $this->label;
116
        }
117
118
        if ($this->lastDrawn) {
119
            $time = microtime(true) - $this->lastDrawn;
120
            if ($time < $this->timeLimit) {
121
                return;
122
            }
123
        }
124
125
        ++$this->current;
126
        if ($this->current >= count($this->characters)) {
127
            $this->current = 0;
128
        }
129
130
        $characters = $this->characters[$this->current];
131
        $this->drawSpinner($characters, $label);
132
        $this->lastDrawn = microtime(true);
133
    }
134
135
136
    /**
137
     * Draw the spinner
138
     *
139
     * @param string $characters
140
     * @param string $label
141
     */
142
    private function drawSpinner($characters, $label)
143
    {
144
        $spinner = "";
145
146
        if ($this->firstLine) {
147
            $this->firstLine = false;
148
        } else {
149
            $spinner .= $this->util->cursor->up(1);
150
            $spinner .= $this->util->cursor->startOfCurrentLine();
151
            $spinner .= $this->util->cursor->deleteCurrentLine();
152
        }
153
154
        $spinner .= trim("{$characters} {$label}");
155
156
        $this->output->write($this->parser->apply($spinner));
157
    }
158
}
159