From 3794182e05b4444e94af63e38a6b5fe794b6d70e Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 13 Nov 2010 14:16:38 +0200 Subject: [PATCH] * add basic implementation for bookmark support. basically, add a file named ~/.mu/bookmarks which looks something like ---- [mu] testarch=subject:test maildir:/archive inbox=maildir:/inbox ---- now, one can do a query, e.g. mu find -b testarch which is equivalend to mu find subject:test maildir:/archive if both a bookmark and a 'normal' search expression are specified, the will be concatenated. bookmarks starting with mu_ are reserved for mu itself. --- src/Makefile.am | 2 + src/mu-cmd-find.c | 108 +++++++++++++++++++++++++++++----------------- src/mu-config.c | 25 +++++++---- src/mu-config.h | 6 ++- src/mu-util.c | 14 +++++- src/mu-util.h | 20 +++++++++ 6 files changed, 124 insertions(+), 51 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ebf14ea9..fe13fd26 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,8 @@ mu_LDADD= \ libmu.la libmu_la_SOURCES= \ + mu-bookmarks.c \ + mu-bookmarks.h \ mu-cmd-extract.c \ mu-cmd-find.c \ mu-cmd-index.c \ diff --git a/src/mu-cmd-find.c b/src/mu-cmd-find.c index bf328826..62c353f6 100644 --- a/src/mu-cmd-find.c +++ b/src/mu-cmd-find.c @@ -34,6 +34,7 @@ #include "mu-query.h" #include "mu-msg-iter.h" #include "mu-msg-str.h" +#include "mu-bookmarks.h" #include "mu-util.h" #include "mu-util-db.h" @@ -133,8 +134,6 @@ run_query (MuQuery *xapian, const gchar *query, MuConfigOptions *opts) const MuMsgField *sortfield; size_t matches; - MU_WRITE_LOG ("query: '%s'", query); - sortfield = NULL; if (opts->sortfield) { sortfield = sort_field_from_string (opts->sortfield); @@ -142,8 +141,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfigOptions *opts) return FALSE; } - iter = mu_query_run (xapian, query, sortfield, - !opts->descending, 0); + iter = mu_query_run (xapian, query, sortfield, !opts->descending, 0); if (!iter) { g_printerr ("error: running query failed\n"); return FALSE; @@ -163,28 +161,6 @@ run_query (MuQuery *xapian, const gchar *query, MuConfigOptions *opts) } -static gboolean -do_output (MuQuery *xapian, MuConfigOptions* opts, - const gchar **params) -{ - gchar *query; - gboolean retval = TRUE; - - query = mu_util_str_from_strv (params); - - /* if xquery is set, we print the xapian query instead of the - * output; this is for debugging purposes */ - if (opts->xquery) - retval = print_xapian_query (xapian, query); - else - retval = run_query (xapian, query, opts); - - g_free (query); - - return retval; -} - - static gboolean query_params_valid (MuConfigOptions *opts) { @@ -193,12 +169,7 @@ query_params_valid (MuConfigOptions *opts) g_printerr ("Invalid option for '--linksdir'\n"); return FALSE; } - - if (!opts->params[0] || !opts->params[1]) { - g_printerr ("Missing search expression\n"); - return FALSE; - } - + if (mu_util_check_dir (opts->xpath, TRUE, FALSE)) return TRUE; @@ -208,13 +179,65 @@ query_params_valid (MuConfigOptions *opts) return FALSE; } +static gchar* +resolve_bookmark (MuConfigOptions *opts) +{ + MuBookmarks *bm; + char* val; + + bm = mu_bookmarks_new (opts->bmpath); + if (!bm) { + g_warning ("Failed to open bookmarks file '%s'", opts->bmpath); + return FALSE; + } + + val = (gchar*)mu_bookmarks_lookup (bm, opts->bookmark); + if (!val) + g_warning ("Bookmark '%s' not found", opts->bookmark); + else + val = g_strdup (val); + + mu_bookmarks_destroy (bm); + + return val; +} + + +static gchar* +get_query (MuConfigOptions *opts) +{ + gchar *query, *bookmarkval; + + /* params[0] is 'find', actual search params start with [1] */ + if (!opts->bookmark && !opts->params[1]) { + g_warning ("Empty search query"); + return FALSE; + } + + if (opts->bookmark && ((bookmarkval = resolve_bookmark (opts)) == NULL)) + return NULL; + + query = mu_util_str_from_strv ((const gchar**)&opts->params[1]); + if (bookmarkval) { + gchar *tmp; + tmp = g_strdup_printf ("%s %s", bookmarkval, query); + g_free (query); + query = tmp; + } + + g_free (bookmarkval); + + return query; +} + + gboolean mu_cmd_find (MuConfigOptions *opts) { MuQuery *xapian; gboolean rv; - const gchar **params; - + gchar *query; + g_return_val_if_fail (opts, FALSE); g_return_val_if_fail (mu_cmd_equals (opts, "find"), FALSE); @@ -222,8 +245,7 @@ mu_cmd_find (MuConfigOptions *opts) return FALSE; if (mu_util_db_is_empty (opts->xpath)) { - g_printerr ("The database is empty; " - "use 'mu index' to add some messages\n"); + g_warning ("Database is empty; use 'mu index' to add messages"); return FALSE; } @@ -233,17 +255,23 @@ mu_cmd_find (MuConfigOptions *opts) } /* first param is 'query', search params are after that */ - params = (const gchar**)&opts->params[1]; + query = get_query (opts); + if (!query) + return FALSE; xapian = mu_query_new (opts->xpath); if (!xapian) { - g_printerr ("Failed to create a Xapian query\n"); + g_warning ("Failed to create a Xapian query\n"); return FALSE; } - rv = do_output (xapian, opts, params); - + if (opts->xquery) + rv = print_xapian_query (xapian, query); + else + rv = run_query (xapian, query, opts); + mu_query_destroy (xapian); + g_free (query); return rv; } diff --git a/src/mu-config.c b/src/mu-config.c index 1c8d0445..4ee2a983 100644 --- a/src/mu-config.c +++ b/src/mu-config.c @@ -138,6 +138,9 @@ set_group_find_defaults (MuConfigOptions *opts) /* FIXME: some warning when summary_len < 0? */ if (opts->summary_len < 1) opts->summary_len = 0; + + /* note: xpath is is *not* settable from the cmdline */ + opts->bmpath = mu_util_guess_bookmark_file (opts->muhome); } @@ -152,6 +155,8 @@ config_options_group_find (MuConfigOptions *opts) "fields to display in the output", NULL}, {"sortfield", 's', 0, G_OPTION_ARG_STRING, &opts->sortfield, "field to sort on", NULL}, + {"bookmark", 'b', 0, G_OPTION_ARG_STRING, &opts->bookmark, + "use a bookmarked query", NULL}, {"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, @@ -230,7 +235,7 @@ config_options_group_extract (MuConfigOptions *opts) static gboolean parse_params (MuConfigOptions *opts, int *argcp, char ***argvp) { - GError *error = NULL; + GError *err; GOptionContext *context; gboolean rv; @@ -246,13 +251,15 @@ parse_params (MuConfigOptions *opts, int *argcp, char ***argvp) config_options_group_mkdir (opts)); g_option_context_add_group (context, config_options_group_extract (opts)); - - rv = g_option_context_parse (context, argcp, argvp, &error); + + err = NULL; + rv = g_option_context_parse (context, argcp, argvp, &err); if (!rv) { - g_printerr ("error in options: %s\n", error->message); - g_error_free (error); - } else - g_option_context_free (context); + g_printerr ("error in options: %s\n", err->message); + g_error_free (err); + } + + g_option_context_free (context); /* fill in the defaults if user did not specify */ set_group_mu_defaults (opts); @@ -288,7 +295,9 @@ mu_config_uninit (MuConfigOptions *opts) g_free (opts->xpath); g_free (opts->maildir); g_free (opts->linksdir); - + g_free (opts->targetdir); + g_free (opts->bmpath); + g_strfreev (opts->params); } diff --git a/src/mu-config.h b/src/mu-config.h index 77b0f6f8..9d062204 100644 --- a/src/mu-config.h +++ b/src/mu-config.h @@ -36,7 +36,7 @@ struct _MuConfigOptions { gboolean quiet; /* don't give any output */ gboolean debug; /* spew out debug info */ char *muhome; /* the House of Mu */ - char *xpath; /* path to the Xapian dir */ + char *xpath; /* path to the Xapian dir (internal) */ gboolean version; /* request mu version */ gboolean log_stderr; /* log to stderr (not logfile) */ gchar** params; /* parameters (for querying) */ @@ -54,7 +54,9 @@ struct _MuConfigOptions { char *fields; /* fields to show in output */ char *sortfield; /* field to sort by (string) */ gboolean descending; /* sort descending? */ - 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 *bmpath; /* path to bookmark file (internal) */ /* output to a maildir with symlinks */ char *linksdir; /* maildir to output symlinks */ gboolean clearlinks; /* clear a linksdir before filling */ diff --git a/src/mu-util.c b/src/mu-util.c index f50abc39..d403341d 100644 --- a/src/mu-util.c +++ b/src/mu-util.c @@ -194,7 +194,6 @@ mu_util_guess_mu_homedir (void) ".mu"); } - gchar* mu_util_guess_xapian_dir (const char* muhome) { @@ -208,6 +207,19 @@ mu_util_guess_xapian_dir (const char* muhome) return xdir; } +gchar* +mu_util_guess_bookmark_file (const char* muhome) +{ + gchar *homedir, *bmpath; + + homedir = muhome ? g_strdup(muhome) : mu_util_guess_mu_homedir (); + bmpath = g_strdup_printf ("%s%c%s", homedir, G_DIR_SEPARATOR, + MU_BOOKMARK_FILENAME); + g_free (homedir); + + return bmpath; +} + gboolean mu_util_create_dir_maybe (const gchar *path) diff --git a/src/mu-util.h b/src/mu-util.h index f119ebed..8e9ba9ab 100644 --- a/src/mu-util.h +++ b/src/mu-util.h @@ -76,6 +76,23 @@ gchar* mu_util_guess_mu_homedir (void); gchar* mu_util_guess_xapian_dir (const gchar *muhome); +/** + * guess the place of the bookmark file (typically, + * ~/.mu/bookmarks). Note that this does not mean the file actually + * exists. + * + * @param muhome the mu home directory or NULL, in which the muhome + * directoy will be guessed as well + * + * @return the guessed mu bookmark file, which needs to be freed with + * g_free when no longer needed. + */ +gchar* mu_util_guess_bookmark_file (const gchar *muhome); + + + + + /** * if path exists, check that's a read/writeable dir; otherwise try to * create it (with perms 0700) @@ -157,6 +174,9 @@ gchar* mu_util_str_from_strv (const gchar **params) G_GNUC_WARN_UNUSED_RESULT; #define MU_XAPIAN_DIR_NAME "xapian" #define MU_XAPIAN_VERSION_KEY "db_version" +/* name of the bookmark file */ +#define MU_BOOKMARK_FILENAME "bookmarks" + /** * log something in the log file; note, we use G_LOG_LEVEL_INFO * for such messages