diff --git a/man/mu-server.1 b/man/mu-server.1 index bdf430c4..f11c5eb4 100644 --- a/man/mu-server.1 +++ b/man/mu-server.1 @@ -19,14 +19,14 @@ In this man-page, we document the commands \fBmu server\fR accepts, as well as their responses. In general, the commands sent to the server are of the form .nf - []* + cmd: []* .fi where each of the parameters is prefixed by their name and a colon. For example, to view a certain message, the command would be: .nf - view docid:12345 + cmd:view docid:12345 .fi Parameters can be sent in any order, and parameters not used by a certain @@ -58,7 +58,7 @@ UTF-8 (in which the s-expressions are encoded). Using the \fBadd\fR command, we can add a message to the database. .nf --> add path: maildir: +-> cmd:add path: maildir: <- (:info add :path :docid ) .fi @@ -73,7 +73,7 @@ e.g. set the subject, sender and recipient for a reply message. Messages of type 'new' don't use the docid: parameter, the other ones do. .nf --> compose type: [docid:] +-> cmd:compose type: [docid:] <- (:compose :original :include ( contacts [personal:true|false] [after:] +-> cmd:contacts [personal:true|false] [after:] <- (:contacts ((:name abc :mail foo@example.com ...) ...) .fi @@ -103,7 +103,7 @@ contacts (name + e-mail address). For the details, see \fBmu-cfind(1)\fR. Using the \fBextract\fR command we can save and open attachments. .nf --> extract action: index: [path:] [what: [param:]] +-> cmd:extract action: index: [path:] [what: [param:]] .fi If the action is 'save', the path argument is required; the attachment will @@ -135,7 +135,7 @@ to a shell command. Using the \fBfind\fR command we can search for messages. .nf --> find query:"" [threads:true|false] [sortfield:] +-> cmd:find query:"" [threads:true|false] [sortfield:] [reverse:true|false] [maxnum:] .fi The \fBquery\fR-parameter provides the search query; the @@ -179,7 +179,7 @@ registers 'my' email addresses; see the documentation for \fBmu_store_set_my_addresses\fR. .nf --> index path: [my-addresses:] +-> cmd:index path: [my-addresses:] .fi As a response, it will send (for each 500 messages): .nf @@ -197,7 +197,7 @@ and finally: Using the \fBmkdir\fR command, we can create a new maildir. .nf --> mkdir path: +-> cmd:mkdir path: <- (:info mkdir :message " has been created") .fi @@ -211,7 +211,7 @@ s-exp describing the updated message, so that it can be updated in the user interface. .nf --> move docid:|msgid: [maildir:] [flags:] +-> cmd:move docid:|msgid: [maildir:] [flags:] <- (:update :move t) .fi @@ -225,7 +225,7 @@ of maildir and flags must be specified. The \fBping\fR command provokes a \fBpong\fR response. It is used for the initial handshake between \fBmu4e\fR and \fBmu server\fR. .nf --> ping +-> cmd:ping <- (:pong "mu" :version :doccount ) .fi @@ -236,7 +236,7 @@ Using the \fBremove\fR command, we can remove the message from disk, and update the database accordingly. .nf --> remove docid: +-> cmd:remove docid: <- (:remove ) .fi @@ -257,18 +257,17 @@ If the optional parameter \fBauto-retrieve-key\fR is \fBtrue\fR, attempt to retrieve public keys online automatically. .nf --> view docid:|msgid: [extract-images:true] [use-agent:false] [auto-retrieve-key:false] +-> cmd:view docid:|msgid: [extract-images:true] [use-agent:false] [auto-retrieve-key:false] <- (:view ) .fi or, alternatively: .nf --> view path: [extract-images:true] [use-agent:false] [auto-retrieve-key:false] +-> cmd:view path: [extract-images:true] [use-agent:false] [auto-retrieve-key:false] <- (:view ) .fi - .SH AUTHOR Dirk-Jan C. Binnema diff --git a/mu/mu-cmd-server.c b/mu/mu-cmd-server.c index 00c668bc..91fee1f0 100644 --- a/mu/mu-cmd-server.c +++ b/mu/mu-cmd-server.c @@ -166,11 +166,11 @@ print_and_clear_g_error (GError **err) } -static GSList* -read_line_as_list (GError **err) +static GHashTable* +read_command_line (GError **err) { char *line; - GSList *lst; + GHashTable *hash; GString *gstr; line = NULL; @@ -190,43 +190,28 @@ read_line_as_list (GError **err) } while (1); line = g_string_free (gstr, FALSE); - lst = mu_str_esc_to_list (line); - + hash = mu_str_parse_arglist (line, err); g_free (line); - return lst; + return hash; } static const char* -get_string_from_args (GSList *args, const char *param, gboolean optional, +get_string_from_args (GHashTable *args, const char *param, gboolean optional, GError **err) { - size_t param_len; + const char *str; - param_len = strlen (param); - - while (args) { - - const char *arg; - arg = (const char*)args->data; - - /* do we have this param */ - if (arg && g_str_has_prefix (arg, param) && - arg[param_len] == ':') - return (const char*) arg + param_len + 1; - - args = g_slist_next (args); - } - - if (!optional) + str = g_hash_table_lookup (args, param); + if (!str && !optional) mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, "parameter '%s' not found", param); - return NULL; + return str; } static gboolean -get_bool_from_args (GSList *args, const char *param, gboolean optional, GError **err) +get_bool_from_args (GHashTable *args, const char *param, gboolean optional, GError **err) { const char *val; @@ -330,7 +315,7 @@ get_docids_from_msgids (MuQuery *query, const char *str, GError **err) * locale the message with message-id in the database, and return its * docid */ static unsigned -determine_docid (MuQuery *query, GSList *args, GError **err) +determine_docid (MuQuery *query, GHashTable *args, GError **err) { const char* docidstr, *msgidstr; @@ -379,7 +364,7 @@ typedef struct _ServerContext ServerContext; * if function return non-MU_OK, the repl will print the error instead */ -typedef MuError (*CmdFunc) (ServerContext*,GSList*,GError**); +typedef MuError (*CmdFunc) (ServerContext*,GHashTable*,GError**); /* 'add' adds a message to the database, and takes two parameters: * 'path', which is the full path to the message, and 'maildir', which @@ -388,7 +373,7 @@ typedef MuError (*CmdFunc) (ServerContext*,GSList*,GError**); * message (details: see code below) */ static MuError -cmd_add (ServerContext *ctx, GSList *args, GError **err) +cmd_add (ServerContext *ctx, GHashTable *args, GError **err) { unsigned docid; const char *maildir, *path; @@ -507,7 +492,7 @@ compose_type (const char *typestr) * Note ':include' t or nil determines whether to include attachments */ static MuError -cmd_compose (ServerContext *ctx, GSList *args, GError **err) +cmd_compose (ServerContext *ctx, GHashTable *args, GError **err) { const gchar *typestr; char *sexp, *atts; @@ -620,7 +605,7 @@ contacts_to_sexp (MuContacts *contacts, gboolean personal, time_t after) static MuError -cmd_contacts (ServerContext *ctx, GSList *args, GError **err) +cmd_contacts (ServerContext *ctx, GHashTable *args, GError **err) { MuContacts *contacts; char *sexp; @@ -680,7 +665,7 @@ print_sexps (MuMsgIter *iter, unsigned maxnum) static MuError save_part (MuMsg *msg, unsigned docid, - unsigned index, GSList *args, GError **err) + unsigned index, GHashTable *args, GError **err) { gboolean rv; const gchar *path; @@ -740,7 +725,7 @@ leave: static MuError -temp_part (MuMsg *msg, unsigned docid, unsigned index, GSList *args, +temp_part (MuMsg *msg, unsigned docid, unsigned index, GHashTable *args, GError **err) { const char *what, *param; @@ -798,7 +783,7 @@ action_type (const char *actionstr) /* 'extract' extracts some mime part from a message */ static MuError -cmd_extract (ServerContext *ctx, GSList *args, GError **err) +cmd_extract (ServerContext *ctx, GHashTable *args, GError **err) { MuMsg *msg; int docid, index, action; @@ -843,7 +828,7 @@ cmd_extract (ServerContext *ctx, GSList *args, GError **err) /* parse the find parameters, and return the values as out params */ static MuError -get_find_params (GSList *args, MuMsgFieldId *sortfield, +get_find_params (GHashTable *args, MuMsgFieldId *sortfield, int *maxnum, MuQueryFlags *qflags, GError **err) { const char *maxnumstr, *sortfieldstr; @@ -897,7 +882,7 @@ get_find_params (GSList *args, MuMsgFieldId *sortfield, * (:found ) */ static MuError -cmd_find (ServerContext *ctx, GSList *args, GError **err) +cmd_find (ServerContext *ctx, GHashTable *args, GError **err) { MuMsgIter *iter; unsigned foundnum; @@ -949,7 +934,7 @@ cmd_find (ServerContext *ctx, GSList *args, GError **err) #ifdef BUILD_GUILE static MuError -cmd_guile (ServerContext *ctx, GSList *args, GError **err) +cmd_guile (ServerContext *ctx, GHashTable *args, GError **err) { const char *script, *file; @@ -966,7 +951,7 @@ cmd_guile (ServerContext *ctx, GSList *args, GError **err) } #else /*!BUILD_GUILE*/ static MuError -cmd_guile (ServerContext *ctx, GSList *args, GError **err) +cmd_guile (ServerContext *ctx, GHashTable *args, GError **err) { print_error (MU_ERROR_INTERNAL, "this mu does not have guile support"); @@ -1063,7 +1048,7 @@ index_and_cleanup (MuIndex *index, const char *path, GError **err) * index ... ) messages while doing so (see the code) */ static MuError -cmd_index (ServerContext *ctx, GSList *args, GError **err) +cmd_index (ServerContext *ctx, GHashTable *args, GError **err) { MuIndex *index; const char *argpath; @@ -1099,7 +1084,7 @@ leave: /* 'mkdir' attempts to create a maildir directory at 'path:'; sends an * (:info mkdir ...) message when it succeeds */ static MuError -cmd_mkdir (ServerContext *ctx, GSList *args, GError **err) +cmd_mkdir (ServerContext *ctx, GHashTable *args, GError **err) { const char *path; @@ -1214,7 +1199,7 @@ leave: * would a message in inbox and sentbox with the same id. we set the * flag on both */ static gboolean -move_msgid_maybe (ServerContext *ctx, GSList *args, GError **err) +move_msgid_maybe (ServerContext *ctx, GHashTable *args, GError **err) { GSList *docids, *cur; const char *maildir = get_string_from_args (args, "maildir", TRUE, err); @@ -1252,7 +1237,7 @@ move_msgid_maybe (ServerContext *ctx, GSList *args, GError **err) * */ static MuError -cmd_move (ServerContext *ctx, GSList *args, GError **err) +cmd_move (ServerContext *ctx, GHashTable *args, GError **err) { unsigned docid; MuMsg *msg; @@ -1305,7 +1290,7 @@ leave: * server using a (:pong ...) message (details: see code below) */ static MuError -cmd_ping (ServerContext *ctx, GSList *args, GError **err) +cmd_ping (ServerContext *ctx, GHashTable *args, GError **err) { unsigned doccount; doccount = mu_store_count (ctx->store, err); @@ -1328,7 +1313,7 @@ cmd_ping (ServerContext *ctx, GSList *args, GError **err) /* 'quit' takes no parameters, terminates this mu server */ static MuError -cmd_quit (ServerContext *ctx, GSList *args , GError **err) +cmd_quit (ServerContext *ctx, GHashTable *args , GError **err) { print_expr (";; quiting"); @@ -1372,7 +1357,7 @@ get_path_from_docid (MuStore *store, unsigned docid, GError **err) * (:remove ...) message when it succeeds */ static MuError -cmd_remove (ServerContext *ctx, GSList *args, GError **err) +cmd_remove (ServerContext *ctx, GHashTable *args, GError **err) { unsigned docid; const char *path; @@ -1413,7 +1398,7 @@ cmd_remove (ServerContext *ctx, GSList *args, GError **err) * message (details: see code below) */ static MuError -cmd_sent (ServerContext *ctx, GSList *args, GError **err) +cmd_sent (ServerContext *ctx, GHashTable *args, GError **err) { unsigned docid; const char *maildir, *path; @@ -1436,7 +1421,7 @@ cmd_sent (ServerContext *ctx, GSList *args, GError **err) } static MuMsgOptions -get_view_msg_opts (GSList *args) +get_view_msg_opts (GHashTable *args) { MuMsgOptions opts; @@ -1458,7 +1443,7 @@ get_view_msg_opts (GSList *args) * identified by either docid: or msgid:; return a (:view ) */ static MuError -cmd_view (ServerContext *ctx, GSList *args, GError **err) +cmd_view (ServerContext *ctx, GHashTable *args, GError **err) { MuMsg *msg; const gchar *path; @@ -1504,7 +1489,7 @@ cmd_view (ServerContext *ctx, GSList *args, GError **err) /*************************************************************************/ static MuError -handle_args (ServerContext *ctx, GSList *args, GError **err) +handle_args (ServerContext *ctx, GHashTable *args, GError **err) { unsigned u; const char *cmd; @@ -1528,7 +1513,8 @@ handle_args (ServerContext *ctx, GSList *args, GError **err) { "view", cmd_view } }; - cmd = (const char*) args->data; + + cmd = g_hash_table_lookup (args, "cmd"); /* ignore empty */ if (mu_str_is_empty (cmd)) @@ -1536,7 +1522,7 @@ handle_args (ServerContext *ctx, GSList *args, GError **err) for (u = 0; u != G_N_ELEMENTS (cmd_map); ++u) if (g_strcmp0(cmd, cmd_map[u].cmd) == 0) - return cmd_map[u].func (ctx, g_slist_next(args), err); + return cmd_map[u].func (ctx, args, err); mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, "unknown command '%s'", cmd ? cmd : ""); @@ -1567,12 +1553,13 @@ mu_cmd_server (MuStore *store, MuConfig *opts/*unused*/, GError **err) do_quit = FALSE; while (!MU_TERMINATE && !do_quit) { - GSList *args; - GError *my_err = NULL; + GHashTable *args; + GError *my_err; /* args will receive a the command as a list of * strings. returning NULL indicates an error */ - args = read_line_as_list (&my_err); + my_err = NULL; + args = read_command_line (&my_err); if (!args || my_err) { print_and_clear_g_error (&my_err); continue; @@ -1587,7 +1574,7 @@ mu_cmd_server (MuStore *store, MuConfig *opts/*unused*/, GError **err) print_and_clear_g_error (&my_err); } - mu_str_free_list (args); + g_hash_table_destroy (args); } mu_store_flush (ctx.store); diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index 7b7992ab..ad7c1270 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -3457,7 +3457,7 @@ started). It calls @t{mu4e-proc-ping}, and registers a (lambda) function for @t{mu4e-proc-pong-func}, to handle the response. @verbatim --> ping +-> cmd:ping <- (pong "mu" :version "x.x.x" :doccount 10000) @end verbatim