Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 200 | Revision 1294 | 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
 
991 lars 98
                case 'compact':
148 lars 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
        }
144
 
145
        $this->setStyles($config['styles'] ?? []);
146
    }
147
 
148
    /**
149
     * Enable or disable compact output.
150
     */
151
    public function setCompact(bool $compact)
152
    {
153
        $this->compact = $compact;
154
    }
155
 
156
    /**
157
     * Get whether to use compact output.
158
     */
159
    public function compact(): bool
160
    {
161
        return $this->compact;
162
    }
163
 
164
    /**
165
     * Set the prompt string.
166
     */
167
    public function setPrompt(string $prompt)
168
    {
169
        $this->prompt = $prompt;
170
    }
171
 
172
    /**
173
     * Get the prompt string.
174
     */
175
    public function prompt(): string
176
    {
177
        return $this->prompt;
178
    }
179
 
180
    /**
181
     * Set the buffer prompt string (used for multi-line input continuation).
182
     */
183
    public function setBufferPrompt(string $bufferPrompt)
184
    {
185
        $this->bufferPrompt = $bufferPrompt;
186
    }
187
 
188
    /**
189
     * Get the buffer prompt string (used for multi-line input continuation).
190
     */
191
    public function bufferPrompt(): string
192
    {
193
        return $this->bufferPrompt;
194
    }
195
 
196
    /**
197
     * Set the prompt string used when replaying history.
198
     */
199
    public function setReplayPrompt(string $replayPrompt)
200
    {
201
        $this->replayPrompt = $replayPrompt;
202
    }
203
 
204
    /**
205
     * Get the prompt string used when replaying history.
206
     */
207
    public function replayPrompt(): string
208
    {
209
        return $this->replayPrompt;
210
    }
211
 
212
    /**
213
     * Set the return value marker.
214
     */
215
    public function setReturnValue(string $returnValue)
216
    {
217
        $this->returnValue = $returnValue;
218
    }
219
 
220
    /**
221
     * Get the return value marker.
222
     */
223
    public function returnValue(): string
224
    {
225
        return $this->returnValue;
226
    }
227
 
228
    /**
229
     * Set the fallback color when "gray" is unavailable.
230
     */
231
    public function setGrayFallback(string $grayFallback)
232
    {
233
        $this->grayFallback = $grayFallback;
234
    }
235
 
236
    /**
237
     * Set the shell output formatter styles.
238
     *
239
     * Accepts a map from style name to [fg, bg, options], for example:
240
     *
241
     *     [
242
     *         'error' => ['white', 'red', ['bold']],
243
     *         'warning' => ['black', 'yellow'],
244
     *     ]
245
     *
246
     * Foreground, background or options can be null, or even omitted entirely.
247
     */
248
    public function setStyles(array $styles)
249
    {
250
        foreach (\array_keys(static::DEFAULT_STYLES) as $name) {
251
            $this->styles[$name] = $styles[$name] ?? static::DEFAULT_STYLES[$name];
252
        }
253
    }
254
 
255
    /**
256
     * Apply the current output formatter styles.
257
     */
258
    public function applyStyles(OutputFormatterInterface $formatter, bool $useGrayFallback)
259
    {
260
        foreach (\array_keys(static::DEFAULT_STYLES) as $name) {
261
            $formatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback)));
262
        }
263
    }
264
 
265
    /**
266
     * Apply the current output formatter error styles.
267
     */
268
    public function applyErrorStyles(OutputFormatterInterface $errorFormatter, bool $useGrayFallback)
269
    {
270
        foreach (static::ERROR_STYLES as $name) {
271
            $errorFormatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback)));
272
        }
273
    }
274
 
275
    private function getStyle(string $name, bool $useGrayFallback): array
276
    {
277
        return \array_map(function ($style) use ($useGrayFallback) {
278
            return ($useGrayFallback && $style === 'gray') ? $this->grayFallback : $style;
279
        }, $this->styles[$name]);
280
    }
281
}