NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
init.h File Reference

Config/command parsing. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include "mutt.h"
#include "hook.h"
#include "mutt_commands.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 770 of file mutt_config.c.

771 {
772  init_types(cs);
773  init_variables(cs);
774 }
static void init_variables(struct ConfigSet *cs)
Define the config variables.
Definition: mutt_config.c:726
static void init_types(struct ConfigSet *cs)
Create the config types.
Definition: mutt_config.c:706
+ 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 1126 of file init.c.

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

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

694 {
695  struct Command *c = NULL;
696  for (size_t i = 0, size = mutt_commands_array(&c); i < size; i++)
697  {
698  if (((c[i].parse == mutt_parse_hook) || (c[i].parse == mutt_parse_idxfmt_hook)) &&
699  mutt_istr_equal(c[i].name, name))
700  {
701  return c[i].data;
702  }
703  }
704  return MUTT_HOOK_NO_FLAGS;
705 }
enum CommandResult mutt_parse_idxfmt_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;index-format-hook&#39; command - Implements Command::parse() -.
Definition: hook.c:372
intptr_t data
Data or flags to pass to the command.
Definition: mutt_commands.h:64
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;hook&#39; family of commands - Implements Command::parse() -This is used by &#39;account-hook&#39;...
Definition: hook.c:82
const char * name
Name of the command.
Definition: mutt_commands.h:49
size_t mutt_commands_array(struct Command **first)
Get Commands array.
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Definition: mutt_commands.h:62
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:38
+ Here is the call graph for this function:
+ Here is the caller 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 715 of file init.c.

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

1309 {
1310  char *pt = buf;
1311  int spaces; /* keep track of the number of leading spaces on the line */
1312 
1313  if (!Context || !Context->mailbox->label_hash)
1314  return 0;
1315 
1316  SKIPWS(buf);
1317  spaces = buf - pt;
1318 
1319  /* first TAB. Collect all the matches */
1320  if (numtabs == 1)
1321  {
1322  struct HashElem *entry = NULL;
1323  struct HashWalkState state = { 0 };
1324 
1325  NumMatched = 0;
1326  mutt_str_copy(UserTyped, buf, sizeof(UserTyped));
1327  memset(Matches, 0, MatchesListsize);
1328  memset(Completed, 0, sizeof(Completed));
1329  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1330  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1332  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_istr_cmp);
1334 
1335  /* All matches are stored. Longest non-ambiguous string is ""
1336  * i.e. don't change 'buf'. Fake successful return this time */
1337  if (UserTyped[0] == '\0')
1338  return 1;
1339  }
1340 
1341  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1342  return 0;
1343 
1344  /* NumMatched will _always_ be at least 1 since the initial
1345  * user-typed string is always stored */
1346  if ((numtabs == 1) && (NumMatched == 2))
1347  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1348  else if ((numtabs > 1) && (NumMatched > 2))
1349  {
1350  /* cycle through all the matches */
1351  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1352  }
1353 
1354  /* return the completed label */
1355  strncpy(buf, Completed, buflen - spaces);
1356 
1357  return 1;
1358 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
The "current" mailbox.
Definition: context.h:37
union HashKey key
Key representing the data.
Definition: hash.h:46
static int NumMatched
Definition: init.c:81
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:129
Cursor to iterate through a Hash Table.
Definition: hash.h:122
struct Mailbox * mailbox
Definition: context.h:49
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:82
int(* sort_t)(const void *a, const void *b)
Prototype for generic comparison function, compatible with qsort.
Definition: sort.h:44
static int MatchesListsize
Definition: init.c:85
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:96
static char UserTyped[1024]
Definition: init.c:79
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
const char * strkey
String key.
Definition: hash.h:36
static const char ** Matches
Definition: init.c:83
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem&#39;s in a Hash Table.
Definition: hash.c:481
The item stored in a Hash Table.
Definition: hash.h:43
static void candidate(char *user, const char *src, char *dest, size_t dlen)
helper function for completion
Definition: init.c:119
+ 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 1372 of file init.c.

