* initial plumbing and some documentation for xml/json/sexp output through
--format= parameter. also, add --format=links, --format=xquery
This commit is contained in:
@ -37,10 +37,46 @@
|
||||
#include "mu-runtime.h"
|
||||
|
||||
#include "mu-util.h"
|
||||
#include "mu-util-db.h"
|
||||
#include "mu-cmd.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
|
||||
update_warning (void)
|
||||
{
|
||||
@ -55,7 +91,7 @@ print_xapian_query (MuQuery *xapian, const gchar *query)
|
||||
{
|
||||
char *querystr;
|
||||
GError *err;
|
||||
|
||||
|
||||
err = NULL;
|
||||
querystr = mu_query_as_string (xapian, query, &err);
|
||||
if (!querystr) {
|
||||
@ -93,7 +129,7 @@ sort_field_from_string (const char* fieldstr)
|
||||
|
||||
static gboolean
|
||||
run_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
size_t *count)
|
||||
OutputFormat format, size_t *count)
|
||||
{
|
||||
GError *err;
|
||||
MuMsgIter *iter;
|
||||
@ -116,14 +152,29 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (opts->linksdir)
|
||||
switch (format) {
|
||||
case FORMAT_LINKS:
|
||||
rv = mu_output_links (iter, opts->linksdir, opts->clearlinks,
|
||||
count);
|
||||
else
|
||||
break;
|
||||
case FORMAT_PLAIN:
|
||||
rv = mu_output_plain (iter, opts->fields, opts->summary_len,
|
||||
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)
|
||||
g_warning ("no matches found");
|
||||
|
||||
@ -136,6 +187,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
static gboolean
|
||||
query_params_valid (MuConfig *opts)
|
||||
{
|
||||
OutputFormat format;
|
||||
const gchar *xpath;
|
||||
|
||||
if (opts->linksdir)
|
||||
@ -144,6 +196,23 @@ query_params_valid (MuConfig *opts)
|
||||
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();
|
||||
|
||||
if (mu_util_check_dir (xpath, TRUE, FALSE))
|
||||
@ -261,12 +330,15 @@ mu_cmd_find (MuConfig *opts)
|
||||
gboolean rv;
|
||||
gchar *query;
|
||||
size_t count;
|
||||
OutputFormat format;
|
||||
|
||||
g_return_val_if_fail (opts, FALSE);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND, FALSE);
|
||||
|
||||
if (!query_params_valid (opts))
|
||||
return MU_EXITCODE_ERROR;
|
||||
|
||||
format = get_output_format (opts->formatstr);
|
||||
|
||||
xapian = get_query_obj ();
|
||||
if (!xapian)
|
||||
@ -276,11 +348,11 @@ mu_cmd_find (MuConfig *opts)
|
||||
query = get_query (opts);
|
||||
if (!query)
|
||||
return MU_EXITCODE_ERROR;
|
||||
|
||||
if (opts->xquery)
|
||||
|
||||
if (format == FORMAT_XQUERY)
|
||||
rv = print_xapian_query (xapian, query);
|
||||
else
|
||||
rv = run_query (xapian, query, opts, &count);
|
||||
rv = run_query (xapian, query, opts, format, &count);
|
||||
|
||||
mu_query_destroy (xapian);
|
||||
g_free (query);
|
||||
@ -291,4 +363,3 @@ mu_cmd_find (MuConfig *opts)
|
||||
return (count == 0) ?
|
||||
MU_EXITCODE_NO_MATCHES : MU_EXITCODE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -49,15 +49,15 @@ config_options_group_mu (MuConfig *opts)
|
||||
GOptionGroup *og;
|
||||
GOptionEntry entries[] = {
|
||||
{"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,
|
||||
"don't give any progress information", NULL},
|
||||
"don't give any progress information (false)", NULL},
|
||||
{"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,
|
||||
"specify an alternative mu directory", NULL},
|
||||
{"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,
|
||||
&opts->params, "parameters", 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,
|
||||
"top of the maildir", NULL},
|
||||
{"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 the database from scratch", NULL},
|
||||
"rebuild the database from scratch (false)", NULL},
|
||||
{"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},
|
||||
{"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,
|
||||
"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}
|
||||
};
|
||||
|
||||
@ -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) {
|
||||
gchar *old = opts->linksdir;
|
||||
opts->linksdir = mu_util_dir_expand(opts->linksdir);
|
||||
@ -138,6 +141,7 @@ set_group_find_defaults (MuConfig *opts)
|
||||
g_free(old);
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: some warning when summary_len < 0? */
|
||||
if (opts->summary_len < 1)
|
||||
opts->summary_len = 0;
|
||||
@ -148,8 +152,6 @@ config_options_group_find (MuConfig *opts)
|
||||
{
|
||||
GOptionGroup *og;
|
||||
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 to display in the output", NULL},
|
||||
{"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,
|
||||
"sort in descending order (z -> a)", NULL},
|
||||
{"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,
|
||||
"output as symbolic links to a target maildir", NULL},
|
||||
{"clearlinks", 0, 0, G_OPTION_ARG_NONE, &opts->clearlinks,
|
||||
"clear old links before filling a linksdir", NULL},
|
||||
/* {"output", 'o', 0, G_OPTION_ARG_STRING, &opts->output, */
|
||||
/* "output type ('plain'(*), 'links', 'xml', 'json', 'sexp')", NULL}, */
|
||||
"clear old links before filling a linksdir (false)", NULL},
|
||||
{"format", 'o', 0, G_OPTION_ARG_STRING, &opts->formatstr,
|
||||
"output format ('plain'(*), 'links', 'xml',"
|
||||
"'json', 'sexp', 'xquery') (plain)", 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 */
|
||||
opts->dirmode = 0755;
|
||||
|
||||
og = g_option_group_new("mkdir",
|
||||
"options for the 'mkdir' command",
|
||||
og = g_option_group_new("mkdir", "options for the 'mkdir' command",
|
||||
"", NULL, NULL);
|
||||
g_option_group_add_entries(og, entries);
|
||||
|
||||
@ -205,15 +207,15 @@ config_options_group_extract(MuConfig *opts)
|
||||
GOptionEntry entries[] = {
|
||||
{"save-attachments", 'a', 0, G_OPTION_ARG_NONE,
|
||||
&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 parts (incl. non-attachments)", NULL},
|
||||
"save all parts (incl. non-attachments) (false)", NULL},
|
||||
{"parts", 0, 0, G_OPTION_ARG_STRING, &opts->parts,
|
||||
"save specific parts (comma-separated list)", NULL},
|
||||
{"target-dir", 0, 0, G_OPTION_ARG_FILENAME, &opts->targetdir,
|
||||
"target directory for saving", NULL},
|
||||
{"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}
|
||||
};
|
||||
|
||||
|
||||
@ -27,6 +27,13 @@
|
||||
|
||||
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 {
|
||||
MU_CONFIG_CMD_INDEX,
|
||||
MU_CONFIG_CMD_FIND,
|
||||
@ -79,6 +86,9 @@ struct _MuConfig {
|
||||
unsigned summary_len; /* max # of lines of msg in summary */
|
||||
char *bookmark; /* use bookmark */
|
||||
|
||||
char *formatstr; /* output type
|
||||
* (plain*,links,xml,json,sexp) */
|
||||
|
||||
/* output to a maildir with symlinks */
|
||||
char *linksdir; /* maildir to output symlinks */
|
||||
gboolean clearlinks; /* clear a linksdir before filling */
|
||||
@ -103,8 +113,8 @@ typedef struct _MuConfig MuConfig;
|
||||
*
|
||||
* @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
|
||||
* members are heap-allocated, so must be freed.
|
||||
|
||||
@ -100,7 +100,6 @@ mu_output_links (MuMsgIter *iter, const char* linksdir,
|
||||
|
||||
g_return_val_if_fail (iter, 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 */
|
||||
if (!create_linksdir_maybe (linksdir, clearlinks))
|
||||
@ -230,3 +229,32 @@ mu_output_plain (MuMsgIter *iter, const char *fields, size_t summary_len,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -52,6 +52,41 @@ gboolean mu_output_plain (MuMsgIter *iter, const char *fields,
|
||||
gboolean mu_output_links (MuMsgIter *iter, const char *linksdir,
|
||||
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
|
||||
|
||||
#endif /*__MU_OUTPUT_H__*/
|
||||
|
||||
Reference in New Issue
Block a user