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