From fb2f5d6a531cca0d2ea2619420526fe967c34e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abd=C3=B3=20Roig-Maranges?= Date: Thu, 6 Dec 2012 19:14:05 +0100 Subject: [PATCH 1/3] Adds an action to change tags header New action mu4e-action-retag-message that reads tag changes from the user and modifies the corresponding header (X-Keywords, X-Label, etc) on the message. --- mu4e/mu4e-actions.el | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/mu4e/mu4e-actions.el b/mu4e/mu4e-actions.el index cafb71d6..4d59830a 100644 --- a/mu4e/mu4e-actions.el +++ b/mu4e/mu4e-actions.el @@ -172,7 +172,7 @@ store your org-contacts." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun mu4e-action-git-apply-patch (msg) "Apply the git [patch] message." - (let ((path (read-directory-name "Target directory: " nil "~/" t) )) + (let ((path (read-directory-name "Target directory: " nil "~/" t) )) (shell-command (format "cd %s; git apply %s" path @@ -180,4 +180,45 @@ store your org-contacts." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar mu4e-action-tags-header "X-Keywords" + "Header where tags are stored.") + +(defun mu4e-action-retag-message (msg) + "Change tags of a message. Example: +tag \"+long tag\" -oldtag + adds 'tag' and 'long tag', and removes oldtag." + (let* ((retag (read-string "Tags: ")) + (path (mu4e-message-field msg :path)) + (maildir (mu4e-message-field msg :maildir)) + (oldtags (mu4e-message-field msg :tags)) + (header mu4e-action-tags-header) + (sep (cond ((string= header "Keywords") " ") + ((string= header "X-Label") " ") + ((string= header "X-Keywords") ", ") + (t ", "))) + (taglist (if oldtags (copy-sequence oldtags) '())) + tagstr) + + (dolist (tag (split-string-and-unquote retag) taglist) + (cond ((string-match "\\+\\(.+\\)" tag) + (setq taglist (push (match-string 1 tag) taglist))) + ((string-match "\\-\\(.+\\)" tag) + (setq taglist (delete (match-string 1 tag) taglist))) + (t + (setq taglist (push tag taglist))))) + + (setq taglist (sort (delete-dups taglist) 'string<)) + (setq tagstr (mapconcat 'identity taglist sep)) + (setq tagstr (replace-regexp-in-string "[\\/&]" "\\\\\\&" tagstr)) + + ;; replaces keywords with sed, restricted to the header + (call-process "sed" nil nil nil "-ine" + (format "1,/^$/s/^%s:.*$/%s: %s/" header header tagstr) path) + + (message (concat "tagging: " (mapconcat 'identity taglist " "))) + (mu4e~proc-add path maildir))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (provide 'mu4e-actions) From 2803b43f6391a4e163dd3de87c486632d28e50cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abd=C3=B3=20Roig-Maranges?= Date: Thu, 6 Dec 2012 19:16:36 +0100 Subject: [PATCH 2/3] Make cmd_add output update information This way, if a message changes, I can use add to force reindexing it, and notify mu4e about the changes. --- mu/mu-cmd-server.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mu/mu-cmd-server.c b/mu/mu-cmd-server.c index 0cfff7fb..b932b444 100644 --- a/mu/mu-cmd-server.c +++ b/mu/mu-cmd-server.c @@ -380,7 +380,6 @@ typedef struct _ServerContext ServerContext; typedef MuError (*CmdFunc) (ServerContext*,GSList*,GError**); - /* 'add' adds a message to the database, and takes two parameters: * 'path', which is the full path to the message, and 'maildir', which * is the maildir this message lives in (e.g. "/inbox"). response with @@ -392,6 +391,8 @@ cmd_add (ServerContext *ctx, GSList *args, GError **err) { unsigned docid; const char *maildir, *path; + MuMsg *msg; + gchar *sexp; GET_STRING_OR_ERROR_RETURN (args, "path", &path, err); GET_STRING_OR_ERROR_RETURN (args, "maildir", &maildir, err); @@ -403,6 +404,15 @@ cmd_add (ServerContext *ctx, GSList *args, GError **err) gchar *escpath; escpath = mu_str_escape_c_literal (path, TRUE); print_expr ("(:info add :path %s :docid %u)", escpath, docid); + + msg = mu_store_get_msg (ctx->store, docid, err); + if (msg) { + sexp = mu_msg_to_sexp (msg, docid, NULL, MU_MSG_OPTION_VERIFY); + print_expr ("(:update %s :move nil)", sexp); + + mu_msg_unref(msg); + g_free (sexp); + } g_free (escpath); } From b875690bc0801358d23918b8cf0f710797ae8f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abd=C3=B3=20Roig-Maranges?= Date: Thu, 6 Dec 2012 20:38:25 +0100 Subject: [PATCH 3/3] Change mode before setting local variables in mu4e-view Otherwise, the mode-change messes up with local bindings. In paricular, this caused mu4e~view-msg contain the wrong path after a flag change. --- mu4e/mu4e-view.el | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mu4e/mu4e-view.el b/mu4e/mu4e-view.el index 3519722b..11963b48 100644 --- a/mu4e/mu4e-view.el +++ b/mu4e/mu4e-view.el @@ -228,19 +228,19 @@ marking if it still had that." (if embedded (local-set-key "q" 'kill-buffer-and-window) - (setq mu4e~view-buffer buf)) + (setq mu4e~view-buffer buf))) + + (unless (eq major-mode 'mu4e-view-mode) + (mu4e-view-mode)) (setq ;; buffer local - mu4e~view-msg msg - mu4e~view-headers-buffer headersbuf)) + mu4e~view-msg msg + mu4e~view-headers-buffer headersbuf) - (unless (or refresh embedded) + (unless (or refresh embedded) ;; no use in trying to set flags again, or when it's an embedded ;; message - (mu4e~view-mark-as-read-maybe)) - - ;; and switch! - (mu4e-view-mode)))) + (mu4e~view-mark-as-read-maybe))))) (defun mu4e~view-construct-header (field val &optional dont-propertize-val)