summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2020-01-19 17:23:24 +0200
committerDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2020-01-22 11:42:15 +0200
commitd2ec85f01c61514e115f66ddb246f7a72aebfaae (patch)
tree85ab266cc739690c70bd45a86d6ddf7d4426bc9b
parentc71f683e396b6a6753d231dfa5df2def1b0e7c88 (diff)
mu4e: use the new command-parser
Update mu4e-proc to use the new mu4e <-> mu protocol
-rw-r--r--lib/utils/mu-utils.cc27
-rw-r--r--lib/utils/mu-utils.hh11
-rw-r--r--mu/mu-cmd.c6
-rw-r--r--mu/mu-config.c5
-rw-r--r--mu/mu-config.h4
-rw-r--r--mu4e/mu4e-main.el13
-rw-r--r--mu4e/mu4e-proc.el154
7 files changed, 116 insertions, 104 deletions
diff --git a/lib/utils/mu-utils.cc b/lib/utils/mu-utils.cc
index 9ebe801..5c8e59e 100644
--- a/lib/utils/mu-utils.cc
+++ b/lib/utils/mu-utils.cc
@@ -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)
{
diff --git a/lib/utils/mu-utils.hh b/lib/utils/mu-utils.hh
index f5b2e61..e988065 100644
--- a/lib/utils/mu-utils.hh
+++ b/lib/utils/mu-utils.hh
@@ -94,6 +94,17 @@ std::string format (const char *frm, va_list args) __attribute__((format(printf,
/**
+ * 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
*
diff --git a/mu/mu-cmd.c b/mu/mu-cmd.c
index 0146bc9..703db94 100644
--- a/mu/mu-cmd.c
+++ b/mu/mu-cmd.c
@@ -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;
}
diff --git a/mu/mu-config.c b/mu/mu-config.c
index e524438..cc8c92d 100644
--- a/mu/mu-config.c
+++ b/mu/mu-config.c
@@ -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)
{
diff --git a/mu/mu-config.h b/mu/mu-config.h
index 3d4f281..d643676 100644
--- a/mu/mu-config.h
+++ b/mu/mu-config.h
@@ -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 */
diff --git a/mu4e/mu4e-main.el b/mu4e/mu4e-main.el
index 9580c78..68ce1a7 100644
--- a/mu4e/mu4e-main.el
+++ b/mu4e/mu4e-main.el
@@ -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)
diff --git a/mu4e/mu4e-proc.el b/mu4e/mu4e-proc.el
index f395b96..1bf2b55 100644
--- a/mu4e/mu4e-proc.el
+++ b/mu4e/mu4e-proc.el
@@ -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