NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
init.h File Reference

Config/command parsing. More...

#include <stddef.h>
#include <stdbool.h>
#include "core/lib.h"
#include "mutt.h"
#include "hook.h"
+ Include dependency graph for init.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void init_config (struct ConfigSet *cs)
 Initialise the config system. More...
 
int mutt_command_complete (char *buf, size_t buflen, int pos, int numtabs)
 Complete a command name. More...
 
int mutt_extract_token (struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
 Extract one token from a string. More...
 
HookFlags mutt_get_hook_type (const char *name)
 Find a hook by name. More...
 
int mutt_init (struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
 Initialise NeoMutt. More...
 
int mutt_label_complete (char *buf, size_t buflen, int numtabs)
 Complete a label name. More...
 
bool mutt_nm_query_complete (char *buf, size_t buflen, int pos, int numtabs)
 Complete to the nearest notmuch tag. More...
 
bool mutt_nm_tag_complete (char *buf, size_t buflen, int numtabs)
 Complete to the nearest notmuch tag. More...
 
void mutt_opts_free (void)
 Clean up before quitting. More...
 
enum CommandResult mutt_parse_rc_buffer (struct Buffer *line, struct Buffer *token, struct Buffer *err)
 Parse a line of user config. More...
 
enum CommandResult mutt_parse_rc_line (const char *line, struct Buffer *err)
 Parse a line of user config. More...
 
int mutt_query_variables (struct ListHead *queries, bool show_docs)
 Implement the -Q command line flag. More...
 
int mutt_var_value_complete (char *buf, size_t buflen, int pos)
 Complete a variable/value. More...
 

Detailed Description

Config/command parsing.

Authors
  • Michael R. Elkins
  • g10 Code GmbH

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 init.h.

Function Documentation

◆ init_config()

void init_config ( struct ConfigSet cs)

Initialise the config system.

Parameters
csConfig items

Definition at line 769 of file mutt_config.c.

770 {
771  init_types(cs);
772  init_variables(cs);
773 }
static void init_types(struct ConfigSet *cs)
Create the config types.
Definition: mutt_config.c:705
static void init_variables(struct ConfigSet *cs)
Define the config variables.
Definition: mutt_config.c:725
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_command_complete()

int mutt_command_complete ( char *  buf,
size_t  buflen,
int  pos,
int  numtabs 
)

Complete a command name.

Parameters
bufBuffer for the result
buflenLength of the buffer
posCursor position in the buffer
numtabsNumber of times the user has hit 'tab'
Return values
1Success, a match
0Error, no match

Definition at line 1130 of file init.c.

1131 {
1132  char *pt = buf;
1133  int spaces; /* keep track of the number of leading spaces on the line */
1134  struct MyVar *myv = NULL;
1135 
1136  SKIPWS(buf);
1137  spaces = buf - pt;
1138 
1139  pt = buf + pos - spaces;
1140  while ((pt > buf) && !isspace((unsigned char) *pt))
1141  pt--;
1142 
1143  if (pt == buf) /* complete cmd */
1144  {
1145  /* first TAB. Collect all the matches */
1146  if (numtabs == 1)
1147  {
1148  NumMatched = 0;
1149  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1150  memset(Matches, 0, MatchesListsize);
1151  memset(Completed, 0, sizeof(Completed));
1152 
1153  struct Command *c = NULL;
1154  for (size_t num = 0, size = mutt_commands_array(&c); num < size; num++)
1155  candidate(UserTyped, c[num].name, Completed, sizeof(Completed));
1158 
1159  /* All matches are stored. Longest non-ambiguous string is ""
1160  * i.e. don't change 'buf'. Fake successful return this time */
1161  if (UserTyped[0] == '\0')
1162  return 1;
1163  }
1164 
1165  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1166  return 0;
1167 
1168  /* NumMatched will _always_ be at least 1 since the initial
1169  * user-typed string is always stored */
1170  if ((numtabs == 1) && (NumMatched == 2))
1171  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1172  else if ((numtabs > 1) && (NumMatched > 2))
1173  {
1174  /* cycle through all the matches */
1175  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1176  }
1177 
1178  /* return the completed command */
1179  strncpy(buf, Completed, buflen - spaces);
1180  }
1181  else if (mutt_str_startswith(buf, "set") || mutt_str_startswith(buf, "unset") ||
1182  mutt_str_startswith(buf, "reset") || mutt_str_startswith(buf, "toggle"))
1183  { /* complete variables */
1184  static const char *const prefixes[] = { "no", "inv", "?", "&", 0 };
1185 
1186  pt++;
1187  /* loop through all the possible prefixes (no, inv, ...) */
1188  if (mutt_str_startswith(buf, "set"))
1189  {
1190  for (int num = 0; prefixes[num]; num++)
1191  {
1192  if (mutt_str_startswith(pt, prefixes[num]))
1193  {
1194  pt += mutt_str_len(prefixes[num]);
1195  break;
1196  }
1197  }
1198  }
1199 
1200  /* first TAB. Collect all the matches */
1201  if (numtabs == 1)
1202  {
1203  NumMatched = 0;
1204  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1205  memset(Matches, 0, MatchesListsize);
1206  memset(Completed, 0, sizeof(Completed));
1207 
1208  struct HashElem *he = NULL;
1209  struct HashElem **list = get_elem_list(NeoMutt->sub->cs);
1210  for (size_t i = 0; list[i]; i++)
1211  {
1212  he = list[i];
1213  const int type = DTYPE(he->type);
1214 
1215  if ((type == DT_SYNONYM) || (type & DT_DEPRECATED))
1216  continue;
1217 
1218  candidate(UserTyped, he->key.strkey, Completed, sizeof(Completed));
1219  }
1220  FREE(&list);
1221 
1222  TAILQ_FOREACH(myv, &MyVars, entries)
1223  {
1224  candidate(UserTyped, myv->name, Completed, sizeof(Completed));
1225  }
1228 
1229  /* All matches are stored. Longest non-ambiguous string is ""
1230  * i.e. don't change 'buf'. Fake successful return this time */
1231  if (UserTyped[0] == '\0')
1232  return 1;
1233  }
1234 
1235  if ((Completed[0] == 0) && UserTyped[0])
1236  return 0;
1237 
1238  /* NumMatched will _always_ be at least 1 since the initial
1239  * user-typed string is always stored */
1240  if ((numtabs == 1) && (NumMatched == 2))
1241  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1242  else if ((numtabs > 1) && (NumMatched > 2))
1243  {
1244  /* cycle through all the matches */
1245  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1246  }
1247 
1248  strncpy(pt, Completed, buf + buflen - pt - spaces);
1249  }
1250  else if (mutt_str_startswith(buf, "exec"))
1251  {
1252  const enum MenuType mtype = menu_get_current_type();
1253  const struct Binding *menu = km_get_table(mtype);
1254  if (!menu && (mtype != MENU_PAGER))
1255  menu = OpGeneric;
1256 
1257  pt++;
1258  /* first TAB. Collect all the matches */
1259  if (numtabs == 1)
1260  {
1261  NumMatched = 0;
1262  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1263  memset(Matches, 0, MatchesListsize);
1264  memset(Completed, 0, sizeof(Completed));
1265  for (int num = 0; menu[num].name; num++)
1266  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1267  /* try the generic menu */
1268  if ((Completed[0] == '\0') && (mtype != MENU_PAGER))
1269  {
1270  menu = OpGeneric;
1271  for (int num = 0; menu[num].name; num++)
1272  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1273  }
1276 
1277  /* All matches are stored. Longest non-ambiguous string is ""
1278  * i.e. don't change 'buf'. Fake successful return this time */
1279  if (UserTyped[0] == '\0')
1280  return 1;
1281  }
1282 
1283  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1284  return 0;
1285 
1286  /* NumMatched will _always_ be at least 1 since the initial
1287  * user-typed string is always stored */
1288  if ((numtabs == 1) && (NumMatched == 2))
1289  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1290  else if ((numtabs > 1) && (NumMatched > 2))
1291  {
1292  /* cycle through all the matches */
1293  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1294  }
1295 
1296  strncpy(pt, Completed, buf + buflen - pt - spaces);
1297  }
1298  else
1299  return 0;
1300 
1301  return 1;
1302 }
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:53
static void candidate(char *user, const char *src, char *dest, size_t dlen)
Helper function for completion.
Definition: init.c:120
static int MatchesListsize
Definition: init.c:86
static char Completed[256]
Definition: init.c:83
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:97
static char UserTyped[1024]
Definition: init.c:80
static const char ** Matches
Definition: init.c:84
static int NumMatched
Definition: init.c:82
const struct Binding * km_get_table(enum MenuType mtype)
Lookup a menu's keybindings.
Definition: keymap.c:1301
#define FREE(x)
Definition: memory.h:40
enum MenuType menu_get_current_type(void)
Get the type of the current Window.
Definition: menu.c:531
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
size_t mutt_commands_array(struct Command **first)
Get Commands array.
struct MyVarList MyVars
List of all the user's custom config variables.
Definition: myvar.c:34
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define SKIPWS(ch)
Definition: string2.h:46
Mapping between a user key and a function.
Definition: keymap.h:92
const char * name
name of the function
Definition: keymap.h:93
const char * name
Name of the command.
Definition: command.h:48
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
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
A user-set variable.
Definition: myvar.h:32
char * name
Name of user variable.
Definition: myvar.h:33
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:75
MenuType
Types of GUI selections.
Definition: type.h:36
@ MENU_PAGER
Pager pager (email viewer)
Definition: type.h:54
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
#define DT_DEPRECATED
Config item shouldn't be used any more.
Definition: types.h:77
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
const char * strkey
String key.
Definition: hash.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_extract_token()

int mutt_extract_token ( struct Buffer dest,
struct Buffer tok,
TokenFlags  flags 
)

Extract one token from a string.

Parameters
destBuffer for the result
tokBuffer containing tokens
flagsFlags, see TokenFlags
Return values
0Success
-1Error

Definition at line 398 of file init.c.

399 {
400  if (!dest || !tok)
401  return -1;
402 
403  char ch;
404  char qc = '\0'; /* quote char */
405  char *pc = NULL;
406 
407  /* Some callers used to rely on the (bad) assumption that dest->data would be
408  * non-NULL after calling this function. Perhaps I've missed a few cases, or
409  * a future caller might make the same mistake. */
410  if (!dest->data)
411  mutt_buffer_alloc(dest, 256);
412 
413  mutt_buffer_reset(dest);
414 
415  SKIPWS(tok->dptr);
416  while ((ch = *tok->dptr))
417  {
418  if (qc == '\0')
419  {
420  if ((IS_SPACE(ch) && !(flags & MUTT_TOKEN_SPACE)) ||
421  ((ch == '#') && !(flags & MUTT_TOKEN_COMMENT)) ||
422  ((ch == '+') && (flags & MUTT_TOKEN_PLUS)) ||
423  ((ch == '-') && (flags & MUTT_TOKEN_MINUS)) ||
424  ((ch == '=') && (flags & MUTT_TOKEN_EQUAL)) ||
425  ((ch == '?') && (flags & MUTT_TOKEN_QUESTION)) ||
426  ((ch == ';') && !(flags & MUTT_TOKEN_SEMICOLON)) ||
427  ((flags & MUTT_TOKEN_PATTERN) && strchr("~%=!|", ch)))
428  {
429  break;
430  }
431  }
432 
433  tok->dptr++;
434 
435  if (ch == qc)
436  qc = 0; /* end of quote */
437  else if (!qc && ((ch == '\'') || (ch == '"')) && !(flags & MUTT_TOKEN_QUOTE))
438  qc = ch;
439  else if ((ch == '\\') && (qc != '\''))
440  {
441  if (tok->dptr[0] == '\0')
442  return -1; /* premature end of token */
443  switch (ch = *tok->dptr++)
444  {
445  case 'c':
446  case 'C':
447  if (tok->dptr[0] == '\0')
448  return -1; /* premature end of token */
449  mutt_buffer_addch(dest, (toupper((unsigned char) tok->dptr[0]) - '@') & 0x7f);
450  tok->dptr++;
451  break;
452  case 'e':
453  mutt_buffer_addch(dest, '\033'); // Escape
454  break;
455  case 'f':
456  mutt_buffer_addch(dest, '\f');
457  break;
458  case 'n':
459  mutt_buffer_addch(dest, '\n');
460  break;
461  case 'r':
462  mutt_buffer_addch(dest, '\r');
463  break;
464  case 't':
465  mutt_buffer_addch(dest, '\t');
466  break;
467  default:
468  if (isdigit((unsigned char) ch) && isdigit((unsigned char) tok->dptr[0]) &&
469  isdigit((unsigned char) tok->dptr[1]))
470  {
471  mutt_buffer_addch(dest, (ch << 6) + (tok->dptr[0] << 3) + tok->dptr[1] - 3504);
472  tok->dptr += 2;
473  }
474  else
475  mutt_buffer_addch(dest, ch);
476  }
477  }
478  else if ((ch == '^') && (flags & MUTT_TOKEN_CONDENSE))
479  {
480  if (tok->dptr[0] == '\0')
481  return -1; /* premature end of token */
482  ch = *tok->dptr++;
483  if (ch == '^')
484  mutt_buffer_addch(dest, ch);
485  else if (ch == '[')
486  mutt_buffer_addch(dest, '\033'); // Escape
487  else if (isalpha((unsigned char) ch))
488  mutt_buffer_addch(dest, toupper((unsigned char) ch) - '@');
489  else
490  {
491  mutt_buffer_addch(dest, '^');
492  mutt_buffer_addch(dest, ch);
493  }
494  }
495  else if ((ch == '`') && (!qc || (qc == '"')))
496  {
497  FILE *fp = NULL;
498  pid_t pid;
499 
500  pc = tok->dptr;
501  do
502  {
503  pc = strpbrk(pc, "\\`");
504  if (pc)
505  {
506  /* skip any quoted chars */
507  if (*pc == '\\')
508  pc += 2;
509  }
510  } while (pc && (pc[0] != '`'));
511  if (!pc)
512  {
513  mutt_debug(LL_DEBUG1, "mismatched backticks\n");
514  return -1;
515  }
516  struct Buffer cmd;
517  mutt_buffer_init(&cmd);
518  *pc = '\0';
519  if (flags & MUTT_TOKEN_BACKTICK_VARS)
520  {
521  /* recursively extract tokens to interpolate variables */
522  mutt_extract_token(&cmd, tok,
525  }
526  else
527  {
528  cmd.data = mutt_str_dup(tok->dptr);
529  }
530  *pc = '`';
531  pid = filter_create(cmd.data, NULL, &fp, NULL);
532  if (pid < 0)
533  {
534  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", cmd.data);
535  FREE(&cmd.data);
536  return -1;
537  }
538 
539  tok->dptr = pc + 1;
540 
541  /* read line */
542  struct Buffer expn = mutt_buffer_make(0);
543  expn.data = mutt_file_read_line(NULL, &expn.dsize, fp, NULL, MUTT_RL_NO_FLAGS);
544  mutt_file_fclose(&fp);
545  int rc = filter_wait(pid);
546  if (rc != 0)
547  mutt_debug(LL_DEBUG1, "backticks exited code %d for command: %s\n", rc, cmd);
548  FREE(&cmd.data);
549 
550  /* if we got output, make a new string consisting of the shell output
551  * plus whatever else was left on the original line */
552  /* BUT: If this is inside a quoted string, directly add output to
553  * the token */
554  if (expn.data)
555  {
556  if (qc)
557  {
558  mutt_buffer_addstr(dest, expn.data);
559  }
560  else
561  {
562  struct Buffer *copy = mutt_buffer_pool_get();
563  mutt_buffer_fix_dptr(&expn);
564  mutt_buffer_copy(copy, &expn);
565  mutt_buffer_addstr(copy, tok->dptr);
566  mutt_buffer_copy(tok, copy);
567  mutt_buffer_seek(tok, 0);
569  }
570  FREE(&expn.data);
571  }
572  }
573  else if ((ch == '$') && (!qc || (qc == '"')) &&
574  ((tok->dptr[0] == '{') || isalpha((unsigned char) tok->dptr[0])))
575  {
576  const char *env = NULL;
577  char *var = NULL;
578 
579  if (tok->dptr[0] == '{')
580  {
581  pc = strchr(tok->dptr, '}');
582  if (pc)
583  {
584  var = mutt_strn_dup(tok->dptr + 1, pc - (tok->dptr + 1));
585  tok->dptr = pc + 1;
586 
587  if ((flags & MUTT_TOKEN_NOSHELL))
588  {
589  mutt_buffer_addch(dest, ch);
590  mutt_buffer_addch(dest, '{');
591  mutt_buffer_addstr(dest, var);
592  mutt_buffer_addch(dest, '}');
593  FREE(&var);
594  }
595  }
596  }
597  else
598  {
599  for (pc = tok->dptr; isalnum((unsigned char) *pc) || (pc[0] == '_'); pc++)
600  ; // do nothing
601 
602  var = mutt_strn_dup(tok->dptr, pc - tok->dptr);
603  tok->dptr = pc;
604  }
605  if (var)
606  {
607  struct Buffer result;
608  mutt_buffer_init(&result);
609  int rc = cs_subset_str_string_get(NeoMutt->sub, var, &result);
610 
611  if (CSR_RESULT(rc) == CSR_SUCCESS)
612  {
613  mutt_buffer_addstr(dest, result.data);
614  FREE(&result.data);
615  }
616  else if ((env = myvar_get(var)))
617  {
618  mutt_buffer_addstr(dest, env);
619  }
620  else if (!(flags & MUTT_TOKEN_NOSHELL) && (env = mutt_str_getenv(var)))
621  {
622  mutt_buffer_addstr(dest, env);
623  }
624  else
625  {
626  mutt_buffer_addch(dest, ch);
627  mutt_buffer_addstr(dest, var);
628  }
629  FREE(&var);
630  }
631  }
632  else
633  mutt_buffer_addch(dest, ch);
634  }
635  mutt_buffer_addch(dest, 0); /* terminate the string */
636  SKIPWS(tok->dptr);
637  return 0;
638 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:466
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:445
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:671
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:398
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:68
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:74
#define MUTT_TOKEN_MINUS
Treat '-' as a special.
Definition: mutt.h:78
#define MUTT_TOKEN_PLUS
Treat '+' as a special.
Definition: mutt.h:77
#define MUTT_TOKEN_COMMENT
Don't reap comments.
Definition: mutt.h:72
#define MUTT_TOKEN_QUOTE
Don't interpret quotes.
Definition: mutt.h:70
#define MUTT_TOKEN_NOSHELL
Don't expand environment variables.
Definition: mutt.h:75
#define MUTT_TOKEN_SPACE
Don't treat whitespace as a term.
Definition: mutt.h:69
#define MUTT_TOKEN_SEMICOLON
Don't treat ; as special.
Definition: mutt.h:73
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:71
#define MUTT_TOKEN_EQUAL
Treat '=' as a special.
Definition: mutt.h:67
#define MUTT_TOKEN_QUESTION
Treat '?' as a special.
Definition: mutt.h:76
const char * myvar_get(const char *var)
Get the value of a "my_" variable.
Definition: myvar.c:92
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define IS_SPACE(ch)
Definition: string2.h:38
String manipulation buffer.
Definition: buffer.h:34
char * dptr
Current read/write position.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:370
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_hook_type()

HookFlags mutt_get_hook_type ( const char *  name)

Find a hook by name.

Parameters
nameName to find
Return values
numHook ID, e.g. MUTT_FOLDER_HOOK
MUTT_HOOK_NO_FLAGSError, no matching hook

Definition at line 698 of file init.c.

699 {
700  struct Command *c = NULL;
701  for (size_t i = 0, size = mutt_commands_array(&c); i < size; i++)
702  {
703  if (((c[i].parse == mutt_parse_hook) || (c[i].parse == mutt_parse_idxfmt_hook)) &&
704  mutt_istr_equal(c[i].name, name))
705  {
706  return c[i].data;
707  }
708  }
709  return MUTT_HOOK_NO_FLAGS;
710 }
enum CommandResult mutt_parse_idxfmt_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'index-format-hook' command - Implements Command::parse() -.
Definition: hook.c:371
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'hook' family of commands - Implements Command::parse() -.
Definition: hook.c:81
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:37
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Definition: command.h:61
intptr_t data
Data or flags to pass to the command.
Definition: command.h:63
+ Here is the call graph for this function:

◆ mutt_init()

int mutt_init ( struct ConfigSet cs,
bool  skip_sys_rc,
struct ListHead *  commands 
)

Initialise NeoMutt.

Parameters
csConfig Set
skip_sys_rcIf true, don't read the system config file
commandsList of config commands to execute
Return values
0Success
1Error

Definition at line 720 of file init.c.

721 {
722  int need_pause = 0;
723  int rc = 1;
724  struct Buffer err = mutt_buffer_make(256);
725  struct Buffer buf = mutt_buffer_make(256);
726 
728  alias_init();
730 #ifdef USE_COMP_MBOX
731  mutt_comp_init();
732 #endif
733 #ifdef USE_IMAP
734  imap_init();
735 #endif
736 #ifdef USE_LUA
737  mutt_lua_init();
738 #endif
741 
742  menu_init();
743 #ifdef USE_SIDEBAR
744  sb_init();
745 #endif
746 #ifdef USE_NOTMUCH
747  nm_init();
748 #endif
749 
750  /* "$spool_file" precedence: config file, environment */
751  const char *p = mutt_str_getenv("MAIL");
752  if (!p)
753  p = mutt_str_getenv("MAILDIR");
754  if (!p)
755  {
756 #ifdef HOMESPOOL
757  mutt_buffer_concat_path(&buf, NONULL(HomeDir), MAILPATH);
758 #else
759  mutt_buffer_concat_path(&buf, MAILPATH, NONULL(Username));
760 #endif
761  p = mutt_buffer_string(&buf);
762  }
763  cs_str_initial_set(cs, "spool_file", p, NULL);
764  cs_str_reset(cs, "spool_file", NULL);
765 
766  p = mutt_str_getenv("REPLYTO");
767  if (p)
768  {
769  struct Buffer token;
770 
771  mutt_buffer_printf(&buf, "Reply-To: %s", p);
772  mutt_buffer_init(&token);
773  parse_my_hdr(&token, &buf, 0, &err); /* adds to UserHeader */
774  FREE(&token.data);
775  }
776 
777  p = mutt_str_getenv("EMAIL");
778  if (p)
779  {
780  cs_str_initial_set(cs, "from", p, NULL);
781  cs_str_reset(cs, "from", NULL);
782  }
783 
784  /* "$mailcap_path" precedence: config file, environment, code */
785  const char *env_mc = mutt_str_getenv("MAILCAPS");
786  if (env_mc)
787  cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
788 
789  /* "$tmpdir" precedence: config file, environment, code */
790  const char *env_tmp = mutt_str_getenv("TMPDIR");
791  if (env_tmp)
792  cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
793 
794  /* "$visual", "$editor" precedence: config file, environment, code */
795  const char *env_ed = mutt_str_getenv("VISUAL");
796  if (!env_ed)
797  env_ed = mutt_str_getenv("EDITOR");
798  if (!env_ed)
799  env_ed = "vi";
800  cs_str_initial_set(cs, "editor", env_ed, NULL);
801 
802  const char *const c_editor = cs_subset_string(NeoMutt->sub, "editor");
803  if (!c_editor)
804  cs_str_reset(cs, "editor", NULL);
805 
806  const char *charset = mutt_ch_get_langinfo_charset();
807  cs_str_initial_set(cs, "charset", charset, NULL);
808  cs_str_reset(cs, "charset", NULL);
809  mutt_ch_set_charset(charset);
810  FREE(&charset);
811 
812  Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *));
813 
814 #ifdef HAVE_GETSID
815  /* Unset suspend by default if we're the session leader */
816  if (getsid(0) == getpid())
817  cs_subset_str_native_set(NeoMutt->sub, "suspend", false, NULL);
818 #endif
819 
820  /* RFC2368, "4. Unsafe headers"
821  * The creator of a mailto URL can't expect the resolver of a URL to
822  * understand more than the "subject" and "body" headers. Clients that
823  * resolve mailto URLs into mail messages should be able to correctly
824  * create RFC822-compliant mail messages using the "subject" and "body"
825  * headers. */
826  add_to_stailq(&MailToAllow, "body");
827  add_to_stailq(&MailToAllow, "subject");
828  /* Cc, In-Reply-To, and References help with not breaking threading on
829  * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
830  add_to_stailq(&MailToAllow, "cc");
831  add_to_stailq(&MailToAllow, "in-reply-to");
832  add_to_stailq(&MailToAllow, "references");
833 
834  if (STAILQ_EMPTY(&Muttrc))
835  {
836  const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
837 
838  if (!xdg_cfg_home && HomeDir)
839  {
840  mutt_buffer_printf(&buf, "%s/.config", HomeDir);
841  xdg_cfg_home = mutt_buffer_string(&buf);
842  }
843 
844  char *config = find_cfg(HomeDir, xdg_cfg_home);
845  if (config)
846  {
847  mutt_list_insert_tail(&Muttrc, config);
848  }
849  }
850  else
851  {
852  struct ListNode *np = NULL;
853  STAILQ_FOREACH(np, &Muttrc, entries)
854  {
855  mutt_buffer_strcpy(&buf, np->data);
856  FREE(&np->data);
858  np->data = mutt_buffer_strdup(&buf);
859  if (access(np->data, F_OK))
860  {
861  mutt_perror(np->data);
862  goto done; // TEST10: neomutt -F missing
863  }
864  }
865  }
866 
867  if (!STAILQ_EMPTY(&Muttrc))
868  {
869  cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
870  }
871 
872  /* Process the global rc file if it exists and the user hasn't explicitly
873  * requested not to via "-n". */
874  if (!skip_sys_rc)
875  {
876  do
877  {
879  break;
880 
881  mutt_buffer_printf(&buf, "%s/neomuttrc", SYSCONFDIR);
882  if (access(mutt_buffer_string(&buf), F_OK) == 0)
883  break;
884 
885  mutt_buffer_printf(&buf, "%s/Muttrc", SYSCONFDIR);
886  if (access(mutt_buffer_string(&buf), F_OK) == 0)
887  break;
888 
889  mutt_buffer_printf(&buf, "%s/neomuttrc", PKGDATADIR);
890  if (access(mutt_buffer_string(&buf), F_OK) == 0)
891  break;
892 
893  mutt_buffer_printf(&buf, "%s/Muttrc", PKGDATADIR);
894  } while (false);
895 
896  if (access(mutt_buffer_string(&buf), F_OK) == 0)
897  {
898  if (source_rc(mutt_buffer_string(&buf), &err) != 0)
899  {
900  mutt_error("%s", err.data);
901  need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
902  }
903  }
904  }
905 
906  /* Read the user's initialization file. */
907  struct ListNode *np = NULL;
908  STAILQ_FOREACH(np, &Muttrc, entries)
909  {
910  if (np->data)
911  {
912  if (source_rc(np->data, &err) != 0)
913  {
914  mutt_error("%s", err.data);
915  need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
916  }
917  }
918  }
919 
920  if (execute_commands(commands) != 0)
921  need_pause = 1; // TEST13: neomutt -e broken
922 
923  if (!get_hostname(cs))
924  goto done;
925 
926  {
927  char name[256] = { 0 };
928  const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
929  if (!c_real_name)
930  {
931  struct passwd *pw = getpwuid(getuid());
932  if (pw)
933  c_real_name = mutt_gecos_name(name, sizeof(name), pw);
934  }
935  cs_str_initial_set(cs, "real_name", c_real_name, NULL);
936  cs_str_reset(cs, "real_name", NULL);
937  }
938 
939  if (need_pause && !OptNoCurses)
940  {
942  if (mutt_any_key_to_continue(NULL) == 'q')
943  goto done; // TEST14: neomutt -e broken (press 'q')
944  }
945 
946  const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
947  mutt_file_mkdir(c_tmpdir, S_IRWXU);
948 
949  mutt_hist_init();
951 
952 #ifdef USE_NOTMUCH
953  const bool c_virtual_spool_file =
954  cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
955  if (c_virtual_spool_file)
956  {
957  /* Find the first virtual folder and open it */
958  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
960  struct MailboxNode *mp = STAILQ_FIRST(&ml);
961  if (mp)
962  cs_str_string_set(cs, "spool_file", mailbox_path(mp->mailbox), NULL);
964  }
965 #endif
966  rc = 0;
967 
968 done:
969  mutt_buffer_dealloc(&err);
970  mutt_buffer_dealloc(&buf);
971  return rc;
972 }
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:664
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:432
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:69
char * HomeDir
User's home directory.
Definition: mutt_globals.h:51
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:455
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:881
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:37
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:90
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'my_hdr' command - Implements Command::parse() -.
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to the terminal - Implements log_dispatcher_t -.
Definition: logging.c:441
#define mutt_error(...)
Definition: logging.h:87
#define mutt_perror(...)
Definition: logging.h:88
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:109
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition: hash.h:110
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
void mutt_hist_read_file(void)
Read the History from a file.
Definition: history.c:599
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:468
void imap_init(void)
Setup feature commands.
Definition: imap.c:83
static int execute_commands(struct ListHead *p)
Execute a set of NeoMutt commands.
Definition: init.c:207
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition: init.c:312
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition: init.c:239
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:348
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:215
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:54
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
void menu_init(void)
Initialise all the Menus.
Definition: menu.c:118
char * mutt_ch_get_langinfo_charset(void)
Get the user's choice of character set.
Definition: charset.c:473
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition: charset.c:1014
void mutt_commands_init(void)
struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:61
struct ListHead Muttrc
List of config files to read.
Definition: mutt_globals.h:68
char * Username
User's login name.
Definition: mutt_globals.h:54
void mutt_lua_init(void)
Setup feature commands.
Definition: mutt_lua.c:469
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1728
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition: muttlib.c:1516
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition: muttlib.c:361
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:164
void nm_init(void)
Setup feature commands.
Definition: notmuch.c:99
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:53
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:47
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:458
int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:393
int cs_str_string_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:595
void sb_init(void)
Set up the Sidebar.
Definition: sidebar.c:198
#define NONULL(x)
Definition: string2.h:37
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
List of Mailboxes.
Definition: mailbox.h:157
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_label_complete()

int mutt_label_complete ( char *  buf,
size_t  buflen,
int  numtabs 
)

Complete a label name.

Parameters
bufBuffer for the result
buflenLength of the buffer
numtabsNumber of times the user has hit 'tab'
Return values
1Success, a match
0Error, no match

Definition at line 1312 of file init.c.

1313 {
1314  char *pt = buf;
1315  int spaces; /* keep track of the number of leading spaces on the line */
1316 
1317  if (!Context || !Context->mailbox->label_hash)
1318  return 0;
1319 
1320  SKIPWS(buf);
1321  spaces = buf - pt;
1322 
1323  /* first TAB. Collect all the matches */
1324  if (numtabs == 1)
1325  {
1326  struct HashElem *entry = NULL;
1327  struct HashWalkState state = { 0 };
1328 
1329  NumMatched = 0;
1330  mutt_str_copy(UserTyped, buf, sizeof(UserTyped));
1331  memset(Matches, 0, MatchesListsize);
1332  memset(Completed, 0, sizeof(Completed));
1333  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1334  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1336  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_istr_cmp);
1338 
1339  /* All matches are stored. Longest non-ambiguous string is ""
1340  * i.e. don't change 'buf'. Fake successful return this time */
1341  if (UserTyped[0] == '\0')
1342  return 1;
1343  }
1344 
1345  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1346  return 0;
1347 
1348  /* NumMatched will _always_ be at least 1 since the initial
1349  * user-typed string is always stored */
1350  if ((numtabs == 1) && (NumMatched == 2))
1351  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1352  else if ((numtabs > 1) && (NumMatched > 2))
1353  {
1354  /* cycle through all the matches */
1355  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1356  }
1357 
1358  /* return the completed label */
1359  strncpy(buf, Completed, buflen - spaces);
1360 
1361  return 1;
1362 }
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem's in a Hash Table.
Definition: hash.c:481
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
int(* sort_t)(const void *a, const void *b)
Definition: sort.h:47
The "current" mailbox.
Definition: context.h:38
struct Mailbox * mailbox
Current Mailbox.
Definition: context.h:49
Cursor to iterate through a Hash Table.
Definition: hash.h:132
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:129
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_nm_query_complete()

bool mutt_nm_query_complete ( char *  buf,
size_t  buflen,
int  pos,
int  numtabs 
)

Complete to the nearest notmuch tag.

Parameters
bufBuffer for the result
buflenLength of the buffer
posCursor position in the buffer
numtabsNumber of times the user has hit 'tab'
Return values
trueSuccess, a match
falseError, no match

Complete the nearest "tag:"-prefixed string previous to pos.

Definition at line 1376 of file init.c.

1377 {
1378  char *pt = buf;
1379  int spaces;
1380 
1381  SKIPWS(buf);
1382  spaces = buf - pt;
1383 
1384  pt = (char *) mutt_strn_rfind((char *) buf, pos, "tag:");
1385  if (pt)
1386  {
1387  pt += 4;
1388  if (numtabs == 1)
1389  {
1390  /* First TAB. Collect all the matches */
1392 
1393  /* All matches are stored. Longest non-ambiguous string is ""
1394  * i.e. don't change 'buf'. Fake successful return this time. */
1395  if (UserTyped[0] == '\0')
1396  return true;
1397  }
1398 
1399  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1400  return false;
1401 
1402  /* NumMatched will _always_ be at least 1 since the initial
1403  * user-typed string is always stored */
1404  if ((numtabs == 1) && (NumMatched == 2))
1405  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1406  else if ((numtabs > 1) && (NumMatched > 2))
1407  {
1408  /* cycle through all the matches */
1409  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1410  }
1411 
1412  /* return the completed query */
1413  strncpy(pt, Completed, buf + buflen - pt - spaces);
1414  }
1415  else
1416  return false;
1417 
1418  return true;
1419 }
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:149
const char * mutt_strn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:953
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_nm_tag_complete()

bool mutt_nm_tag_complete ( char *  buf,
size_t  buflen,
int  numtabs 
)

Complete to the nearest notmuch tag.

Parameters
bufBuffer for the result
buflenLength of the buffer
numtabsNumber of times the user has hit 'tab'
Return values
trueSuccess, a match
falseError, no match

Complete the nearest "+" or "-" -prefixed string previous to pos.

Definition at line 1433 of file init.c.

1434 {
1435  if (!buf)
1436  return false;
1437 
1438  char *pt = buf;
1439 
1440  /* Only examine the last token */
1441  char *last_space = strrchr(buf, ' ');
1442  if (last_space)
1443  pt = (last_space + 1);
1444 
1445  /* Skip the +/- */
1446  if ((pt[0] == '+') || (pt[0] == '-'))
1447  pt++;
1448 
1449  if (numtabs == 1)
1450  {
1451  /* First TAB. Collect all the matches */
1453 
1454  /* All matches are stored. Longest non-ambiguous string is ""
1455  * i.e. don't change 'buf'. Fake successful return this time. */
1456  if (UserTyped[0] == '\0')
1457  return true;
1458  }
1459 
1460  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1461  return false;
1462 
1463  /* NumMatched will _always_ be at least 1 since the initial
1464  * user-typed string is always stored */
1465  if ((numtabs == 1) && (NumMatched == 2))
1466  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1467  else if ((numtabs > 1) && (NumMatched > 2))
1468  {
1469  /* cycle through all the matches */
1470  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1471  }
1472 
1473  /* return the completed query */
1474  strncpy(pt, Completed, buf + buflen - pt);
1475 
1476  return true;
1477 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_opts_free()

void mutt_opts_free ( void  )

Clean up before quitting.

Definition at line 643 of file init.c.

644 {
646 
647  alias_shutdown();
648 #ifdef USE_SIDEBAR
649  sb_shutdown();
650 #endif
651 
657 
661 
662  /* Lists of strings */
672 
674 
676  FREE(&HomeDir);
677  FREE(&LastFolder);
679  FREE(&Username);
680 
682 
684 
685  mutt_hist_free();
686  mutt_keys_free();
687 
690 }
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:672
void mutt_colors_cleanup(void)
Cleanup all the colours.
Definition: color.c:163
void clear_source_stack(void)
Free memory from the stack used for the source command.
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:43
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:40
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:42
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:41
struct ListHead Ignore
List of header patterns to ignore.
Definition: globals.c:35
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:36
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:102
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:449
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:441
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:327
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1731
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:171
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:448
void mutt_commands_free(void)
Free Commands array.
char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:57
char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:52
struct ListHead MimeLookupList
List of mime types that that shouldn't use the mailcap entry.
Definition: mutt_globals.h:67
struct ListHead AlternativeOrderList
List of preferred mime types to display.
Definition: mutt_globals.h:64
struct ListHead AutoViewList
List of mime types to auto view.
Definition: mutt_globals.h:65
char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:56
struct ListHead UserHeader
List of custom headers to add to outgoing emails.
Definition: mutt_globals.h:70
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition: mutt_globals.h:66
void sb_shutdown(void)
Clean up the Sidebar.
Definition: sidebar.c:210
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_rc_buffer()

enum CommandResult mutt_parse_rc_buffer ( struct Buffer line,
struct Buffer token,
struct Buffer err 
)

Parse a line of user config.

Parameters
lineconfig line to read
tokenscratch buffer to be used by parser
errwhere to write error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

The reason for token is to avoid having to allocate and deallocate a lot of memory if we are parsing many lines. the caller can pass in the memory to use, which avoids having to create new space for every call to this function.

Definition at line 720 of file init.c.

987 {
988  if (mutt_buffer_len(line) == 0)
989  return 0;
990 
992 
993  mutt_buffer_reset(err);
994 
995  /* Read from the beginning of line->data */
996  mutt_buffer_seek(line, 0);
997 
998  SKIPWS(line->dptr);
999  while (*line->dptr)
1000  {
1001  if (*line->dptr == '#')
1002  break; /* rest of line is a comment */
1003  if (*line->dptr == ';')
1004  {
1005  line->dptr++;
1006  continue;
1007  }
1009 
1010  struct Command *cmd = NULL;
1011  size_t size = mutt_commands_array(&cmd);
1012  size_t i;
1013  for (i = 0; i < size; i++)
1014  {
1015  if (mutt_str_equal(token->data, cmd[i].name))
1016  {
1017  mutt_debug(LL_NOTIFY, "NT_COMMAND: %s\n", cmd[i].name);
1018  rc = cmd[i].parse(token, line, cmd[i].data, err);
1019  if ((rc == MUTT_CMD_ERROR) || (rc == MUTT_CMD_FINISH))
1020  goto finish; /* Propagate return code */
1021 
1022  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
1023  break; /* Continue with next command */
1024  }
1025  }
1026  if (i == size)
1027  {
1028  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1029  rc = MUTT_CMD_ERROR;
1030  break; /* Ignore the rest of the line */
1031  }
1032  }
1033 finish:
1034  return rc;
1035 }
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
CommandResult
Error codes for command_t parse functions.
Definition: command.h:34
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:37
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:35
@ MUTT_CMD_FINISH
Finish: Stop processing this file.
Definition: command.h:38
@ LL_NOTIFY
Log of notifications.
Definition: logging.h:45
#define _(a)
Definition: message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
@ NT_COMMAND
A Command has been executed, Command.
Definition: notify_type.h:40
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
+ Here is the caller graph for this function:

◆ mutt_parse_rc_line()

enum CommandResult mutt_parse_rc_line ( const char *  line,
struct Buffer err 
)

Parse a line of user config.

Parameters
lineConfig line to read
errWhere to write error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 720 of file init.c.

1044 {
1045  if (!line || (*line == '\0'))
1046  return MUTT_CMD_ERROR;
1047 
1048  struct Buffer *line_buffer = mutt_buffer_pool_get();
1049  struct Buffer *token = mutt_buffer_pool_get();
1050 
1051  mutt_buffer_strcpy(line_buffer, line);
1052 
1053  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1054 
1055  mutt_buffer_pool_release(&line_buffer);
1056  mutt_buffer_pool_release(&token);
1057  return rc;
1058 }
enum CommandResult mutt_parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:985
+ Here is the caller graph for this function:

◆ mutt_query_variables()

int mutt_query_variables ( struct ListHead *  queries,
bool  show_docs 
)

Implement the -Q command line flag.

Parameters
queriesList of query strings
show_docsIf true, show one-liner docs for the config item
Return values
0Success, all queries exist
1Error

Definition at line 1067 of file init.c.

1068 {
1069  struct Buffer value = mutt_buffer_make(256);
1070  struct Buffer tmp = mutt_buffer_make(256);
1071  int rc = 0;
1072 
1073  struct ListNode *np = NULL;
1074  STAILQ_FOREACH(np, queries, entries)
1075  {
1076  mutt_buffer_reset(&value);
1077 
1078  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
1079  if (!he)
1080  {
1081  mutt_warning(_("No such variable: %s"), np->data);
1082  rc = 1;
1083  continue;
1084  }
1085 
1086  if (he->type & DT_DEPRECATED)
1087  {
1088  mutt_warning(_("Config variable '%s' is deprecated"), np->data);
1089  rc = 1;
1090  continue;
1091  }
1092 
1093  int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1094  if (CSR_RESULT(rv) != CSR_SUCCESS)
1095  {
1096  rc = 1;
1097  continue;
1098  }
1099 
1100  int type = DTYPE(he->type);
1101  if (type == DT_PATH)
1102  mutt_pretty_mailbox(value.data, value.dsize);
1103 
1104  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
1105  {
1106  mutt_buffer_reset(&tmp);
1107  pretty_var(value.data, &tmp);
1108  mutt_buffer_strcpy(&value, tmp.data);
1109  }
1110 
1111  dump_config_neo(NeoMutt->sub->cs, he, &value, NULL,
1112  show_docs ? CS_DUMP_SHOW_DOCS : CS_DUMP_NO_FLAGS, stdout);
1113  }
1114 
1115  mutt_buffer_dealloc(&value);
1116  mutt_buffer_dealloc(&tmp);
1117 
1118  return rc; // TEST16: neomutt -Q charset
1119 }
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
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:106
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:526
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
#define mutt_warning(...)
Definition: logging.h:85
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:354
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:179
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
#define DT_LONG
a number (long)
Definition: types.h:33
#define DT_BOOL
boolean option
Definition: types.h:30
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_NUMBER
a number
Definition: types.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_var_value_complete()

int mutt_var_value_complete ( char *  buf,
size_t  buflen,
int  pos 
)

Complete a variable/value.

Parameters
bufBuffer for the result
buflenLength of the buffer
posCursor position in the buffer

Definition at line 1486 of file init.c.

1487 {
1488  char *pt = buf;
1489 
1490  if (buf[0] == '\0')
1491  return 0;
1492 
1493  SKIPWS(buf);
1494  const int spaces = buf - pt;
1495 
1496  pt = buf + pos - spaces;
1497  while ((pt > buf) && !isspace((unsigned char) *pt))
1498  pt--;
1499  pt++; /* move past the space */
1500  if (*pt == '=') /* abort if no var before the '=' */
1501  return 0;
1502 
1503  if (mutt_str_startswith(buf, "set"))
1504  {
1505  const char *myvarval = NULL;
1506  char var[256];
1507  mutt_str_copy(var, pt, sizeof(var));
1508  /* ignore the trailing '=' when comparing */
1509  int vlen = mutt_str_len(var);
1510  if (vlen == 0)
1511  return 0;
1512 
1513  var[vlen - 1] = '\0';
1514 
1515  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, var);
1516  if (!he)
1517  {
1518  myvarval = myvar_get(var);
1519  if (myvarval)
1520  {
1521  struct Buffer pretty = mutt_buffer_make(256);
1522  pretty_var(myvarval, &pretty);
1523  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1524  mutt_buffer_dealloc(&pretty);
1525  return 1;
1526  }
1527  return 0; /* no such variable. */
1528  }
1529  else
1530  {
1531  struct Buffer value = mutt_buffer_make(256);
1532  struct Buffer pretty = mutt_buffer_make(256);
1533  int rc = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1534  if (CSR_RESULT(rc) == CSR_SUCCESS)
1535  {
1536  pretty_var(value.data, &pretty);
1537  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1538  mutt_buffer_dealloc(&value);
1539  mutt_buffer_dealloc(&pretty);
1540  return 0;
1541  }
1542  mutt_buffer_dealloc(&value);
1543  mutt_buffer_dealloc(&pretty);
1544  return 1;
1545  }
1546  }
1547  return 0;
1548 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function: