* initial plumbing and some documentation for xml/json/sexp output through

--format= parameter.

  also, add --format=links, --format=xquery
This commit is contained in:
Dirk-Jan C. Binnema 2011-01-05 20:35:50 +02:00
parent 56f1664d8c
commit 6539ae4bd7
6 changed files with 258 additions and 56 deletions

View File

@ -1,4 +1,4 @@
.TH MU FIND 1 "November 2010" "User Manuals" .TH MU FIND 1 "January 2011" "User Manuals"
.SH NAME .SH NAME
@ -12,9 +12,9 @@ database
.SH DESCRIPTION .SH DESCRIPTION
\fBmu find\fR is the \fBmu\fR sub-command for searching e-mail message that \fBmu find\fR is the \fBmu\fR command for searching e-mail message that
were stored earlier using were stored earlier using
\fBmu index(1)\bR. \fBmu index(1)\fR.
.SH SEARCHING MAIL .SH SEARCHING MAIL
@ -25,7 +25,18 @@ search pattern. For example:
$ mu find subject:snow from:john $ mu find subject:snow from:john
.fi .fi
would find all messages from John with 'snow' in the subject field. would find all messages from John with 'snow' in the subject field, something
like:
.nf
2009-03-05 17:57:33 EET Lucia <lucia@example.com> running in the snow
2009-03-05 18:38:24 EET Marius <marius@foobar.com> Re: running in the snow
.fi
Note, this the default, plain-text output, which is the default, so you don't
have to use \fB--format=plain\fR. For other types of output (such as symlinks,
XML, JSON or s-expressions), see the discussion in the \fBOPTIONS\fR-section
below about \fB--format\fR.
The search pattern is taken as a command-line parameter. If the search The search pattern is taken as a command-line parameter. If the search
parameter consists of multiple parts (as in the example) they are treated as parameter consists of multiple parts (as in the example) they are treated as
@ -104,6 +115,7 @@ extra discusion.
First, the message flags field describes certain properties of the message, as First, the message flags field describes certain properties of the message, as
listed in the following table: listed in the following table:
.nf .nf
d,draft Draft Message d,draft Draft Message
f,flagged Flagged f,flagged Flagged
@ -162,16 +174,21 @@ at 23:59.
To get all messages between (inclusive) the 5th of May 2009 and the 2nd of To get all messages between (inclusive) the 5th of May 2009 and the 2nd of
June 2010, you could use: June 2010, you could use:
.nf .nf
$ mu find date:20090505..20100602 $ mu find date:20090505..20100602
.fi .fi
Characters like ':', '/', '-' and single '.' are ignored, so the following is Characters like ':', '/', '-' and single '.' are ignored, so the following is
equivalent but more readable: equivalent but more readable:
.nf .nf
$ mu find date:2009-05-05..2010-06-02 $ mu find date:2009-05-05..2010-06-02
.fi .fi
Precision is up to the minute and 24-hour notation for times is used, so Precision is up to the minute and 24-hour notation for times is used, so
another example would be: another example would be:
.nf .nf
$ mu find date:2009-05-05/12:23..2010-06-02/17:18 $ mu find date:2009-05-05/12:23..2010-06-02/17:18
.fi .fi
@ -193,6 +210,7 @@ examples will explain this:
Using this notation, you can for example match messages between two and three Using this notation, you can for example match messages between two and three
weeks old: weeks old:
.nf .nf
$ mu find date:3w..2w $ mu find date:3w..2w
.fi .fi
@ -222,9 +240,11 @@ from), which will replace with the actual field in the output. Fields that are
not known will be output as-is, allowing for some simple formatting. not known will be output as-is, allowing for some simple formatting.
For example: For example:
.nf .nf
$ mu find subject:snow --fields "d f s" $ mu find subject:snow --fields "d f s"
.fi .fi
would list the date, subject and sender of all messages with 'snow' in the would list the date, subject and sender of all messages with 'snow' in the
their subject. their subject.
@ -278,15 +298,33 @@ choice, but for dates it may be more useful to sort in the opposite direction.
.TP .TP
\fB\-\-xquery\fR \fB\-\-xquery\fR
shows the Xapian query corresponding to your search terms. This is primarily
meant for for debugging purposes.
.TP .TP
\fB\-k\fR, \fB\-\-summary\-len\fR=\fI<len>\fR \fB\-k\fR, \fB\-\-summary\-len\fR=\fI<len>\fR
output a summary based on up to \fI\len\fR lines of the message. The default is output a summary based on up to \fI\len\fR lines of the message. The default
.B 0 is \fB0\fR: no summary at all.
, or no summary.
.TP
\fB\-\-format\fR=\fIplain|links|xquery|xml|json|sexp\fR
output results in the specified format.
The default is \fBplain\fR, i.e normal output with one line per message.
\fBlinks\fR outputs the results as a maildir with symbolic links to the found
messages. This enables easy integration with mail-clients (see below for more
information). See \fB\-\-linksdir\fR and \fB\-\-clearlinks\fR below.
\fBxml\fR formats the search results as XML.
\fBjson\fR formats the search results as JSON (\fIJavascript Object
Notation\fR).
\fBsexp\fR formats the search results as an s-expression as used in Lisp
programming environments.
\fBxquery\fR shows the Xapian query corresponding to your search terms. This
is meant for for debugging purposes.
.TP .TP
\fB\-\-linksdir\fR \fR=\fI<dir>\fR and \fB\-c\fR, \fB\-\-clearlinks\fR \fB\-\-linksdir\fR \fR=\fI<dir>\fR and \fB\-c\fR, \fB\-\-clearlinks\fR
output the results as a maildir with symbolic links to the found output the results as a maildir with symbolic links to the found
@ -364,51 +402,69 @@ Find all messages with attachments:
.TP .TP
\fBmutt\fR \fBmutt\fR
For \fBmutt\fR you can use the following in your \fImuttrc\fR; pressing the F8 For \fBmutt\fR you can use the following in your \fImuttrc\fR; pressing the F8
key will start a search, and F9 will take you to the results. key will start a search, and F9 will take you to the results.
.nf .nf
# mutt macros for mu # mutt macros for mu
macro index <F8> "<shell-escape>mu find -c -l ~/Maildir/search " \ macro index <F8> "<shell-escape>mu find -c -l ~/Maildir/search " \\
"mu find" "mu find"
macro index <F9> "<change-folder-readonly>~/Maildir/search" \ macro index <F9> "<change-folder-readonly>~/Maildir/search" \\
"display mu find results" "mu find results"
.fi .fi
.TP .TP
\fBWanderlust\fR \fBWanderlust\fR
If you use the Wanderlust e-mail client for \fBemacs\fR, the following If you use the Wanderlust e-mail client for \fBemacs\fR, the following
definitions can be used; typing 'Q' will start a query. definitions can be used; typing 'Q' will start a query.
.nf .nf
;; mu integration for Wanderlust (defvar mu-wl-mu-program "/usr/local/bin/mu")
(defvar mu-wl-mu-program "mu")
(defvar mu-wl-search-folder "search") (defvar mu-wl-search-folder "search")
(defun mu-wl-search () (defun mu-wl-search ()
"search for messages with `mu', and jump to the results" "search for messages with `mu', and jump to the results"
(interactive) (let* ((muexpr (read-string "Find messages matching: "))
(let* ((muexpr (read-string "Find messages matching: "))
(sfldr (concat elmo-maildir-folder-path "/" (sfldr (concat elmo-maildir-folder-path "/"
mu-wl-search-folder)) mu-wl-search-folder))
(cmdline (concat mu-wl-mu-program " find " (cmdline (concat mu-wl-mu-program " find "
"--clearlinks --linksdir='" sfldr "' " "--clearlinks --format=links --linksdir='" sfldr "' "
muexpr))) muexpr))
(= 0 (shell-command cmdline)))) (rv (shell-command cmdline)))
(cond
((= rv 0) (message "Query succeeded"))
((= rv 2) (message "No matches found"))
(t (message "Error running query")))
(= rv 0)))
(defun mu-wl-search-and-goto () (defun mu-wl-search-and-goto ()
"search and jump to the folder with the results" "search and jump to the folder with the results"
(interactive) (interactive)
(when (mu-wl-search)
(if (mu-wl-search)
(wl-summary-goto-folder-subr (wl-summary-goto-folder-subr
(concat "." mu-wl-search-folder) (concat "." mu-wl-search-folder)
'force-update nil nil t) 'force-update nil nil t)
(message "Query failed"))) (wl-summary-sort-by-date)))
;; querying both in summary and folder
(define-key wl-summary-mode-map (kbd "Q") ;; => query
'(lambda()(interactive)(mu-wl-search-and-goto)))
(define-key wl-folder-mode-map (kbd "Q") ;; => query
'(lambda()(interactive)(mu-wl-search-and-goto)))
.fi .fi
.SH RETURN VALUE
\fBmu\fR returns 0 for searches with at least one matching message, 2 for
searches that do not match anything. In case of errors 1 or any number greater
than 2 will be returned.
.SH BUGS .SH BUGS
Please report bugs if you find them: Please report bugs if you find them:

View File

@ -37,10 +37,46 @@
#include "mu-runtime.h" #include "mu-runtime.h"
#include "mu-util.h" #include "mu-util.h"
#include "mu-util-db.h"
#include "mu-cmd.h" #include "mu-cmd.h"
#include "mu-output.h" #include "mu-output.h"
enum _OutputFormat {
FORMAT_JSON,
FORMAT_LINKS,
FORMAT_PLAIN,
FORMAT_SEXP,
FORMAT_XML,
FORMAT_XQUERY,
FORMAT_NONE
};
typedef enum _OutputFormat OutputFormat;
static OutputFormat
get_output_format (const char *formatstr)
{
int i;
struct {
const char* name;
OutputFormat format;
} formats [] = {
{MU_CONFIG_FORMAT_JSON, FORMAT_JSON},
{MU_CONFIG_FORMAT_LINKS, FORMAT_LINKS},
{MU_CONFIG_FORMAT_PLAIN, FORMAT_PLAIN},
{MU_CONFIG_FORMAT_SEXP, FORMAT_SEXP},
{MU_CONFIG_FORMAT_XML, FORMAT_XML},
{MU_CONFIG_FORMAT_XQUERY, FORMAT_XQUERY}
};
for (i = 0; i != G_N_ELEMENTS(formats); i++)
if (strcmp (formats[i].name, formatstr) == 0)
return formats[i].format;
return FORMAT_NONE;
}
static void static void
update_warning (void) update_warning (void)
{ {
@ -55,7 +91,7 @@ print_xapian_query (MuQuery *xapian, const gchar *query)
{ {
char *querystr; char *querystr;
GError *err; GError *err;
err = NULL; err = NULL;
querystr = mu_query_as_string (xapian, query, &err); querystr = mu_query_as_string (xapian, query, &err);
if (!querystr) { if (!querystr) {
@ -93,7 +129,7 @@ sort_field_from_string (const char* fieldstr)
static gboolean static gboolean
run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, run_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
size_t *count) OutputFormat format, size_t *count)
{ {
GError *err; GError *err;
MuMsgIter *iter; MuMsgIter *iter;
@ -116,14 +152,29 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
return FALSE; return FALSE;
} }
if (opts->linksdir) switch (format) {
case FORMAT_LINKS:
rv = mu_output_links (iter, opts->linksdir, opts->clearlinks, rv = mu_output_links (iter, opts->linksdir, opts->clearlinks,
count); count);
else break;
case FORMAT_PLAIN:
rv = mu_output_plain (iter, opts->fields, opts->summary_len, rv = mu_output_plain (iter, opts->fields, opts->summary_len,
count); count);
break;
case FORMAT_XML:
rv = mu_output_xml (iter, count);
break;
case FORMAT_JSON:
rv = mu_output_json (iter, count);
break;
case FORMAT_SEXP:
rv = mu_output_sexp (iter, count);
break;
default:
g_assert_not_reached ();
return FALSE;
}
if (count && *count == 0) if (count && *count == 0)
g_warning ("no matches found"); g_warning ("no matches found");
@ -136,6 +187,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
static gboolean static gboolean
query_params_valid (MuConfig *opts) query_params_valid (MuConfig *opts)
{ {
OutputFormat format;
const gchar *xpath; const gchar *xpath;
if (opts->linksdir) if (opts->linksdir)
@ -144,6 +196,23 @@ query_params_valid (MuConfig *opts)
return FALSE; return FALSE;
} }
format = get_output_format (opts->formatstr);
if (format == FORMAT_NONE) {
g_warning ("invalid output format %s",
opts->formatstr ? opts->formatstr : "<none>");
return FALSE;
}
if (format == FORMAT_LINKS && !opts->linksdir) {
g_warning ("missing --linksdir argument");
return FALSE;
}
if (opts->linksdir && format != FORMAT_LINKS) {
g_warning ("--linksdir is only valid with --format=links");
return FALSE;
}
xpath = mu_runtime_xapian_dir(); xpath = mu_runtime_xapian_dir();
if (mu_util_check_dir (xpath, TRUE, FALSE)) if (mu_util_check_dir (xpath, TRUE, FALSE))
@ -261,12 +330,15 @@ mu_cmd_find (MuConfig *opts)
gboolean rv; gboolean rv;
gchar *query; gchar *query;
size_t count; size_t count;
OutputFormat format;
g_return_val_if_fail (opts, FALSE); g_return_val_if_fail (opts, FALSE);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND, FALSE); g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND, FALSE);
if (!query_params_valid (opts)) if (!query_params_valid (opts))
return MU_EXITCODE_ERROR; return MU_EXITCODE_ERROR;
format = get_output_format (opts->formatstr);
xapian = get_query_obj (); xapian = get_query_obj ();
if (!xapian) if (!xapian)
@ -276,11 +348,11 @@ mu_cmd_find (MuConfig *opts)
query = get_query (opts); query = get_query (opts);
if (!query) if (!query)
return MU_EXITCODE_ERROR; return MU_EXITCODE_ERROR;
if (opts->xquery) if (format == FORMAT_XQUERY)
rv = print_xapian_query (xapian, query); rv = print_xapian_query (xapian, query);
else else
rv = run_query (xapian, query, opts, &count); rv = run_query (xapian, query, opts, format, &count);
mu_query_destroy (xapian); mu_query_destroy (xapian);
g_free (query); g_free (query);
@ -291,4 +363,3 @@ mu_cmd_find (MuConfig *opts)
return (count == 0) ? return (count == 0) ?
MU_EXITCODE_NO_MATCHES : MU_EXITCODE_OK; MU_EXITCODE_NO_MATCHES : MU_EXITCODE_OK;
} }

View File

@ -49,15 +49,15 @@ config_options_group_mu (MuConfig *opts)
GOptionGroup *og; GOptionGroup *og;
GOptionEntry entries[] = { GOptionEntry entries[] = {
{"debug", 'd', 0, G_OPTION_ARG_NONE, &opts->debug, {"debug", 'd', 0, G_OPTION_ARG_NONE, &opts->debug,
"print debug output to standard error", NULL}, "print debug output to standard error (false)", NULL},
{"quiet", 'q', 0, G_OPTION_ARG_NONE, &opts->quiet, {"quiet", 'q', 0, G_OPTION_ARG_NONE, &opts->quiet,
"don't give any progress information", NULL}, "don't give any progress information (false)", NULL},
{"version", 'v', 0, G_OPTION_ARG_NONE, &opts->version, {"version", 'v', 0, G_OPTION_ARG_NONE, &opts->version,
"display version and copyright information", NULL}, "display version and copyright information (false)", NULL},
{"muhome", 0, 0, G_OPTION_ARG_FILENAME, &opts->muhome, {"muhome", 0, 0, G_OPTION_ARG_FILENAME, &opts->muhome,
"specify an alternative mu directory", NULL}, "specify an alternative mu directory", NULL},
{"log-stderr", 0, 0, G_OPTION_ARG_NONE, &opts->log_stderr, {"log-stderr", 0, 0, G_OPTION_ARG_NONE, &opts->log_stderr,
"log to standard error", NULL}, "log to standard error (false)", NULL},
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY,
&opts->params, "parameters", NULL}, &opts->params, "parameters", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, 0, NULL, NULL, NULL}
@ -94,16 +94,16 @@ config_options_group_index (MuConfig * opts)
{"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &opts->maildir, {"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &opts->maildir,
"top of the maildir", NULL}, "top of the maildir", NULL},
{"reindex", 0, 0, G_OPTION_ARG_NONE, &opts->reindex, {"reindex", 0, 0, G_OPTION_ARG_NONE, &opts->reindex,
"index even already indexed messages", NULL}, "index even already indexed messages (false)", NULL},
{"rebuild", 0, 0, G_OPTION_ARG_NONE, &opts->rebuild, {"rebuild", 0, 0, G_OPTION_ARG_NONE, &opts->rebuild,
"rebuild the database from scratch", NULL}, "rebuild the database from scratch (false)", NULL},
{"autoupgrade", 0, 0, G_OPTION_ARG_NONE, &opts->autoupgrade, {"autoupgrade", 0, 0, G_OPTION_ARG_NONE, &opts->autoupgrade,
"automatically upgrade the database with new mu versions", "auto-upgrade the database with new mu versions (false)",
NULL}, NULL},
{"nocleanup", 0, 0, G_OPTION_ARG_NONE, &opts->nocleanup, {"nocleanup", 0, 0, G_OPTION_ARG_NONE, &opts->nocleanup,
"don't clean up the database after indexing", NULL}, "don't clean up the database after indexing (false)", NULL},
{"xbatchsize", 0, 0, G_OPTION_ARG_INT, &opts->xbatchsize, {"xbatchsize", 0, 0, G_OPTION_ARG_INT, &opts->xbatchsize,
"set a custom batchsize for committing to xapian or 0 for default", NULL}, "set transaction batchsize for xapian commits (0)", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, 0, NULL, NULL, NULL}
}; };
@ -129,6 +129,9 @@ set_group_find_defaults (MuConfig *opts)
} }
} }
if (!opts->formatstr) /* by default, use plain output */
opts->formatstr = MU_CONFIG_FORMAT_PLAIN;
if (opts->linksdir) { if (opts->linksdir) {
gchar *old = opts->linksdir; gchar *old = opts->linksdir;
opts->linksdir = mu_util_dir_expand(opts->linksdir); opts->linksdir = mu_util_dir_expand(opts->linksdir);
@ -138,6 +141,7 @@ set_group_find_defaults (MuConfig *opts)
g_free(old); g_free(old);
} }
/* FIXME: some warning when summary_len < 0? */ /* FIXME: some warning when summary_len < 0? */
if (opts->summary_len < 1) if (opts->summary_len < 1)
opts->summary_len = 0; opts->summary_len = 0;
@ -148,8 +152,6 @@ config_options_group_find (MuConfig *opts)
{ {
GOptionGroup *og; GOptionGroup *og;
GOptionEntry entries[] = { GOptionEntry entries[] = {
{"xquery", 0, 0, G_OPTION_ARG_NONE, &opts->xquery,
"print the Xapian query (for debugging)", NULL},
{"fields", 'f', 0, G_OPTION_ARG_STRING, &opts->fields, {"fields", 'f', 0, G_OPTION_ARG_STRING, &opts->fields,
"fields to display in the output", NULL}, "fields to display in the output", NULL},
{"sortfield", 's', 0, G_OPTION_ARG_STRING, &opts->sortfield, {"sortfield", 's', 0, G_OPTION_ARG_STRING, &opts->sortfield,
@ -159,13 +161,14 @@ config_options_group_find (MuConfig *opts)
{"descending", 'z', 0, G_OPTION_ARG_NONE, &opts->descending, {"descending", 'z', 0, G_OPTION_ARG_NONE, &opts->descending,
"sort in descending order (z -> a)", NULL}, "sort in descending order (z -> a)", NULL},
{"summary-len", 'k', 0, G_OPTION_ARG_INT, &opts->summary_len, {"summary-len", 'k', 0, G_OPTION_ARG_INT, &opts->summary_len,
"max number of lines for summary", NULL}, "max number of lines for summary (0)", NULL},
{"linksdir", 0, 0, G_OPTION_ARG_STRING, &opts->linksdir, {"linksdir", 0, 0, G_OPTION_ARG_STRING, &opts->linksdir,
"output as symbolic links to a target maildir", NULL}, "output as symbolic links to a target maildir", NULL},
{"clearlinks", 0, 0, G_OPTION_ARG_NONE, &opts->clearlinks, {"clearlinks", 0, 0, G_OPTION_ARG_NONE, &opts->clearlinks,
"clear old links before filling a linksdir", NULL}, "clear old links before filling a linksdir (false)", NULL},
/* {"output", 'o', 0, G_OPTION_ARG_STRING, &opts->output, */ {"format", 'o', 0, G_OPTION_ARG_STRING, &opts->formatstr,
/* "output type ('plain'(*), 'links', 'xml', 'json', 'sexp')", NULL}, */ "output format ('plain'(*), 'links', 'xml',"
"'json', 'sexp', 'xquery') (plain)", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, 0, NULL, NULL, NULL}
}; };
@ -190,8 +193,7 @@ config_options_group_mkdir (MuConfig *opts)
/* set dirmode before, because '0000' is a valid mode */ /* set dirmode before, because '0000' is a valid mode */
opts->dirmode = 0755; opts->dirmode = 0755;
og = g_option_group_new("mkdir", og = g_option_group_new("mkdir", "options for the 'mkdir' command",
"options for the 'mkdir' command",
"", NULL, NULL); "", NULL, NULL);
g_option_group_add_entries(og, entries); g_option_group_add_entries(og, entries);
@ -205,15 +207,15 @@ config_options_group_extract(MuConfig *opts)
GOptionEntry entries[] = { GOptionEntry entries[] = {
{"save-attachments", 'a', 0, G_OPTION_ARG_NONE, {"save-attachments", 'a', 0, G_OPTION_ARG_NONE,
&opts->save_attachments, &opts->save_attachments,
"save all attachments", NULL}, "save all attachments (false)", NULL},
{"save-all", 0, 0, G_OPTION_ARG_NONE, &opts->save_all, {"save-all", 0, 0, G_OPTION_ARG_NONE, &opts->save_all,
"save all parts (incl. non-attachments)", NULL}, "save all parts (incl. non-attachments) (false)", NULL},
{"parts", 0, 0, G_OPTION_ARG_STRING, &opts->parts, {"parts", 0, 0, G_OPTION_ARG_STRING, &opts->parts,
"save specific parts (comma-separated list)", NULL}, "save specific parts (comma-separated list)", NULL},
{"target-dir", 0, 0, G_OPTION_ARG_FILENAME, &opts->targetdir, {"target-dir", 0, 0, G_OPTION_ARG_FILENAME, &opts->targetdir,
"target directory for saving", NULL}, "target directory for saving", NULL},
{"overwrite", 0, 0, G_OPTION_ARG_NONE, &opts->overwrite, {"overwrite", 0, 0, G_OPTION_ARG_NONE, &opts->overwrite,
"overwrite existing files", NULL}, "overwrite existing files (false)", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, 0, NULL, NULL, NULL}
}; };

View File

@ -27,6 +27,13 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define MU_CONFIG_FORMAT_PLAIN "plain" /* plain text output */
#define MU_CONFIG_FORMAT_LINKS "links" /* output as symlinks */
#define MU_CONFIG_FORMAT_XML "xml" /* output xml */
#define MU_CONFIG_FORMAT_JSON "json" /* output json */
#define MU_CONFIG_FORMAT_SEXP "sexp" /* output sexps */
#define MU_CONFIG_FORMAT_XQUERY "xquery" /* output the xapian query */
enum _MuConfigCmd { enum _MuConfigCmd {
MU_CONFIG_CMD_INDEX, MU_CONFIG_CMD_INDEX,
MU_CONFIG_CMD_FIND, MU_CONFIG_CMD_FIND,
@ -79,6 +86,9 @@ struct _MuConfig {
unsigned summary_len; /* max # of lines of msg in summary */ unsigned summary_len; /* max # of lines of msg in summary */
char *bookmark; /* use bookmark */ char *bookmark; /* use bookmark */
char *formatstr; /* output type
* (plain*,links,xml,json,sexp) */
/* output to a maildir with symlinks */ /* output to a maildir with symlinks */
char *linksdir; /* maildir to output symlinks */ char *linksdir; /* maildir to output symlinks */
gboolean clearlinks; /* clear a linksdir before filling */ gboolean clearlinks; /* clear a linksdir before filling */
@ -103,8 +113,8 @@ typedef struct _MuConfig MuConfig;
* *
* @param opts options * @param opts options
*/ */
MuConfig *mu_config_new (int *argcp, char ***argvp); MuConfig *mu_config_new (int *argcp, char ***argvp)
G_GNUC_WARN_UNUSED_RESULT;
/** /**
* free the MuOptionsConfig structure; the the muhome and maildir * free the MuOptionsConfig structure; the the muhome and maildir
* members are heap-allocated, so must be freed. * members are heap-allocated, so must be freed.

View File

@ -100,7 +100,6 @@ mu_output_links (MuMsgIter *iter, const char* linksdir,
g_return_val_if_fail (iter, FALSE); g_return_val_if_fail (iter, FALSE);
g_return_val_if_fail (linksdir, FALSE); g_return_val_if_fail (linksdir, FALSE);
g_return_val_if_fail (!mu_msg_iter_is_done (iter), FALSE);
/* note: we create the linksdir even if there are no search results */ /* note: we create the linksdir even if there are no search results */
if (!create_linksdir_maybe (linksdir, clearlinks)) if (!create_linksdir_maybe (linksdir, clearlinks))
@ -230,3 +229,32 @@ mu_output_plain (MuMsgIter *iter, const char *fields, size_t summary_len,
return TRUE; return TRUE;
} }
gboolean
mu_output_xml (MuMsgIter *iter, size_t *count)
{
g_print ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
g_print ("%s\n", __FUNCTION__);
return TRUE;
}
gboolean
mu_output_json (MuMsgIter *iter, size_t *count)
{
g_print ("{\n");
g_print ("\t%s\n", __FUNCTION__);
g_print ("}\n");
return TRUE;
}
gboolean
mu_output_sexp (MuMsgIter *iter, size_t *count)
{
g_print ("(%s)\n", __FUNCTION__);
return TRUE;
}

View File

@ -52,6 +52,41 @@ gboolean mu_output_plain (MuMsgIter *iter, const char *fields,
gboolean mu_output_links (MuMsgIter *iter, const char *linksdir, gboolean mu_output_links (MuMsgIter *iter, const char *linksdir,
gboolean clearlinks, size_t *count); gboolean clearlinks, size_t *count);
/**
* output the search results (MsgIter) as XML to standard
* output
*
* @param iter iterator pointing to a message row
* @param count output param to receive the number of messages found, or NULL
*
* @return TRUE if the printing succeeded, FALSE in case of error
*/
gboolean mu_output_xml (MuMsgIter *iter, size_t *count);
/**
* output the search results (MsgIter) as JSON to standard
* output
*
* @param iter iterator pointing to a message row
* @param count output param to receive the number of messages found, or NULL
*
* @return TRUE if the printing succeeded, FALSE in case of error
*/
gboolean mu_output_json (MuMsgIter *iter, size_t *count);
/**
* output the search results (MsgIter) as s-expressions to standard
* output
*
* @param iter iterator pointing to a message row
* @param count output param to receive the number of messages found, or NULL
*
* @return TRUE if the printing succeeded, FALSE in case of error
*/
gboolean mu_output_sexp (MuMsgIter *iter, size_t *count);
G_END_DECLS G_END_DECLS
#endif /*__MU_OUTPUT_H__*/ #endif /*__MU_OUTPUT_H__*/