1373 {
1374  char *pt = buf;
1375  int spaces;
1376 
1377  SKIPWS(buf);
1378  spaces = buf - pt;
1379 
1380  pt = (char *) mutt_strn_rfind((char *) buf, pos, "tag:");
1381  if (pt)
1382  {
1383  pt += 4;
1384  if (numtabs == 1)
1385  {
1386  /* First TAB. Collect all the matches */
1388 
1389  /* All matches are stored. Longest non-ambiguous string is ""
1390  * i.e. don't change 'buf'. Fake successful return this time. */
1391  if (UserTyped[0] == '\0')
1392  return true;
1393  }
1394 
1395  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1396  return false;
1397 
1398  /* NumMatched will _always_ be at least 1 since the initial
1399  * user-typed string is always stored */
1400  if ((numtabs == 1) && (NumMatched == 2))
1401  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1402  else if ((numtabs > 1) && (NumMatched > 2))
1403  {
1404  /* cycle through all the matches */
1405  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1406  }
1407 
1408  /* return the completed query */
1409  strncpy(pt, Completed, buf + buflen - pt - spaces);
1410  }
1411  else
1412  return false;
1413 
1414  return true;
1415 }
static int NumMatched
Definition: init.c:81
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:82
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:148
static char UserTyped[1024]
Definition: init.c:79
static const char ** Matches
Definition: init.c:83
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 1429 of file init.c.

1430 {
1431  if (!buf)
1432  return false;
1433 
1434  char *pt = buf;
1435 
1436  /* Only examine the last token */
1437  char *last_space = strrchr(buf, ' ');
1438  if (last_space)
1439  pt = (last_space + 1);
1440 
1441  /* Skip the +/- */
1442  if ((pt[0] == '+') || (pt[0] == '-'))
1443  pt++;
1444 
1445  if (numtabs == 1)
1446  {
1447  /* First TAB. Collect all the matches */
1449 
1450  /* All matches are stored. Longest non-ambiguous string is ""
1451  * i.e. don't change 'buf'. Fake successful return this time. */
1452  if (UserTyped[0] == '\0')
1453  return true;
1454  }
1455 
1456  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1457  return false;
1458 
1459  /* NumMatched will _always_ be at least 1 since the initial
1460  * user-typed string is always stored */
1461  if ((numtabs == 1) && (NumMatched == 2))
1462  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1463  else if ((numtabs > 1) && (NumMatched > 2))
1464  {
1465  /* cycle through all the matches */
1466  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1467  }
1468 
1469  /* return the completed query */
1470  strncpy(pt, Completed, buf + buflen - pt);
1471 
1472  return true;
1473 }
static int NumMatched
Definition: init.c:81
static char Completed[256]
Definition: init.c:82
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:148
static char UserTyped[1024]
Definition: init.c:79
static const char ** Matches
Definition: init.c:83
+ 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 638 of file init.c.

639 {
641 
642  alias_shutdown();
643 #ifdef USE_SIDEBAR
644  sb_shutdown();
645 #endif
646 
652 
656 
657  /* Lists of strings */
658  mutt_list_free(&AlternativeOrderList);
659  mutt_list_free(&AutoViewList);
660  mutt_list_free(&HeaderOrderList);
663  mutt_list_free(&MimeLookupList);
664  mutt_list_free(&Muttrc);
666  mutt_list_free(&UserHeader);
667 
669 
671  FREE(&HomeDir);
672  FREE(&LastFolder);
674  FREE(&Username);
675 
677 
679 
680  mutt_hist_free();
681  mutt_keys_free();
682 
685 }
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:43
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:449
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:40
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:328
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:41
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:448
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
void clear_source_stack(void)
Free memory from the stack used for the souce command.
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:672
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
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1743
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:37
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:37
void mutt_colors_cleanup(void)
Cleanup all the colours.
Definition: color.c:384
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:51
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:36
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:50
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:42
#define FREE(x)
Definition: memory.h:40
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:38
void mutt_commands_free(void)
Free Commands array.
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:55
WHERE struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:55
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:441
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:171
+ 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 980 of file init.c.

982 {
983  if (mutt_buffer_len(line) == 0)
984  return 0;
985 
987 
988  mutt_buffer_reset(err);
989 
990  /* Read from the beginning of line->data */
991  mutt_buffer_seek(line, 0);
992 
993  SKIPWS(line->dptr);
994  while (*line->dptr)
995  {
996  if (*line->dptr == '#')
997  break; /* rest of line is a comment */
998  if (*line->dptr == ';')
999  {
1000  line->dptr++;
1001  continue;
1002  }
1004 
1005  struct Command *cmd = NULL;
1006  size_t size = mutt_commands_array(&cmd);
1007  size_t i;
1008  for (i = 0; i < size; i++)
1009  {
1010  if (mutt_str_equal(token->data, cmd[i].name))
1011  {
1012  mutt_debug(LL_NOTIFY, "NT_COMMAND: %s\n", cmd[i].name);
1013  rc = cmd[i].parse(token, line, cmd[i].data, err);
1014  if (rc != MUTT_CMD_SUCCESS)
1015  { /* -1 Error, +1 Finish */
1016  goto finish; /* Propagate return code */
1017  }
1018  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
1019  break; /* Continue with next command */
1020  }
1021  }
1022  if (i == size)
1023  {
1024  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1025  rc = MUTT_CMD_ERROR;
1026  break; /* Ignore the rest of the line */
1027  }
1028  }
1029 finish:
1030  return rc;
1031 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
intptr_t data
Data or flags to pass to the command.
Definition: mutt_commands.h:64
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
Log of notifications.
Definition: logging.h:45
#define _(a)
Definition: message.h:28
const char * name
Name of the command.
Definition: mutt_commands.h:49
A Command has been executed, Command.
Definition: notify_type.h:40
size_t mutt_commands_array(struct Command **first)
Get Commands array.
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Definition: mutt_commands.h:62
#define SKIPWS(ch)
Definition: string2.h:46
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Success: Command worked.
Definition: mutt_commands.h:38
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
set current read/write position to offset from beginning
Definition: buffer.c:466
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
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
+ Here is the call graph for this function:
+ 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 1039 of file init.c.

1040 {
1041  if (!line || (*line == '\0'))
1042  return MUTT_CMD_ERROR;
1043 
1044  struct Buffer *line_buffer = mutt_buffer_pool_get();
1045  struct Buffer *token = mutt_buffer_pool_get();
1046 
1047  mutt_buffer_strcpy(line_buffer, line);
1048 
1049  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1050 
1051  mutt_buffer_pool_release(&line_buffer);
1052  mutt_buffer_pool_release(&token);
1053  return rc;
1054 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
enum CommandResult mutt_parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:980
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
+ Here is the call graph for this function:
+ 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 1063 of file init.c.

1064 {
1065  struct Buffer value = mutt_buffer_make(256);
1066  struct Buffer tmp = mutt_buffer_make(256);
1067  int rc = 0;
1068 
1069  struct ListNode *np = NULL;
1070  STAILQ_FOREACH(np, queries, entries)
1071  {
1072  mutt_buffer_reset(&value);
1073 
1074  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
1075  if (!he)
1076  {
1077  mutt_warning(_("No such variable: %s"), np->data);
1078  rc = 1;
1079  continue;
1080  }
1081 
1082  if (he->type & DT_DEPRECATED)
1083  {
1084  mutt_warning(_("Config variable '%s' is deprecated"), np->data);
1085  rc = 1;
1086  continue;
1087  }
1088 
1089  int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1090  if (CSR_RESULT(rv) != CSR_SUCCESS)
1091  {
1092  rc = 1;
1093  continue;
1094  }
1095 
1096  int type = DTYPE(he->type);
1097  if (type == DT_PATH)
1098  mutt_pretty_mailbox(value.data, value.dsize);
1099 
1100  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
1101  {
1102  mutt_buffer_reset(&tmp);
1103  pretty_var(value.data, &tmp);
1104  mutt_buffer_strcpy(&value, tmp.data);
1105  }
1106 
1107  dump_config_neo(NeoMutt->sub->cs, he, &value, NULL,
1108  show_docs ? CS_DUMP_SHOW_DOCS : CS_DUMP_NO_FLAGS, stdout);
1109  }
1110 
1111  mutt_buffer_dealloc(&value);
1112  mutt_buffer_dealloc(&tmp);
1113 
1114  return rc; // TEST16: neomutt -Q charset
1115 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:526
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
#define DT_LONG
a number (long)
Definition: types.h:33
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
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
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
#define CSR_RESULT(x)
Definition: set.h:52
size_t dsize
Length of data.
Definition: buffer.h:37
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
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
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define mutt_warning(...)
Definition: logging.h:86
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:77
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
char * data
Pointer to data.
Definition: buffer.h:35
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * data
String.
Definition: list.h:36
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
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
The item stored in a Hash Table.
Definition: hash.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
#define DT_NUMBER
a number
Definition: types.h:35
#define DT_BOOL
boolean option
Definition: types.h:30
+ 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 1482 of file init.c.

1483 {
1484  char *pt = buf;
1485 
1486  if (buf[0] == '\0')
1487  return 0;
1488 
1489  SKIPWS(buf);
1490  const int spaces = buf - pt;
1491 
1492  pt = buf + pos - spaces;
1493  while ((pt > buf) && !isspace((unsigned char) *pt))
1494  pt--;
1495  pt++; /* move past the space */
1496  if (*pt == '=') /* abort if no var before the '=' */
1497  return 0;
1498 
1499  if (mutt_str_startswith(buf, "set"))
1500  {
1501  const char *myvarval = NULL;
1502  char var[256];
1503  mutt_str_copy(var, pt, sizeof(var));
1504  /* ignore the trailing '=' when comparing */
1505  int vlen = mutt_str_len(var);
1506  if (vlen == 0)
1507  return 0;
1508 
1509  var[vlen - 1] = '\0';
1510 
1511  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, var);
1512  if (!he)
1513  {
1514  myvarval = myvar_get(var);
1515  if (myvarval)
1516  {
1517  struct Buffer pretty = mutt_buffer_make(256);
1518  pretty_var(myvarval, &pretty);
1519  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1520  mutt_buffer_dealloc(&pretty);
1521  return 1;
1522  }
1523  return 0; /* no such variable. */
1524  }
1525  else
1526  {
1527  struct Buffer value = mutt_buffer_make(256);
1528  struct Buffer pretty = mutt_buffer_make(256);
1529  int rc = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1530  if (CSR_RESULT(rc) == CSR_SUCCESS)
1531  {
1532  pretty_var(value.data, &pretty);
1533  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1534  mutt_buffer_dealloc(&value);
1535  mutt_buffer_dealloc(&pretty);
1536  return 0;
1537  }
1538  mutt_buffer_dealloc(&value);
1539  mutt_buffer_dealloc(&pretty);
1540  return 1;
1541  }
1542  }
1543  return 0;
1544 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:179
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define CSR_RESULT(x)
Definition: set.h:52
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
#define SKIPWS(ch)
Definition: string2.h:46
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
char * data
Pointer to data.
Definition: buffer.h:35
const char * myvar_get(const char *var)
Get the value of a "my_" variable.
Definition: myvar.c:92
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
The item stored in a Hash Table.
Definition: hash.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function: