NeoMutt  2025-01-09-117-gace867
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 "commands.h"
#include "extract.h"
#include "muttlib.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 (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 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 58 of file set.c.

59{
60 ASSERT(value);
61 if (CONFIG_TYPE(type) == DT_PATH)
62 {
63 if (type & (D_PATH_DIR | D_PATH_FILE))
64 buf_expand_path(value);
65 else
67 }
68 else if (IS_MAILBOX(type))
69 {
70 buf_expand_path(value);
71 }
72 else if (IS_COMMAND(type))
73 {
74 struct Buffer *scratch = buf_pool_get();
75 buf_copy(scratch, value);
76
77 if (!mutt_str_equal(value->data, "builtin"))
78 {
79 buf_expand_path(scratch);
80 }
81 buf_reset(value);
82 buf_addstr(value, buf_string(scratch));
83 buf_pool_release(&scratch);
84 }
85}
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:661
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:315
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
#define ASSERT(COND)
Definition: signal2.h:60
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:43
char * home_dir
User's home directory.
Definition: neomutt.h:53
#define CONFIG_TYPE(t)
Definition: types.h:49
#define IS_MAILBOX(flags)
Definition: types.h:121
#define D_PATH_DIR
Path is a directory.
Definition: types.h:102
#define D_PATH_FILE
Path is a file.
Definition: types.h:103
@ DT_PATH
a path to a file/directory
Definition: types.h:39
#define IS_COMMAND(flags)
Definition: types.h:122
+ 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 99 of file set.c.

101{
102 ASSERT(name);
103 ASSERT(value);
104 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
105 if (!he)
106 {
107 // In case it is a my_var, we have to create it
108 if (mutt_str_startswith(name->data, "my_"))
109 {
110 struct ConfigDef my_cdef = { 0 };
111 my_cdef.name = name->data;
112 my_cdef.type = DT_MYVAR;
113 he = cs_create_variable(NeoMutt->sub->cs, &my_cdef, err);
114 if (!he)
115 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
116 }
117 else
118 {
119 buf_printf(err, _("Unknown option %s"), name->data);
120 return MUTT_CMD_ERROR;
121 }
122 }
123
124 if (he->type & D_INTERNAL_DEPRECATED)
125 {
126 mutt_warning(_("Option %s is deprecated"), name->data);
127 return MUTT_CMD_SUCCESS;
128 }
129 int rc = CSR_ERR_CODE;
130
131 if (CONFIG_TYPE(he->type) == DT_MYVAR)
132 {
133 // my variables do not expand their value
134 rc = cs_subset_he_string_set(NeoMutt->sub, he, value->data, err);
135 }
136 else
137 {
138 command_set_expand_value(he->type, value);
139 rc = cs_subset_he_string_set(NeoMutt->sub, he, value->data, err);
140 }
141 if (CSR_RESULT(rc) != CSR_SUCCESS)
142 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
143
144 return MUTT_CMD_SUCCESS;
145}
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:38
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:36
struct HashElem * cs_create_variable(const struct ConfigSet *cs, struct ConfigDef *cdef, struct Buffer *err)
Create and register one config item.
Definition: set.c:326
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:34
#define CSR_RESULT(x)
Definition: set.h:50
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:33
#define mutt_warning(...)
Definition: logging2.h:91
#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:231
void command_set_expand_value(int type, struct Buffer *value)
Expand special characters.
Definition: set.c:58
Definition: set.h:62
const char * name
User-visible name.
Definition: set.h:63
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:64
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:47
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:366
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:189
#define D_INTERNAL_DEPRECATED
Config item shouldn't be used any more.
Definition: types.h:87
@ 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 159 of file set.c.

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

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

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

302{
303 ASSERT(name);
304 // Handle special "reset all" syntax
305 if (mutt_str_equal(name->data, "all"))
306 {
307 struct HashElemArray hea = get_elem_list(NeoMutt->sub->cs, GEL_ALL_CONFIG);
308 struct HashElem **hep = NULL;
309 ARRAY_FOREACH(hep, &hea)
310 {
311 struct HashElem *he = *hep;
312 if (CONFIG_TYPE(he->type) == DT_MYVAR)
314 else
315 cs_subset_he_reset(NeoMutt->sub, he, NULL);
316 }
317
318 ARRAY_FREE(&hea);
319 return MUTT_CMD_SUCCESS;
320 }
321
322 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
323 if (!he)
324 {
325 buf_printf(err, _("Unknown option %s"), name->data);
326 return MUTT_CMD_ERROR;
327 }
328
329 if (he->type & D_INTERNAL_DEPRECATED)
330 {
331 mutt_warning(_("Option %s is deprecated"), name->data);
332 return MUTT_CMD_SUCCESS;
333 }
334
335 int rc = CSR_ERR_CODE;
336 if (CONFIG_TYPE(he->type) == DT_MYVAR)
337 {
338 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
339 }
340 else
341 {
342 rc = cs_subset_he_reset(NeoMutt->sub, he, err);
343 }
344 if (CSR_RESULT(rc) != CSR_SUCCESS)
345 return MUTT_CMD_ERROR; // LCOV_EXCL_LINE
346
347 return MUTT_CMD_SUCCESS;
348}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:214
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
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:314
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition: subset.c:80
@ 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 360 of file set.c.

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

407{
408 ASSERT(name);
409 // In the interactive case (outside of the initial parsing of neomuttrc) we
410 // support additional syntax: "set" (no arguments) and "set all".
411 // If not in interactive mode, we recognise them but do nothing.
412
413 // Handle "set" (no arguments), i.e. show list of changed variables.
414 if (buf_is_empty(name))
415 {
416 if (StartupComplete)
417 return set_dump(GEL_CHANGED_CONFIG, err);
418 else
419 return MUTT_CMD_SUCCESS;
420 }
421 // Handle special "set all" syntax
422 if (mutt_str_equal(name->data, "all"))
423 {
424 if (StartupComplete)
425 return set_dump(GEL_ALL_CONFIG, err);
426 else
427 return MUTT_CMD_SUCCESS;
428 }
429
430 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
431 if (!he)
432 {
433 buf_printf(err, _("Unknown option %s"), name->data);
434 return MUTT_CMD_ERROR;
435 }
436
437 if (he->type & D_INTERNAL_DEPRECATED)
438 {
439 mutt_warning(_("Option %s is deprecated"), name->data);
440 return MUTT_CMD_SUCCESS;
441 }
442
443 buf_addstr(err, name->data);
444 buf_addch(err, '=');
445 struct Buffer *value = buf_pool_get();
446 int rc = cs_subset_he_string_get(NeoMutt->sub, he, value);
447 if (CSR_RESULT(rc) != CSR_SUCCESS)
448 {
449 // LCOV_EXCL_START
450 buf_reset(err);
451 buf_addstr(err, value->data);
452 buf_pool_release(&value);
453 return MUTT_CMD_ERROR;
454 // LCOV_EXCL_STOP
455 }
456 if (CONFIG_TYPE(he->type) == DT_PATH)
457 mutt_pretty_mailbox(value->data, value->dsize);
458 pretty_var(value->data, err);
459 buf_pool_release(&value);
460
461 return MUTT_CMD_SUCCESS;
462}
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
enum CommandResult set_dump(enum GetElemListFlags flags, struct Buffer *err)
Dump list of config variables into a file/pager.
Definition: commands.c:888
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:85
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:440
bool StartupComplete
When the config has been read.
Definition: address.c:14
size_t dsize
Length of data.
Definition: buffer.h:39
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:334
@ 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: