Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Revision 991 | Zur aktuellen Revision | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of Psy Shell.
5
 *
200 lars 6
 * (c) 2012-2023 Justin Hileman
148 lars 7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Psy\Output;
13
 
14
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
15
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
16
 
17
/**
18
 * An output Theme, which controls prompt strings, formatter styles, and compact output.
19
 */
20
class Theme
21
{
22
    const MODERN_THEME = []; // Defaults :)
23
 
24
    const COMPACT_THEME = [
25
        'compact' => true,
26
    ];
27
 
28
    const CLASSIC_THEME = [
29
        'compact' => true,
30
 
31
        'prompt'       => '>>> ',
32
        'bufferPrompt' => '... ',
33
        'replayPrompt' => '--> ',
34
        'returnValue'  => '=>  ',
35
    ];
36
 
37
    const DEFAULT_STYLES = [
38
        'info'    => ['white', 'blue', ['bold']],
39
        'warning' => ['black', 'yellow'],
40
        'error'   => ['white', 'red', ['bold']],
41
        'whisper' => ['gray'],
42
 
43
        'aside'  => ['blue'],
44
        'strong' => [null, null, ['bold']],
45
        'return' => ['cyan'],
46
        'urgent' => ['red'],
47
        'hidden' => ['black'],
48
 
49
        // Visibility
50
        'public'    => [null, null, ['bold']],
51
        'protected' => ['yellow'],
52
        'private'   => ['red'],
53
        'global'    => ['cyan', null, ['bold']],
54
        'const'     => ['cyan'],
55
        'class'     => ['blue', null, ['underscore']],
56
        'function'  => [null],
57
        'default'   => [null],
58
 
59
        // Types
60
        'number'   => ['magenta'],
61
        'integer'  => ['magenta'],
62
        'float'    => ['yellow'],
63
        'string'   => ['green'],
64
        'bool'     => ['cyan'],
65
        'keyword'  => ['yellow'],
66
        'comment'  => ['blue'],
67
        'object'   => ['blue'],
68
        'resource' => ['yellow'],
69
 
70
        // Code-specific formatting
71
        'inline_html' => ['cyan'],
72
    ];
73
 
74
    const ERROR_STYLES = ['info', 'warning', 'error', 'whisper'];
75
 
76
    private $compact = false;
77
 
78
    private $prompt = '> ';
79
    private $bufferPrompt = '. ';
80
    private $replayPrompt = '- ';
81
    private $returnValue = '= ';
82
 
83
    private $grayFallback = 'blue';
84
 
85
    private $styles = [];
86
 
87
    /**
88
     * @param string|array $config theme name or config options
89
     */
90
    public function __construct($config = 'modern')
91
    {
92
        if (\is_string($config)) {
93
            switch ($config) {
94
                case 'modern':
95
                    $config = static::MODERN_THEME;
96
                    break;
97
 
98
                    case 'compact':
99
                    $config = static::COMPACT_THEME;
100
                    break;
101
 
102
                case 'classic':
103
                    $config = static::CLASSIC_THEME;
104
                    break;
105
 
106
                default:
107
                    \trigger_error(\sprintf('Unknown theme: %s', $config), \E_USER_NOTICE);
108
                    $config = static::MODERN_THEME;
109
                    break;
110
            }
111
        }
112
 
113
        if (!\is_array($config)) {
114
            throw new \InvalidArgumentException('Invalid theme config');
115
        }
116
 
117
        foreach ($config as $name => $value) {
118
            switch ($name) {
119
                case 'compact':
120
                    $this->setCompact($value);
121
                    break;
122
 
123
                case 'prompt':
124
                    $this->setPrompt($value);
125
                    break;
126
 
127
                case 'bufferPrompt':
128
                    $this->setBufferPrompt($value);
129
                    break;
130
 
131
                case 'replayPrompt':
132
                    $this->setReplayPrompt($value);
133
                    break;
134
 
135
                case 'returnValue':
136
                    $this->setReturnValue($value);
137
                    break;
138
 
139
                case 'grayFallback':
140
                    $this->setGrayFallback($value);
141
                    break;
142
 
143
                case 'compact':
144
                    $this->setCompact($value);
145
                    break;
146
            }
147
        }
148
 
149
        $this->setStyles($config['styles'] ?? []);
150
    }
151
 
152
    /**
153
     * Enable or disable compact output.
154
     */
155
    public function setCompact(bool $compact)
156
    {
157
        $this->compact = $compact;
158
    }
159
 
160
    /**
161
     * Get whether to use compact output.
162
     */
163
    public function compact(): bool
164
    {
165
        return $this->compact;
166
    }
167
 
168
    /**
169
     * Set the prompt string.
170
     */
171
    public function setPrompt(string $prompt)
172
    {
173
        $this->prompt = $prompt;
174
    }
175
 
176
    /**
177
     * Get the prompt string.
178
     */
179
    public function prompt(): string
180
    {
181
        return $this->prompt;
182
    }
183
 
184
    /**
185
     * Set the buffer prompt string (used for multi-line input continuation).
186
     */
187
    public function setBufferPrompt(string $bufferPrompt)
188
    {
189
        $this->bufferPrompt = $bufferPrompt;
190
    }
191
 
192
    /**
193
     * Get the buffer prompt string (used for multi-line input continuation).
194
     */
195
    public function bufferPrompt(): string
196
    {
197
        return $this->bufferPrompt;
198
    }
199
 
200
    /**
201
     * Set the prompt string used when replaying history.
202
     */
203
    public function setReplayPrompt(string $replayPrompt)
204
    {
205
        $this->replayPrompt = $replayPrompt;
206
    }
207
 
208
    /**
209
     * Get the prompt string used when replaying history.
210
     */
211
    public function replayPrompt(): string
212
    {
213
        return $this->replayPrompt;
214
    }
215
 
216
    /**
217
     * Set the return value marker.
218
     */
219
    public function setReturnValue(string $returnValue)
220
    {
221
        $this->returnValue = $returnValue;
222
    }
223
 
224
    /**
225
     * Get the return value marker.
226
     */
227
    public function returnValue(): string
228
    {
229
        return $this->returnValue;
230
    }
231
 
232
    /**
233
     * Set the fallback color when "gray" is unavailable.
234
     */
235
    public function setGrayFallback(string $grayFallback)
236
    {
237
        $this->grayFallback = $grayFallback;
238
    }
239
 
240
    /**
241
     * Set the shell output formatter styles.
242
     *
243
     * Accepts a map from style name to [fg, bg, options], for example:
244
     *
245
     *     [
246
     *         'error' => ['white', 'red', ['bold']],
247
     *         'warning' => ['black', 'yellow'],
248
     *     ]
249
     *
250
     * Foreground, background or options can be null, or even omitted entirely.
251
     */
252
    public function setStyles(array $styles)
253
    {
254
        foreach (\array_keys(static::DEFAULT_STYLES) as $name) {
255
            $this->styles[$name] = $styles[$name] ?? static::DEFAULT_STYLES[$name];
256
        }
257
    }
258
 
259
    /**
260
     * Apply the current output formatter styles.
261
     */
262
    public function applyStyles(OutputFormatterInterface $formatter, bool $useGrayFallback)
263
    {
264
        foreach (\array_keys(static::DEFAULT_STYLES) as $name) {
265
            $formatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback)));
266
        }
267
    }
268
 
269
    /**
270
     * Apply the current output formatter error styles.
271
     */
272
    public function applyErrorStyles(OutputFormatterInterface $errorFormatter, bool $useGrayFallback)
273
    {
274
        foreach (static::ERROR_STYLES as $name) {
275
            $errorFormatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback)));
276
        }
277
    }
278
 
279
    private function getStyle(string $name, bool $useGrayFallback): array
280
    {
281
        return \array_map(function ($style) use ($useGrayFallback) {
282
            return ($useGrayFallback && $style === 'gray') ? $this->grayFallback : $style;
283
        }, $this->styles[$name]);
284
    }
285
}