NeoMutt  2025-12-11-435-g4ac674
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:662
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:121
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 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
144
145 return MUTT_CMD_SUCCESS;
146}
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
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_ERR_CODE
Problem with the code.
Definition set.h:34
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:52
#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:65
uint32_t type
Variable type, e.g. DT_STRING.
Definition set.h:66
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 160 of file set.c.

162{
163 ASSERT(name);
164 ASSERT(value);
165 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
166 if (!he)
167 {
168 // In case it is a my_var, we have to create it
169 if (mutt_str_startswith(name->data, "my_"))
170 {
171 struct ConfigDef my_cdef = { 0 };
172 my_cdef.name = name->data;
173 my_cdef.type = DT_MYVAR;
174 he = cs_create_variable(NeoMutt->sub->cs, &my_cdef, err);
175 if (!he)
176 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
177 }
178 else
179 {
180 buf_printf(err, _("Unknown option %s"), name->data);
181 return MUTT_CMD_ERROR;
182 }
183 }
184
185 if (he->type & D_INTERNAL_DEPRECATED)
186 {
187 mutt_warning(_("Option %s is deprecated"), name->data);
188 return MUTT_CMD_SUCCESS;
189 }
190
191 int rc = CSR_ERR_CODE;
192
193 if (CONFIG_TYPE(he->type) == DT_MYVAR)
194 {
195 // my variables do not expand their value
196 rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, value->data, err);
197 }
198 else
199 {
200 command_set_expand_value(he->type, value);
201 rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, value->data, err);
202 }
203 if (CSR_RESULT(rc) != CSR_SUCCESS)
204 return MUTT_CMD_ERROR;
205
206 return MUTT_CMD_SUCCESS;
207}
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 221 of file set.c.

223{
224 ASSERT(name);
225 ASSERT(value);
226 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
227 if (!he)
228 {
229 buf_printf(err, _("Unknown option %s"), name->data);
230 return MUTT_CMD_ERROR;
231 }
232
233 if (he->type & D_INTERNAL_DEPRECATED)
234 {
235 mutt_warning(_("Option %s is deprecated"), name->data);
236 return MUTT_CMD_SUCCESS;
237 }
238
239 command_set_expand_value(he->type, value);
240 int rc = cs_subset_he_string_minus_equals(NeoMutt->sub, he, value->data, err);
241 if (CSR_RESULT(rc) != CSR_SUCCESS)
242 return MUTT_CMD_ERROR;
243
244 return MUTT_CMD_SUCCESS;
245}
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 257 of file set.c.

258{
259 ASSERT(name);
260 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
261 if (!he)
262 {
263 buf_printf(err, _("Unknown option %s"), name->data);
264 return MUTT_CMD_ERROR;
265 }
266
267 if (he->type & D_INTERNAL_DEPRECATED)
268 {
269 mutt_warning(_("Option %s is deprecated"), name->data);
270 return MUTT_CMD_SUCCESS;
271 }
272
273 int rc = CSR_ERR_CODE;
274 if (CONFIG_TYPE(he->type) == DT_MYVAR)
275 {
276 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
277 }
278 else if ((CONFIG_TYPE(he->type) == DT_BOOL) || (CONFIG_TYPE(he->type) == DT_QUAD))
279 {
280 rc = cs_subset_he_native_set(NeoMutt->sub, he, false, err);
281 }
282 else
283 {
284 rc = cs_subset_he_string_set(NeoMutt->sub, he, NULL, err);
285 }
286 if (CSR_RESULT(rc) != CSR_SUCCESS)
287 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
288
289 return MUTT_CMD_SUCCESS;
290}
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 302 of file set.c.

303{
304 ASSERT(name);
305 // Handle special "reset all" syntax
306 if (mutt_str_equal(name->data, "all"))
307 {
308 struct HashElemArray hea = get_elem_list(NeoMutt->sub->cs, GEL_ALL_CONFIG);
309 struct HashElem **hep = NULL;
310 ARRAY_FOREACH(hep, &hea)
311 {
312 struct HashElem *he = *hep;
313 if (CONFIG_TYPE(he->type) == DT_MYVAR)
315 else
316 cs_subset_he_reset(NeoMutt->sub, he, NULL);
317 }
318
319 ARRAY_FREE(&hea);
320 return MUTT_CMD_SUCCESS;
321 }
322
323 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
324 if (!he)
325 {
326 buf_printf(err, _("Unknown option %s"), name->data);
327 return MUTT_CMD_ERROR;
328 }
329
330 if (he->type & D_INTERNAL_DEPRECATED)
331 {
332 mutt_warning(_("Option %s is deprecated"), name->data);
333 return MUTT_CMD_SUCCESS;
334 }
335
336 int rc = CSR_ERR_CODE;
337 if (CONFIG_TYPE(he->type) == DT_MYVAR)
338 {
339 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
340 }
341 else
342 {
343 rc = cs_subset_he_reset(NeoMutt->sub, he, err);
344 }
345 if (CSR_RESULT(rc) != CSR_SUCCESS)
346 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
347
348 return MUTT_CMD_SUCCESS;
349}
#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 361 of file set.c.

362{
363 ASSERT(name);
364 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
365 if (!he)
366 {
367 buf_printf(err, _("Unknown option %s"), name->data);
368 return MUTT_CMD_ERROR;
369 }
370
371 if (he->type & D_INTERNAL_DEPRECATED)
372 {
373 mutt_warning(_("Option %s is deprecated"), name->data);
374 return MUTT_CMD_SUCCESS;
375 }
376
377 if (CONFIG_TYPE(he->type) == DT_BOOL)
378 {
379 bool_he_toggle(NeoMutt->sub, he, err);
380 }
381 else if (CONFIG_TYPE(he->type) == DT_QUAD)
382 {
383 quad_he_toggle(NeoMutt->sub, he, err);
384 }
385 else if (CONFIG_TYPE(he->type) == DT_NUMBER)
386 {
387 number_he_toggle(NeoMutt->sub, he, err);
388 }
389 else
390 {
391 buf_printf(err, _("Command '%s' can only be used with bool/quad variables"), "toggle");
392 return MUTT_CMD_ERROR;
393 }
394 return MUTT_CMD_SUCCESS;
395}
int bool_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a bool.
Definition bool.c:201
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:224
@ 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 407 of file set.c.

408{
409 ASSERT(name);
410 // In the interactive case (outside of the initial parsing of neomuttrc) we
411 // support additional syntax: "set" (no arguments) and "set all".
412 // If not in interactive mode, we recognise them but do nothing.
413
414 // Handle "set" (no arguments), i.e. show list of changed variables.
415 if (buf_is_empty(name))
416 {
417 if (StartupComplete)
418 return set_dump(GEL_CHANGED_CONFIG, err);
419 else
420 return MUTT_CMD_SUCCESS;
421 }
422 // Handle special "set all" syntax
423 if (mutt_str_equal(name->data, "all"))
424 {
425 if (StartupComplete)
426 return set_dump(GEL_ALL_CONFIG, err);
427 else
428 return MUTT_CMD_SUCCESS;
429 }
430
431 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
432 if (!he)
433 {
434 buf_printf(err, _("Unknown option %s"), name->data);
435 return MUTT_CMD_ERROR;
436 }
437
438 if (he->type & D_INTERNAL_DEPRECATED)
439 {
440 mutt_warning(_("Option %s is deprecated"), name->data);
441 return MUTT_CMD_SUCCESS;
442 }
443
444 buf_addstr(err, name->data);
445 buf_addch(err, '=');
446 struct Buffer *value = buf_pool_get();
447 int rc = cs_subset_he_string_get(NeoMutt->sub, he, value);
448 if (CSR_RESULT(rc) != CSR_SUCCESS)
449 {
450 // LCOV_EXCL_START
451 buf_reset(err);
452 buf_addstr(err, value->data);
453 buf_pool_release(&value);
454 return MUTT_CMD_ERROR;
455 // LCOV_EXCL_STOP
456 }
457 if (CONFIG_TYPE(he->type) == DT_PATH)
458 pretty_mailbox(value);
459 pretty_var(value->data, err);
460 buf_pool_release(&value);
461
462 return MUTT_CMD_SUCCESS;
463}
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:427
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function: