NeoMutt  2025-12-11-694-ga89709
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
set.c File Reference

Parse the 'set' command. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "set.h"
#include "dump.h"
#include "extract.h"
#include "muttlib.h"
#include "perror.h"
+ Include dependency graph for set.c:

Go to the source code of this file.

Functions

void command_set_expand_value (int type, struct Buffer *value)
 Expand special characters.
 
enum CommandResult command_set_set (struct Buffer *name, struct Buffer *value, struct Buffer *err)
 Set a variable to the given value.
 
enum CommandResult command_set_increment (struct Buffer *name, struct Buffer *value, struct Buffer *err)
 Increment a variable by a value.
 
enum CommandResult command_set_decrement (struct Buffer *name, struct Buffer *value, struct Buffer *err)
 Decrement a variable by a value.
 
enum CommandResult command_set_unset (struct Buffer *name, struct Buffer *err)
 Unset a variable.
 
enum CommandResult command_set_reset (struct Buffer *name, struct Buffer *err)
 Reset a variable.
 
enum CommandResult command_set_toggle (struct Buffer *name, struct Buffer *err)
 Toggle a boolean, quad, or number variable.
 
enum CommandResult command_set_query (struct Buffer *name, struct Buffer *err)
 Query a variable.
 
enum CommandResult parse_set (const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
 Parse the 'set' family of commands - Implements Command::parse() -.
 

Detailed Description

Parse the 'set' command.

Authors
  • Richard Russon
  • Dennis Schön
  • Rayford Shireman

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file set.c.

Function Documentation

◆ command_set_expand_value()

void command_set_expand_value ( int type,
struct Buffer * value )

Expand special characters.

Parameters
typeType of the value, see note below
[in,out]valueBuffer containing the value, will also contain the final result
Precondition
value is not NULL

Expand any special characters in paths, mailboxes or commands. e.g. ~ ($HOME), + ($folder)

The type influences which expansions are done.

Note
The type must be the full HashElem.type, not the sanitized CONFIG_TYPE(HashElem.type)
The value is expanded in-place

Definition at line 59 of file set.c.

60{
61 ASSERT(value);
62 if (CONFIG_TYPE(type) == DT_PATH)
63 {
64 if (type & (D_PATH_DIR | D_PATH_FILE))
65 expand_path(value, false);
66 else
68 }
69 else if (IS_MAILBOX(type))
70 {
71 expand_path(value, false);
72 }
73 else if (IS_COMMAND(type))
74 {
75 struct Buffer *scratch = buf_pool_get();
76 buf_copy(scratch, value);
77
78 if (!mutt_str_equal(value->data, "builtin"))
79 {
80 expand_path(scratch, false);
81 }
82 buf_reset(value);
83 buf_addstr(value, buf_string(scratch));
84 buf_pool_release(&scratch);
85 }
86}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
bool mutt_path_tilde(struct Buffer *path, const char *homedir)
Expand '~' in a path.
Definition path.c:194
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define ASSERT(COND)
Definition signal2.h:59
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
Container for Accounts, Notifications.
Definition neomutt.h:41
char * home_dir
User's home directory.
Definition neomutt.h:56
#define CONFIG_TYPE(t)
Extract the type from the flags.
Definition types.h:50
#define IS_MAILBOX(flags)
Definition types.h:122
#define D_PATH_DIR
Path is a directory.
Definition types.h:103
#define D_PATH_FILE
Path is a file.
Definition types.h:104
@ DT_PATH
a path to a file/directory
Definition types.h:39
#define IS_COMMAND(flags)
Definition types.h:123
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_set()

enum CommandResult command_set_set ( struct Buffer * name,
struct Buffer * value,
struct Buffer * err )

Set a variable to the given value.

Parameters
[in]nameName of the config; must not be NULL
[in]valueValue the config should be set to
[out]errBuffer for error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL
value is not NULL

This implements "set foo = bar" command where "bar" is present.

Definition at line 100 of file set.c.

102{
103 ASSERT(name);
104 ASSERT(value);
105 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
106 if (!he)
107 {
108 // In case it is a my_var, we have to create it
109 if (mutt_str_startswith(name->data, "my_"))
110 {
111 struct ConfigDef my_cdef = { 0 };
112 my_cdef.name = name->data;
113 my_cdef.type = DT_MYVAR;
114 he = cs_create_variable(NeoMutt->sub->cs, &my_cdef, err);
115 if (!he)
116 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
117 }
118 else
119 {
120 buf_printf(err, _("Unknown option %s"), name->data);
121 return MUTT_CMD_ERROR;
122 }
123 }
124
125 if (he->type & D_INTERNAL_DEPRECATED)
126 {
127 mutt_warning(_("Option %s is deprecated"), name->data);
128 return MUTT_CMD_SUCCESS;
129 }
130 int rc = CSR_ERR_CODE;
131
132 if (CONFIG_TYPE(he->type) == DT_MYVAR)
133 {
134 // my variables do not expand their value
135 rc = cs_subset_he_string_set(NeoMutt->sub, he, value->data, err);
136 }
137 else
138 {
139 command_set_expand_value(he->type, value);
140 rc = cs_subset_he_string_set(NeoMutt->sub, he, value->data, err);
141 }
142 if (CSR_RESULT(rc) != CSR_SUCCESS)
143 {
144 if (rc & CSR_INV_WARNING)
145 return MUTT_CMD_WARNING;
146 return MUTT_CMD_ERROR;
147 }
148
149 return MUTT_CMD_SUCCESS;
150}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
struct HashElem * cs_create_variable(const struct ConfigSet *cs, struct ConfigDef *cdef, struct Buffer *err)
Create and register one config item.
Definition set.c:327
#define CSR_INV_WARNING
Report as a warning, not an error.
Definition set.h:48
#define CSR_ERR_CODE
Problem with the code.
Definition set.h:34
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:53
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define mutt_warning(...)
Definition logging2.h:92
#define _(a)
Definition message.h:28
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:234
void command_set_expand_value(int type, struct Buffer *value)
Expand special characters.
Definition set.c:59
const char * name
User-visible name.
Definition set.h:66
uint32_t type
Variable type, e.g. DT_STRING.
Definition set.h:67
struct ConfigSet * cs
Parent ConfigSet.
Definition subset.h:50
The item stored in a Hash Table.
Definition hash.h:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Set a config item by string.
Definition subset.c:370
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition subset.c:193
#define D_INTERNAL_DEPRECATED
Config item shouldn't be used any more.
Definition types.h:88
@ DT_MYVAR
a user-defined variable (my_foo)
Definition types.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_increment()

enum CommandResult command_set_increment ( struct Buffer * name,
struct Buffer * value,
struct Buffer * err )

Increment a variable by a value.

Parameters
[in]nameName of the config; must not be NULL
[in]valueValue the config should be incremented by
[out]errBuffer for error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL
value is not NULL

This implements "set foo += bar" command where "bar" is present.

Definition at line 164 of file set.c.

166{
167 ASSERT(name);
168 ASSERT(value);
169 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
170 if (!he)
171 {
172 // In case it is a my_var, we have to create it
173 if (mutt_str_startswith(name->data, "my_"))
174 {
175 struct ConfigDef my_cdef = { 0 };
176 my_cdef.name = name->data;
177 my_cdef.type = DT_MYVAR;
178 he = cs_create_variable(NeoMutt->sub->cs, &my_cdef, err);
179 if (!he)
180 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
181 }
182 else
183 {
184 buf_printf(err, _("Unknown option %s"), name->data);
185 return MUTT_CMD_ERROR;
186 }
187 }
188
189 if (he->type & D_INTERNAL_DEPRECATED)
190 {
191 mutt_warning(_("Option %s is deprecated"), name->data);
192 return MUTT_CMD_SUCCESS;
193 }
194
195 int rc = CSR_ERR_CODE;
196
197 if (CONFIG_TYPE(he->type) == DT_MYVAR)
198 {
199 // my variables do not expand their value
200 rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, value->data, err);
201 }
202 else
203 {
204 command_set_expand_value(he->type, value);
205 rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, value->data, err);
206 }
207 if (CSR_RESULT(rc) != CSR_SUCCESS)
208 return MUTT_CMD_ERROR;
209
210 return MUTT_CMD_SUCCESS;
211}
int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Add to a config item by string.
Definition subset.c:408
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_decrement()

