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