NeoMutt  2024-12-12-14-g7b49f7
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 "globals.h"
#include "muttlib.h"
+ Include dependency graph for set.c:

Go to the source code of this file.

Functions

static void command_set_expand_value (uint32_t type, struct Buffer *value)
 Expand special characters.
 
static enum CommandResult command_set_set (struct Buffer *name, struct Buffer *value, struct Buffer *err)
 Set a variable to the given value.
 
static enum CommandResult command_set_increment (struct Buffer *name, struct Buffer *value, struct Buffer *err)
 Increment a variable by a value.
 
static enum CommandResult command_set_decrement (struct Buffer *name, struct Buffer *value, struct Buffer *err)
 Decrement a variable by a value.
 
static enum CommandResult command_set_unset (struct Buffer *name, struct Buffer *err)
 Unset a variable.
 
static enum CommandResult command_set_reset (struct Buffer *name, struct Buffer *err)
 Reset a variable.
 
static enum CommandResult command_set_toggle (struct Buffer *name, struct Buffer *err)
 Toggle a boolean, quad, or number variable.
 
static 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()

static void command_set_expand_value ( uint32_t  type,
struct Buffer value 
)
static

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 DTYPE(HashElem.type)
The value is expanded in-place

Definition at line 59 of file set.c.

60{
61 ASSERT(value);
62 if (DTYPE(type) == DT_PATH)
63 {
64 if (type & (D_PATH_DIR | D_PATH_FILE))
65 buf_expand_path(value);
66 else
68 }
69 else if (IS_MAILBOX(type))
70 {
71 buf_expand_path(value);
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 buf_expand_path(scratch);
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
char * HomeDir
User's home directory.
Definition: globals.c:37
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:660
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:58
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
#define IS_MAILBOX(flags)
Definition: types.h:122
#define DTYPE(t)
Definition: types.h:50
#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:40
#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()

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

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;
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 (DTYPE(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;
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:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
struct HashElem * cs_create_variable(const struct ConfigSet *cs, struct ConfigDef *cdef, struct Buffer *err)
Create and register one config item.
Definition: set.c:318
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define mutt_warning(...)
Definition: logging2.h:90
#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:230
static void command_set_expand_value(uint32_t type, struct Buffer *value)
Expand special characters.
Definition: set.c:59
Definition: set.h:64
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:51
The item stored in a Hash Table.
Definition: hash.h:43
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:44
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
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:364
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:187
#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:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_increment()

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

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;
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 (DTYPE(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:402
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_decrement()

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

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:424
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_unset()

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

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 (DTYPE(he->type) == DT_MYVAR)
275 {
276 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
277 }
278 else if ((DTYPE(he->type) == DT_BOOL) || (DTYPE(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;
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:275
int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Delete config item from a config.
Definition: subset.c:445
@ DT_BOOL
boolean option
Definition: types.h:32
@ DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_reset()

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

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 HashElem **he_list = get_elem_list(NeoMutt->sub->cs);
309 if (!he_list)
310 return MUTT_CMD_ERROR;
311
312 for (size_t i = 0; he_list[i]; i++)
313 {
314 if (DTYPE(he_list[i]->type) == DT_MYVAR)
315 cs_subset_he_delete(NeoMutt->sub, he_list[i], err);
316 else
317 cs_subset_he_reset(NeoMutt->sub, he_list[i], NULL);
318 }
319
320 FREE(&he_list);
321 return MUTT_CMD_SUCCESS;
322 }
323
324 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
325 if (!he)
326 {
327 buf_printf(err, _("Unknown option %s"), name->data);
328 return MUTT_CMD_ERROR;
329 }
330
331 if (he->type & D_INTERNAL_DEPRECATED)
332 {
333 mutt_warning(_("Option %s is deprecated"), name->data);
334 return MUTT_CMD_SUCCESS;
335 }
336
337 int rc = CSR_ERR_CODE;
338 if (DTYPE(he->type) == DT_MYVAR)
339 {
340 rc = cs_subset_he_delete(NeoMutt->sub, he, err);
341 }
342 else
343 {
344 rc = cs_subset_he_reset(NeoMutt->sub, he, err);
345 }
346 if (CSR_RESULT(rc) != CSR_SUCCESS)
347 return MUTT_CMD_ERROR;
348
349 return MUTT_CMD_SUCCESS;
350}
#define FREE(x)
Definition: memory.h:55
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:79
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:312
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ command_set_toggle()

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

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 362 of file set.c.

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

◆ command_set_query()

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

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 408 of file set.c.

409{
410 ASSERT(name);
411 // In the interactive case (outside of the initial parsing of neomuttrc) we
412 // support additional syntax: "set" (no arguments) and "set all".
413 // If not in interactive mode, we recognise them but do nothing.
414
415 // Handle "set" (no arguments), i.e. show list of changed variables.
416 if (buf_is_empty(name))
417 {
418 if (StartupComplete)
419 return set_dump(CS_DUMP_ONLY_CHANGED, err);
420 else
421 return MUTT_CMD_SUCCESS;
422 }
423 // Handle special "set all" syntax
424 if (mutt_str_equal(name->data, "all"))
425 {
426 if (StartupComplete)
427 return set_dump(CS_DUMP_NO_FLAGS, err);
428 else
429 return MUTT_CMD_SUCCESS;
430 }
431
432 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, name->data);
433 if (!he)
434 {
435 buf_printf(err, _("Unknown option %s"), name->data);
436 return MUTT_CMD_ERROR;
437 }
438
439 if (he->type & D_INTERNAL_DEPRECATED)
440 {
441 mutt_warning(_("Option %s is deprecated"), name->data);
442 return MUTT_CMD_SUCCESS;
443 }
444
445 buf_addstr(err, name->data);
446 buf_addch(err, '=');
447 struct Buffer *value = buf_pool_get();
448 int rc = cs_subset_he_string_get(NeoMutt->sub, he, value);
449 if (CSR_RESULT(rc) != CSR_SUCCESS)
450 {
451 buf_reset(err);
452 buf_addstr(err, value->data);
453 buf_pool_release(&value);
454 return MUTT_CMD_ERROR;
455 }
456 if (DTYPE(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(ConfigDumpFlags flags, struct Buffer *err)
Dump list of config variables into a file/pager.
Definition: commands.c:874
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
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
bool StartupComplete
When the config has been read.
Definition: main.c:189
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:332
+ Here is the call graph for this function:
+ Here is the caller graph for this function: