X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch.c;h=93f319442c20a24dbf57497de9c4e9d02fc717e5;hp=f5669fcda2093cf5116f7bb99e7c5674745eb9d3;hb=565d87c2aab7d3c389a958c068323683316e5e0f;hpb=e2dd4ac00b9979de34bd517fa57de56260d38755 diff --git a/notmuch.c b/notmuch.c index f5669fcd..93f31944 100644 --- a/notmuch.c +++ b/notmuch.c @@ -32,6 +32,18 @@ typedef struct command { const char *documentation; } command_t; +#define MAX_ALIAS_SUBSTITUTIONS 3 + +typedef struct alias { + const char *name; + const char *substitutions[MAX_ALIAS_SUBSTITUTIONS]; +} alias_t; + +alias_t aliases[] = { + { "part", { "show", "--format=raw"}}, + { "search-tags", {"search", "--output=tags", "*"}} +}; + static int notmuch_help_command (void *ctx, int argc, char *argv[]); @@ -44,6 +56,9 @@ static const char search_terms_help[] = "\tthe given terms/phrases in the body, the subject, or any of\n" "\tthe sender or recipient headers.\n" "\n" + "\tAs a special case, a search string consisting of exactly a\n" + "\tsingle asterisk (\"*\") will match all messages.\n" + "\n" "\tIn addition to free text, the following prefixes can be used\n" "\tto force terms to match against specific portions of an email,\n" "\t(where indicate user-supplied values):\n" @@ -55,6 +70,7 @@ static const char search_terms_help[] = "\t\ttag: (or is:)\n" "\t\tid:\n" "\t\tthread:\n" + "\t\tfolder:\n" "\n" "\tThe from: prefix is used to match the name or address of\n" "\tthe sender of an email message.\n" @@ -79,6 +95,11 @@ static const char search_terms_help[] = "\tmessages). These thread ID values can be seen in the first\n" "\tcolumn of output from \"notmuch search\".\n" "\n" + "\tThe folder: prefix can be used to search for email message\n" + "\tfiles that are contained within particular directories within\n" + "\tthe mail store. Only the directory components below the top-level\n" + "\tmail database path are available to be searched.\n" + "\n" "\tIn addition to individual terms, multiple terms can be\n" "\tcombined with Boolean operators (\"and\", \"or\", \"not\", etc.).\n" "\tEach term in the query will be implicitly connected by a\n" @@ -106,7 +127,7 @@ static const char search_terms_help[] = "\n" "\t\t$(date +%%s -d 2009-10-01)..$(date +%%s)\n\n"; -command_t commands[] = { +static command_t commands[] = { { "setup", notmuch_setup_command, NULL, "Interactively setup notmuch for first use.", @@ -162,6 +183,39 @@ command_t commands[] = { "\t\tPresents the results in either JSON or\n" "\t\tplain-text (default)\n" "\n" + "\t--output=(summary|threads|messages|files|tags)\n" + "\n" + "\t\tsummary (default)\n" + "\n" + "\t\tOutput a summary of each thread with any message matching the\n" + "\t\tsearch terms. The summary includes the thread ID, date, the\n" + "\t\tnumber of messages in the thread (both the number matched and\n" + "\t\tthe total number), the authors of the thread and the subject.\n" + "\n" + "\t\tthreads\n" + "\n" + "\t\tOutput the thread IDs of all threads with any message matching\n" + "\t\tthe search terms, either one per line (--format=text) or as a\n" + "\t\tJSON array (--format=json).\n" + "\n" + "\t\tmessages\n" + "\n" + "\t\tOutput the message IDs of all messages matching the search\n" + "\t\tterms, either one per line (--format=text) or as a JSON array\n" + "\t\t(--format=json).\n" + "\n" + "\t\tfiles\n" + "\n" + "\t\tOutput the filenames of all messages matching the search\n" + "\t\tterms, either one per line (--format=text) or as a JSON array\n" + "\t\t(--format=json).\n" + "\n" + "\t\ttags\n" + "\n" + "\t\tOutput all tags that appear on any message matching the search\n" + "\t\tterms, either one per line (--format=text) or as a JSON array\n" + "\t\t(--format=json).\n" + "\n" "\t--sort=(newest-first|oldest-first)\n" "\n" "\t\tPresent results in either chronological order\n" @@ -186,23 +240,76 @@ command_t commands[] = { "\t\tall messages in the same thread as any matched\n" "\t\tmessage will be displayed.\n" "\n" - "\t--format=(json|text)\n" + "\t--format=(text|json|mbox|raw)\n" "\n" - "\t\ttext\t(default)\n" + "\t\ttext (default for messages)\n" "\n" - "\t\tThe plain-text has all text-content MIME parts decoded.\n" - "\t\tVarious components in the output, ('message', 'header',\n" + "\t\tThe default plain-text format has all text-content MIME parts\n" + "\t\tdecoded. Various components in the output, ('message', 'header',\n" "\t\t'body', 'attachment', and MIME 'part') are delimited by\n" "\t\teasily-parsed markers. Each marker consists of a Control-L\n" "\t\tcharacter (ASCII decimal 12), the name of the marker, and\n" "\t\tthen either an opening or closing brace, '{' or '}' to\n" - "\t\teither open or close the component.\n" + "\t\teither open or close the component. For a multipart MIME\n" + "\t\tmessage, these parts will be nested.\n" "\n" "\t\tjson\n" "\n" - "\t\tFormat output as Javascript Object Notation (JSON).\n" - "\t\tJSON output always includes all messages in a matching,\n" - "\t\tthread i.e. '--output=json' implies '--entire-thread'\n" + "\t\tThe output is formatted with Javascript Object Notation\n" + "\t\t(JSON). This format is more robust than the text format\n" + "\t\tfor automated processing. The nested structure of multipart\n" + "\t\tMIME messages is reflected in nested JSON output. JSON\n" + "\t\toutput always includes all messages in a matching thread;\n" + "\t\tin effect '--format=json' implies '--entire-thread'\n" + "\n" + "\t\tmbox\n" + "\n" + "\t\tAll matching messages are output in the traditional, Unix\n" + "\t\tmbox format with each message being prefixed by a line\n" + "\t\tbeginning with 'From ' and a blank line separating each\n" + "\t\tmessage. Lines in the message content beginning with 'From '\n" + "\t\t(preceded by zero or more '>' characters) have an additional\n" + "\t\t'>' character added. This reversible escaping is termed\n" + "\t\t\"mboxrd\" format and described in detail here:\n" + "\n" + "\t\thttp://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html\n" + "\n" + "\t\traw (default for a single part, see --part)\n" + "\n" + "\t\tFor a message, the original, raw content of the email\n" + "\t\tmessage is output. Consumers of this format should\n" + "\t\texpect to implement MIME decoding and similar functions.\n" + "\n" + "\t\tFor a single part (--part) the raw part content is output\n" + "\t\tafter performing any necessary MIME decoding.\n" + "\n" + "\t\tThe raw format must only be used with search terms matching\n" + "\t\tsingle message.\n" + "\n" + "\t--part=N\n" + "\n" + "\t\tOutput the single decoded MIME part N of a single message.\n" + "\t\tThe search terms must match only a single message.\n" + "\t\tMessage parts are numbered in a depth-first walk of the\n" + "\t\tmessage MIME structure, and are identified in the 'json' or\n" + "\t\t'text' output formats.\n" + "\n" + "\t--verify\n" + "\n" + "\t\tCompute and report the validity of any MIME cryptographic\n" + "\t\tsignatures found in the selected content (ie.\n" + "\t\t\"multipart/signed\" parts). Status of the signature will be\n" + "\t\treported (currently only supported with --format=json) and\n" + "\t\tthe multipart/signed part will be replaced by the signed data.\n" + "\n" + "\t--decrypt\n" + "\n" + "\t\tDecrypt any MIME encrypted parts found in the selected content\n" + "\t\t(ie. \"multipart/encrypted\" parts). Status of the decryption\n" + "\t\twill be reported (currently only supported with --format=json)\n" + "\t\tand the multipart/encrypted part will be replaced by the\n" + "\t\tdecrypted content.\n" + "\n" "\n" "\tA common use of \"notmuch show\" is to display a single\n" "\tthread of email messages. For this, use a search term of\n" @@ -216,12 +323,11 @@ command_t commands[] = { "Count messages matching the search terms.", "\tThe number of matching messages is output to stdout.\n" "\n" - "\tA common use of \"notmuch count\" is to display the count\n" - "\tof messages matching both a specific tag and either inbox\n" - "\tor unread\n" + "\tWith no search terms, a count of all messages in the database\n" + "\twill be displayed.\n" "\n" "\tSee \"notmuch help search-terms\" for details of the search\n" - "\t\tterms syntax." }, + "\tterms syntax." }, { "reply", notmuch_reply_command, "[options...] [...]", "Construct a reply template for a set of messages.", @@ -285,26 +391,31 @@ command_t commands[] = { "\tSo if you've previously been using sup for mail, then the\n" "\t\"notmuch restore\" command provides you a way to import\n" "\tall of your tags (or labels as sup calls them)." }, - { "search-tags", notmuch_search_tags_command, - "[ [...] ]", - "List all tags found in the database or matching messages.", - "\tRun this command without any search-term(s) to obtain a list\n" - "\tof all tags found in the database. If you provide one or more\n" - "\tsearch-terms as argument(s) then the resulting list will\n" - "\tcontain tags only from messages that match the search-term(s).\n" - "\n" - "\tIn both cases the list will be alphabetically sorted." }, - { "part", notmuch_part_command, - "--part= ", - "Output a single MIME part of a message.", - "\tA single decoded MIME part, with no encoding or framing,\n" - "\tis output to stdout. The search terms must match only a single\n" - "\tmessage, otherwise this command will fail.\n" - "\n" - "\tThe part number should match the part \"id\" field output\n" - "\tby the \"--format=json\" option of \"notmuch show\". If the\n" - "\tmessage specified by the search terms does not include a\n" - "\tpart with the specified \"id\" there will be no output." }, + { "config", notmuch_config_command, + "[get|set]
. [value ...]", + "Get or set settings in the notmuch configuration file.", + " config get
.\n" + "\n" + "\tThe value of the specified configuration item is printed\n" + "\tto stdout. If the item has multiple values, each value\n" + "\tis separated by a newline character.\n" + "\n" + "\tAvailable configuration items include at least\n" + "\n" + "\t\tdatabase.path\n" + "\t\tuser.name\n" + "\t\tuser.primary_email\n" + "\t\tuser.other_email\n" + "\t\tnew.tags\n" + "\n" + " config set
. [value ...]\n" + "\n" + "\tThe specified configuration item is set to the given value.\n" + "\tTo specify a multiple-value item, provide each value as\n" + "\ta separate command-line argument.\n" + "\n" + "\tIf no values are provided, the specified configuration item\n" + "\twill be removed from the configuration file." }, { "help", notmuch_help_command, "[]", "This message, or more detailed help for the named command.", @@ -459,7 +570,11 @@ main (int argc, char *argv[]) { void *local; command_t *command; - unsigned int i; + alias_t *alias; + unsigned int i, j; + const char **argv_local; + + talloc_enable_null_tracking (); local = talloc_new (NULL); @@ -472,10 +587,44 @@ main (int argc, char *argv[]) return notmuch_help_command (NULL, 0, NULL); if (STRNCMP_LITERAL (argv[1], "--version") == 0) { - printf ("notmuch version " STRINGIFY(NOTMUCH_VERSION) "\n"); + printf ("notmuch " STRINGIFY(NOTMUCH_VERSION) "\n"); return 0; } + for (i = 0; i < ARRAY_SIZE (aliases); i++) { + alias = &aliases[i]; + + if (strcmp (argv[1], alias->name) == 0) + { + int substitutions; + + argv_local = talloc_size (local, sizeof (char *) * + (argc + MAX_ALIAS_SUBSTITUTIONS - 1)); + if (argv_local == NULL) { + fprintf (stderr, "Out of memory.\n"); + return 1; + } + + /* Copy all substution arguments from the alias. */ + argv_local[0] = argv[0]; + for (j = 0; j < MAX_ALIAS_SUBSTITUTIONS; j++) { + if (alias->substitutions[j] == NULL) + break; + argv_local[j+1] = alias->substitutions[j]; + } + substitutions = j; + + /* And copy all original arguments (skipping the argument + * that matched the alias of course. */ + for (j = 2; j < (unsigned) argc; j++) { + argv_local[substitutions+j-1] = argv[j]; + } + + argc += substitutions - 1; + argv = (char **) argv_local; + } + } + for (i = 0; i < ARRAY_SIZE (commands); i++) { command = &commands[i];