1 /**
2  * @file
3  * Definitions of config variables
4  *
5  * @authors
6  * Copyright (C) 1996-2002,2007,2010,2012-2013,2016 Michael R. Elkins <me@mutt.org>
7  * Copyright (C) 2004 g10 Code GmbH
8  *
9  * @copyright
10  * This program is free software: you can redistribute it and/or modify it under
11  * the terms of the GNU General Public License as published by the Free Software
12  * Foundation, either version 2 of the License, or (at your option) any later
13  * version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 /**
25  * @page neo_mutt_config Definitions of config variables
26  *
27  * Definitions of config variables
28  */
29 
30 #include "config.h"
31 #include <stddef.h>
32 #include <stdbool.h>
33 #include <stdint.h>
34 #include "mutt/lib.h"
35 #include "config/lib.h"
36 #include "core/lib.h"
37 #include "init.h"
38 #include "mutt_logging.h"
39 #include "mutt_thread.h"
40 #include "mx.h"
41 #include "options.h"
42 
43 #define CONFIG_INIT_TYPE(CS, NAME)                                             \
44   extern const struct ConfigSetType Cst##NAME;                                 \
45   cs_register_type(CS, &Cst##NAME)
46 
47 #define CONFIG_INIT_VARS(CS, NAME)                                             \
48   bool config_init_##NAME(struct ConfigSet *cs);                               \
49   config_init_##NAME(CS)
50 
51 /**
52  * SortAuxMethods - Sort methods for '$sort_aux' for the index
53  */
54 static const struct Mapping SortAuxMethods[] = {
55   // clang-format off
56   { "date",          SORT_DATE },
57   { "date-sent",     SORT_DATE },
58   { "threads",       SORT_DATE },
59   { "date-received", SORT_RECEIVED },
60   { "from",          SORT_FROM },
61   { "label",         SORT_LABEL },
62   { "unsorted",      SORT_ORDER },
63   { "mailbox-order", SORT_ORDER },
64   { "score",         SORT_SCORE },
65   { "size",          SORT_SIZE },
66   { "spam",          SORT_SPAM },
67   { "subject",       SORT_SUBJECT },
68   { "to",            SORT_TO },
69   { NULL, 0 },
70   // clang-format on
71 };
72 
73 /**
74  * SortMethods - Sort methods for '$sort' for the index
75  */
76 const struct Mapping SortMethods[] = {
77   // clang-format off
78   { "date",          SORT_DATE },
79   { "date-sent",     SORT_DATE },
80   { "date-received", SORT_RECEIVED },
81   { "from",          SORT_FROM },
82   { "label",         SORT_LABEL },
83   { "unsorted",      SORT_ORDER },
84   { "mailbox-order", SORT_ORDER },
85   { "score",         SORT_SCORE },
86   { "size",          SORT_SIZE },
87   { "spam",          SORT_SPAM },
88   { "subject",       SORT_SUBJECT },
89   { "threads",       SORT_THREADS },
90   { "to",            SORT_TO },
91   { NULL, 0 },
92   // clang-format on
93 };
94 
95 /**
96  * SortBrowserMethods - Sort methods for the folder/dir browser
97  */
98 const struct Mapping SortBrowserMethods[] = {
99   // clang-format off
100   { "alpha",    SORT_SUBJECT },
101   { "count",    SORT_COUNT },
102   { "date",     SORT_DATE },
103   { "desc",     SORT_DESC },
104   { "new",      SORT_UNREAD },
105   { "unread",   SORT_UNREAD },
106   { "size",     SORT_SIZE },
107   { "unsorted", SORT_ORDER },
108   { NULL, 0 },
109   // clang-format on
110 };
111 
112 /**
113  * multipart_validator - Validate the "show_multipart_alternative" config variable - Implements ConfigDef::validator() - @ingroup cfg_def_validator
114  */
multipart_validator(const struct ConfigSet * cs,const struct ConfigDef * cdef,intptr_t value,struct Buffer * err)115 int multipart_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
116                         intptr_t value, struct Buffer *err)
117 {
118   if (value == 0)
119     return CSR_SUCCESS;
120 
121   const char *str = (const char *) value;
122 
123   if (mutt_str_equal(str, "inline") || mutt_str_equal(str, "info"))
124     return CSR_SUCCESS;
125 
126   mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, str);
127   return CSR_ERR_INVALID;
128 }
129 
130 /**
131  * reply_validator - Validate the "reply_regex" config variable - Implements ConfigDef::validator() - @ingroup cfg_def_validator
132  */
reply_validator(const struct ConfigSet * cs,const struct ConfigDef * cdef,intptr_t value,struct Buffer * err)133 int reply_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
134                     intptr_t value, struct Buffer *err)
135 {
136   if (!OptAttachMsg)
137     return CSR_SUCCESS;
138 
139   mutt_buffer_printf(err, _("Option %s may not be set when in attach-message mode"),
140                      cdef->name);
141   return CSR_ERR_INVALID;
142 }
143 
144 static struct ConfigDef MainVars[] = {
145   // clang-format off
146   { "abort_backspace", DT_BOOL, true, 0, NULL,
147     "Hitting backspace against an empty prompt aborts the prompt"
148   },
149   { "abort_key", DT_STRING|DT_NOT_EMPTY, IP "\007", 0, NULL,
150     "String representation of key to abort prompts"
151   },
152   { "arrow_cursor", DT_BOOL|R_MENU, false, 0, NULL,
153     "Use an arrow '->' instead of highlighting in the index"
154   },
155   { "arrow_string", DT_STRING|DT_NOT_EMPTY, IP "->", 0, NULL,
156     "Use an custom string for arrow_cursor"
157   },
158   { "ascii_chars", DT_BOOL|R_INDEX|R_PAGER, false, 0, NULL,
159     "Use plain ASCII characters, when drawing email threads"
160   },
161   { "ask_bcc", DT_BOOL, false, 0, NULL,
162     "Ask the user for the blind-carbon-copy recipients"
163   },
164   { "ask_cc", DT_BOOL, false, 0, NULL,
165     "Ask the user for the carbon-copy recipients"
166   },
167   { "assumed_charset", DT_STRING, 0, 0, charset_validator,
168     "If a message is missing a character set, assume this character set"
169   },
170   { "attach_format", DT_STRING|DT_NOT_EMPTY, IP "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] ", 0, NULL,
171     "printf-like format string for the attachment menu"
172   },
173   { "attach_save_dir", DT_PATH|DT_PATH_DIR, IP "./", 0, NULL,
174     "Default directory where attachments are saved"
175   },
176   { "attach_save_without_prompting", DT_BOOL, false, 0, NULL,
177     "If true, then don't prompt to save"
178   },
179   { "attach_sep", DT_STRING, IP "\n", 0, NULL,
180     "Separator to add between saved/printed/piped attachments"
181   },
182   { "attach_split", DT_BOOL, true, 0, NULL,
183     "Save/print/pipe tagged messages individually"
184   },
185   { "attribution", DT_STRING, IP "On %d, %n wrote:", 0, NULL,
186     "Message to start a reply, 'On DATE, PERSON wrote:'"
187   },
188   { "attribution_locale", DT_STRING, 0, 0, NULL,
189     "Locale for dates in the attribution message"
190   },
191   { "auto_edit", DT_BOOL, false, 0, NULL,
192     "Skip the initial compose menu and edit the email"
193   },
194   { "auto_subscribe", DT_BOOL, false, 0, NULL,
195     "Automatically check if the user is subscribed to a mailing list"
196   },
197   { "auto_tag", DT_BOOL, false, 0, NULL,
198     "Automatically apply actions to all tagged messages"
199   },
200   { "beep", DT_BOOL, true, 0, NULL,
201     "Make a noise when an error occurs"
202   },
203   { "beep_new", DT_BOOL, false, 0, NULL,
204     "Make a noise when new mail arrives"
205   },
206   { "bounce", DT_QUAD, MUTT_ASKYES, 0, NULL,
207     "Confirm before bouncing a message"
208   },
209   { "braille_friendly", DT_BOOL, false, 0, NULL,
210     "Move the cursor to the beginning of the line"
211   },
212   { "browser_abbreviate_mailboxes", DT_BOOL, true, 0, NULL,
213     "Abbreviate mailboxes using '~' and '=' in the browser"
214   },
215   { "charset", DT_STRING|DT_NOT_EMPTY|DT_CHARSET_SINGLE, 0, 0, charset_validator,
216     "Default character set for displaying text on screen"
217   },
218   { "collapse_flagged", DT_BOOL, true, 0, NULL,
219     "Prevent the collapse of threads with flagged emails"
220   },
221   { "collapse_unread", DT_BOOL, true, 0, NULL,
222     "Prevent the collapse of threads with unread emails"
223   },
224   { "config_charset", DT_STRING, 0, 0, charset_validator,
225     "Character set that the config files are in"
226   },
227   { "confirm_append", DT_BOOL, true, 0, NULL,
228     "Confirm before appending emails to a mailbox"
229   },
230   { "confirm_create", DT_BOOL, true, 0, NULL,
231     "Confirm before creating a new mailbox"
232   },
233   { "copy_decode_weed", DT_BOOL, false, 0, NULL,
234     "Controls whether to weed headers when copying or saving emails"
235   },
236   { "count_alternatives", DT_BOOL, false, 0, NULL,
237     "Recurse inside multipart/alternatives while counting attachments"
238   },
239   { "crypt_chars", DT_MBTABLE|R_INDEX|R_PAGER, IP "SPsK ", 0, NULL,
240     "User-configurable crypto flags: signed, encrypted etc."
241   },
242   { "date_format", DT_STRING|DT_NOT_EMPTY|R_MENU, IP "!%a, %b %d, %Y at %I:%M:%S%p %Z", 0, NULL,
243     "strftime format string for the `%d` expando"
244   },
245   { "debug_file", DT_PATH|DT_PATH_FILE, IP "~/.neomuttdebug", 0, NULL,
246     "File to save debug logs"
247   },
248   { "debug_level", DT_NUMBER, 0, 0, level_validator,
249     "Logging level for debug logs"
250   },
251   { "default_hook", DT_STRING, IP "~f %s !~P | (~P ~C %s)", 0, NULL,
252     "Pattern to use for hooks that only have a simple regex"
253   },
254   { "delete", DT_QUAD, MUTT_ASKYES, 0, NULL,
255     "Really delete messages, when the mailbox is closed"
256   },
257   { "delete_untag", DT_BOOL, true, 0, NULL,
258     "Untag messages when they are marked for deletion"
259   },
260   { "digest_collapse", DT_BOOL, true, 0, NULL,
261     "Hide the subparts of a multipart/digest"
262   },
263   { "display_filter", DT_STRING|DT_COMMAND|R_PAGER, 0, 0, NULL,
264     "External command to pre-process an email before display"
265   },
266   { "duplicate_threads", DT_BOOL|R_RESORT|R_RESORT_INIT|R_INDEX, true, 0, NULL,
267     "Highlight messages with duplicated message IDs"
268   },
269   { "editor", DT_STRING|DT_NOT_EMPTY|DT_COMMAND, 0, 0, NULL,
270     "External command to use as an email editor"
271   },
272   { "flag_chars", DT_MBTABLE|R_INDEX|R_PAGER, IP "*!DdrONon- ", 0, NULL,
273     "User-configurable index flags: tagged, new, etc"
274   },
275   { "flag_safe", DT_BOOL, false, 0, NULL,
276     "Protect flagged messages from deletion"
277   },
278   { "folder", DT_STRING|DT_MAILBOX, IP "~/Mail", 0, NULL,
279     "Base folder for a set of mailboxes"
280   },
281   { "folder_format", DT_STRING|DT_NOT_EMPTY|R_MENU, IP "%2C %t %N %F %2l %-8.8u %-8.8g %8s %d %i", 0, NULL,
282     "printf-like format string for the browser's display of folders"
283   },
284   { "force_name", DT_BOOL, false, 0, NULL,
285     "Save outgoing mail in a folder of their name"
286   },
287   { "forward_attachments", DT_QUAD, MUTT_ASKYES, 0, NULL,
288     "Forward attachments when forwarding a message"
289   },
290   { "forward_decode", DT_BOOL, true, 0, NULL,
291     "Decode the message when forwarding it"
292   },
293   { "forward_quote", DT_BOOL, false, 0, NULL,
294     "Automatically quote a forwarded message using `$indent_string`"
295   },
296   { "from", DT_ADDRESS, 0, 0, NULL,
297     "Default 'From' address to use, if isn't otherwise set"
298   },
299   { "from_chars", DT_MBTABLE|R_INDEX|R_PAGER, 0, 0, NULL,
300     "User-configurable index flags: to address, cc address, etc"
301   },
302   { "gecos_mask", DT_REGEX, IP "^[^,]*", 0, NULL,
303     "Regex for parsing GECOS field of /etc/passwd"
304   },
305   { "greeting", DT_STRING, 0, 0, NULL,
306     "Greeting string added to the top of all messages"
307   },
308   { "header", DT_BOOL, false, 0, NULL,
309     "Include the message headers in the reply email (Weed applies)"
310   },
311   { "hidden_tags", DT_SLIST|SLIST_SEP_COMMA, IP "unread,draft,flagged,passed,replied,attachment,signed,encrypted", 0, NULL,
312     "List of tags that shouldn't be displayed on screen (comma-separated)"
313   },
314   { "hide_limited", DT_BOOL|R_TREE|R_INDEX, false, 0, NULL,
315     "Don't indicate hidden messages, in the thread tree"
316   },
317   { "hide_missing", DT_BOOL|R_TREE|R_INDEX, true, 0, NULL,
318     "Don't indicate missing messages, in the thread tree"
319   },
320   { "hide_thread_subject", DT_BOOL|R_TREE|R_INDEX, true, 0, NULL,
321     "Hide subjects that are similar to that of the parent message"
322   },
323   { "hide_top_limited", DT_BOOL|R_TREE|R_INDEX, false, 0, NULL,
324     "Don't indicate hidden top message, in the thread tree"
325   },
326   { "hide_top_missing", DT_BOOL|R_TREE|R_INDEX, true, 0, NULL,
327     "Don't indicate missing top message, in the thread tree"
328   },
329   { "honor_disposition", DT_BOOL, false, 0, NULL,
330     "Don't display MIME parts inline if they have a disposition of 'attachment'"
331   },
332   { "hostname", DT_STRING, 0, 0, NULL,
333     "Fully-qualified domain name of this machine"
334   },
335 #ifdef HAVE_LIBIDN
336   { "idn_decode", DT_BOOL|R_MENU, true, 0, NULL,
337     "(idn) Decode international domain names"
338   },
339   { "idn_encode", DT_BOOL|R_MENU, true, 0, NULL,
340     "(idn) Encode international domain names"
341   },
342 #endif
343   { "implicit_autoview", DT_BOOL, false, 0, NULL,
344     "Display MIME attachments inline if a 'copiousoutput' mailcap entry exists"
345   },
346   { "include_encrypted", DT_BOOL, false, 0, NULL,
347     "Whether to include encrypted content when replying"
348   },
349   { "include_only_first", DT_BOOL, false, 0, NULL,
350     "Only include the first attachment when replying"
351   },
352   { "indent_string", DT_STRING, IP "> ", 0, NULL,
353     "String used to indent 'reply' text"
354   },
355   { "index_format", DT_STRING|DT_NOT_EMPTY|R_INDEX|R_PAGER, IP "%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s", 0, NULL,
356     "printf-like format string for the index menu (emails)"
357   },
358   { "keep_flagged", DT_BOOL, false, 0, NULL,
359     "Don't move flagged messages from `$spool_file` to `$mbox`"
360   },
361   { "local_date_header", DT_BOOL, true, 0, NULL,
362     "Convert the date in the Date header of sent emails into local timezone, UTC otherwise"
363   },
364   { "mail_check", DT_NUMBER|DT_NOT_NEGATIVE, 5, 0, NULL,
365     "Number of seconds before NeoMutt checks for new mail"
366   },
367   { "mail_check_recent", DT_BOOL, true, 0, NULL,
368     "Notify the user about new mail since the last time the mailbox was opened"
369   },
370   { "mail_check_stats", DT_BOOL, false, 0, NULL,
371     "Periodically check for new mail"
372   },
373   { "mail_check_stats_interval", DT_NUMBER|DT_NOT_NEGATIVE, 60, 0, NULL,
374     "How often to check for new mail"
375   },
376   { "mailcap_path", DT_SLIST|SLIST_SEP_COLON, IP "~/.mailcap:" PKGDATADIR "/mailcap:" SYSCONFDIR "/mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap", 0, NULL,
377     "List of mailcap files (colon-separated)"
378   },
379   { "mailcap_sanitize", DT_BOOL, true, 0, NULL,
380     "Restrict the possible characters in mailcap expandos"
381   },
382   { "mark_old", DT_BOOL|R_INDEX|R_PAGER, true, 0, NULL,
383     "Mark new emails as old when leaving the mailbox"
384   },
385   { "markers", DT_BOOL|R_PAGER_FLOW, true, 0, NULL,
386     "Display a '+' at the beginning of wrapped lines in the pager"
387   },
388   { "mask", DT_REGEX|DT_REGEX_MATCH_CASE|DT_REGEX_ALLOW_NOT|DT_REGEX_NOSUB, IP "!^\\.[^.]", 0, NULL,
389     "Only display files/dirs matching this regex in the browser"
390   },
391   { "mbox", DT_STRING|DT_MAILBOX|R_INDEX|R_PAGER, IP "~/mbox", 0, NULL,
392     "Folder that receives read emails (see Move)"
393   },
394   { "mbox_type", DT_ENUM, MUTT_MBOX, IP &MboxTypeDef, NULL,
395     "Default type for creating new mailboxes"
396   },
397   { "message_cache_clean", DT_BOOL, false, 0, NULL,
398     "(imap/pop) Clean out obsolete entries from the message cache"
399   },
400   { "message_cachedir", DT_PATH|DT_PATH_DIR, 0, 0, NULL,
401     "(imap/pop) Directory for the message cache"
402   },
403   { "message_format", DT_STRING|DT_NOT_EMPTY, IP "%s", 0, NULL,
404     "printf-like format string for listing attached messages"
405   },
406   { "meta_key", DT_BOOL, false, 0, NULL,
407     "Interpret 'ALT-x' as 'ESC-x'"
408   },
409   { "mime_forward", DT_QUAD, MUTT_NO, 0, NULL,
410     "Forward a message as a 'message/RFC822' MIME part"
411   },
412   { "mime_forward_rest", DT_QUAD, MUTT_YES, 0, NULL,
413     "Forward all attachments, even if they can't be decoded"
414   },
415 #ifdef MIXMASTER
416   { "mix_entry_format", DT_STRING|DT_NOT_EMPTY, IP "%4n %c %-16s %a", 0, NULL,
417     "(mixmaster) printf-like format string for the mixmaster chain"
418   },
419   { "mixmaster", DT_STRING|DT_COMMAND, IP MIXMASTER, 0, NULL,
420     "(mixmaster) External command to route a mixmaster message"
421   },
422 #endif
423   { "move", DT_QUAD, MUTT_NO, 0, NULL,
424     "Move emails from `$spool_file` to `$mbox` when read"
425   },
426   { "narrow_tree", DT_BOOL|R_TREE|R_INDEX, false, 0, NULL,
427     "Draw a narrower thread tree in the index"
428   },
429   { "net_inc", DT_NUMBER|DT_NOT_NEGATIVE, 10, 0, NULL,
430     "(socket) Update the progress bar after this many KB sent/received (0 to disable)"
431   },
432   { "new_mail_command", DT_STRING|DT_COMMAND, 0, 0, NULL,
433     "External command to run when new mail arrives"
434   },
435   { "pager", DT_STRING|DT_COMMAND, IP "builtin", 0, NULL,
436     "External command for viewing messages, or 'builtin' to use NeoMutt's"
437   },
438   { "pager_format", DT_STRING|R_PAGER, IP "-%Z- %C/%m: %-20.20n   %s%*  -- (%P)", 0, NULL,
439     "printf-like format string for the pager's status bar"
440   },
441   { "pipe_decode", DT_BOOL, false, 0, NULL,
442     "Decode the message when piping it"
443   },
444   { "pipe_decode_weed", DT_BOOL, true, 0, NULL,
445     "Control whether to weed headers when piping an email"
446   },
447   { "pipe_sep", DT_STRING, IP "\n", 0, NULL,
448     "Separator to add between multiple piped messages"
449   },
450   { "pipe_split", DT_BOOL, false, 0, NULL,
451     "Run the pipe command on each message separately"
452   },
453   { "postponed", DT_STRING|DT_MAILBOX|R_INDEX, IP "~/postponed", 0, NULL,
454     "Folder to store postponed messages"
455   },
456   { "preferred_languages", DT_SLIST|SLIST_SEP_COMMA, 0, 0, NULL,
457     "List of Preferred Languages for multilingual MIME (comma-separated)"
458   },
459   { "print", DT_QUAD, MUTT_ASKNO, 0, NULL,
460     "Confirm before printing a message"
461   },
462   { "print_command", DT_STRING|DT_COMMAND, IP "lpr", 0, NULL,
463     "External command to print a message"
464   },
465   { "print_decode", DT_BOOL, true, 0, NULL,
466     "Decode message before printing it"
467   },
468   { "print_decode_weed", DT_BOOL, true, 0, NULL,
469     "Control whether to weed headers when printing an email "
470   },
471   { "print_split", DT_BOOL, false, 0, NULL,
472     "Print multiple messages separately"
473   },
474   { "prompt_after", DT_BOOL, true, 0, NULL,
475     "Pause after running an external pager"
476   },
477   { "quit", DT_QUAD, MUTT_YES, 0, NULL,
478     "Prompt before exiting NeoMutt"
479   },
480   { "quote_regex", DT_REGEX|R_PAGER, IP "^([ \t]*[|>:}#])+", 0, NULL,
481     "Regex to match quoted text in a reply"
482   },
483   { "read_inc", DT_NUMBER|DT_NOT_NEGATIVE, 10, 0, NULL,
484     "Update the progress bar after this many records read (0 to disable)"
485   },
486   { "read_only", DT_BOOL, false, 0, NULL,
487     "Open folders in read-only mode"
488   },
489   { "real_name", DT_STRING|R_INDEX|R_PAGER, 0, 0, NULL,
490     "Real name of the user"
491   },
492   { "record", DT_STRING|DT_MAILBOX, IP "~/sent", 0, NULL,
493     "Folder to save 'sent' messages"
494   },
495   { "reflow_space_quotes", DT_BOOL, true, 0, NULL,
496     "Insert spaces into reply quotes for 'format=flowed' messages"
497   },
498   { "reflow_text", DT_BOOL, true, 0, NULL,
499     "Reformat paragraphs of 'format=flowed' text"
500   },
501   { "reflow_wrap", DT_NUMBER, 78, 0, NULL,
502     "Maximum paragraph width for reformatting 'format=flowed' text"
503   },
504   { "reply_regex", DT_REGEX|R_INDEX|R_RESORT, IP "^((re|aw|sv)(\\[[0-9]+\\])*:[ \t]*)*", 0, reply_validator,
505     "Regex to match message reply subjects like 're: '"
506   },
507   { "resolve", DT_BOOL, true, 0, NULL,
508     "Move to the next email whenever a command modifies an email"
509   },
510   { "resume_draft_files", DT_BOOL, false, 0, NULL,
511     "Process draft files like postponed messages"
512   },
513   { "resume_edited_draft_files", DT_BOOL, true, 0, NULL,
514     "Resume editing previously saved draft files"
515   },
516   { "reverse_alias", DT_BOOL|R_INDEX|R_PAGER, false, 0, NULL,
517     "Display the alias in the index, rather than the message's sender"
518   },
519   { "rfc2047_parameters", DT_BOOL, false, 0, NULL,
520     "Decode RFC2047-encoded MIME parameters"
521   },
522   { "save_address", DT_BOOL, false, 0, NULL,
523     "Use sender's full address as a default save folder"
524   },
525   { "save_empty", DT_BOOL, true, 0, NULL,
526     "(mbox,mmdf) Preserve empty mailboxes"
527   },
528   { "save_name", DT_BOOL, false, 0, NULL,
529     "Save outgoing message to mailbox of recipient's name if it exists"
530   },
531   { "score", DT_BOOL, true, 0, NULL,
532     "Use message scoring"
533   },
534   { "score_threshold_delete", DT_NUMBER, -1, 0, NULL,
535     "Messages with a lower score will be automatically deleted"
536   },
537   { "score_threshold_flag", DT_NUMBER, 9999, 0, NULL,
538     "Messages with a greater score will be automatically flagged"
539   },
540   { "score_threshold_read", DT_NUMBER, -1, 0, NULL,
541     "Messages with a lower score will be automatically marked read"
542   },
543   { "send_charset", DT_STRING|DT_CHARSET_STRICT, IP "us-ascii:iso-8859-1:utf-8", 0, charset_validator,
544     "Character sets for outgoing mail"
545   },
546   { "shell", DT_STRING|DT_COMMAND, IP "/bin/sh", 0, NULL,
547     "External command to run subshells in"
548   },
549   { "show_multipart_alternative", DT_STRING, 0, 0, multipart_validator,
550     "How to display 'multipart/alternative' MIME parts"
551   },
552   { "simple_search", DT_STRING, IP "~f %s | ~s %s", 0, NULL,
553     "Pattern to search for when search doesn't contain ~'s"
554   },
555   { "size_show_bytes", DT_BOOL|R_MENU, false, 0, NULL,
556     "Show smaller sizes in bytes"
557   },
558   { "size_show_fractions", DT_BOOL|R_MENU, true, 0, NULL,
559     "Show size fractions with a single decimal place"
560   },
561   { "size_show_mb", DT_BOOL|R_MENU, true, 0, NULL,
562     "Show sizes in megabytes for sizes greater than 1 megabyte"
563   },
564   { "size_units_on_left", DT_BOOL|R_MENU, false, 0, NULL,
565     "Show the units as a prefix to the size"
566   },
567   { "sleep_time", DT_NUMBER|DT_NOT_NEGATIVE, 1, 0, NULL,
568     "Time to pause after certain info messages"
569   },
570   { "sort", DT_SORT|DT_SORT_REVERSE|DT_SORT_LAST|R_INDEX|R_RESORT, SORT_DATE, IP SortMethods, sort_validator,
571     "Sort method for the index"
572   },
573   { "sort_aux", DT_SORT|DT_SORT_REVERSE|DT_SORT_LAST|R_INDEX|R_RESORT|R_RESORT_SUB, SORT_DATE, IP SortAuxMethods, NULL,
574     "Secondary sort method for the index"
575   },
576   { "sort_browser", DT_SORT|DT_SORT_REVERSE, SORT_ALPHA, IP SortBrowserMethods, NULL,
577     "Sort method for the browser"
578   },
579   { "sort_re", DT_BOOL|R_INDEX|R_RESORT|R_RESORT_INIT, true, 0, NULL,
580     "Whether $reply_regex must be matched when not $strict_threads"
581   },
582   { "spam_separator", DT_STRING, IP ",", 0, NULL,
583     "Separator for multiple spam headers"
584   },
585   { "spool_file", DT_STRING|DT_MAILBOX, 0, 0, NULL,
586     "Inbox"
587   },
588   { "status_chars", DT_MBTABLE|R_INDEX|R_PAGER, IP "-*%A", 0, NULL,
589     "Indicator characters for the status bar"
590   },
591   { "status_format", DT_STRING|R_INDEX|R_PAGER, IP "-%r-NeoMutt: %D [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b?%?l? %l?]---(%?T?%T/?%s/%S)-%>-(%P)---", 0, NULL,
592     "printf-like format string for the index's status line"
593   },
594   { "status_on_top", DT_BOOL, false, 0, NULL,
595     "Display the status bar at the top"
596   },
597   { "strict_threads", DT_BOOL|R_RESORT|R_RESORT_INIT|R_INDEX, false, 0, NULL,
598     "Thread messages using 'In-Reply-To' and 'References' headers"
599   },
600   { "suspend", DT_BOOL, true, 0, NULL,
601     "Allow the user to suspend NeoMutt using '^Z'"
602   },
603   { "text_flowed", DT_BOOL, false, 0, NULL,
604     "Generate 'format=flowed' messages"
605   },
606   { "thread_received", DT_BOOL|R_RESORT|R_RESORT_INIT|R_INDEX, false, 0, NULL,
607     "Sort threaded messages by their received date"
608   },
609   { "time_inc", DT_NUMBER|DT_NOT_NEGATIVE, 0, 0, NULL,
610     "Frequency of progress bar updates (milliseconds)"
611   },
612   { "timeout", DT_NUMBER|DT_NOT_NEGATIVE, 600, 0, NULL,
613     "Time to wait for user input in menus"
614   },
615   { "tmpdir", DT_PATH|DT_PATH_DIR|DT_NOT_EMPTY, IP TMPDIR, 0, NULL,
616     "Directory for temporary files"
617   },
618   { "to_chars", DT_MBTABLE|R_INDEX|R_PAGER, IP " +TCFLR", 0, NULL,
619     "Indicator characters for the 'To' field in the index"
620   },
621   { "toggle_quoted_show_levels", DT_NUMBER|DT_NOT_NEGATIVE, 0, 0, NULL,
622     "Number of quote levels to show with toggle-quoted"
623   },
624   { "trash", DT_STRING|DT_MAILBOX, 0, 0, NULL,
625     "Folder to put deleted emails"
626   },
627   { "ts_enabled", DT_BOOL|R_INDEX|R_PAGER, false, 0, NULL,
628     "Allow NeoMutt to set the terminal status line and icon"
629   },
630   { "ts_icon_format", DT_STRING|R_INDEX|R_PAGER, IP "M%?n?AIL&ail?", 0, NULL,
631     "printf-like format string for the terminal's icon title"
632   },
633   { "ts_status_format", DT_STRING|R_INDEX|R_PAGER, IP "NeoMutt with %?m?%m messages&no messages?%?n? [%n NEW]?", 0, NULL,
634     "printf-like format string for the terminal's status (window title)"
635   },
636   { "use_domain", DT_BOOL, true, 0, NULL,
637     "Qualify local addresses using this domain"
638   },
639   { "use_threads", DT_ENUM|R_INDEX|R_RESORT, UT_UNSET, IP &UseThreadsTypeDef, NULL,
640     "Whether to use threads for the index"
641   },
642   { "wait_key", DT_BOOL, true, 0, NULL,
643     "Prompt to press a key after running external commands"
644   },
645   { "weed", DT_BOOL, true, 0, NULL,
646     "Filter headers when displaying/forwarding/printing/replying"
647   },
648   { "wrap", DT_NUMBER|R_PAGER_FLOW, 0, 0, NULL,
649     "Width to wrap text in the pager"
650   },
651   { "wrap_search", DT_BOOL, true, 0, NULL,
652     "Wrap around when the search hits the end"
653   },
654   { "write_bcc", DT_BOOL, false, 0, NULL,
655     "Write out the 'Bcc' field when preparing to send a mail"
656   },
657   { "write_inc", DT_NUMBER|DT_NOT_NEGATIVE, 10, 0, NULL,
658     "Update the progress bar after this many records written (0 to disable)"
659   },
660 
661   { "escape",                    DT_DEPRECATED|DT_STRING,            IP "~" },
662   { "ignore_linear_white_space", DT_DEPRECATED|DT_BOOL,              false },
663   { "visual",                    DT_DEPRECATED|DT_STRING|DT_COMMAND, 0 },
664 
665   { "askbcc",                    DT_SYNONYM, IP "ask_bcc",                    },
666   { "askcc",                     DT_SYNONYM, IP "ask_cc",                     },
667   { "autoedit",                  DT_SYNONYM, IP "auto_edit",                  },
668   { "confirmappend",             DT_SYNONYM, IP "confirm_append",             },
669   { "confirmcreate",             DT_SYNONYM, IP "confirm_create",             },
670   { "edit_hdrs",                 DT_SYNONYM, IP "edit_headers",               },
671   { "forw_decode",               DT_SYNONYM, IP "forward_decode",             },
672   { "forw_quote",                DT_SYNONYM, IP "forward_quote",              },
673   { "hdr_format",                DT_SYNONYM, IP "index_format",               },
674   { "include_onlyfirst",         DT_SYNONYM, IP "include_only_first",         },
675   { "indent_str",                DT_SYNONYM, IP "indent_string",              },
676   { "mime_fwd",                  DT_SYNONYM, IP "mime_forward",               },
677   { "msg_format",                DT_SYNONYM, IP "message_format",             },
678   { "print_cmd",                 DT_SYNONYM, IP "print_command",              },
679   { "quote_regexp",              DT_SYNONYM, IP "quote_regex",                },
680   { "realname",                  DT_SYNONYM, IP "real_name",                  },
681   { "reply_regexp",              DT_SYNONYM, IP "reply_regex",                },
682   { "spoolfile",                 DT_SYNONYM, IP "spool_file",                 },
683   { "xterm_icon",                DT_SYNONYM, IP "ts_icon_format",             },
684   { "xterm_set_titles",          DT_SYNONYM, IP "ts_enabled",                 },
685   { "xterm_title",               DT_SYNONYM, IP "ts_status_format",           },
686 
687   { NULL },
688   // clang-format on
689 };
690 
691 /**
692  * config_init_main - Register main config variables - Implements ::module_init_config_t - @ingroup cfg_module_api
693  */
config_init_main(struct ConfigSet * cs)694 static bool config_init_main(struct ConfigSet *cs)
695 {
696   return cs_register_variables(cs, MainVars, 0);
697 }
698 
699 /**
700  * init_types - Create the config types
701  * @param cs Config items
702  *
703  * Define the config types, e.g. #DT_STRING.
704  */
init_types(struct ConfigSet * cs)705 static void init_types(struct ConfigSet *cs)
706 {
707   CONFIG_INIT_TYPE(cs, Address);
708   CONFIG_INIT_TYPE(cs, Bool);
709   CONFIG_INIT_TYPE(cs, Enum);
710   CONFIG_INIT_TYPE(cs, Long);
711   CONFIG_INIT_TYPE(cs, Mbtable);
712   CONFIG_INIT_TYPE(cs, Number);
713   CONFIG_INIT_TYPE(cs, Path);
714   CONFIG_INIT_TYPE(cs, Quad);
715   CONFIG_INIT_TYPE(cs, Regex);
716   CONFIG_INIT_TYPE(cs, Slist);
717   CONFIG_INIT_TYPE(cs, Sort);
718   CONFIG_INIT_TYPE(cs, String);
719 }
720 
721 /**
722  * init_variables - Define the config variables
723  * @param cs Config items
724  */
init_variables(struct ConfigSet * cs)725 static void init_variables(struct ConfigSet *cs)
726 {
727   // Define the config variables
728   config_init_main(cs);
729   CONFIG_INIT_VARS(cs, alias);
730 #ifdef USE_AUTOCRYPT
731   CONFIG_INIT_VARS(cs, autocrypt);
732 #endif
733   CONFIG_INIT_VARS(cs, compose);
734   CONFIG_INIT_VARS(cs, conn);
735 #ifdef USE_HCACHE
736   CONFIG_INIT_VARS(cs, hcache);
737 #endif
738   CONFIG_INIT_VARS(cs, helpbar);
739   CONFIG_INIT_VARS(cs, history);
740   CONFIG_INIT_VARS(cs, index);
741 #ifdef USE_IMAP
742   CONFIG_INIT_VARS(cs, imap);
743 #endif
744   CONFIG_INIT_VARS(cs, maildir);
745   CONFIG_INIT_VARS(cs, mbox);
746   CONFIG_INIT_VARS(cs, menu);
747   CONFIG_INIT_VARS(cs, ncrypt);
748 #ifdef USE_NNTP
749   CONFIG_INIT_VARS(cs, nntp);
750 #endif
751 #ifdef USE_NOTMUCH
752   CONFIG_INIT_VARS(cs, notmuch);
753 #endif
754   CONFIG_INIT_VARS(cs, pager);
755   CONFIG_INIT_VARS(cs, pattern);
756 #ifdef USE_POP
757   CONFIG_INIT_VARS(cs, pop);
758 #endif
759   CONFIG_INIT_VARS(cs, send);
760 #ifdef USE_SIDEBAR
761   CONFIG_INIT_VARS(cs, sidebar);
762 #endif
763 }
764 
765 /**
766  * init_config - Initialise the config system
767  * @param cs Config items
768  */
init_config(struct ConfigSet * cs)769 void init_config(struct ConfigSet *cs)
770 {
771   init_types(cs);
772   init_variables(cs);
773 }
774