mirror of https://github.com/djcb/mu.git
mu4e: use the new command-parser
Update mu4e-proc to use the new mu4e <-> mu protocol
This commit is contained in:
parent
c71f683e39
commit
d2ec85f01c
|
@ -445,6 +445,33 @@ Mu::size_to_string (const std::string& val, bool is_first)
|
|||
}
|
||||
|
||||
|
||||
std::string
|
||||
Mu::quoted (const std::string& str)
|
||||
{
|
||||
std::string res{"\""};
|
||||
for (auto&& c : str) {
|
||||
if (c == '\\' || c == '\"')
|
||||
res += '\\';
|
||||
res += c;
|
||||
}
|
||||
|
||||
return res + '"';
|
||||
}
|
||||
|
||||
// std::string
|
||||
// Mu::quoted (const char* str)
|
||||
// {
|
||||
// if (!str)
|
||||
// return str;
|
||||
|
||||
// char *s{g_strescape(str, NULL)};
|
||||
// auto res = format("\"%s\"", s ? s : "");
|
||||
// g_free(s);
|
||||
|
||||
// return res;
|
||||
// }
|
||||
|
||||
|
||||
void
|
||||
Mu::assert_equal(const std::string& s1, const std::string& s2)
|
||||
{
|
||||
|
|
|
@ -93,6 +93,17 @@ std::string format (const char *frm, ...) __attribute__((format(printf, 1, 2)));
|
|||
std::string format (const char *frm, va_list args) __attribute__((format(printf, 1, 0)));
|
||||
|
||||
|
||||
/**
|
||||
* Quote a string -- put in "" and escape any special characters by putting '\'
|
||||
* in front of them.
|
||||
*
|
||||
* @param str
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::string quoted (const std::string& str);
|
||||
|
||||
|
||||
/**
|
||||
* Convert an ISO date to the corresponding time expressed as a string
|
||||
* with a 10-digit time_t
|
||||
|
|
|
@ -696,7 +696,11 @@ mu_cmd_execute (MuConfig *opts, GError **err)
|
|||
case MU_CONFIG_CMD_TICKLE:
|
||||
merr = with_store (mu_cmd_tickle, opts, FALSE, err); break;
|
||||
case MU_CONFIG_CMD_SERVER:
|
||||
merr = with_store (mu_cmd_server, opts, FALSE, err); break;
|
||||
if (opts->commands)
|
||||
merr = mu_cmd_server (NULL, opts, err);
|
||||
else
|
||||
merr = with_store (mu_cmd_server, opts, FALSE, err);
|
||||
break;
|
||||
default:
|
||||
merr = MU_ERROR_IN_PARAMETERS; break;
|
||||
}
|
||||
|
|
|
@ -441,8 +441,8 @@ config_options_group_server (void)
|
|||
GOptionEntry entries[] = {
|
||||
{"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.maildir,
|
||||
"top of the maildir", "<maildir>"},
|
||||
{"list-commands", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.list_commands,
|
||||
"overwrite existing files (false)", NULL},
|
||||
{"commands", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.commands,
|
||||
"list the available command and their parameters, then exit", NULL},
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -760,7 +760,6 @@ mu_config_uninit (MuConfig *opts)
|
|||
memset (opts, 0, sizeof(MU_CONFIG));
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
mu_config_param_num (MuConfig *opts)
|
||||
{
|
||||
|
|
|
@ -179,8 +179,8 @@ struct _MuConfig {
|
|||
gboolean play; /* after saving, try to 'play'
|
||||
* (open) the attmnt using xdgopen */
|
||||
/* for server */
|
||||
gboolean list_commands; /* dump documentations for server
|
||||
* commands */
|
||||
gboolean commands; /* dump documentations for server
|
||||
* commands */
|
||||
|
||||
/* options for mu-script */
|
||||
gchar *script; /* script to run */
|
||||
|
|
|
@ -118,16 +118,9 @@ clicked."
|
|||
"* "
|
||||
(propertize "mu4e - mu for emacs version " 'face 'mu4e-title-face)
|
||||
(propertize mu4e-mu-version 'face 'mu4e-header-key-face)
|
||||
|
||||
;; show some server properties; in this case; a big C when there's
|
||||
;; crypto support, a big G when there's Guile support
|
||||
" "
|
||||
(propertize
|
||||
(concat
|
||||
(when (plist-get mu4e~server-props :crypto) "C")
|
||||
(when (plist-get mu4e~server-props :guile) "G")
|
||||
(when (plist-get mu4e~server-props :mux) "X"))
|
||||
'face 'mu4e-title-face)
|
||||
(propertize "; (in store: " 'face 'mu4e-title-face)
|
||||
(propertize (format "%s" (plist-get mu4e~server-props :doccount)) 'face 'mu4e-header-key-face)
|
||||
(propertize " messages)" 'face 'mu4e-title-face)
|
||||
|
||||
"\n\n"
|
||||
(propertize " Basics\n\n" 'face 'mu4e-title-face)
|
||||
|
|
|
@ -274,8 +274,7 @@ Start the process if needed."
|
|||
(proc (and (buffer-live-p buf) (get-buffer-process buf))))
|
||||
(when proc
|
||||
(let ((delete-exited-processes t))
|
||||
;; the mu server signal handler will make it quit after 'quit'
|
||||
(mu4e~proc-send-command "cmd:quit"))
|
||||
(mu4e~call-mu '(quit)))
|
||||
;; try sending SIGINT (C-c) to process, so it can exit gracefully
|
||||
(ignore-errors
|
||||
(signal-process proc 'SIGINT))))
|
||||
|
@ -307,11 +306,18 @@ Start the process if needed."
|
|||
(t
|
||||
(error "Something bad happened to the mu server process")))))
|
||||
|
||||
(defun mu4e~call-mu (form)
|
||||
"Call 'mu' with some command."
|
||||
(unless (mu4e~proc-running-p) (mu4e~proc-start))
|
||||
(let ((cmd (format "%S" form)))
|
||||
(mu4e-log 'to-server "%s" cmd)
|
||||
(process-send-string mu4e~proc-process (concat cmd "\n"))))
|
||||
|
||||
(defun mu4e~docid-msgid-param (docid-or-msgid)
|
||||
"Construct a backend parameter based on DOCID-OR-MSGID."
|
||||
(if (stringp docid-or-msgid)
|
||||
(concat "msgid:" (mu4e~escape docid-or-msgid))
|
||||
(format "docid:%d" docid-or-msgid)))
|
||||
`(:msgid ,(mu4e~escape docid-or-msgid))
|
||||
`(:docid ,docid-or-msgid)))
|
||||
|
||||
(defun mu4e~proc-find (query threads sortfield sortdir maxnum skip-dups
|
||||
include-related)
|
||||
|
@ -330,20 +336,14 @@ For each result found, a function is called, depending on the
|
|||
kind of result. The variables `mu4e-error-func' contain the
|
||||
function that will be called for, resp., a message (header row)
|
||||
or an error."
|
||||
(mu4e~proc-send-command
|
||||
(concat
|
||||
"cmd:find query:%s threads:%s sortfield:%s reverse:%s maxnum:%d "
|
||||
"skip-dups:%s include-related:%s")
|
||||
(base64-encode-string (encode-coding-string query 'utf-8 t) t)
|
||||
(if threads "true" "false")
|
||||
;; sortfield is e.g. ':subject'; this removes the ':'
|
||||
(if (null sortfield) "nil" (substring (symbol-name sortfield) 1))
|
||||
;; TODO: use ascending/descending in backend too (it's clearer than
|
||||
;; 'reverse'
|
||||
(if (eq sortdir 'descending) "true" "false")
|
||||
(if maxnum maxnum -1)
|
||||
(if skip-dups "true" "false")
|
||||
(if include-related "true" "false")))
|
||||
(mu4e~call-mu `(find
|
||||
:query ,query
|
||||
:threads ,threads
|
||||
;; :sortfield ,sortfield
|
||||
:sortdir ,sortdir
|
||||
:maxnum ,maxnum
|
||||
:skip-dups ,skip-dups
|
||||
:include-related ,include-related)))
|
||||
|
||||
(defun mu4e~proc-move (docid-or-msgid &optional maildir flags no-view)
|
||||
"Move message identified by DOCID-OR-MSGID.
|
||||
|
@ -394,40 +394,32 @@ Returns either (:update ... ) or (:error ) sexp, which are handled my
|
|||
(rename
|
||||
(if (and maildir mu4e-change-filenames-when-moving)
|
||||
"true" "false")))
|
||||
(mu4e~proc-send-command "cmd:move %s %s %s %s %s"
|
||||
idparam
|
||||
(or flagstr "")
|
||||
(or path "")
|
||||
(format "newname:%s" rename)
|
||||
(format "noview:%s" (if no-view "true" "false")))))
|
||||
(mu4e~call-mu `(move
|
||||
:docid ,(if (stringp docid-or-msgid) nil docid-or-msgid)
|
||||
:msgid ,(if (stringp docid-or-msgid) docid-or-msgid nil)
|
||||
:flags ,(or flags nil)
|
||||
:maildir ,(or maildir nil)
|
||||
:rename ,(and maildir mu4e-change-filenames-when-moving)
|
||||
:noview ,no-view))))
|
||||
|
||||
(defun mu4e~proc-index (path my-addresses cleanup lazy-check)
|
||||
"Index messages on PATH with possible CLEANUP and LAZY-CHECK.
|
||||
PATH should point to some maildir directory structure.
|
||||
MY-ADDRESSES is a list of 'my' email addresses (see
|
||||
`mu4e-user-mail-address-list')."
|
||||
(let ((path (mu4e~escape path))
|
||||
(addrs (when my-addresses (mapconcat 'identity my-addresses ","))))
|
||||
(if addrs
|
||||
(mu4e~proc-send-command
|
||||
"cmd:index path:%s my-addresses:%s cleanup:%s lazy-check:%s contacts:%s"
|
||||
path
|
||||
addrs
|
||||
(if cleanup "true" : "false")
|
||||
(if lazy-check "true")
|
||||
(if mu4e-compose-complete-addresses "true"))
|
||||
(mu4e~proc-send-command "cmd:index path:%s" path))))
|
||||
(mu4e~call-mu `(index
|
||||
:my-addresses ,my-addresses
|
||||
:cleanup ,cleanup
|
||||
:lazy-check ,lazy-check)))
|
||||
|
||||
(defun mu4e~proc-add (path maildir)
|
||||
"Add the message at PATH to the database.
|
||||
With MAILDIR set to the maildir this message resides in,
|
||||
e.g. '/drafts'; if this works, we will receive (:info add :path
|
||||
<path> :docid <docid>) as well as (:update <msg-sexp>)."
|
||||
(mu4e~proc-send-command "cmd:add path:%s %s"
|
||||
(mu4e~escape path)
|
||||
(if maildir
|
||||
(format "maildir:%s" (mu4e~escape maildir))
|
||||
"")))
|
||||
(mu4e~call-mu `(add
|
||||
:path ,path
|
||||
:maildir ,maildir)))
|
||||
|
||||
(defun mu4e~proc-sent (path maildir)
|
||||
"Add the message at PATH to the database.
|
||||
|
@ -436,9 +428,9 @@ e.g. '/drafts'.
|
|||
|
||||
if this works, we will receive (:info add :path <path> :docid
|
||||
<docid> :fcc <path>)."
|
||||
(mu4e~proc-send-command "cmd:sent path:%s maildir:%s"
|
||||
(mu4e~escape path) (mu4e~escape maildir)))
|
||||
|
||||
(mu4e~call-mu `(sent
|
||||
:path ,path
|
||||
:maildir ,maildir)))
|
||||
|
||||
(defun mu4e~proc-compose (type decrypt &optional docid)
|
||||
"Compose a message of TYPE, DECRYPT it and use DOCID.
|
||||
|
@ -448,49 +440,37 @@ editing, resending) with DOCID or nil for type `new'.
|
|||
|
||||
The result is delivered to the function registered as
|
||||
`mu4e-compose-func'."
|
||||
(unless (member type '(forward reply edit resend new))
|
||||
(mu4e-error "Unsupported compose-type %S" type))
|
||||
(unless (eq (null docid) (eq type 'new))
|
||||
(mu4e-error "`new' implies docid not-nil, and vice-versa"))
|
||||
(mu4e~proc-send-command
|
||||
"cmd:compose type:%s docid:%d extract-encrypted:%s use-agent:true"
|
||||
(symbol-name type) docid (if decrypt "true" "false")))
|
||||
(mu4e~call-mu `(compose
|
||||
:type ,type
|
||||
:decrypt ,decrypt
|
||||
:docid ,docid)))
|
||||
|
||||
(defun mu4e~proc-mkdir (path)
|
||||
"Create a new maildir-directory at filesystem PATH."
|
||||
(mu4e~proc-send-command "cmd:mkdir path:%s" (mu4e~escape path)))
|
||||
;;(mu4e~proc-send-command "cmd:mkdir path:%s" (mu4e~escape path))
|
||||
(mu4e~call-mu `(mkdir :path ,path)))
|
||||
|
||||
(defun mu4e~proc-extract (action docid partidx decrypt
|
||||
(defun mu4e~proc-extract (action docid index decrypt
|
||||
&optional path what param)
|
||||
"Perform ACTION on part with DOCID PARTIDX DECRYPT PATH WHAT PARAM.
|
||||
"Perform ACTION on part with DOCID INDEX DECRYPT PATH WHAT PARAM.
|
||||
Use a message with DOCID and perform ACTION on it (as symbol,
|
||||
either `save', `open', `temp') which mean: * save: save the part
|
||||
to PATH (a path) (non-optional for save)$ * open: open the part
|
||||
with the default application registered for doing so * temp: save
|
||||
to a temporary file, then respond with
|
||||
(:temp <path> :what <what> :param <param>)."
|
||||
(let ((cmd
|
||||
(concat "cmd:extract "
|
||||
(cl-case action
|
||||
(save
|
||||
(format "action:save docid:%d index:%d path:%s extract-encrypted:%s use-agent:true"
|
||||
docid partidx (mu4e~escape path) (if decrypt "true" "false")))
|
||||
(open (format "action:open docid:%d index:%d extract-encrypted:%s use-agent:true"
|
||||
docid partidx (if decrypt "true" "false")))
|
||||
(temp
|
||||
(format "action:temp docid:%d index:%d what:%s%s extract-encrypted:%s use-agent:true"
|
||||
docid partidx what
|
||||
(if param
|
||||
(if (stringp param)
|
||||
(format " param:%s" (mu4e~escape param))
|
||||
(format " param:%S" param)) "") (if decrypt "true" "false")))
|
||||
(otherwise (mu4e-error "Unsupported action %S" action))))
|
||||
))
|
||||
(mu4e~proc-send-command "%s" cmd)))
|
||||
(mu4e~call-mu `(extract
|
||||
:action ,action
|
||||
:docid ,docid
|
||||
:index ,index
|
||||
:decrypt ,decrypt
|
||||
:path ,path
|
||||
:what ,what
|
||||
:param ,param)))
|
||||
|
||||
(defun mu4e~proc-ping ()
|
||||
"Sends a ping to the mu server, expecting a (:pong ...) in response."
|
||||
(mu4e~proc-send-command "cmd:ping"))
|
||||
(mu4e~call-mu '(ping)))
|
||||
|
||||
(defun mu4e~proc-contacts (personal after tstamp)
|
||||
"Ask for contacts with PERSONAL AFTER TSTAMP.
|
||||
|
@ -498,11 +478,10 @@ S-expression (:contacts (<list>) :tstamp \"<tstamp>\") is expected in
|
|||
response. If PERSONAL is non-nil, only get personal contacts, if
|
||||
AFTER is non-nil, get only contacts seen AFTER (the time_t
|
||||
value)."
|
||||
(mu4e~proc-send-command
|
||||
"cmd:contacts personal:%s after:%d tstamp:%s"
|
||||
(if personal "true" "false")
|
||||
(or after 0)
|
||||
(or tstamp "0")))
|
||||
(mu4e~call-mu `(contacts
|
||||
:personal ,personal
|
||||
;; :after ,(or after nil)
|
||||
:tstamp ,(or tstamp nil))))
|
||||
|
||||
(defun mu4e~proc-view (docid-or-msgid &optional images decrypt)
|
||||
"Get a message DOCID-OR-MSGID.
|
||||
|
@ -510,11 +489,11 @@ Optionally, if IMAGES is non-nil, backend will any images
|
|||
attached to the message, and return them as temp files. DECRYPT
|
||||
if necessary. The result will be delivered to the function
|
||||
registered as `mu4e-view-func'."
|
||||
(mu4e~proc-send-command
|
||||
"cmd:view %s extract-images:%s extract-encrypted:%s use-agent:true"
|
||||
(mu4e~docid-msgid-param docid-or-msgid)
|
||||
(if images "true" "false")
|
||||
(if decrypt "true" "false")))
|
||||
(mu4e~call-mu `(view
|
||||
:docid ,(if (stringp docid-or-msgid) nil docid-or-msgid)
|
||||
:msgid ,(if (stringp docid-or-msgid) docid-or-msgid nil)
|
||||
:extract-images ,images
|
||||
:extract-encrypt ,decrypt)))
|
||||
|
||||
(defun mu4e~proc-view-path (path &optional images decrypt)
|
||||
"View message at PATH..
|
||||
|
@ -522,18 +501,17 @@ Optionally, if IMAGES is non-nil, backend will any images
|
|||
attached to the message, and return them as temp files. The
|
||||
result will be delivered to the function registered as
|
||||
`mu4e-view-func'. Optionally DECRYPT."
|
||||
(mu4e~proc-send-command
|
||||
"cmd:view path:%s extract-images:%s extract-encrypted:%s use-agent:true"
|
||||
(mu4e~escape path)
|
||||
(if images "true" "false")
|
||||
(if decrypt "true" "false")))
|
||||
(mu4e~call-mu `(view-path
|
||||
:path ,path
|
||||
:images ,images
|
||||
:decrypt ,decrypt)))
|
||||
|
||||
(defun mu4e~proc-remove (docid)
|
||||
"Remove message with DOCID.
|
||||
The results are reporter through either (:update ... )
|
||||
or (:error) sexp, which are handled my `mu4e-error-func',
|
||||
respectively."
|
||||
(mu4e~proc-send-command "cmd:remove docid:%d" docid))
|
||||
(mu4e~call-mu `(remove :docid ,docid)))
|
||||
|
||||
(provide 'mu4e-proc)
|
||||
;;; mu4e-proc.el ends here
|
||||
|
|
Loading…
Reference in New Issue