enum CommandResult command_set_decrement ( struct Buffer * name,
struct Buffer * value,
struct Buffer * err )

Decrement a variable by a value.

Parameters
[in]nameName of the config; must not be NULL
[in]valueValue the config should be decremented by
[out]errBuffer for error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL
value is not NULL

This implements "set foo -= bar" command where "bar" is present.

Definition at line 225 of file set.c.

227{
228 ASSERT(name);
229 ASSERT(value);
230 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
231 if (!he)
232 {
233 buf_printf(err, _("Unknown option %s"), name->data);
234 return MUTT_CMD_ERROR;
235 }
236
237 if (he->type & D_INTERNAL_DEPRECATED)
238 {
239 mutt_warning(_("Option %s is deprecated"), name->data);
240 return MUTT_CMD_SUCCESS;
241 }
242
243 command_set_expand_value(he->type, value);
244 int rc = cs_subset_he_string_minus_equals(NeoMutt->sub, he, value->data, err);
245 if (CSR_RESULT(rc) != CSR_SUCCESS)
246 return MUTT_CMD_ERROR;
247
248 return MUTT_CMD_SUCCESS;
249}
int cs_subset_he_string_minus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition subset.c:430
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_unset()

enum CommandResult command_set_unset ( struct Buffer * name,
struct Buffer * err )

Unset a variable.

Parameters
[in]nameName of the config variable to be unset
[out]errBuffer for error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL

This implements "unset foo"

Definition at line 261 of file set.c.

262{
263 ASSERT(name);
264 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
265 if (!he)
266 {
267 buf_printf(err, _("Unknown option %s"), name->data);
268 return MUTT_CMD_ERROR;
269 }
270
271 if (he->type & D_INTERNAL_DEPRECATED)
272 {
273 mutt_warning(_("Option %s is deprecated"), name->data);
274 return MUTT_CMD_SUCCESS;
275 }
276
277 int rc = CSR_ERR_CODE;
278 if (CONFIG_TYPE(he->type) == DT_MYVAR)
279 {
280 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
281 }
282 else if ((CONFIG_TYPE(he->type) == DT_BOOL) || (CONFIG_TYPE(he->type) == DT_QUAD))
283 {
284 rc = cs_subset_he_native_set(NeoMutt->sub, he, false, err);
285 }
286 else
287 {
288 rc = cs_subset_he_string_set(NeoMutt->sub, he, NULL, err);
289 }
290 if (CSR_RESULT(rc) != CSR_SUCCESS)
291 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
292
293 return MUTT_CMD_SUCCESS;
294}
int cs_subset_he_native_set(const struct ConfigSubset *sub, struct HashElem *he, intptr_t value, struct Buffer *err)
Natively set the value of a HashElem config item.
Definition subset.c:281
int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Delete config item from a config.
Definition subset.c:451
@ DT_BOOL
boolean option
Definition types.h:32
@ DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition types.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_reset()

enum CommandResult command_set_reset ( struct Buffer * name,
struct Buffer * err )

Reset a variable.

Parameters
[in]nameName of the config variable to be reset
[out]errBuffer for error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL

This implements "reset foo" (foo being any config variable) and "reset all".

Definition at line 306 of file set.c.

307{
308 ASSERT(name);
309 // Handle special "reset all" syntax
310 if (mutt_str_equal(name->data, "all"))
311 {
312 struct HashElemArray hea = get_elem_list(NeoMutt->sub->cs, GEL_ALL_CONFIG);
313 struct HashElem **hep = NULL;
314 ARRAY_FOREACH(hep, &hea)
315 {
316 struct HashElem *he = *hep;
317 if (CONFIG_TYPE(he->type) == DT_MYVAR)
319 else
320 cs_subset_he_reset(NeoMutt->sub, he, NULL);
321 }
322
323 ARRAY_FREE(&hea);
324 return MUTT_CMD_SUCCESS;
325 }
326
327 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
328 if (!he)
329 {
330 buf_printf(err, _("Unknown option %s"), name->data);
331 return MUTT_CMD_ERROR;
332 }
333
334 if (he->type & D_INTERNAL_DEPRECATED)
335 {
336 mutt_warning(_("Option %s is deprecated"), name->data);
337 return MUTT_CMD_SUCCESS;
338 }
339
340 int rc = CSR_ERR_CODE;
341 if (CONFIG_TYPE(he->type) == DT_MYVAR)
342 {
343 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
344 }
345 else
346 {
347 rc = cs_subset_he_reset(NeoMutt->sub, he, err);
348 }
349 if (CSR_RESULT(rc) != CSR_SUCCESS)
350 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
351
352 return MUTT_CMD_SUCCESS;
353}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition subset.c:318
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition subset.c:81
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition subset.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_toggle()

enum CommandResult command_set_toggle ( struct Buffer * name,
struct Buffer * err )

Toggle a boolean, quad, or number variable.

Parameters
[in]nameName of the config variable to be toggled
[out]errBuffer for error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL

This implements "toggle foo".

Definition at line 365 of file set.c.

366{
367 ASSERT(name);
368 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
369 if (!he)
370 {
371 buf_printf(err, _("Unknown option %s"), name->data);
372 return MUTT_CMD_ERROR;
373 }
374
375 if (he->type & D_INTERNAL_DEPRECATED)
376 {
377 mutt_warning(_("Option %s is deprecated"), name->data);
378 return MUTT_CMD_SUCCESS;
379 }
380
381 if (CONFIG_TYPE(he->type) == DT_BOOL)
382 {
383 bool_he_toggle(NeoMutt->sub, he, err);
384 }
385 else if (CONFIG_TYPE(he->type) == DT_QUAD)
386 {
387 quad_he_toggle(NeoMutt->sub, he, err);
388 }
389 else if (CONFIG_TYPE(he->type) == DT_NUMBER)
390 {
391 number_he_toggle(NeoMutt->sub, he, err);
392 }
393 else
394 {
395 buf_printf(err, _("Command '%s' can only be used with bool/quad variables"), "toggle");
396 return MUTT_CMD_ERROR;
397 }
398 return MUTT_CMD_SUCCESS;
399}
int bool_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a bool.
Definition bool.c:203
int number_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a number (value <-> 0)
Definition number.c:307
int quad_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a quad.
Definition quad.c:234
@ DT_NUMBER
a number
Definition types.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_query()

enum CommandResult command_set_query ( struct Buffer * name,
struct Buffer * err )

Query a variable.

Parameters
[in]nameName of the config variable to queried
[out]errBuffer where the pretty printed result will be written to. On failure contains the error message.
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS
Precondition
name is not NULL

This implements "set foo?". The buffer err will contain something like "set foo = bar".

Definition at line 411 of file set.c.

412{
413 ASSERT(name);
414 // In the interactive case (outside of the initial parsing of neomuttrc) we
415 // support additional syntax: "set" (no arguments) and "set all".
416 // If not in interactive mode, we recognise them but do nothing.
417
418 // Handle "set" (no arguments), i.e. show list of changed variables.
419 if (buf_is_empty(name))
420 {
421 if (StartupComplete)
422 return set_dump(GEL_CHANGED_CONFIG, err);
423 else
424 return MUTT_CMD_SUCCESS;
425 }
426 // Handle special "set all" syntax
427 if (mutt_str_equal(name->data, "all"))
428 {
429 if (StartupComplete)
430 return set_dump(GEL_ALL_CONFIG, err);
431 else
432 return MUTT_CMD_SUCCESS;
433 }
434
435 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
436 if (!he)
437 {
438 buf_printf(err, _("Unknown option %s"), name->data);
439 return MUTT_CMD_ERROR;
440 }
441
442 if (he->type & D_INTERNAL_DEPRECATED)
443 {
444 mutt_warning(_("Option %s is deprecated"), name->data);
445 return MUTT_CMD_SUCCESS;
446 }
447
448 buf_addstr(err, name->data);
449 buf_addch(err, '=');
450 struct Buffer *value = buf_pool_get();
451 int rc = cs_subset_he_string_get(NeoMutt->sub, he, value);
452 if (CSR_RESULT(rc) != CSR_SUCCESS)
453 {
454 // LCOV_EXCL_START
455 buf_reset(err);
456 buf_addstr(err, value->data);
457 buf_pool_release(&value);
458 return MUTT_CMD_ERROR;
459 // LCOV_EXCL_STOP
460 }
461 if (CONFIG_TYPE(he->type) == DT_PATH)
462 pretty_mailbox(value);
463
464 const int type = CONFIG_TYPE(he->type);
465 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
466 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT))
467 {
468 pretty_var(value->data, err);
469 }
470 else
471 {
472 buf_addstr(err, value->data);
473 }
474 buf_pool_release(&value);
475
476 return MUTT_CMD_SUCCESS;
477}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition dump.c:87
bool StartupComplete
When the config has been read.
Definition address.c:11
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:428
enum CommandResult set_dump(enum GetElemListFlags flags, struct Buffer *err)
Dump list of config variables into a file/pager.
Definition dump.c:54
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition subset.c:338
@ GEL_CHANGED_CONFIG
Only config that has been changed.
Definition subset.h:82
@ DT_SORT
sorting methods
Definition types.h:43
@ DT_LONG
a number (long)
Definition types.h:35
@ DT_ENUM
an enumeration
Definition types.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function: