NeoMutt  2024-12-12-14-g7b49f7
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
parse_color.c
Go to the documentation of this file.
1
27#include "config.h"
28#include <stdbool.h>
29#include <stddef.h>
30#include <stdlib.h>
31#include "mutt/lib.h"
32#include "core/lib.h"
33#include "gui/lib.h"
34#include "parse_color.h"
35#include "parse/lib.h"
36#include "attr.h"
37#include "color.h"
38#include "debug.h"
39
41const struct Mapping ColorNames[] = {
42 // clang-format off
43 { "black", COLOR_BLACK },
44 { "blue", COLOR_BLUE },
45 { "cyan", COLOR_CYAN },
46 { "green", COLOR_GREEN },
47 { "magenta", COLOR_MAGENTA },
48 { "red", COLOR_RED },
49 { "white", COLOR_WHITE },
50 { "yellow", COLOR_YELLOW },
51 { "default", COLOR_DEFAULT },
52 { 0, 0 },
53 // clang-format on
54};
55
59static struct Mapping AttributeNames[] = {
60 // clang-format off
61 { "bold", A_BOLD },
62 { "italic", A_ITALIC },
63 { "none", A_NORMAL },
64 { "normal", A_NORMAL },
65 { "reverse", A_REVERSE },
66 { "standout", A_STANDOUT },
67 { "underline", A_UNDERLINE },
68 { NULL, 0 },
69 // clang-format on
70};
71
82int parse_color_prefix(const char *s, enum ColorPrefix *prefix)
83{
84 if (!s || !prefix)
85 return 0;
86
87 int clen = 0;
88
89 if ((clen = mutt_istr_startswith(s, "bright")))
90 {
91 color_debug(LL_DEBUG5, "bright\n");
92 if (prefix)
93 *prefix = COLOR_PREFIX_BRIGHT;
94 }
95 else if ((clen = mutt_istr_startswith(s, "alert")))
96 {
97 color_debug(LL_DEBUG5, "alert\n");
98 if (prefix)
99 *prefix = COLOR_PREFIX_ALERT;
100 }
101 else if ((clen = mutt_istr_startswith(s, "light")))
102 {
103 color_debug(LL_DEBUG5, "light\n");
104 if (prefix)
105 *prefix = COLOR_PREFIX_LIGHT;
106 }
107
108 return clen;
109}
110
119enum CommandResult parse_color_namedcolor(const char *s, struct ColorElement *elem,
120 struct Buffer *err)
121{
122 if (!s || !elem)
123 return MUTT_CMD_ERROR;
124
125 // COLOR_DEFAULT (-1) interferes with mutt_map_get_value()
126 if (mutt_str_equal(s, "default"))
127 {
128 elem->color = COLOR_DEFAULT;
129 elem->type = CT_SIMPLE;
131 return MUTT_CMD_SUCCESS;
132 }
133
134 enum ColorPrefix prefix = COLOR_PREFIX_NONE;
135 s += parse_color_prefix(s, &prefix);
136
137 int color = mutt_map_get_value(s, ColorNames);
138 if (color == -1)
139 return MUTT_CMD_WARNING;
140
141 elem->color = color;
142 elem->type = CT_SIMPLE;
143 elem->prefix = prefix;
144
145 const char *name = mutt_map_get_name(elem->color, ColorNames);
146 if (name)
147 color_debug(LL_DEBUG5, "color: %s\n", name);
148
149 return MUTT_CMD_SUCCESS;
150}
151
163enum CommandResult parse_color_colornnn(const char *s, struct ColorElement *elem,
164 struct Buffer *err)
165{
166 if (!s || !elem)
167 return MUTT_CMD_ERROR;
168
169 /* prefixes bright, alert, light are only allowed for named colours and
170 * colorNNN for backwards compatibility. */
171 enum ColorPrefix prefix = COLOR_PREFIX_NONE;
172 s += parse_color_prefix(s, &prefix);
173
174 int clen = 0;
175 /* allow aliases for xterm color resources */
176 if ((clen = mutt_istr_startswith(s, "color")) == 0)
177 return MUTT_CMD_WARNING;
178
179 s += clen;
180 char *eptr = NULL;
181
182 unsigned long color = strtoul(s, &eptr, 10);
183 /* There are only 256 xterm colors. Do not confuse with COLORS which is
184 * the number of colours the terminal supports (usually one of 16, 256,
185 * 16777216 (=24bit)). */
186 if ((*s == '\0') || (*eptr != '\0') || (color >= 256))
187 {
188 buf_printf(err, _("%s: color not supported by term"), s);
189 return MUTT_CMD_ERROR;
190 }
191
192 elem->color = color;
193 elem->type = CT_PALETTE;
194 elem->prefix = prefix;
195
196 color_debug(LL_DEBUG5, "colorNNN %d\n", elem->color);
197 return MUTT_CMD_SUCCESS;
198}
199
211enum CommandResult parse_color_rrggbb(const char *s, struct ColorElement *elem,
212 struct Buffer *err)
213{
214 if (!s || !elem)
215 return MUTT_CMD_ERROR;
216
217 /* parse #RRGGBB colours */
218 if (s[0] != '#')
219 return MUTT_CMD_WARNING;
220
221 s++;
222 char *eptr = NULL;
223 unsigned long color = strtoul(s, &eptr, 16);
224
225 if ((*s == '\0') || !eptr || (*eptr != '\0') || ((eptr - s) != 6))
226 {
227 buf_printf(err, _("%s: color not supported by term"), s);
228 return MUTT_CMD_ERROR;
229 }
230
231 elem->color = color;
232 elem->type = CT_RGB;
234
235 color_debug(LL_DEBUG5, "#RRGGBB: %ld\n", color);
236 return MUTT_CMD_SUCCESS;
237}
238
248enum CommandResult parse_color_name(const char *s, struct ColorElement *elem,
249 struct Buffer *err)
250{
251 color_debug(LL_DEBUG5, "Parsing color name: %s\n", s);
252
253 /* Try the different colour syntaxes. A return value of MUTT_CMD_WARNING
254 * means, we should try the next syntax. */
255 enum CommandResult cr;
256
257 /* #RRGGBB */
258 cr = parse_color_rrggbb(s, elem, err);
259 if (cr != MUTT_CMD_WARNING)
260 return cr;
261
262 /* color123 */
263 cr = parse_color_colornnn(s, elem, err);
264 if (cr != MUTT_CMD_WARNING)
265 return cr;
266
267 /* named color, e.g. "brightred" */
268 cr = parse_color_namedcolor(s, elem, err);
269 if (cr != MUTT_CMD_WARNING)
270 return cr;
271
272 buf_printf(err, _("%s: no such color"), s);
273 return MUTT_CMD_WARNING;
274}
275
281enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s,
282 struct AttrColor *ac, struct Buffer *err)
283{
284 while (true)
285 {
286 if (!MoreArgsF(s, TOKEN_COMMENT))
287 {
288 buf_printf(err, _("%s: too few arguments"), "color");
289 return MUTT_CMD_WARNING;
290 }
291
293 if (buf_is_empty(buf))
294 continue;
295
296 int attr = mutt_map_get_value(buf->data, AttributeNames);
297 if (attr == -1)
298 {
299 enum CommandResult rc = parse_color_name(buf->data, &ac->fg, err);
300 if (rc != MUTT_CMD_SUCCESS)
301 return rc;
302 break;
303 }
304
305 if (attr == A_NORMAL)
306 ac->attrs = attr; // Clear all attributes
307 else
308 ac->attrs |= attr; // Merge with other attributes
309 }
310
311 if (!MoreArgsF(s, TOKEN_COMMENT))
312 {
313 buf_printf(err, _("%s: too few arguments"), "color");
314 return MUTT_CMD_WARNING;
315 }
316
318
319 return parse_color_name(buf->data, &ac->bg, err);
320}
321
325enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s,
326 struct AttrColor *ac, struct Buffer *err)
327{
328 if (!buf || !s || !ac)
329 return MUTT_CMD_ERROR;
330
331 if (!MoreArgs(s))
332 {
333 buf_printf(err, _("%s: too few arguments"), "mono");
334 return MUTT_CMD_WARNING;
335 }
336
338
339 int attr = mutt_map_get_value(buf->data, AttributeNames);
340 if (attr == -1)
341 {
342 buf_printf(err, _("%s: no such attribute"), buf->data);
343 return MUTT_CMD_WARNING;
344 }
345
346 if (attr == A_NORMAL)
347 ac->attrs = attr; // Clear all attributes
348 else
349 ac->attrs |= attr; // Merge with other attributes
350
351 return MUTT_CMD_SUCCESS;
352}
Colour and attributes.
ColorPrefix
Constants for colour prefixes of named colours.
Definition: attr.h:45
@ COLOR_PREFIX_NONE
no prefix
Definition: attr.h:46
@ COLOR_PREFIX_ALERT
"alert" colour prefix
Definition: attr.h:47
@ COLOR_PREFIX_LIGHT
"light" colour prefix
Definition: attr.h:49
@ COLOR_PREFIX_BRIGHT
"bright" colour prefix
Definition: attr.h:48
@ CT_SIMPLE
Simple colour, e.g. "Red".
Definition: attr.h:36
@ CT_PALETTE
Palette colour, e.g. "color207".
Definition: attr.h:37
@ CT_RGB
True colour, e.g. "#11AAFF".
Definition: attr.h:38
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
Color and attribute parsing.
#define COLOR_DEFAULT
Definition: color.h:96
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
Convenience wrapper for the core headers.
Colour Debugging.
static int color_debug(enum LogLevel level, const char *format,...)
Definition: debug.h:52
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:50
#define MoreArgsF(buf, flags)
Definition: extract.h:35
#define MoreArgs(buf)
Definition: extract.h:32
#define TOKEN_COMMENT
Don't reap comments.
Definition: extract.h:52
#define TOKEN_NO_FLAGS
No flags are set.
Definition: extract.h:46
enum CommandResult parse_attr_spec(struct Buffer *buf, struct Buffer *s, struct AttrColor *ac, struct Buffer *err)
Parse an attribute description - Implements parser_callback_t -.
Definition: parse_color.c:325
enum CommandResult parse_color_pair(struct Buffer *buf, struct Buffer *s, struct AttrColor *ac, struct Buffer *err)
Parse a pair of colours - Implements parser_callback_t -.
Definition: parse_color.c:281
Convenience wrapper for the gui headers.
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:660
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:242
#define A_ITALIC
Definition: mutt_curses.h:49
Text parsing functions.
int parse_color_prefix(const char *s, enum ColorPrefix *prefix)
Parse a colour prefix, e.g.
Definition: parse_color.c:82
const struct Mapping ColorNames[]
Mapping between a colour name and an ncurses colour.
Definition: parse_color.c:41
static struct Mapping AttributeNames[]
Mapping of attribute names to their IDs.
Definition: parse_color.c:59
enum CommandResult parse_color_colornnn(const char *s, struct ColorElement *elem, struct Buffer *err)
Parse a colorNNN, e.g.
Definition: parse_color.c:163
enum CommandResult parse_color_name(const char *s, struct ColorElement *elem, struct Buffer *err)
Parse a colour name.
Definition: parse_color.c:248
enum CommandResult parse_color_rrggbb(const char *s, struct ColorElement *elem, struct Buffer *err)
Parse an RGB colour, e.g.
Definition: parse_color.c:211
enum CommandResult parse_color_namedcolor(const char *s, struct ColorElement *elem, struct Buffer *err)
Parse a named colour, e.g.
Definition: parse_color.c:119
Parse colour commands.
A curses colour and its attributes.
Definition: attr.h:66
struct ColorElement bg
Background colour.
Definition: attr.h:68
struct ColorElement fg
Foreground colour.
Definition: attr.h:67
int attrs
Text attributes, e.g. A_BOLD.
Definition: attr.h:69
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
One element of a Colour.
Definition: attr.h:56
enum ColorType type
Type of Colour.
Definition: attr.h:58
color_t color
Colour.
Definition: attr.h:57
enum ColorPrefix prefix
Optional Colour Modifier.
Definition: attr.h:59
Mapping between user-readable string and a constant.
Definition: mapping.h:33
const char * name
String value.
Definition: mapping.h:34