* mu: update the server command and (use 'cmd:' for commands)

This commit is contained in:
djcb 2013-05-20 05:11:49 +03:00
parent dfb6382c04
commit 2f5d6e246b
3 changed files with 57 additions and 71 deletions

View File

@ -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 their responses. In general, the commands sent to the server are of the form
.nf .nf
<command> [<parameters>]* cmd:<command> [<parameters>]*
.fi .fi
where each of the parameters is prefixed by their name and a colon. For where each of the parameters is prefixed by their name and a colon. For
example, to view a certain message, the command would be: example, to view a certain message, the command would be:
.nf .nf
view docid:12345 cmd:view docid:12345
.fi .fi
Parameters can be sent in any order, and parameters not used by a certain 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. Using the \fBadd\fR command, we can add a message to the database.
.nf .nf
-> add path:<path> maildir:<maildir> -> cmd:add path:<path> maildir:<maildir>
<- (:info add :path <path> :docid <docid>) <- (:info add :path <path> :docid <docid>)
.fi .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. Messages of type 'new' don't use the docid: parameter, the other ones do.
.nf .nf
-> compose type:<reply|forward|edit|new> [docid:<docid>] -> cmd:compose type:<reply|forward|edit|new> [docid:<docid>]
<- (:compose <reply|forward|edit|new> :original <s-exp> :include (<list-of-attachments)) <- (:compose <reply|forward|edit|new> :original <s-exp> :include (<list-of-attachments))
.fi .fi
@ -93,7 +93,7 @@ Using the \fBcompose\fR command, we can retrieve an s-expression with all known
contacts (name + e-mail address). For the details, see \fBmu-cfind(1)\fR. contacts (name + e-mail address). For the details, see \fBmu-cfind(1)\fR.
.nf .nf
-> contacts [personal:true|false] [after:<time_t>] -> cmd:contacts [personal:true|false] [after:<time_t>]
<- (:contacts ((:name abc :mail foo@example.com ...) ...) <- (:contacts ((:name abc :mail foo@example.com ...) ...)
.fi .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. Using the \fBextract\fR command we can save and open attachments.
.nf .nf
-> extract action:<save|open|temp> index:<index> [path:<path>] [what:<what> [param:<param>]] -> cmd:extract action:<save|open|temp> index:<index> [path:<path>] [what:<what> [param:<param>]]
.fi .fi
If the action is 'save', the path argument is required; the attachment will 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. Using the \fBfind\fR command we can search for messages.
.nf .nf
-> find query:"<query>" [threads:true|false] [sortfield:<sortfield>] -> cmd:find query:"<query>" [threads:true|false] [sortfield:<sortfield>]
[reverse:true|false] [maxnum:<maxnum>] [reverse:true|false] [maxnum:<maxnum>]
.fi .fi
The \fBquery\fR-parameter provides the search query; the 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. \fBmu_store_set_my_addresses\fR.
.nf .nf
-> index path:<path> [my-addresses:<comma-separated-list-of-email-addresses>] -> cmd:index path:<path> [my-addresses:<comma-separated-list-of-email-addresses>]
.fi .fi
As a response, it will send (for each 500 messages): As a response, it will send (for each 500 messages):
.nf .nf
@ -197,7 +197,7 @@ and finally:
Using the \fBmkdir\fR command, we can create a new maildir. Using the \fBmkdir\fR command, we can create a new maildir.
.nf .nf
-> mkdir path:<path> -> cmd:mkdir path:<path>
<- (:info mkdir :message "<maildir> has been created") <- (:info mkdir :message "<maildir> has been created")
.fi .fi
@ -211,7 +211,7 @@ s-exp describing the updated message, so that it can be updated in the user
interface. interface.
.nf .nf
-> move docid:<docid>|msgid:<msgid> [maildir:<maildir>] [flags:<flags>] -> cmd:move docid:<docid>|msgid:<msgid> [maildir:<maildir>] [flags:<flags>]
<- (:update <s-exp> :move t) <- (:update <s-exp> :move t)
.fi .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 The \fBping\fR command provokes a \fBpong\fR response. It is used for the initial
handshake between \fBmu4e\fR and \fBmu server\fR. handshake between \fBmu4e\fR and \fBmu server\fR.
.nf .nf
-> ping -> cmd:ping
<- (:pong "mu" :version <version> :doccount <doccount>) <- (:pong "mu" :version <version> :doccount <doccount>)
.fi .fi
@ -236,7 +236,7 @@ Using the \fBremove\fR command, we can remove the message from disk, and
update the database accordingly. update the database accordingly.
.nf .nf
-> remove docid:<docid> -> cmd:remove docid:<docid>
<- (:remove <docid>) <- (:remove <docid>)
.fi .fi
@ -257,18 +257,17 @@ If the optional parameter \fBauto-retrieve-key\fR is \fBtrue\fR, attempt to
retrieve public keys online automatically. retrieve public keys online automatically.
.nf .nf
-> view docid:<docid>|msgid:<msgid> [extract-images:true] [use-agent:false] [auto-retrieve-key:false] -> cmd:view docid:<docid>|msgid:<msgid> [extract-images:true] [use-agent:false] [auto-retrieve-key:false]
<- (:view <s-exp>) <- (:view <s-exp>)
.fi .fi
or, alternatively: or, alternatively:
.nf .nf
-> view path:<path-to-msg> [extract-images:true] [use-agent:false] [auto-retrieve-key:false] -> cmd:view path:<path-to-msg> [extract-images:true] [use-agent:false] [auto-retrieve-key:false]
<- (:view <s-exp>) <- (:view <s-exp>)
.fi .fi
.SH AUTHOR .SH AUTHOR
Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>

View File

@ -166,11 +166,11 @@ print_and_clear_g_error (GError **err)
} }
static GSList* static GHashTable*
read_line_as_list (GError **err) read_command_line (GError **err)
{ {
char *line; char *line;
GSList *lst; GHashTable *hash;
GString *gstr; GString *gstr;
line = NULL; line = NULL;
@ -190,43 +190,28 @@ read_line_as_list (GError **err)
} while (1); } while (1);
line = g_string_free (gstr, FALSE); line = g_string_free (gstr, FALSE);
lst = mu_str_esc_to_list (line); hash = mu_str_parse_arglist (line, err);
g_free (line); g_free (line);
return lst; return hash;
} }
static const char* 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) GError **err)
{ {
size_t param_len; const char *str;
param_len = strlen (param); str = g_hash_table_lookup (args, param);
if (!str && !optional)
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)
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
"parameter '%s' not found", param); "parameter '%s' not found", param);
return NULL; return str;
} }
static gboolean 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; 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 * locale the message with message-id in the database, and return its
* docid */ * docid */
static unsigned static unsigned
determine_docid (MuQuery *query, GSList *args, GError **err) determine_docid (MuQuery *query, GHashTable *args, GError **err)
{ {
const char* docidstr, *msgidstr; 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 * 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: /* 'add' adds a message to the database, and takes two parameters:
* 'path', which is the full path to the message, and 'maildir', which * '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) * message (details: see code below)
*/ */
static MuError static MuError
cmd_add (ServerContext *ctx, GSList *args, GError **err) cmd_add (ServerContext *ctx, GHashTable *args, GError **err)
{ {
unsigned docid; unsigned docid;
const char *maildir, *path; const char *maildir, *path;
@ -507,7 +492,7 @@ compose_type (const char *typestr)
* Note ':include' t or nil determines whether to include attachments * Note ':include' t or nil determines whether to include attachments
*/ */
static MuError static MuError
cmd_compose (ServerContext *ctx, GSList *args, GError **err) cmd_compose (ServerContext *ctx, GHashTable *args, GError **err)
{ {
const gchar *typestr; const gchar *typestr;
char *sexp, *atts; char *sexp, *atts;
@ -620,7 +605,7 @@ contacts_to_sexp (MuContacts *contacts, gboolean personal, time_t after)
static MuError static MuError
cmd_contacts (ServerContext *ctx, GSList *args, GError **err) cmd_contacts (ServerContext *ctx, GHashTable *args, GError **err)
{ {
MuContacts *contacts; MuContacts *contacts;
char *sexp; char *sexp;
@ -680,7 +665,7 @@ print_sexps (MuMsgIter *iter, unsigned maxnum)
static MuError static MuError
save_part (MuMsg *msg, unsigned docid, save_part (MuMsg *msg, unsigned docid,
unsigned index, GSList *args, GError **err) unsigned index, GHashTable *args, GError **err)
{ {
gboolean rv; gboolean rv;
const gchar *path; const gchar *path;
@ -740,7 +725,7 @@ leave:
static MuError static MuError
temp_part (MuMsg *msg, unsigned docid, unsigned index, GSList *args, temp_part (MuMsg *msg, unsigned docid, unsigned index, GHashTable *args,
GError **err) GError **err)
{ {
const char *what, *param; const char *what, *param;
@ -798,7 +783,7 @@ action_type (const char *actionstr)
/* 'extract' extracts some mime part from a message */ /* 'extract' extracts some mime part from a message */
static MuError static MuError
cmd_extract (ServerContext *ctx, GSList *args, GError **err) cmd_extract (ServerContext *ctx, GHashTable *args, GError **err)
{ {
MuMsg *msg; MuMsg *msg;
int docid, index, action; 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 */ /* parse the find parameters, and return the values as out params */
static MuError static MuError
get_find_params (GSList *args, MuMsgFieldId *sortfield, get_find_params (GHashTable *args, MuMsgFieldId *sortfield,
int *maxnum, MuQueryFlags *qflags, GError **err) int *maxnum, MuQueryFlags *qflags, GError **err)
{ {
const char *maxnumstr, *sortfieldstr; const char *maxnumstr, *sortfieldstr;
@ -897,7 +882,7 @@ get_find_params (GSList *args, MuMsgFieldId *sortfield,
* (:found <number of found messages>) * (:found <number of found messages>)
*/ */
static MuError static MuError
cmd_find (ServerContext *ctx, GSList *args, GError **err) cmd_find (ServerContext *ctx, GHashTable *args, GError **err)
{ {
MuMsgIter *iter; MuMsgIter *iter;
unsigned foundnum; unsigned foundnum;
@ -949,7 +934,7 @@ cmd_find (ServerContext *ctx, GSList *args, GError **err)
#ifdef BUILD_GUILE #ifdef BUILD_GUILE
static MuError static MuError
cmd_guile (ServerContext *ctx, GSList *args, GError **err) cmd_guile (ServerContext *ctx, GHashTable *args, GError **err)
{ {
const char *script, *file; const char *script, *file;
@ -966,7 +951,7 @@ cmd_guile (ServerContext *ctx, GSList *args, GError **err)
} }
#else /*!BUILD_GUILE*/ #else /*!BUILD_GUILE*/
static MuError static MuError
cmd_guile (ServerContext *ctx, GSList *args, GError **err) cmd_guile (ServerContext *ctx, GHashTable *args, GError **err)
{ {
print_error (MU_ERROR_INTERNAL, print_error (MU_ERROR_INTERNAL,
"this mu does not have guile support"); "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) * index ... ) messages while doing so (see the code)
*/ */
static MuError static MuError
cmd_index (ServerContext *ctx, GSList *args, GError **err) cmd_index (ServerContext *ctx, GHashTable *args, GError **err)
{ {
MuIndex *index; MuIndex *index;
const char *argpath; const char *argpath;
@ -1099,7 +1084,7 @@ leave:
/* 'mkdir' attempts to create a maildir directory at 'path:'; sends an /* 'mkdir' attempts to create a maildir directory at 'path:'; sends an
* (:info mkdir ...) message when it succeeds */ * (:info mkdir ...) message when it succeeds */
static MuError static MuError
cmd_mkdir (ServerContext *ctx, GSList *args, GError **err) cmd_mkdir (ServerContext *ctx, GHashTable *args, GError **err)
{ {
const char *path; const char *path;
@ -1214,7 +1199,7 @@ leave:
* would a message in inbox and sentbox with the same id. we set the * would a message in inbox and sentbox with the same id. we set the
* flag on both */ * flag on both */
static gboolean static gboolean
move_msgid_maybe (ServerContext *ctx, GSList *args, GError **err) move_msgid_maybe (ServerContext *ctx, GHashTable *args, GError **err)
{ {
GSList *docids, *cur; GSList *docids, *cur;
const char *maildir = get_string_from_args (args, "maildir", TRUE, err); 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 static MuError
cmd_move (ServerContext *ctx, GSList *args, GError **err) cmd_move (ServerContext *ctx, GHashTable *args, GError **err)
{ {
unsigned docid; unsigned docid;
MuMsg *msg; MuMsg *msg;
@ -1305,7 +1290,7 @@ leave:
* server using a (:pong ...) message (details: see code below) * server using a (:pong ...) message (details: see code below)
*/ */
static MuError static MuError
cmd_ping (ServerContext *ctx, GSList *args, GError **err) cmd_ping (ServerContext *ctx, GHashTable *args, GError **err)
{ {
unsigned doccount; unsigned doccount;
doccount = mu_store_count (ctx->store, err); 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 */ /* 'quit' takes no parameters, terminates this mu server */
static MuError static MuError
cmd_quit (ServerContext *ctx, GSList *args , GError **err) cmd_quit (ServerContext *ctx, GHashTable *args , GError **err)
{ {
print_expr (";; quiting"); print_expr (";; quiting");
@ -1372,7 +1357,7 @@ get_path_from_docid (MuStore *store, unsigned docid, GError **err)
* (:remove ...) message when it succeeds * (:remove ...) message when it succeeds
*/ */
static MuError static MuError
cmd_remove (ServerContext *ctx, GSList *args, GError **err) cmd_remove (ServerContext *ctx, GHashTable *args, GError **err)
{ {
unsigned docid; unsigned docid;
const char *path; const char *path;
@ -1413,7 +1398,7 @@ cmd_remove (ServerContext *ctx, GSList *args, GError **err)
* message (details: see code below) * message (details: see code below)
*/ */
static MuError static MuError
cmd_sent (ServerContext *ctx, GSList *args, GError **err) cmd_sent (ServerContext *ctx, GHashTable *args, GError **err)
{ {
unsigned docid; unsigned docid;
const char *maildir, *path; const char *maildir, *path;
@ -1436,7 +1421,7 @@ cmd_sent (ServerContext *ctx, GSList *args, GError **err)
} }
static MuMsgOptions static MuMsgOptions
get_view_msg_opts (GSList *args) get_view_msg_opts (GHashTable *args)
{ {
MuMsgOptions opts; MuMsgOptions opts;
@ -1458,7 +1443,7 @@ get_view_msg_opts (GSList *args)
* identified by either docid: or msgid:; return a (:view <sexp>) * identified by either docid: or msgid:; return a (:view <sexp>)
*/ */
static MuError static MuError
cmd_view (ServerContext *ctx, GSList *args, GError **err) cmd_view (ServerContext *ctx, GHashTable *args, GError **err)
{ {
MuMsg *msg; MuMsg *msg;
const gchar *path; const gchar *path;
@ -1504,7 +1489,7 @@ cmd_view (ServerContext *ctx, GSList *args, GError **err)
/*************************************************************************/ /*************************************************************************/
static MuError static MuError
handle_args (ServerContext *ctx, GSList *args, GError **err) handle_args (ServerContext *ctx, GHashTable *args, GError **err)
{ {
unsigned u; unsigned u;
const char *cmd; const char *cmd;
@ -1528,7 +1513,8 @@ handle_args (ServerContext *ctx, GSList *args, GError **err)
{ "view", cmd_view } { "view", cmd_view }
}; };
cmd = (const char*) args->data;
cmd = g_hash_table_lookup (args, "cmd");
/* ignore empty */ /* ignore empty */
if (mu_str_is_empty (cmd)) 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) for (u = 0; u != G_N_ELEMENTS (cmd_map); ++u)
if (g_strcmp0(cmd, cmd_map[u].cmd) == 0) 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, mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
"unknown command '%s'", cmd ? cmd : ""); "unknown command '%s'", cmd ? cmd : "");
@ -1567,12 +1553,13 @@ mu_cmd_server (MuStore *store, MuConfig *opts/*unused*/, GError **err)
do_quit = FALSE; do_quit = FALSE;
while (!MU_TERMINATE && !do_quit) { while (!MU_TERMINATE && !do_quit) {
GSList *args; GHashTable *args;
GError *my_err = NULL; GError *my_err;
/* args will receive a the command as a list of /* args will receive a the command as a list of
* strings. returning NULL indicates an error */ * 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) { if (!args || my_err) {
print_and_clear_g_error (&my_err); print_and_clear_g_error (&my_err);
continue; continue;
@ -1587,7 +1574,7 @@ mu_cmd_server (MuStore *store, MuConfig *opts/*unused*/, GError **err)
print_and_clear_g_error (&my_err); print_and_clear_g_error (&my_err);
} }
mu_str_free_list (args); g_hash_table_destroy (args);
} }
mu_store_flush (ctx.store); mu_store_flush (ctx.store);

View File

@ -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. @t{mu4e-proc-pong-func}, to handle the response.
@verbatim @verbatim
-> ping -> cmd:ping
<- (pong "mu" :version "x.x.x" :doccount 10000) <- (pong "mu" :version "x.x.x" :doccount 10000)
@end verbatim @end verbatim