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