NeoMutt  2025-12-11-117-gc1a713
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
dump.c
Go to the documentation of this file.
1
24
30
31#include "config.h"
32#include <stdbool.h>
33#include <stdio.h>
34#include <string.h>
35#include "mutt/lib.h"
36#include "dump.h"
37#include "set.h"
38#include "types.h"
39
40void mutt_pretty_mailbox(char *buf, size_t buflen);
41
48size_t escape_string(struct Buffer *buf, const char *src)
49{
50 if (!buf || !src)
51 return 0;
52
53 size_t len = 0;
54 for (; *src; src++)
55 {
56 switch (*src)
57 {
58 case '\007':
59 len += buf_addstr(buf, "\\g");
60 break;
61 case '\n':
62 len += buf_addstr(buf, "\\n");
63 break;
64 case '\r':
65 len += buf_addstr(buf, "\\r");
66 break;
67 case '\t':
68 len += buf_addstr(buf, "\\t");
69 break;
70 case '`':
71 len += buf_addstr(buf, "\\`");
72 break;
73 default:
74 if ((*src == '\\') || (*src == '"'))
75 len += buf_addch(buf, '\\');
76 len += buf_addch(buf, src[0]);
77 }
78 }
79 return len;
80}
81
88size_t pretty_var(const char *str, struct Buffer *buf)
89{
90 if (!buf || !str)
91 return 0;
92
93 int len = 0;
94
95 len += buf_addch(buf, '"');
96 len += escape_string(buf, str);
97 len += buf_addch(buf, '"');
98
99 return len;
100}
101
111void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
112 struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
113{
114 if (!he || !value || !fp)
115 return;
116
117 const char *name = he->key.strkey;
118
119 if ((flags & CS_DUMP_ONLY_CHANGED) &&
120 (!initial || mutt_str_equal(value->data, initial->data)))
121 {
122 return;
123 }
124
125 if (he->type == DT_SYNONYM)
126 {
127 const struct ConfigDef *cdef = he->data;
128 const char *syn = (const char *) cdef->initial;
129 fprintf(fp, "# synonym: %s -> %s\n", name, syn);
130 return;
131 }
132
133 if (flags & CS_DUMP_SHOW_DOCS)
134 {
135 const struct ConfigDef *cdef = he->data;
136 fprintf(fp, "# %s\n", cdef->docs);
137 }
138
139 bool show_name = !(flags & CS_DUMP_HIDE_NAME);
140 bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
141
142 if (show_name && show_value)
143 fprintf(fp, "set ");
144 if (show_name)
145 {
146 if (flags & CS_DUMP_LINK_DOCS)
147 {
148 // Used to generate unique ids for the urls
149 static int seq_num = 1;
150
151 if (CONFIG_TYPE(he->type) == DT_MYVAR)
152 {
153 static const char *url = "https://neomutt.org/guide/configuration#set-myvar";
154 fprintf(fp, "\033]8;id=%d;%s\a%s\033]8;;\a", seq_num++, url, name);
155 }
156 else
157 {
158 char *fragment = mutt_str_dup(name);
159 for (char *underscore = fragment; (underscore = strchr(underscore, '_')); underscore++)
160 {
161 *underscore = '-';
162 }
163
164 static const char *url = "https://neomutt.org/guide/reference";
165 fprintf(fp, "\033]8;id=%d;%s#%s\a%s\033]8;;\a", seq_num++, url, fragment, name);
166 FREE(&fragment);
167 }
168 }
169 else
170 {
171 fprintf(fp, "%s", name);
172 }
173 }
174 if (show_name && show_value)
175 fprintf(fp, " = ");
176 if (show_value)
177 fprintf(fp, "%s", value->data);
178 if (show_name || show_value)
179 fprintf(fp, "\n");
180
181 if (flags & CS_DUMP_SHOW_DEFAULTS)
182 {
183 const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
184 if (cst)
185 fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
186 }
187
188 if (flags & CS_DUMP_SHOW_DOCS)
189 fprintf(fp, "\n");
190}
191
199bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea,
200 ConfigDumpFlags flags, FILE *fp)
201{
202 if (!cs || !hea || !fp)
203 return false;
204
205 bool result = true;
206
207 struct Buffer *value = buf_pool_get();
208 struct Buffer *initial = buf_pool_get();
209 struct Buffer *tmp = buf_pool_get();
210
211 struct HashElem **hep = NULL;
212 ARRAY_FOREACH(hep, hea)
213 {
214 struct HashElem *he = *hep;
215 buf_reset(value);
216 buf_reset(initial);
217 const int type = CONFIG_TYPE(he->type);
218
219 /* If necessary, get the current value */
220 if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
221 (flags & CS_DUMP_SHOW_DEFAULTS))
222 {
223 int rc = cs_he_string_get(cs, he, value);
224 if (CSR_RESULT(rc) != CSR_SUCCESS)
225 {
226 result = false; /* LCOV_EXCL_LINE */
227 break; /* LCOV_EXCL_LINE */
228 }
229
230 const struct ConfigDef *cdef = he->data;
231 if ((type == DT_STRING) && (cdef->type & D_SENSITIVE) &&
232 (flags & CS_DUMP_HIDE_SENSITIVE) && !buf_is_empty(value))
233 {
234 buf_reset(value);
235 buf_addstr(value, "***");
236 }
237
238 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (buf_at(value, 0) == '/'))
239 mutt_pretty_mailbox(value->data, value->dsize);
240
241 // Quote/escape the values of config options NOT of these types
242 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
243 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
244 !(flags & CS_DUMP_NO_ESCAPING))
245 {
246 buf_reset(tmp);
247 pretty_var(value->data, tmp);
248 buf_strcpy(value, tmp->data);
249 }
250 }
251
252 /* If necessary, get the default value */
254 {
255 int rc = cs_he_initial_get(cs, he, initial);
256 if (CSR_RESULT(rc) != CSR_SUCCESS)
257 {
258 result = false; /* LCOV_EXCL_LINE */
259 break; /* LCOV_EXCL_LINE */
260 }
261
262 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (buf_at(initial, 0) == '/'))
263 mutt_pretty_mailbox(initial->data, initial->dsize);
264
265 // Quote/escape the values of config options NOT of these types
266 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
267 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
268 !(flags & CS_DUMP_NO_ESCAPING))
269 {
270 buf_reset(tmp);
271 pretty_var(initial->data, tmp);
272 buf_strcpy(initial, tmp->data);
273 }
274 }
275
276 dump_config_neo(cs, he, value, initial, flags, fp);
277 }
278
279 buf_pool_release(&value);
281 buf_pool_release(&tmp);
282
283 return result;
284}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition dump.c:48
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition dump.c:88
bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition dump.c:199
void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
Dump the config in the style of NeoMutt.
Definition dump.c:111
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:440
Dump all the config.
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition dump.h:41
#define CS_DUMP_NO_ESCAPING
Do not escape special chars, or quote the string.
Definition dump.h:39
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition dump.h:38
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition dump.h:35
#define CS_DUMP_LINK_DOCS
Link to the online docs.
Definition dump.h:47
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition dump.h:37
#define CS_DUMP_HIDE_NAME
Do not print the name of the config item.
Definition dump.h:40
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition dump.h:42
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition dump.h:46
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition set.c:199
int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition set.c:692
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition set.c:558
A collection of config items.
#define CSR_RESULT(x)
Definition set.h:50
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define FREE(x)
Definition memory.h:63
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
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
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
const char * name
User-visible name.
Definition set.h:63
intptr_t initial
Initial value.
Definition set.h:65
uint32_t type
Variable type, e.g. DT_STRING.
Definition set.h:64
const char * docs
One-liner description.
Definition set.h:81
const char * name
Name of the type, e.g. "String".
Definition set.h:95
Container for lots of config items.
Definition set.h:248
The item stored in a Hash Table.
Definition hash.h:44
union HashKey key
Key representing the data.
Definition hash.h:46
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
void * data
User-supplied data.
Definition hash.h:47
Constants for all the config types.
#define CONFIG_TYPE(t)
Definition types.h:49
#define IS_MAILBOX(flags)
Definition types.h:121
@ DT_NUMBER
a number
Definition types.h:38
@ DT_BOOL
boolean option
Definition types.h:32
@ DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition types.h:40
@ DT_SYNONYM
synonym for another variable
Definition types.h:45
@ DT_STRING
a string
Definition types.h:44
@ DT_SORT
sorting methods
Definition types.h:43
@ DT_MYVAR
a user-defined variable (my_foo)
Definition types.h:37
@ DT_LONG
a number (long)
Definition types.h:35
@ DT_ENUM
an enumeration
Definition types.h:33
@ DT_PATH
a path to a file/directory
Definition types.h:39
#define D_SENSITIVE
Contains sensitive value, e.g. password.
Definition types.h:80
const char * strkey
String key.
Definition hash.h:36