NeoMutt  2025-01-09-81-g753ae0
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 "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 default:
71 if ((*src == '\\') || (*src == '"'))
72 len += buf_addch(buf, '\\');
73 len += buf_addch(buf, src[0]);
74 }
75 }
76 return len;
77}
78
85size_t pretty_var(const char *str, struct Buffer *buf)
86{
87 if (!buf || !str)
88 return 0;
89
90 int len = 0;
91
92 len += buf_addch(buf, '"');
93 len += escape_string(buf, str);
94 len += buf_addch(buf, '"');
95
96 return len;
97}
98
108void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
109 struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
110{
111 if (!he || !value || !fp)
112 return;
113
114 const char *name = he->key.strkey;
115
116 if ((flags & CS_DUMP_ONLY_CHANGED) &&
117 (!initial || mutt_str_equal(value->data, initial->data)))
118 {
119 return;
120 }
121
122 if (he->type == DT_SYNONYM)
123 {
124 const struct ConfigDef *cdef = he->data;
125 const char *syn = (const char *) cdef->initial;
126 fprintf(fp, "# synonym: %s -> %s\n", name, syn);
127 return;
128 }
129
130 if (flags & CS_DUMP_SHOW_DOCS)
131 {
132 const struct ConfigDef *cdef = he->data;
133 fprintf(fp, "# %s\n", cdef->docs);
134 }
135
136 bool show_name = !(flags & CS_DUMP_HIDE_NAME);
137 bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
138
139 if (show_name && show_value)
140 fprintf(fp, "set ");
141 if (show_name)
142 {
143 if (flags & CS_DUMP_LINK_DOCS)
144 {
145 // Used to generate unique ids for the urls
146 static int seq_num = 1;
147
148 if (CONFIG_TYPE(he->type) == DT_MYVAR)
149 {
150 static const char *url = "https://neomutt.org/guide/configuration#set-myvar";
151 fprintf(fp, "\033]8;id=%d;%s\a%s\033]8;;\a", seq_num++, url, name);
152 }
153 else
154 {
155 char *fragment = mutt_str_dup(name);
156 for (char *underscore = fragment; (underscore = strchr(underscore, '_')); underscore++)
157 {
158 *underscore = '-';
159 }
160
161 static const char *url = "https://neomutt.org/guide/reference";
162 fprintf(fp, "\033]8;id=%d;%s#%s\a%s\033]8;;\a", seq_num++, url, fragment, name);
163 FREE(&fragment);
164 }
165 }
166 else
167 {
168 fprintf(fp, "%s", name);
169 }
170 }
171 if (show_name && show_value)
172 fprintf(fp, " = ");
173 if (show_value)
174 fprintf(fp, "%s", value->data);
175 if (show_name || show_value)
176 fprintf(fp, "\n");
177
178 if (flags & CS_DUMP_SHOW_DEFAULTS)
179 {
180 const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
181 if (cst)
182 fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
183 }
184
185 if (flags & CS_DUMP_SHOW_DOCS)
186 fprintf(fp, "\n");
187}
188
196bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea,
197 ConfigDumpFlags flags, FILE *fp)
198{
199 if (!cs || !hea || !fp)
200 return false;
201
202 bool result = true;
203
204 struct Buffer *value = buf_pool_get();
205 struct Buffer *initial = buf_pool_get();
206 struct Buffer *tmp = buf_pool_get();
207
208 struct HashElem **hep = NULL;
209 ARRAY_FOREACH(hep, hea)
210 {
211 struct HashElem *he = *hep;
212 buf_reset(value);
213 buf_reset(initial);
214 const int type = CONFIG_TYPE(he->type);
215
216 if ((type == DT_SYNONYM) && !(flags & CS_DUMP_SHOW_SYNONYMS))
217 continue;
218
219 if ((he->type & D_INTERNAL_DEPRECATED) && !(flags & CS_DUMP_SHOW_DEPRECATED))
220 continue;
221
222 if (type != DT_SYNONYM)
223 {
224 /* If necessary, get the current value */
225 if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
226 (flags & CS_DUMP_SHOW_DEFAULTS))
227 {
228 int rc = cs_he_string_get(cs, he, value);
229 if (CSR_RESULT(rc) != CSR_SUCCESS)
230 {
231 result = false; /* LCOV_EXCL_LINE */
232 break; /* LCOV_EXCL_LINE */
233 }
234
235 const struct ConfigDef *cdef = he->data;
236 if ((type == DT_STRING) && (cdef->type & D_SENSITIVE) &&
237 (flags & CS_DUMP_HIDE_SENSITIVE) && !buf_is_empty(value))
238 {
239 buf_reset(value);
240 buf_addstr(value, "***");
241 }
242
243 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (value->data[0] == '/'))
244 mutt_pretty_mailbox(value->data, value->dsize);
245
246 // Quote/escape the values of config options NOT of these types
247 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
248 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
249 !(flags & CS_DUMP_NO_ESCAPING))
250 {
251 buf_reset(tmp);
252 pretty_var(value->data, tmp);
253 buf_strcpy(value, tmp->data);
254 }
255 }
256
257 /* If necessary, get the default value */
259 {
260 int rc = cs_he_initial_get(cs, he, initial);
261 if (CSR_RESULT(rc) != CSR_SUCCESS)
262 {
263 result = false; /* LCOV_EXCL_LINE */
264 break; /* LCOV_EXCL_LINE */
265 }
266
267 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (initial->data[0] == '/'))
268 mutt_pretty_mailbox(initial->data, initial->dsize);
269
270 // Quote/escape the values of config options NOT of these types
271 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
272 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
273 !(flags & CS_DUMP_NO_ESCAPING))
274 {
275 buf_reset(tmp);
276 pretty_var(initial->data, tmp);
277 buf_strcpy(initial, tmp->data);
278 }
279 }
280 }
281
282 dump_config_neo(cs, he, value, initial, flags, fp);
283 }
284
285 buf_pool_release(&value);
287 buf_pool_release(&tmp);
288
289 return result;
290}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
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:48
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:85
bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:196
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:108
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:44
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:41
#define CS_DUMP_SHOW_DEPRECATED
Show config items that aren't used any more.
Definition: dump.h:45
#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: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:715
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:581
#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:254
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
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:83
const char * name
Name of the type, e.g. "String".
Definition: set.h:97
Container for lots of config items.
Definition: set.h:250
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
#define D_INTERNAL_DEPRECATED
Config item shouldn't be used any more.
Definition: types.h:87
@ 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