Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 1294 | 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
1294 lars 60
        'number'       => ['magenta'],
61
        'integer'      => ['magenta'],
62
        'float'        => ['yellow'],
63
        'string'       => ['green'],
64
        'bool'         => ['cyan'],
65
        'keyword'      => ['yellow'],
66
        'comment'      => ['blue'],
67
        'code_comment' => ['gray'],
68
        'object'       => ['blue'],
69
        'resource'     => ['yellow'],
148 lars 70
 
71
        // Code-specific formatting
72
        'inline_html' => ['cyan'],
73
    ];
74
 
1663 lars 75
    const ERROR_STYLES = ['info', 'warning', 'error', 'whisper', 'class'];
148 lars 76
 
77
    private $compact = false;
78
 
79
    private $prompt = '> ';
80
    private $bufferPrompt = '. ';
81
    private $replayPrompt = '- ';
82
    private $returnValue = '= ';
83
 
84
    private $grayFallback = 'blue';
85
 
86
    private $styles = [];
87
 
88
    /**
89
     * @param string|array $config theme name or config options
90
     */
91
    public function __construct($config = 'modern')
92
    {
93
        if (\is_string($config)) {
94
            switch ($config) {
95
                case 'modern':
96
                    $config = static::MODERN_THEME;
97
                    break;
98
 
991 lars 99
                case 'compact':
148 lars 100
                    $config = static::COMPACT_THEME;
101
                    break;
102
 
103
                case 'classic':
104
                    $config = static::CLASSIC_THEME;
105
                    break;
106
 
107
                default:
108
                    \trigger_error(\sprintf('Unknown theme: %s', $config), \E_USER_NOTICE);
109
                    $config = static::MODERN_THEME;
110
                    break;
111
            }
112
        }
113
 
114
        if (!\is_array($config)) {
115
            throw new \InvalidArgumentException('Invalid theme config');
116
        }
117
 
118
        foreach ($config as $name => $value) {
119
            switch ($name) {
120
                case 'compact':
121
                    $this->setCompact($value);
122
                    break;
123
 
124
                case 'prompt':
125
                    $this->setPrompt($value);
126
                    break;
127
 
128
                case 'bufferPrompt':
129
                    $this->setBufferPrompt($value);
130
                    break;
131
 
132
                case 'replayPrompt':
133
                    $this->setReplayPrompt($value);
134
                    break;
135
 
136
                case 'returnValue':
137
                    $this->setReturnValue($value);
138
                    break;
139
 
140
                case 'grayFallback':
141
                    $this->setGrayFallback($value);
142
                    break;
143
            }
144
        }
145
 
146
        $this->setStyles($config['styles'] ?? []);
147
    }
148
 
149
    /**
150
     * Enable or disable compact output.
151
     */
152
    public function setCompact(bool $compact)
153
    {
154
        $this->compact = $compact;
155
    }
156
 
157
    /**
158
     * Get whether to use compact output.
159
     */
160
    public function compact(): bool
161
    {
162
        return $this->compact;
163
    }
164
 
165
    /**
166
     * Set the prompt string.
167
     */
168
    public function setPrompt(string $prompt)
169
    {
170
        $this->prompt = $prompt;
171
    }
172
 
173
    /**
174
     * Get the prompt string.
175
     */
176
    public function prompt(): string
177
    {
178
        return $this->prompt;
179
    }
180
 
181
    /**
182
     * Set the buffer prompt string (used for multi-line input continuation).
183
     */
184
    public function setBufferPrompt(string $bufferPrompt)
185
    {
186
        $this->bufferPrompt = $bufferPrompt;
187
    }
188
 
189
    /**
190
     * Get the buffer prompt string (used for multi-line input continuation).
191
     */
192
    public function bufferPrompt(): string
193
    {
194
        return $this->bufferPrompt;
195
    }
196
 
197
    /**
198
     * Set the prompt string used when replaying history.
199
     */
200
    public function setReplayPrompt(string $replayPrompt)
201
    {
202
        $this->replayPrompt = $replayPrompt;
203
    }
204
 
205
    /**
206
     * Get the prompt string used when replaying history.
207
     */
208
    public function replayPrompt(): string
209
    {
210
        return $this->replayPrompt;
211
    }
212
 
213
    /**
214
     * Set the return value marker.
215
     */
216
    public function setReturnValue(string $returnValue)
217
    {
218
        $this->returnValue = $returnValue;
219
    }
220
 
221
    /**
222
     * Get the return value marker.
223
     */
224
    public function returnValue(): string
225
    {
226
        return $this->returnValue;
227
    }
228
 
229
    /**
230
     * Set the fallback color when "gray" is unavailable.
231
     */
232
    public function setGrayFallback(string $grayFallback)
233
    {
234
        $this->grayFallback = $grayFallback;
235
    }
236
 
237
    /**
238
     * Set the shell output formatter styles.
239
     *
240
     * Accepts a map from style name to [fg, bg, options], for example:
241
     *
242
     *     [
243
     *         'error' => ['white', 'red', ['bold']],
244
     *         'warning' => ['black', 'yellow'],
245
     *     ]
246
     *
247
     * Foreground, background or options can be null, or even omitted entirely.
248
     */
249
    public function setStyles(array $styles)
250
    {
251
        foreach (\array_keys(static::DEFAULT_STYLES) as $name) {
252
            $this->styles[$name] = $styles[$name] ?? static::DEFAULT_STYLES[$name];
253
        }
254
    }
255
 
256
    /**
257
     * Apply the current output formatter styles.
258
     */
259
    public function applyStyles(OutputFormatterInterface $formatter, bool $useGrayFallback)
260
    {
261
        foreach (\array_keys(static::DEFAULT_STYLES) as $name) {
262
            $formatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback)));
263
        }
264
    }
265
 
266
    /**
267
     * Apply the current output formatter error styles.
268
     */
269
    public function applyErrorStyles(OutputFormatterInterface $errorFormatter, bool $useGrayFallback)
270
    {
271
        foreach (static::ERROR_STYLES as $name) {
272
            $errorFormatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback)));
273
        }
274
    }
275
 
276
    private function getStyle(string $name, bool $useGrayFallback): array
277
    {
278
        return \array_map(function ($style) use ($useGrayFallback) {
279
            return ($useGrayFallback && $style === 'gray') ? $this->grayFallback : $style;
280
        }, $this->styles[$name]);
281
    }
282
}