* renamed mm -> mu4e
This commit is contained in:
@ -18,18 +18,17 @@ include $(top_srcdir)/gtest.mk
|
|||||||
|
|
||||||
SUBDIRS=
|
SUBDIRS=
|
||||||
|
|
||||||
BUILT_SOURCES=mm-version.el
|
BUILT_SOURCES=mu4e-version.el
|
||||||
|
|
||||||
mm-version.el:
|
mu4e-version.el:
|
||||||
@echo -e ";; auto-generated\n\
|
@echo -e ";; auto-generated\n\
|
||||||
(defconst mm/mu-version \"$(VERSION)\" \"Required mu binary version.\")\n\
|
(defconst mu4e-mu-version \"$(VERSION)\" \"Required mu binary version.\")\n\
|
||||||
(provide 'mm-version)\n" >$@
|
(provide 'mu4e-version)\n" >$@
|
||||||
|
|
||||||
EXTRA_DIST= \
|
EXTRA_DIST= \
|
||||||
mm.el \
|
mu4e.el \
|
||||||
mm-hdrs.el \
|
mu4e-hdrs.el \
|
||||||
mm-view.el \
|
mu4e-view.el \
|
||||||
mm-proc.el \
|
mu4e-proc.el \
|
||||||
mm-send.el \
|
mu4e-send.el \
|
||||||
mm-version.el
|
mu4e-version.el
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
;; mm-hdrs.el -- part of mm, the mu mail user agent
|
;; mu4e-hdrs.el -- part of mm, the mu mail user agent
|
||||||
;;
|
;;
|
||||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||||
|
|
||||||
@ -34,55 +34,53 @@
|
|||||||
|
|
||||||
(eval-when-compile (require 'cl))
|
(eval-when-compile (require 'cl))
|
||||||
|
|
||||||
(require 'mm-proc)
|
(require 'mu4e-proc)
|
||||||
|
|
||||||
;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defvar mm/last-expr nil
|
(defvar mu4e-last-expr nil
|
||||||
"*internal* The most recent search expression.")
|
"*internal* The most recent search expression.")
|
||||||
(defvar mm/sortfield nil
|
(defvar mu4e-sortfield nil
|
||||||
"*internal* Field to sort headers by")
|
"*internal* Field to sort headers by")
|
||||||
(defvar mm/sort-descending nil
|
(defvar mu4e-sort-descending nil
|
||||||
"*internal Whether to sort in descending order")
|
"*internal Whether to sort in descending order")
|
||||||
|
|
||||||
|
|
||||||
(defconst mm/hdrs-buffer-name "*mm-headers*"
|
(defconst mu4e-hdrs-buffer-name "*mu4e-headers*"
|
||||||
"*internal* Name of the buffer for message headers.")
|
"*internal* Name of the buffer for message headers.")
|
||||||
|
|
||||||
(defvar mm/hdrs-buffer nil
|
(defvar mu4e-hdrs-buffer nil
|
||||||
"*internal* Buffer for message headers")
|
"*internal* Buffer for message headers")
|
||||||
|
|
||||||
(defun mm/hdrs-search (expr &optional full-search)
|
(defun mu4e-hdrs-search (expr &optional full-search)
|
||||||
"Search in the mu database for EXPR, and switch to the output
|
"Search in the mu database for EXPR, and switch to the output
|
||||||
buffer for the results. If FULL-SEARCH is non-nil return all
|
buffer for the results. If FULL-SEARCH is non-nil return all
|
||||||
results, otherwise, limit number of results to
|
results, otherwise, limit number of results to
|
||||||
`mm/search-results-limit'."
|
`mu4e-search-results-limit'."
|
||||||
(let ((buf (get-buffer-create mm/hdrs-buffer-name))
|
(let ((buf (get-buffer-create mu4e-hdrs-buffer-name))
|
||||||
(inhibit-read-only t))
|
(inhibit-read-only t))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(mm/hdrs-mode)
|
(mu4e-hdrs-mode)
|
||||||
(setq
|
(setq
|
||||||
mm/mm/marks-map nil
|
|
||||||
mm/msg-map (make-hash-table :size 1024 :rehash-size 2 :weakness nil)
|
|
||||||
mode-name expr
|
mode-name expr
|
||||||
mm/last-expr expr
|
mu4e-last-expr expr
|
||||||
mm/hdrs-buffer buf)))
|
mu4e-hdrs-buffer buf)))
|
||||||
(switch-to-buffer mm/hdrs-buffer)
|
(switch-to-buffer mu4e-hdrs-buffer)
|
||||||
(mm/proc-find expr ;; '-1' means 'unlimited search'
|
(mu4e-proc-find expr ;; '-1' means 'unlimited search'
|
||||||
(if full-search -1 mm/search-results-limit)))
|
(if full-search -1 mu4e-search-results-limit)))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; handler functions
|
;; handler functions
|
||||||
;;
|
;;
|
||||||
;; next are a bunch of handler functions; those will be called from mm-proc in
|
;; next are a bunch of handler functions; those will be called from mu4e-proc in
|
||||||
;; response to output from the server process
|
;; response to output from the server process
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-view-handler (msg)
|
(defun mu4e-hdrs-view-handler (msg)
|
||||||
"Handler function for displaying a message."
|
"Handler function for displaying a message."
|
||||||
(mm/view msg mm/hdrs-buffer))
|
(mu4e-view msg mu4e-hdrs-buffer))
|
||||||
|
|
||||||
(defun mm/hdrs-error-handler (err)
|
(defun mu4e-hdrs-error-handler (err)
|
||||||
"Handler function for showing an error."
|
"Handler function for showing an error."
|
||||||
(let ((errcode (plist-get err :error))
|
(let ((errcode (plist-get err :error))
|
||||||
(errmsg (plist-get err :error-message)))
|
(errmsg (plist-get err :error-message)))
|
||||||
@ -90,57 +88,57 @@ results, otherwise, limit number of results to
|
|||||||
(4 (message "No matches for this search query."))
|
(4 (message "No matches for this search query."))
|
||||||
(t (message (format "Error %d: %s" errcode errmsg))))))
|
(t (message (format "Error %d: %s" errcode errmsg))))))
|
||||||
|
|
||||||
(defun mm/hdrs-update-handler (msg is-move)
|
(defun mu4e-hdrs-update-handler (msg is-move)
|
||||||
"Update handler, will be called when a message has been updated
|
"Update handler, will be called when a message has been updated
|
||||||
in the database. This function will update the current list of
|
in the database. This function will update the current list of
|
||||||
headers."
|
headers."
|
||||||
(when (buffer-live-p mm/hdrs-buffer)
|
(when (buffer-live-p mu4e-hdrs-buffer)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(let* ((docid (plist-get msg :docid))
|
(let* ((docid (plist-get msg :docid))
|
||||||
(marker (gethash docid mm/msg-map))
|
(marker (gethash docid mu4e-msg-map))
|
||||||
(point (when marker (marker-position marker))))
|
(point (when marker (marker-position marker))))
|
||||||
(when point ;; is the message present in this list?
|
(when point ;; is the message present in this list?
|
||||||
;; if it's marked, unmark it now
|
;; if it's marked, unmark it now
|
||||||
(when (mm/hdrs-docid-is-marked docid) (mm/hdrs-mark 'unmark))
|
(when (mu4e-hdrs-docid-is-marked docid) (mu4e-hdrs-mark 'unmark))
|
||||||
;; first, remove the old one (otherwise, we'd have to headers with
|
;; first, remove the old one (otherwise, we'd have to headers with
|
||||||
;; the same docid...
|
;; the same docid...
|
||||||
(mm/hdrs-remove-handler docid)
|
(mu4e-hdrs-remove-handler docid)
|
||||||
|
|
||||||
;; if we we're actually viewing this message (in mm/view mode), we
|
;; if we we're actually viewing this message (in mu4e-view mode), we
|
||||||
;; update the `mm/current-msg' there as well; that way, the flags can
|
;; update the `mu4e-current-msg' there as well; that way, the flags can
|
||||||
;; be updated, as well as the path (which is useful for viewing the
|
;; be updated, as well as the path (which is useful for viewing the
|
||||||
;; raw message)
|
;; raw message)
|
||||||
(let ((viewbuf (get-buffer mm/view-buffer-name)))
|
(let ((viewbuf (get-buffer mu4e-view-buffer-name)))
|
||||||
(when (and viewbuf (buffer-live-p viewbuf))
|
(when (and viewbuf (buffer-live-p viewbuf))
|
||||||
(with-current-buffer viewbuf
|
(with-current-buffer viewbuf
|
||||||
(when (eq docid (plist-get mm/current-msg :docid))
|
(when (eq docid (plist-get mu4e-current-msg :docid))
|
||||||
(setq mm/current-msg msg)))))
|
(setq mu4e-current-msg msg)))))
|
||||||
|
|
||||||
;; now, if this update was about *moving* a message, we don't show it
|
;; now, if this update was about *moving* a message, we don't show it
|
||||||
;; anymore (of course, we cannot be sure if the message really no
|
;; anymore (of course, we cannot be sure if the message really no
|
||||||
;; longer matches the query, but this seem a good heuristic.
|
;; longer matches the query, but this seem a good heuristic.
|
||||||
;; if it was only a flag-change, show the message with its updated flags.
|
;; if it was only a flag-change, show the message with its updated flags.
|
||||||
(unless is-move
|
(unless is-move
|
||||||
(mm/hdrs-header-handler msg point)))))))
|
(mu4e-hdrs-header-handler msg point)))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-remove-handler (docid)
|
(defun mu4e-hdrs-remove-handler (docid)
|
||||||
"Remove handler, will be called when a message has been removed
|
"Remove handler, will be called when a message has been removed
|
||||||
from the database. This function will hide the remove message in
|
from the database. This function will hide the remove message in
|
||||||
the current list of headers."
|
the current list of headers."
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(let* ((marker (gethash docid mm/msg-map))
|
(let* ((marker (gethash docid mu4e-msg-map))
|
||||||
(pos (and marker (marker-position marker)))
|
(pos (and marker (marker-position marker)))
|
||||||
(docid-at-pos (and pos (mm/hdrs-get-docid pos))))
|
(docid-at-pos (and pos (mu4e-hdrs-get-docid pos))))
|
||||||
(unless marker (error "Message %d not found" docid))
|
(unless marker (error "Message %d not found" docid))
|
||||||
(unless (eq docid docid-at-pos)
|
(unless (eq docid docid-at-pos)
|
||||||
(error "At point %d, expected docid %d, but got %d"
|
(error "At point %d, expected docid %d, but got %d"
|
||||||
pos docid docid-at-pos))
|
pos docid docid-at-pos))
|
||||||
(mm/hdrs-remove-header docid pos))))
|
(mu4e-hdrs-remove-header docid pos))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defun mm/hdrs-contact-str (contacts)
|
(defun mu4e-hdrs-contact-str (contacts)
|
||||||
"Turn the list of contacts CONTACTS (with elements (NAME . EMAIL)
|
"Turn the list of contacts CONTACTS (with elements (NAME . EMAIL)
|
||||||
into a string."
|
into a string."
|
||||||
(mapconcat
|
(mapconcat
|
||||||
@ -148,7 +146,7 @@ into a string."
|
|||||||
(let ((name (car ct)) (email (cdr ct)))
|
(let ((name (car ct)) (email (cdr ct)))
|
||||||
(or name email "?"))) contacts ", "))
|
(or name email "?"))) contacts ", "))
|
||||||
|
|
||||||
(defun mm/thread-prefix (thread)
|
(defun mu4e-thread-prefix (thread)
|
||||||
"Calculate the thread prefix based on thread info THREAD."
|
"Calculate the thread prefix based on thread info THREAD."
|
||||||
(if thread
|
(if thread
|
||||||
(let ( (level (plist-get thread :level))
|
(let ( (level (plist-get thread :level))
|
||||||
@ -167,12 +165,12 @@ into a string."
|
|||||||
;; FIXME: when updating an header line, we don't know the thread
|
;; FIXME: when updating an header line, we don't know the thread
|
||||||
;; stuff
|
;; stuff
|
||||||
|
|
||||||
(defun mm/hdrs-header-handler (msg &optional point)
|
(defun mu4e-hdrs-header-handler (msg &optional point)
|
||||||
"Create a one line description of MSG in this buffer, at POINT,
|
"Create a one line description of MSG in this buffer, at POINT,
|
||||||
if provided, or at the end of the buffer otherwise."
|
if provided, or at the end of the buffer otherwise."
|
||||||
(let* ( (docid (plist-get msg :docid))
|
(let* ( (docid (plist-get msg :docid))
|
||||||
(thread-info
|
(thread-info
|
||||||
(or (plist-get msg :thread) (gethash docid mm/thread-info-map)))
|
(or (plist-get msg :thread) (gethash docid mu4e-thread-info-map)))
|
||||||
(line
|
(line
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (f-w)
|
(lambda (f-w)
|
||||||
@ -180,50 +178,50 @@ if provided, or at the end of the buffer otherwise."
|
|||||||
(val (plist-get msg field))
|
(val (plist-get msg field))
|
||||||
(str
|
(str
|
||||||
(case field
|
(case field
|
||||||
(:subject (concat (mm/thread-prefix thread-info) val))
|
(:subject (concat (mu4e-thread-prefix thread-info) val))
|
||||||
((:maildir :path) val)
|
((:maildir :path) val)
|
||||||
((:to :from :cc :bcc) (mm/hdrs-contact-str val))
|
((:to :from :cc :bcc) (mu4e-hdrs-contact-str val))
|
||||||
;; if we (ie. `user-mail-address' is the 'From', show
|
;; if we (ie. `user-mail-address' is the 'From', show
|
||||||
;; 'To', otherwise show From
|
;; 'To', otherwise show From
|
||||||
(:from-or-to
|
(:from-or-to
|
||||||
(let* ((from-lst (plist-get msg :from))
|
(let* ((from-lst (plist-get msg :from))
|
||||||
(from (and from-lst (cdar from-lst))))
|
(from (and from-lst (cdar from-lst))))
|
||||||
(if (and from (string-match
|
(if (and from (string-match
|
||||||
mm/user-mail-address-regexp from))
|
mu4e-user-mail-address-regexp from))
|
||||||
(concat "To "
|
(concat "To "
|
||||||
(mm/hdrs-contact-str (plist-get msg :to)))
|
(mu4e-hdrs-contact-str (plist-get msg :to)))
|
||||||
(mm/hdrs-contact-str from-lst))))
|
(mu4e-hdrs-contact-str from-lst))))
|
||||||
(:date (format-time-string mm/headers-date-format val))
|
(:date (format-time-string mu4e-headers-date-format val))
|
||||||
(:flags (mm/flags-to-string val))
|
(:flags (mu4e-flags-to-string val))
|
||||||
(:size (mm/display-size val))
|
(:size (mu4e-display-size val))
|
||||||
(t (error "Unsupported header field (%S)" field)))))
|
(t (error "Unsupported header field (%S)" field)))))
|
||||||
(when str
|
(when str
|
||||||
(if (not width)
|
(if (not width)
|
||||||
str
|
str
|
||||||
(truncate-string-to-width str width 0 ?\s t)))))
|
(truncate-string-to-width str width 0 ?\s t)))))
|
||||||
mm/headers-fields " "))
|
mu4e-headers-fields " "))
|
||||||
(flags (plist-get msg :flags))
|
(flags (plist-get msg :flags))
|
||||||
(line (cond
|
(line (cond
|
||||||
((member 'draft flags)
|
((member 'draft flags)
|
||||||
(propertize line 'face 'mm/draft-face 'draft t))
|
(propertize line 'face 'mu4e-draft-face 'draft t))
|
||||||
((member 'trashed flags)
|
((member 'trashed flags)
|
||||||
(propertize line 'face 'mm/trashed-face))
|
(propertize line 'face 'mu4e-trashed-face))
|
||||||
((member 'unread flags)
|
((member 'unread flags)
|
||||||
(propertize line 'face 'mm/unread-face))
|
(propertize line 'face 'mu4e-unread-face))
|
||||||
(t ;; else
|
(t ;; else
|
||||||
(propertize line 'face 'mm/header-face)))))
|
(propertize line 'face 'mu4e-header-face)))))
|
||||||
|
|
||||||
;; store the thread info, so we can use it when updating the message
|
;; store the thread info, so we can use it when updating the message
|
||||||
(when thread-info
|
(when thread-info
|
||||||
(puthash docid thread-info mm/thread-info-map))
|
(puthash docid thread-info mu4e-thread-info-map))
|
||||||
(mm/hdrs-add-header line (plist-get msg :docid)
|
(mu4e-hdrs-add-header line (plist-get msg :docid)
|
||||||
(if point point (point-max)))))
|
(if point point (point-max)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-found-handler (count)
|
(defun mu4e-hdrs-found-handler (count)
|
||||||
"Create a one line description of the number of headers found
|
"Create a one line description of the number of headers found
|
||||||
after the end of the search results."
|
after the end of the search results."
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
@ -235,7 +233,7 @@ after the end of the search results."
|
|||||||
(otherwise "End of search results"))
|
(otherwise "End of search results"))
|
||||||
;; (1 "Found 1 message")
|
;; (1 "Found 1 message")
|
||||||
;; (otherwise (format "Found %d messages" count)))
|
;; (otherwise (format "Found %d messages" count)))
|
||||||
'face 'mm/system-face 'intangible t))))))
|
'face 'mu4e-system-face 'intangible t))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
@ -243,115 +241,116 @@ after the end of the search results."
|
|||||||
|
|
||||||
|
|
||||||
;;; hdrs-mode and mode-map ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; hdrs-mode and mode-map ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(setq mm/hdrs-mode-map nil)
|
(setq mu4e-hdrs-mode-map nil)
|
||||||
(defvar mm/hdrs-mode-map nil
|
(defvar mu4e-hdrs-mode-map nil
|
||||||
"Keymap for *mm-headers* buffers.")
|
"Keymap for *mu4e-headers* buffers.")
|
||||||
(unless mm/hdrs-mode-map
|
(unless mu4e-hdrs-mode-map
|
||||||
(setq mm/hdrs-mode-map
|
(setq mu4e-hdrs-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
|
|
||||||
(define-key map "s" 'mm/search)
|
(define-key map "s" 'mu4e-search)
|
||||||
(define-key map "S" 'mm/search-full)
|
(define-key map "S" 'mu4e-search-full)
|
||||||
|
|
||||||
(define-key map "b" 'mm/search-bookmark)
|
(define-key map "b" 'mu4e-search-bookmark)
|
||||||
|
|
||||||
(define-key map "q" 'mm/quit-buffer)
|
(define-key map "q" 'mu4e-quit-buffer)
|
||||||
;; (define-key map "o" 'mm/change-sort)
|
;; (define-key map "o" 'mu4e-change-sort)
|
||||||
(define-key map "g" 'mm/rerun-search)
|
(define-key map "g" 'mu4e-rerun-search)
|
||||||
|
|
||||||
;; navigation
|
;; navigation
|
||||||
(define-key map "n" 'mm/next-header)
|
(define-key map "n" 'mu4e-next-header)
|
||||||
(define-key map "p" 'mm/prev-header)
|
(define-key map "p" 'mu4e-prev-header)
|
||||||
|
|
||||||
|
|
||||||
;; marking/unmarking/executing
|
;; marking/unmarking/executing
|
||||||
(define-key map (kbd "<backspace>") 'mm/mark-for-trash)
|
(define-key map (kbd "<backspace>") 'mu4e-mark-for-trash)
|
||||||
(define-key map "d" 'mm/mark-for-trash)
|
(define-key map "d" 'mu4e-mark-for-trash)
|
||||||
|
|
||||||
(define-key map (kbd "<delete>") 'mm/mark-for-delete)
|
(define-key map (kbd "<delete>") 'mu4e-mark-for-delete)
|
||||||
(define-key map "D" 'mm/mark-for-delete)
|
(define-key map "D" 'mu4e-mark-for-delete)
|
||||||
|
|
||||||
(define-key map "j" 'mm/jump-to-maildir)
|
(define-key map "j" 'mu4e-jump-to-maildir)
|
||||||
(define-key map "m" 'mm/mark-for-move)
|
(define-key map "m" 'mu4e-mark-for-move)
|
||||||
|
|
||||||
(define-key map "u" 'mm/unmark)
|
(define-key map "u" 'mu4e-unmark)
|
||||||
(define-key map "U" 'mm/unmark-all)
|
(define-key map "U" 'mu4e-unmark-all)
|
||||||
(define-key map "x" 'mm/execute-marks)
|
(define-key map "x" 'mu4e-execute-marks)
|
||||||
|
|
||||||
;; message composition
|
;; message composition
|
||||||
(define-key map "r" 'mm/compose-reply)
|
(define-key map "r" 'mu4e-compose-reply)
|
||||||
(define-key map "f" 'mm/compose-forward)
|
(define-key map "f" 'mu4e-compose-forward)
|
||||||
(define-key map "c" 'mm/compose-new)
|
(define-key map "c" 'mu4e-compose-new)
|
||||||
(define-key map "e" 'mm/edit-draft)
|
(define-key map "e" 'mu4e-edit-draft)
|
||||||
|
|
||||||
(define-key map (kbd "RET") 'mm/view-message)
|
(define-key map (kbd "RET") 'mu4e-view-message)
|
||||||
|
|
||||||
;; menu
|
;; menu
|
||||||
(define-key map [menu-bar] (make-sparse-keymap))
|
(define-key map [menu-bar] (make-sparse-keymap))
|
||||||
(let ((menumap (make-sparse-keymap "Headers")))
|
(let ((menumap (make-sparse-keymap "Headers")))
|
||||||
(define-key map [menu-bar headers] (cons "Headers" menumap))
|
(define-key map [menu-bar headers] (cons "Headers" menumap))
|
||||||
|
|
||||||
(define-key menumap [quit-buffer] '("Quit view" . mm/quit-buffer))
|
(define-key menumap [quit-buffer] '("Quit view" . mu4e-quit-buffer))
|
||||||
(define-key menumap [sepa0] '("--"))
|
(define-key menumap [sepa0] '("--"))
|
||||||
|
|
||||||
(define-key menumap [execute-marks] '("Execute marks" . mm/execute-marks))
|
(define-key menumap [execute-marks] '("Execute marks" . mu4e-execute-marks))
|
||||||
(define-key menumap [unmark-all] '("Unmark all" . mm/unmark-all))
|
(define-key menumap [unmark-all] '("Unmark all" . mu4e-unmark-all))
|
||||||
(define-key menumap [unmark] '("Unmark" . mm/unmark))
|
(define-key menumap [unmark] '("Unmark" . mu4e-unmark))
|
||||||
(define-key menumap [mark-delete] '("Mark for deletion" . mm/mark-for-delete))
|
(define-key menumap [mark-delete] '("Mark for deletion" . mu4e-mark-for-delete))
|
||||||
(define-key menumap [mark-trash] '("Mark for trash" . mm/mark-for-trash))
|
(define-key menumap [mark-trash] '("Mark for trash" . mu4e-mark-for-trash))
|
||||||
(define-key menumap [mark-move] '("Mark for move" . mm/mark-for-move))
|
(define-key menumap [mark-move] '("Mark for move" . mu4e-mark-for-move))
|
||||||
(define-key menumap [sepa1] '("--"))
|
(define-key menumap [sepa1] '("--"))
|
||||||
|
|
||||||
(define-key menumap [compose-new] '("Compose new" . mm/compose-new))
|
(define-key menumap [compose-new] '("Compose new" . mu4e-compose-new))
|
||||||
(define-key menumap [forward] '("Forward" . mm/compose-forward))
|
(define-key menumap [forward] '("Forward" . mu4e-compose-forward))
|
||||||
(define-key menumap [reply] '("Reply" . mm/compose-reply))
|
(define-key menumap [reply] '("Reply" . mu4e-compose-reply))
|
||||||
(define-key menumap [sepa2] '("--"))
|
(define-key menumap [sepa2] '("--"))
|
||||||
|
|
||||||
(define-key menumap [refresh] '("Refresh" . mm/rerun-search))
|
(define-key menumap [refresh] '("Refresh" . mu4e-rerun-search))
|
||||||
(define-key menumap [search] '("Search" . mm/search))
|
(define-key menumap [search] '("Search" . mu4e-search))
|
||||||
(define-key menumap [search-full] '("Search full" . mm/search-full))
|
(define-key menumap [search-full] '("Search full" . mu4e-search-full))
|
||||||
|
|
||||||
(define-key menumap [jump] '("Jump to maildir" . mm/jump-to-maildir))
|
(define-key menumap [jump] '("Jump to maildir" . mu4e-jump-to-maildir))
|
||||||
(define-key menumap [sepa3] '("--"))
|
(define-key menumap [sepa3] '("--"))
|
||||||
|
|
||||||
(define-key menumap [view] '("View" . mm/view-message))
|
(define-key menumap [view] '("View" . mu4e-view-message))
|
||||||
(define-key menumap [next] '("Next" . mm/next-header))
|
(define-key menumap [next] '("Next" . mu4e-next-header))
|
||||||
(define-key menumap [previous] '("Previous" . mm/prev-header))
|
(define-key menumap [previous] '("Previous" . mu4e-prev-header))
|
||||||
(define-key menumap [sepa4] '("--")))
|
(define-key menumap [sepa4] '("--")))
|
||||||
|
|
||||||
;;(define-key menumap [draft] '("Edit draft" . mm/compose-new))
|
;;(define-key menumap [draft] '("Edit draft" . mu4e-compose-new))
|
||||||
map)))
|
map)))
|
||||||
|
|
||||||
(fset 'mm/hdrs-mode-map mm/hdrs-mode-map)
|
(fset 'mu4e-hdrs-mode-map mu4e-hdrs-mode-map)
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-mode ()
|
(defun mu4e-hdrs-mode ()
|
||||||
"Major mode for displaying mua search results."
|
"Major mode for displaying mua search results."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
|
||||||
(kill-all-local-variables)
|
(kill-all-local-variables)
|
||||||
(use-local-map mm/hdrs-mode-map)
|
(use-local-map mu4e-hdrs-mode-map)
|
||||||
|
|
||||||
(make-local-variable 'mm/last-expr)
|
(make-local-variable 'mu4e-last-expr)
|
||||||
(make-local-variable 'mm/hdrs-proc)
|
(make-local-variable 'mu4e-hdrs-proc)
|
||||||
(make-local-variable 'mm/marks-map)
|
(make-local-variable 'mu4e-marks-map)
|
||||||
(make-local-variable 'mm/msg-map)
|
(make-local-variable 'mu4e-msg-map)
|
||||||
(make-local-variable 'mm/thread-info-map)
|
(make-local-variable 'mu4e-thread-info-map)
|
||||||
|
|
||||||
;; we register our handler functions for the mm-proc (mu server) output
|
;; we register our handler functions for the mu4e-proc (mu server) output
|
||||||
(setq mm/proc-error-func 'mm/hdrs-error-handler)
|
(setq mu4e-proc-error-func 'mu4e-hdrs-error-handler)
|
||||||
(setq mm/proc-update-func 'mm/hdrs-update-handler)
|
(setq mu4e-proc-update-func 'mu4e-hdrs-update-handler)
|
||||||
(setq mm/proc-header-func 'mm/hdrs-header-handler)
|
(setq mu4e-proc-header-func 'mu4e-hdrs-header-handler)
|
||||||
(setq mm/proc-found-func 'mm/hdrs-found-handler)
|
(setq mu4e-proc-found-func 'mu4e-hdrs-found-handler)
|
||||||
(setq mm/proc-view-func 'mm/hdrs-view-handler)
|
(setq mu4e-proc-view-func 'mu4e-hdrs-view-handler)
|
||||||
(setq mm/proc-remove-func 'mm/hdrs-remove-handler)
|
(setq mu4e-proc-remove-func 'mu4e-hdrs-remove-handler)
|
||||||
;; this last one is defined in mm-send.el
|
;; this last one is defined in mu4e-send.el
|
||||||
(setq mm/proc-compose-func 'mm/send-compose-handler)
|
(setq mu4e-proc-compose-func 'mu4e-send-compose-handler)
|
||||||
|
|
||||||
(setq
|
(setq
|
||||||
mm/marks-map (make-hash-table :size 16 :rehash-size 2)
|
mu4e-marks-map (make-hash-table :size 16 :rehash-size 2)
|
||||||
mm/thread-info-map (make-hash-table :size 512 :rehash-size 2)
|
mu4e-msg-map (make-hash-table :size 1024 :rehash-size 2 :weakness nil)
|
||||||
major-mode 'mm/hdrs-mode
|
mu4e-thread-info-map (make-hash-table :size 512 :rehash-size 2)
|
||||||
|
major-mode 'mu4e-hdrs-mode
|
||||||
mode-name "mm: message headers"
|
mode-name "mm: message headers"
|
||||||
truncate-lines t
|
truncate-lines t
|
||||||
buffer-read-only t
|
buffer-read-only t
|
||||||
@ -361,17 +360,17 @@ after the end of the search results."
|
|||||||
(cons "* "
|
(cons "* "
|
||||||
(map 'list
|
(map 'list
|
||||||
(lambda (item) ;; FIXME
|
(lambda (item) ;; FIXME
|
||||||
(let ((field (cdr (assoc (car item) mm/header-names)))
|
(let ((field (cdr (assoc (car item) mu4e-header-names)))
|
||||||
(width (cdr item)))
|
(width (cdr item)))
|
||||||
(concat
|
(concat
|
||||||
(propertize
|
(propertize
|
||||||
(if width
|
(if width
|
||||||
(truncate-string-to-width field width 0 ?\s t)
|
(truncate-string-to-width field width 0 ?\s t)
|
||||||
field)
|
field)
|
||||||
'face 'mm/title-face) " ")))
|
'face 'mu4e-title-face) " ")))
|
||||||
mm/headers-fields))))
|
mu4e-headers-fields))))
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defvar mm/msg-map nil
|
(defvar mu4e-msg-map nil
|
||||||
"*internal* A map (hashtable) which maps a database (Xapian)
|
"*internal* A map (hashtable) which maps a database (Xapian)
|
||||||
docid (which uniquely identifies a message to a marker. where
|
docid (which uniquely identifies a message to a marker. where
|
||||||
marker points to the buffer position for the message.
|
marker points to the buffer position for the message.
|
||||||
@ -380,71 +379,71 @@ Using this map, we can update message headers which are currently
|
|||||||
on the screen, when we receive (:update ) notices from the mu
|
on the screen, when we receive (:update ) notices from the mu
|
||||||
server.")
|
server.")
|
||||||
|
|
||||||
(defun mm/hdrs-add-header (str docid point)
|
(defun mu4e-hdrs-add-header (str docid point)
|
||||||
"Add header STR with DOCID to the buffer at POINT."
|
"Add header STR with DOCID to the buffer at POINT."
|
||||||
(unless docid (error "Invalid message"))
|
(unless docid (error "Invalid message"))
|
||||||
(when (buffer-live-p mm/hdrs-buffer)
|
(when (buffer-live-p mu4e-hdrs-buffer)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char point)
|
(goto-char point)
|
||||||
;; Update `mm/msg-map' with MSG, and MARKER pointing to the buffer
|
;; Update `mu4e-msg-map' with MSG, and MARKER pointing to the buffer
|
||||||
;; position for the message header."
|
;; position for the message header."
|
||||||
(insert (propertize (concat " " str "\n") 'docid docid))
|
(insert (propertize (concat " " str "\n") 'docid docid))
|
||||||
(puthash docid (copy-marker point t) mm/msg-map))))))
|
(puthash docid (copy-marker point t) mu4e-msg-map))))))
|
||||||
|
|
||||||
(defun mm/hdrs-remove-header (docid point)
|
(defun mu4e-hdrs-remove-header (docid point)
|
||||||
"Remove header with DOCID at POINT."
|
"Remove header with DOCID at POINT."
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(goto-char point)
|
(goto-char point)
|
||||||
;; sanity check
|
;; sanity check
|
||||||
(unless (eq docid (mm/hdrs-get-docid))
|
(unless (eq docid (mu4e-hdrs-get-docid))
|
||||||
(error "%d: Expected %d, but got %d"
|
(error "%d: Expected %d, but got %d"
|
||||||
(line-number-at-pos) docid (mm/hdrs-get-docid)))
|
(line-number-at-pos) docid (mu4e-hdrs-get-docid)))
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
;; (put-text-property (line-beginning-position line-beginning-positio 2)
|
;; (put-text-property (line-beginning-position line-beginning-positio 2)
|
||||||
;; 'invisible t))
|
;; 'invisible t))
|
||||||
(delete-region (line-beginning-position) (line-beginning-position 2)))
|
(delete-region (line-beginning-position) (line-beginning-position 2)))
|
||||||
(remhash docid mm/msg-map)))
|
(remhash docid mu4e-msg-map)))
|
||||||
|
|
||||||
(defun mm/hdrs-mark-header (docid mark)
|
(defun mu4e-hdrs-mark-header (docid mark)
|
||||||
"(Visually) mark the header for DOCID with character MARK."
|
"(Visually) mark the header for DOCID with character MARK."
|
||||||
(let ((marker (gethash docid mm/msg-map)))
|
(let ((marker (gethash docid mu4e-msg-map)))
|
||||||
;; (unless marker (error "Unregistered message"))
|
;; (unless marker (error "Unregistered message"))
|
||||||
(when marker
|
(when marker
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((inhibit-read-only t) (pos (marker-position marker)))
|
(let ((inhibit-read-only t) (pos (marker-position marker)))
|
||||||
(goto-char pos)
|
(goto-char pos)
|
||||||
(delete-char 2)
|
(delete-char 2)
|
||||||
(insert (propertize mark 'face 'mm/hdrs-marks-face) " ")
|
(insert (propertize mark 'face 'mu4e-hdrs-marks-face) " ")
|
||||||
(put-text-property pos
|
(put-text-property pos
|
||||||
(line-beginning-position 2) 'docid docid)
|
(line-beginning-position 2) 'docid docid)
|
||||||
;; update the msg-map, ie., move it back to the start of the line
|
;; update the msg-map, ie., move it back to the start of the line
|
||||||
(puthash docid
|
(puthash docid
|
||||||
(copy-marker (line-beginning-position) t)
|
(copy-marker (line-beginning-position) t)
|
||||||
mm/msg-map)))))))
|
mu4e-msg-map)))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-get-docid (&optional point)
|
(defun mu4e-hdrs-get-docid (&optional point)
|
||||||
"Get the docid for the message at POINT, if provided, or (point), otherwise."
|
"Get the docid for the message at POINT, if provided, or (point), otherwise."
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(get-text-property (if point point (point)) 'docid)))
|
(get-text-property (if point point (point)) 'docid)))
|
||||||
|
|
||||||
(defun mm/dump-msg-map ()
|
(defun mu4e-dump-msg-map ()
|
||||||
"*internal* dump the message map (for debugging)."
|
"*internal* dump the message map (for debugging)."
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(message "msg-map (%d)" (hash-table-count mm/msg-map))
|
(message "msg-map (%d)" (hash-table-count mu4e-msg-map))
|
||||||
(maphash
|
(maphash
|
||||||
(lambda (k v)
|
(lambda (k v)
|
||||||
(message "%s => %s" k v))
|
(message "%s => %s" k v))
|
||||||
mm/msg-map)))
|
mu4e-msg-map)))
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; threadinfo-map ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; threadinfo-map ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defvar mm/thread-info-map nil
|
(defvar mu4e-thread-info-map nil
|
||||||
"Map (hash) of docid->threadinfo; when filling the list of
|
"Map (hash) of docid->threadinfo; when filling the list of
|
||||||
messages, we fill a map of thread info, such that when a header
|
messages, we fill a map of thread info, such that when a header
|
||||||
changes (e.g., it's read-flag gets set) through some (:update
|
changes (e.g., it's read-flag gets set) through some (:update
|
||||||
@ -456,7 +455,7 @@ server.")
|
|||||||
|
|
||||||
|
|
||||||
;;; marks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; marks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defvar mm/marks-map nil
|
(defvar mu4e-marks-map nil
|
||||||
"Map (hash) of docid->markinfo; when a message is marked, the
|
"Map (hash) of docid->markinfo; when a message is marked, the
|
||||||
information is added here.
|
information is added here.
|
||||||
|
|
||||||
@ -467,7 +466,7 @@ where
|
|||||||
MARK is the type of mark (move, trash, delete)
|
MARK is the type of mark (move, trash, delete)
|
||||||
TARGET (optional) is the target directory (for 'move')")
|
TARGET (optional) is the target directory (for 'move')")
|
||||||
|
|
||||||
(defun mm/hdrs-mark-message (mark &optional target)
|
(defun mu4e-hdrs-mark-message (mark &optional target)
|
||||||
"Mark (or unmark) message at point. MARK specifies the
|
"Mark (or unmark) message at point. MARK specifies the
|
||||||
mark-type. For `move'-marks there is also the TARGET argument,
|
mark-type. For `move'-marks there is also the TARGET argument,
|
||||||
which specifies to which maildir the message is to be moved.
|
which specifies to which maildir the message is to be moved.
|
||||||
@ -477,10 +476,10 @@ The following marks are available, and the corresponding props:
|
|||||||
MARK TARGET description
|
MARK TARGET description
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
`move' y move the message to some folder
|
`move' y move the message to some folder
|
||||||
`trash' n move the message to `mm/trash-folder'
|
`trash' n move the message to `mu4e-trash-folder'
|
||||||
`delete' n remove the message
|
`delete' n remove the message
|
||||||
`unmark' n unmark this message"
|
`unmark' n unmark this message"
|
||||||
(let* ((docid (mm/hdrs-get-docid))
|
(let* ((docid (mu4e-hdrs-get-docid))
|
||||||
(markkar
|
(markkar
|
||||||
(case mark ;; the visual mark
|
(case mark ;; the visual mark
|
||||||
('move "m")
|
('move "m")
|
||||||
@ -491,45 +490,45 @@ The following marks are available, and the corresponding props:
|
|||||||
(t (error "Invalid mark %S" mark)))))
|
(t (error "Invalid mark %S" mark)))))
|
||||||
(unless docid (error "No message on this line"))
|
(unless docid (error "No message on this line"))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(when (mm/hdrs-mark-header docid markkar))
|
(when (mu4e-hdrs-mark-header docid markkar))
|
||||||
;; update the hash -- remove everything current, and if add the new stuff,
|
;; update the hash -- remove everything current, and if add the new stuff,
|
||||||
;; unless we're unmarking
|
;; unless we're unmarking
|
||||||
(remhash docid mm/marks-map)
|
(remhash docid mu4e-marks-map)
|
||||||
;; remove possible overlays
|
;; remove possible overlays
|
||||||
(remove-overlays (line-beginning-position) (line-end-position))
|
(remove-overlays (line-beginning-position) (line-end-position))
|
||||||
|
|
||||||
;; now, let's set a mark (unless we were unmarking)
|
;; now, let's set a mark (unless we were unmarking)
|
||||||
(unless (eql mark 'unmark)
|
(unless (eql mark 'unmark)
|
||||||
(puthash docid (list (point-marker) mark target) mm/marks-map)
|
(puthash docid (list (point-marker) mark target) mu4e-marks-map)
|
||||||
;; when we have a target (ie., when moving), show the target folder in
|
;; when we have a target (ie., when moving), show the target folder in
|
||||||
;; an overlay
|
;; an overlay
|
||||||
(when target
|
(when target
|
||||||
(let* ((targetstr (propertize (concat "-> " target " ")
|
(let* ((targetstr (propertize (concat "-> " target " ")
|
||||||
'face 'mm/system-face))
|
'face 'mu4e-system-face))
|
||||||
(start (+ 2 (line-beginning-position))) ;; +2 for the marker fringe
|
(start (+ 2 (line-beginning-position))) ;; +2 for the marker fringe
|
||||||
(overlay (make-overlay start (+ start (length targetstr)))))
|
(overlay (make-overlay start (+ start (length targetstr)))))
|
||||||
(overlay-put overlay 'display targetstr)))))))
|
(overlay-put overlay 'display targetstr)))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-mark (mark &optional target)
|
(defun mu4e-hdrs-mark (mark &optional target)
|
||||||
"Mark the header at point, or, if
|
"Mark the header at point, or, if
|
||||||
region is active, mark all headers in the region. Als see
|
region is active, mark all headers in the region. Als see
|
||||||
`mm/hdrs-mark-message'."
|
`mu4e-hdrs-mark-message'."
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(if (use-region-p)
|
(if (use-region-p)
|
||||||
;; mark all messages in the region.
|
;; mark all messages in the region.
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((b (region-beginning)) (e (region-end)))
|
(let ((b (region-beginning)) (e (region-end)))
|
||||||
(goto-char b)
|
(goto-char b)
|
||||||
(while (<= (line-beginning-position) e)
|
(while (<= (line-beginning-position) e)
|
||||||
(mm/hdrs-mark-message mark target)
|
(mu4e-hdrs-mark-message mark target)
|
||||||
(forward-line 1))))
|
(forward-line 1))))
|
||||||
;; just a single message
|
;; just a single message
|
||||||
(mm/hdrs-mark-message mark target))))
|
(mu4e-hdrs-mark-message mark target))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-marks-execute ()
|
(defun mu4e-hdrs-marks-execute ()
|
||||||
"Execute the actions for all marked messages in this
|
"Execute the actions for all marked messages in this
|
||||||
buffer. After the actions have been executed succesfully, the
|
buffer. After the actions have been executed succesfully, the
|
||||||
affected messages are *hidden* from the current header list. Since
|
affected messages are *hidden* from the current header list. Since
|
||||||
@ -539,47 +538,47 @@ certainty, we need to rerun the search, but we don't want to do
|
|||||||
that automatically, as it may be too slow and/or break the users
|
that automatically, as it may be too slow and/or break the users
|
||||||
flow. Therefore, we hide the message, which in practice seems to
|
flow. Therefore, we hide the message, which in practice seems to
|
||||||
work well."
|
work well."
|
||||||
(if (= 0 (hash-table-count mm/marks-map))
|
(if (= 0 (hash-table-count mu4e-marks-map))
|
||||||
(message "Nothing is marked")
|
(message "Nothing is marked")
|
||||||
(maphash
|
(maphash
|
||||||
(lambda (docid val)
|
(lambda (docid val)
|
||||||
(let ((marker (nth 0 val)) (mark (nth 1 val)) (target (nth 2 val)))
|
(let ((marker (nth 0 val)) (mark (nth 1 val)) (target (nth 2 val)))
|
||||||
(case mark
|
(case mark
|
||||||
(move
|
(move
|
||||||
(mm/proc-move-msg docid target))
|
(mu4e-proc-move-msg docid target))
|
||||||
(trash
|
(trash
|
||||||
(unless mm/trash-folder
|
(unless mu4e-trash-folder
|
||||||
(error "`mm/trash-folder' not set"))
|
(error "`mu4e-trash-folder' not set"))
|
||||||
(mm/proc-move-msg docid mm/trash-folder "+T"))
|
(mu4e-proc-move-msg docid mu4e-trash-folder "+T"))
|
||||||
(delete
|
(delete
|
||||||
(mm/proc-remove-msg docid)))))
|
(mu4e-proc-remove-msg docid)))))
|
||||||
mm/marks-map)
|
mu4e-marks-map)
|
||||||
(mm/hdrs-unmark-all)))
|
(mu4e-hdrs-unmark-all)))
|
||||||
|
|
||||||
(defun mm/hdrs-unmark-all ()
|
(defun mu4e-hdrs-unmark-all ()
|
||||||
"Unmark all marked messages."
|
"Unmark all marked messages."
|
||||||
(unless (/= 0 (hash-table-count mm/marks-map))
|
(unless (/= 0 (hash-table-count mu4e-marks-map))
|
||||||
(error "Nothing is marked"))
|
(error "Nothing is marked"))
|
||||||
(maphash
|
(maphash
|
||||||
(lambda (docid val)
|
(lambda (docid val)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (marker-position (nth 0 val)))
|
(goto-char (marker-position (nth 0 val)))
|
||||||
(mm/hdrs-mark 'unmark)))
|
(mu4e-hdrs-mark 'unmark)))
|
||||||
mm/marks-map))
|
mu4e-marks-map))
|
||||||
|
|
||||||
(defun mm/hdrs-view ()
|
(defun mu4e-hdrs-view ()
|
||||||
"View message at point."
|
"View message at point."
|
||||||
(let ((docid (mm/hdrs-get-docid)))
|
(let ((docid (mu4e-hdrs-get-docid)))
|
||||||
(unless docid (error "No message at point."))
|
(unless docid (error "No message at point."))
|
||||||
(mm/proc-view-msg docid)))
|
(mu4e-proc-view-msg docid)))
|
||||||
|
|
||||||
(defun mm/hdrs-compose (compose-type)
|
(defun mu4e-hdrs-compose (compose-type)
|
||||||
"Compose either a reply/forward based on the message at point. or
|
"Compose either a reply/forward based on the message at point. or
|
||||||
start editing it. COMPOSE-TYPE is either `reply', `forward' or
|
start editing it. COMPOSE-TYPE is either `reply', `forward' or
|
||||||
`edit'."
|
`edit'."
|
||||||
(if (eq compose-type 'new)
|
(if (eq compose-type 'new)
|
||||||
(mm/send-compose-handler 'new)
|
(mu4e-send-compose-handler 'new)
|
||||||
(let ((docid (mm/hdrs-get-docid))
|
(let ((docid (mu4e-hdrs-get-docid))
|
||||||
;; note, the first two chars of the line (the mark margin) does *not*
|
;; note, the first two chars of the line (the mark margin) does *not*
|
||||||
;; have the 'draft property; thus, we check one char before the end of
|
;; have the 'draft property; thus, we check one char before the end of
|
||||||
;; the current line instead
|
;; the current line instead
|
||||||
@ -588,17 +587,17 @@ start editing it. COMPOSE-TYPE is either `reply', `forward' or
|
|||||||
(error "No message at point."))
|
(error "No message at point."))
|
||||||
(cond
|
(cond
|
||||||
((member compose-type '(reply forward))
|
((member compose-type '(reply forward))
|
||||||
(mm/proc-compose compose-type docid))
|
(mu4e-proc-compose compose-type docid))
|
||||||
((eq compose-type 'edit)
|
((eq compose-type 'edit)
|
||||||
(unless is-draft
|
(unless is-draft
|
||||||
(error "Cannot edit a non-draft message"))
|
(error "Cannot edit a non-draft message"))
|
||||||
(mm/proc-compose 'edit docid))
|
(mu4e-proc-compose 'edit docid))
|
||||||
(t (error "invalid compose type %S" compose-type))))))
|
(t (error "invalid compose type %S" compose-type))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/hdrs-docid-is-marked (docid)
|
(defun mu4e-hdrs-docid-is-marked (docid)
|
||||||
"Is the given docid marked?"
|
"Is the given docid marked?"
|
||||||
(when (gethash docid mm/marks-map) t))
|
(when (gethash docid mu4e-marks-map) t))
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|
||||||
@ -606,174 +605,174 @@ start editing it. COMPOSE-TYPE is either `reply', `forward' or
|
|||||||
|
|
||||||
|
|
||||||
;;; interactive functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; interactive functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defun mm/ignore-marks ()
|
(defun mu4e-ignore-marks ()
|
||||||
(let*
|
(let*
|
||||||
((num
|
((num
|
||||||
(hash-table-count mm/marks-map))
|
(hash-table-count mu4e-marks-map))
|
||||||
(unmark (or (= 0 num)
|
(unmark (or (= 0 num)
|
||||||
(y-or-n-p
|
(y-or-n-p
|
||||||
(format "Sure you want to unmark %d message(s)?" num)))))
|
(format "Sure you want to unmark %d message(s)?" num)))))
|
||||||
(message nil)
|
(message nil)
|
||||||
unmark))
|
unmark))
|
||||||
|
|
||||||
(defun mm/search (expr)
|
(defun mu4e-search (expr)
|
||||||
"Start a new mu search, limited to `mm/search-results-limit'
|
"Start a new mu search, limited to `mu4e-search-results-limit'
|
||||||
results."
|
results."
|
||||||
(interactive "s[mu] search for: ")
|
(interactive "s[mu] search for: ")
|
||||||
(when (mm/ignore-marks) (mm/hdrs-search expr)))
|
(when (mu4e-ignore-marks) (mu4e-hdrs-search expr)))
|
||||||
|
|
||||||
(defun mm/search-full (expr)
|
(defun mu4e-search-full (expr)
|
||||||
"Start a new mu search; resturn *all* results."
|
"Start a new mu search; resturn *all* results."
|
||||||
(interactive "s[mu] full search for: ")
|
(interactive "s[mu] full search for: ")
|
||||||
(when (mm/ignore-marks)
|
(when (mu4e-ignore-marks)
|
||||||
(mm/hdrs-search expr t)))
|
(mu4e-hdrs-search expr t)))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/search-bookmark ()
|
(defun mu4e-search-bookmark ()
|
||||||
"Search using some bookmarked query."
|
"Search using some bookmarked query."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((query (mm/ask-bookmark "Bookmark: ")))
|
(let ((query (mu4e-ask-bookmark "Bookmark: ")))
|
||||||
(when query
|
(when query
|
||||||
(mm/hdrs-search query))))
|
(mu4e-hdrs-search query))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/quit-buffer ()
|
(defun mu4e-quit-buffer ()
|
||||||
"Quit the current buffer."
|
"Quit the current buffer."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/ignore-marks)
|
(when (mu4e-ignore-marks)
|
||||||
(mm/kill-proc) ;; hmmm...
|
(mu4e-kill-proc) ;; hmmm...
|
||||||
(kill-buffer)
|
(kill-buffer)
|
||||||
(mm)))
|
(mm)))
|
||||||
|
|
||||||
(defun mm/rerun-search ()
|
(defun mu4e-rerun-search ()
|
||||||
"Rerun the search for the last search expression; if none exists,
|
"Rerun the search for the last search expression; if none exists,
|
||||||
do a new search."
|
do a new search."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/ignore-marks)
|
(when (mu4e-ignore-marks)
|
||||||
(if mm/last-expr
|
(if mu4e-last-expr
|
||||||
(mm/hdrs-search mm/last-expr)
|
(mu4e-hdrs-search mu4e-last-expr)
|
||||||
(mm/search))))
|
(mu4e-search))))
|
||||||
|
|
||||||
(defun mm/view-message ()
|
(defun mu4e-view-message ()
|
||||||
"View the message at point."
|
"View the message at point."
|
||||||
(interactive)
|
(interactive)
|
||||||
(mm/hdrs-view))
|
(mu4e-hdrs-view))
|
||||||
|
|
||||||
(defun mm/next-header ()
|
(defun mu4e-next-header ()
|
||||||
"Move point to the next message header. If this succeeds, return
|
"Move point to the next message header. If this succeeds, return
|
||||||
the new docid. Otherwise, return nil."
|
the new docid. Otherwise, return nil."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(when (= 0 (forward-line 1))
|
(when (= 0 (forward-line 1))
|
||||||
(or (mm/hdrs-get-docid) (mm/next-header)) ;; skip non-headers
|
(or (mu4e-hdrs-get-docid) (mu4e-next-header)) ;; skip non-headers
|
||||||
;; trick to move point, even if this function is called when this window
|
;; trick to move point, even if this function is called when this window
|
||||||
;; is not visible
|
;; is not visible
|
||||||
(set-window-point (get-buffer-window mm/hdrs-buffer) (point)))))
|
(set-window-point (get-buffer-window mu4e-hdrs-buffer) (point)))))
|
||||||
|
|
||||||
(defun mm/prev-header ()
|
(defun mu4e-prev-header ()
|
||||||
"Move point to the previous message header. If this succeeds,
|
"Move point to the previous message header. If this succeeds,
|
||||||
return the new docid. Otherwise, return nil."
|
return the new docid. Otherwise, return nil."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(when (= 0 (forward-line -1))
|
(when (= 0 (forward-line -1))
|
||||||
(or (mm/hdrs-get-docid) (mm/prev-header)) ;; skip non-headers
|
(or (mu4e-hdrs-get-docid) (mu4e-prev-header)) ;; skip non-headers
|
||||||
;; trick to move point, even if this function is called when this window
|
;; trick to move point, even if this function is called when this window
|
||||||
;; is not visible
|
;; is not visible
|
||||||
(set-window-point (get-buffer-window mm/hdrs-buffer) (point)))))
|
(set-window-point (get-buffer-window mu4e-hdrs-buffer) (point)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/jump-to-maildir ()
|
(defun mu4e-jump-to-maildir ()
|
||||||
"Show the messages in maildir TARGET. If TARGET is not provided,
|
"Show the messages in maildir TARGET. If TARGET is not provided,
|
||||||
ask user for it."
|
ask user for it."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((fld (mm/ask-maildir "Jump to maildir: ")))
|
(let ((fld (mu4e-ask-maildir "Jump to maildir: ")))
|
||||||
(when fld
|
(when fld
|
||||||
(mm/hdrs-search (concat "maildir:" fld)))))
|
(mu4e-hdrs-search (concat "maildir:" fld)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/mark-for-move (&optional target)
|
(defun mu4e-mark-for-move (&optional target)
|
||||||
"Mark message at point for moving to maildir TARGET. If target is
|
"Mark message at point for moving to maildir TARGET. If target is
|
||||||
not provided, function asks for it."
|
not provided, function asks for it."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(let* ((target (or target (mm/ask-maildir "Move message to: ")))
|
(let* ((target (or target (mu4e-ask-maildir "Move message to: ")))
|
||||||
(fulltarget (concat mm/maildir target)))
|
(fulltarget (concat mu4e-maildir target)))
|
||||||
(when (or (file-directory-p fulltarget)
|
(when (or (file-directory-p fulltarget)
|
||||||
(and (yes-or-no-p
|
(and (yes-or-no-p
|
||||||
(format "%s does not exist. Create now?" fulltarget))
|
(format "%s does not exist. Create now?" fulltarget))
|
||||||
(mm/proc-mkdir fulltarget)))
|
(mu4e-proc-mkdir fulltarget)))
|
||||||
(mm/hdrs-mark 'move target)
|
(mu4e-hdrs-mark 'move target)
|
||||||
(mm/next-header)))))
|
(mu4e-next-header)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/mark-for-trash ()
|
(defun mu4e-mark-for-trash ()
|
||||||
"Mark message at point for moving to the trash
|
"Mark message at point for moving to the trash
|
||||||
folder (`mm/trash-folder')."
|
folder (`mu4e-trash-folder')."
|
||||||
(interactive)
|
(interactive)
|
||||||
(unless mm/trash-folder
|
(unless mu4e-trash-folder
|
||||||
(error "`mm/trash-folder' is not set"))
|
(error "`mu4e-trash-folder' is not set"))
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(mm/hdrs-mark 'trash)
|
(mu4e-hdrs-mark 'trash)
|
||||||
(mm/next-header)))
|
(mu4e-next-header)))
|
||||||
|
|
||||||
(defun mm/mark-for-delete ()
|
(defun mu4e-mark-for-delete ()
|
||||||
"Mark message at point for direct deletion."
|
"Mark message at point for direct deletion."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(mm/hdrs-mark 'delete)
|
(mu4e-hdrs-mark 'delete)
|
||||||
(mm/next-header)))
|
(mu4e-next-header)))
|
||||||
|
|
||||||
(defun mm/unmark ()
|
(defun mu4e-unmark ()
|
||||||
"Unmark message at point."
|
"Unmark message at point."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(mm/hdrs-mark 'unmark)
|
(mu4e-hdrs-mark 'unmark)
|
||||||
(mm/next-header)))
|
(mu4e-next-header)))
|
||||||
|
|
||||||
(defun mm/unmark-all ()
|
(defun mu4e-unmark-all ()
|
||||||
"Unmark all messages."
|
"Unmark all messages."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(if (= 0 (hash-table-count mm/marks-map))
|
(if (= 0 (hash-table-count mu4e-marks-map))
|
||||||
(message "Nothing is marked")
|
(message "Nothing is marked")
|
||||||
(when (mm/ignore-marks)
|
(when (mu4e-ignore-marks)
|
||||||
(mm/hdrs-unmark-all)))))
|
(mu4e-hdrs-unmark-all)))))
|
||||||
|
|
||||||
(defun mm/execute-marks ()
|
(defun mu4e-execute-marks ()
|
||||||
"Execute the actions for the marked messages."
|
"Execute the actions for the marked messages."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(if (= 0 (hash-table-count mm/marks-map))
|
(if (= 0 (hash-table-count mu4e-marks-map))
|
||||||
(message "Nothing is marked")
|
(message "Nothing is marked")
|
||||||
(when (y-or-n-p (format "Sure you want to execute marks on %d message(s)?"
|
(when (y-or-n-p (format "Sure you want to execute marks on %d message(s)?"
|
||||||
(hash-table-count mm/marks-map)))
|
(hash-table-count mu4e-marks-map)))
|
||||||
(mm/hdrs-marks-execute)
|
(mu4e-hdrs-marks-execute)
|
||||||
(message nil)))))
|
(message nil)))))
|
||||||
|
|
||||||
(defun mm/compose-reply ()
|
(defun mu4e-compose-reply ()
|
||||||
"Start composing a reply to the current message."
|
"Start composing a reply to the current message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(mm/hdrs-compose 'reply)))
|
(mu4e-hdrs-compose 'reply)))
|
||||||
|
|
||||||
(defun mm/compose-forward ()
|
(defun mu4e-compose-forward ()
|
||||||
"Start composing a forward to the current message."
|
"Start composing a forward to the current message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(mm/hdrs-compose 'forward)))
|
(mu4e-hdrs-compose 'forward)))
|
||||||
|
|
||||||
(defun mm/compose-new ()
|
(defun mu4e-compose-new ()
|
||||||
"Compose a new, empty message."
|
"Compose a new, empty message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(mm/hdrs-compose 'new))
|
(mu4e-hdrs-compose 'new))
|
||||||
|
|
||||||
(defun mm/edit-draft ()
|
(defun mu4e-edit-draft ()
|
||||||
"Start editing the existing draft message at point."
|
"Start editing the existing draft message at point."
|
||||||
(interactive)
|
(interactive)
|
||||||
(with-current-buffer mm/hdrs-buffer
|
(with-current-buffer mu4e-hdrs-buffer
|
||||||
(mm/hdrs-compose 'edit)))
|
(mu4e-hdrs-compose 'edit)))
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(provide 'mm-hdrs)
|
(provide 'mu4e-hdrs)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
;;; mm-main.el -- part of mm, the mu mail user agent
|
;;; mu4e-main.el -- part of mm, the mu mail user agent
|
||||||
;;
|
;;
|
||||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||||
|
|
||||||
@ -29,85 +29,85 @@
|
|||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; mm main view mode + keybindings
|
;; mm main view mode + keybindings
|
||||||
(defconst mm/main-buffer-name "*mm*"
|
(defconst mu4e-main-buffer-name "*mu4e-main*"
|
||||||
"*internal* Name of the mm main view buffer.")
|
"*internal* Name of the mm main buffer.")
|
||||||
|
|
||||||
(defvar mm/mm-mode-map
|
(defvar mu4e-main-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
|
|
||||||
(define-key map "b" 'mm/search-bookmark)
|
(define-key map "b" 'mu4e-search-bookmark)
|
||||||
(define-key map "s" 'mm/search)
|
(define-key map "s" 'mu4e-search)
|
||||||
(define-key map "S" 'mm/search-full)
|
(define-key map "S" 'mu4e-search-full)
|
||||||
(define-key map "q" 'mm/quit-mm)
|
(define-key map "q" 'mu4e-quit-mm)
|
||||||
(define-key map "j" 'mm/jump-to-maildir)
|
(define-key map "j" 'mu4e-jump-to-maildir)
|
||||||
(define-key map "c" 'mm/compose-new)
|
(define-key map "c" 'mu4e-compose-new)
|
||||||
|
|
||||||
(define-key map "m" 'mm/toggle-mail-sending-mode)
|
(define-key map "m" 'mu4e-toggle-mail-sending-mode)
|
||||||
(define-key map "f" 'smtpmail-send-queued-mail)
|
(define-key map "f" 'smtpmail-send-queued-mail)
|
||||||
(define-key map "u" 'mm/retrieve-mail-update-db)
|
(define-key map "u" 'mu4e-retrieve-mail-update-db)
|
||||||
|
|
||||||
map)
|
map)
|
||||||
"Keymap for the *mm* buffer.")
|
"Keymap for the *mm* buffer.")
|
||||||
(fset 'mm/mm-mode-map mm/mm-mode-map)
|
(fset 'mu4e-main-mode-map mu4e-main-mode-map)
|
||||||
|
|
||||||
(defun mm/mm-mode ()
|
(defun mu4e-main-mode ()
|
||||||
"Major mode for the mm main screen."
|
"Major mode for the mm main screen."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
|
||||||
(kill-all-local-variables)
|
(kill-all-local-variables)
|
||||||
(use-local-map mm/mm-mode-map)
|
(use-local-map mu4e-main-mode-map)
|
||||||
|
|
||||||
(setq
|
(setq
|
||||||
mm/marks-map (make-hash-table :size 16 :rehash-size 2)
|
mu4e-marks-map (make-hash-table :size 16 :rehash-size 2)
|
||||||
major-mode 'mm/mm-mode
|
major-mode 'mu4e-main-mode
|
||||||
mode-name "mm: main view"
|
mode-name "mu for emacs"
|
||||||
truncate-lines t
|
truncate-lines t
|
||||||
buffer-read-only t
|
buffer-read-only t
|
||||||
overwrite-mode 'overwrite-mode-binary))
|
overwrite-mode 'overwrite-mode-binary))
|
||||||
|
|
||||||
(defun mm/action-str (str)
|
(defun mu4e-action-str (str)
|
||||||
"Highlight the first occurence of [..] in STR."
|
"Highlight the first occurence of [..] in STR."
|
||||||
(if (string-match "\\[\\(\\w+\\)\\]" str)
|
(if (string-match "\\[\\(\\w+\\)\\]" str)
|
||||||
(let* ((key (match-string 1 str))
|
(let* ((key (match-string 1 str))
|
||||||
(keystr (propertize key 'face 'mm/highlight-face)))
|
(keystr (propertize key 'face 'mu4e-highlight-face)))
|
||||||
(replace-match keystr nil t str 1))
|
(replace-match keystr nil t str 1))
|
||||||
str))
|
str))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/main-view()
|
(defun mu4e-main-view()
|
||||||
"Show the mm main view."
|
"Show the mm main view."
|
||||||
(let ((buf (get-buffer-create mm/main-buffer-name))
|
(let ((buf (get-buffer-create mu4e-main-buffer-name))
|
||||||
(inhibit-read-only t))
|
(inhibit-read-only t))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert
|
(insert
|
||||||
"* "
|
"* "
|
||||||
(propertize "mm - mu mail for emacs version " 'face 'mm/title-face)
|
(propertize "mu4e - mu for emacs version " 'face 'mu4e-title-face)
|
||||||
(propertize mm/mu-version 'face 'mm/view-header-key-face)
|
(propertize mu4e-mu-version 'face 'mu4e-view-header-key-face)
|
||||||
"\n\n"
|
"\n\n"
|
||||||
(propertize " Basics\n\n" 'face 'mm/title-face)
|
(propertize " Basics\n\n" 'face 'mu4e-title-face)
|
||||||
(mm/action-str "\t* [j]ump to some maildir\n")
|
(mu4e-action-str "\t* [j]ump to some maildir\n")
|
||||||
(mm/action-str "\t* enter a [s]earch query\n")
|
(mu4e-action-str "\t* enter a [s]earch query\n")
|
||||||
(mm/action-str "\t* [c]ompose a new message\n")
|
(mu4e-action-str "\t* [c]ompose a new message\n")
|
||||||
"\n"
|
"\n"
|
||||||
(propertize " Bookmarks\n\n" 'face 'mm/title-face)
|
(propertize " Bookmarks\n\n" 'face 'mu4e-title-face)
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (bm)
|
(lambda (bm)
|
||||||
(let* ((query (nth 0 bm)) (title (nth 1 bm)) (key (nth 2 bm)))
|
(let* ((query (nth 0 bm)) (title (nth 1 bm)) (key (nth 2 bm)))
|
||||||
(mm/action-str
|
(mu4e-action-str
|
||||||
(concat "\t* [b" (make-string 1 key) "] " title))))
|
(concat "\t* [b" (make-string 1 key) "] " title))))
|
||||||
mm/bookmarks "\n")
|
mu4e-bookmarks "\n")
|
||||||
|
|
||||||
"\n"
|
"\n"
|
||||||
(propertize " Misc\n\n" 'face 'mm/title-face)
|
(propertize " Misc\n\n" 'face 'mu4e-title-face)
|
||||||
(mm/action-str "\t* [u]pdate email & database\n")
|
(mu4e-action-str "\t* [u]pdate email & database\n")
|
||||||
(mm/action-str "\t* toggle [m]ail sending mode ")
|
(mu4e-action-str "\t* toggle [m]ail sending mode ")
|
||||||
"(" (propertize (if smtpmail-queue-mail "queued" "direct")
|
"(" (propertize (if smtpmail-queue-mail "queued" "direct")
|
||||||
'face 'mm/view-header-key-face) ")\n"
|
'face 'mu4e-view-header-key-face) ")\n"
|
||||||
(mm/action-str "\t* [f]lush queued mail\n")
|
(mu4e-action-str "\t* [f]lush queued mail\n")
|
||||||
"\n"
|
"\n"
|
||||||
(mm/action-str "\t* [q]uit mm\n"))
|
(mu4e-action-str "\t* [q]uit mm\n"))
|
||||||
(mm/mm-mode)
|
(mu4e-main-mode)
|
||||||
(switch-to-buffer buf))))
|
(switch-to-buffer buf))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -115,12 +115,12 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Interactive functions
|
;; Interactive functions
|
||||||
|
|
||||||
(defun mm/retrieve-mail-update-db ()
|
(defun mu4e-retrieve-mail-update-db ()
|
||||||
"Get new mail and update the database."
|
"Get new mail and update the database."
|
||||||
(interactive)
|
(interactive)
|
||||||
(mm/proc-retrieve-mail-update-db))
|
(mu4e-proc-retrieve-mail-update-db))
|
||||||
|
|
||||||
(defun mm/toggle-mail-sending-mode ()
|
(defun mu4e-toggle-mail-sending-mode ()
|
||||||
"Toggle sending mail mode, either queued or direct."
|
"Toggle sending mail mode, either queued or direct."
|
||||||
(interactive)
|
(interactive)
|
||||||
(setq smtpmail-queue-mail (not smtpmail-queue-mail))
|
(setq smtpmail-queue-mail (not smtpmail-queue-mail))
|
||||||
@ -131,12 +131,12 @@
|
|||||||
(mm))
|
(mm))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/quit-mm()
|
(defun mu4e-quit-mm()
|
||||||
"Quit the mm session."
|
"Quit the mm session."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (y-or-n-p "Are you sure you want to quit mm? ")
|
(when (y-or-n-p "Are you sure you want to quit mm? ")
|
||||||
(message nil)
|
(message nil)
|
||||||
(mm/kill-proc)
|
(mu4e-kill-proc)
|
||||||
(kill-buffer)))
|
(kill-buffer)))
|
||||||
|
|
||||||
(provide 'mm-main)
|
(provide 'mu4e-main)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
;;; mm-proc.el -- part of mm, the mu mail user agent
|
;;; mu4e-proc.el -- part of mm, the mu mail user agent
|
||||||
;;
|
;;
|
||||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||||
|
|
||||||
@ -30,65 +30,65 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; internal vars
|
;; internal vars
|
||||||
|
|
||||||
(defvar mm/mu-proc nil
|
(defvar mu4e-mu-proc nil
|
||||||
"*internal* The mu-server process")
|
"*internal* The mu-server process")
|
||||||
|
|
||||||
(defvar mm/proc-error-func 'mm/default-handler
|
(defvar mu4e-proc-error-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each error returned from the
|
"*internal* A function called for each error returned from the
|
||||||
server process; the function is passed an error plist as
|
server process; the function is passed an error plist as
|
||||||
argument. See `mm/proc-filter' for the format.")
|
argument. See `mu4e-proc-filter' for the format.")
|
||||||
|
|
||||||
(defvar mm/proc-update-func 'mm/default-handler
|
(defvar mu4e-proc-update-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each :update sexp returned from
|
"*internal* A function called for each :update sexp returned from
|
||||||
the server process; the function is passed a msg sexp as
|
the server process; the function is passed a msg sexp as
|
||||||
argument. See `mm/proc-filter' for the format.")
|
argument. See `mu4e-proc-filter' for the format.")
|
||||||
|
|
||||||
(defvar mm/proc-remove-func 'mm/default-handler
|
(defvar mu4e-proc-remove-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each :remove sexp returned from
|
"*internal* A function called for each :remove sexp returned from
|
||||||
the server process, when some message has been deleted. The
|
the server process, when some message has been deleted. The
|
||||||
function is passed the docid of the removed message.")
|
function is passed the docid of the removed message.")
|
||||||
|
|
||||||
(defvar mm/proc-view-func 'mm/default-handler
|
(defvar mu4e-proc-view-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each single message sexp
|
"*internal* A function called for each single message sexp
|
||||||
returned from the server process. The function is passed a message
|
returned from the server process. The function is passed a message
|
||||||
sexp as argument. See `mm/proc-filter' for the
|
sexp as argument. See `mu4e-proc-filter' for the
|
||||||
format.")
|
format.")
|
||||||
|
|
||||||
(defvar mm/proc-header-func 'mm/default-handler
|
(defvar mu4e-proc-header-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each message returned from the
|
"*internal* A function called for each message returned from the
|
||||||
server process; the function is passed a msg plist as argument. See
|
server process; the function is passed a msg plist as argument. See
|
||||||
`mm/proc-filter' for the format.")
|
`mu4e-proc-filter' for the format.")
|
||||||
|
|
||||||
(defvar mm/proc-found-func 'mm/default-handler
|
(defvar mu4e-proc-found-func 'mu4e-default-handler
|
||||||
"*internal* A function called for when we received a :found sexp
|
"*internal* A function called for when we received a :found sexp
|
||||||
after the headers have returns, to report on the number of
|
after the headers have returns, to report on the number of
|
||||||
matches. See `mm/proc-filter' for the format.")
|
matches. See `mu4e-proc-filter' for the format.")
|
||||||
|
|
||||||
(defvar mm/proc-compose-func 'mm/default-handler
|
(defvar mu4e-proc-compose-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each message returned from the
|
"*internal* A function called for each message returned from the
|
||||||
server process that is used as basis for composing a new
|
server process that is used as basis for composing a new
|
||||||
message (ie., either a reply or a forward); the function is passed
|
message (ie., either a reply or a forward); the function is passed
|
||||||
msg and a symbol (either reply or forward). See `mm/proc-filter'
|
msg and a symbol (either reply or forward). See `mu4e-proc-filter'
|
||||||
for the format of <msg-plist>.")
|
for the format of <msg-plist>.")
|
||||||
|
|
||||||
(defvar mm/proc-info-func 'mm/default-handler
|
(defvar mu4e-proc-info-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each (:info type ....) sexp
|
"*internal* A function called for each (:info type ....) sexp
|
||||||
received from the server process.")
|
received from the server process.")
|
||||||
|
|
||||||
(defvar mm/proc-pong-func 'mm/default-handler
|
(defvar mu4e-proc-pong-func 'mu4e-default-handler
|
||||||
"*internal* A function called for each (:pong type ....) sexp
|
"*internal* A function called for each (:pong type ....) sexp
|
||||||
received from the server process.")
|
received from the server process.")
|
||||||
|
|
||||||
(defvar mm/buf nil
|
(defvar mu4e-buf nil
|
||||||
"*internal* Buffer for results data.")
|
"*internal* Buffer for results data.")
|
||||||
|
|
||||||
(defvar mm/path-docid-map
|
(defvar mu4e-path-docid-map
|
||||||
(make-hash-table :size 32 :rehash-size 2 :test 'equal :weakness nil)
|
(make-hash-table :size 32 :rehash-size 2 :test 'equal :weakness nil)
|
||||||
"*internal* hash we use to keep a path=>docid mapping for message
|
"*internal* hash we use to keep a path=>docid mapping for message
|
||||||
we added ourselves (ie., draft messages), so we can e.g. move them
|
we added ourselves (ie., draft messages), so we can e.g. move them
|
||||||
to the sent folder using their docid")
|
to the sent folder using their docid")
|
||||||
|
|
||||||
(defun mm/proc-info-handler (info)
|
(defun mu4e-proc-info-handler (info)
|
||||||
"Handler function for (:info ...) sexps received from the server
|
"Handler function for (:info ...) sexps received from the server
|
||||||
process."
|
process."
|
||||||
(let ((type (plist-get info :info)))
|
(let ((type (plist-get info :info)))
|
||||||
@ -97,12 +97,12 @@ process."
|
|||||||
((eq type 'add)
|
((eq type 'add)
|
||||||
;; update our path=>docid map; we use this when composing messages to
|
;; update our path=>docid map; we use this when composing messages to
|
||||||
;; add draft messages to the db, so when we're sending them, we can move
|
;; add draft messages to the db, so when we're sending them, we can move
|
||||||
;; to the sent folder using the `mm/proc-move'.
|
;; to the sent folder using the `mu4e-proc-move'.
|
||||||
(puthash (plist-get info :path) (plist-get info :docid) mm/path-docid-map))
|
(puthash (plist-get info :path) (plist-get info :docid) mu4e-path-docid-map))
|
||||||
((eq type 'version)
|
((eq type 'version)
|
||||||
(setq
|
(setq
|
||||||
mm/version (plist-get info :version)
|
mu4e-version (plist-get info :version)
|
||||||
mm/doccount (plist-get-info :doccount)))
|
mu4e-doccount (plist-get-info :doccount)))
|
||||||
((eq type 'index)
|
((eq type 'index)
|
||||||
(if (eq (plist-get info :status) 'running)
|
(if (eq (plist-get info :status) 'running)
|
||||||
(message (format "Indexing... processed %d, updated %d"
|
(message (format "Indexing... processed %d, updated %d"
|
||||||
@ -114,78 +114,79 @@ process."
|
|||||||
((plist-get info :message) (message "%s" (plist-get info :message))))))
|
((plist-get info :message) (message "%s" (plist-get info :message))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/default-handler (&rest args)
|
(defun mu4e-default-handler (&rest args)
|
||||||
"Dummy handler function."
|
"Dummy handler function."
|
||||||
(error "Not handled: %S" args))
|
(error "Not handled: %S" args))
|
||||||
|
|
||||||
(defconst mm/server-name "*mm-server"
|
(defconst mu4e-server-name "*mu4e-server"
|
||||||
"*internal* Name of the server process, buffer.")
|
"*internal* Name of the server process, buffer.")
|
||||||
|
|
||||||
(defun mm/start-proc ()
|
(defun mu4e-start-proc ()
|
||||||
"Start the mu server process."
|
"Start the mu server process."
|
||||||
;; TODO: add version check
|
;; TODO: add version check
|
||||||
(unless (file-executable-p mm/mu-binary)
|
(unless (file-executable-p mu4e-mu-binary)
|
||||||
(error (format "%S not found" mm/mu-binary)))
|
(error (format "%S not found" mu4e-mu-binary)))
|
||||||
(let* ((process-connection-type nil) ;; use a pipe
|
(let* ((process-connection-type nil) ;; use a pipe
|
||||||
(args '("server"))
|
(args '("server"))
|
||||||
(args (append args (when mm/mu-home
|
(args (append args (when mu4e-mu-home
|
||||||
(list (concat "--muhome=" mm/mu-home))))))
|
(list (concat "--muhome=" mu4e-mu-home))))))
|
||||||
(setq mm/buf "")
|
(setq mu4e-buf "")
|
||||||
(setq mm/mu-proc (apply 'start-process mm/server-name mm/server-name
|
(setq mu4e-mu-proc (apply 'start-process
|
||||||
mm/mu-binary args))
|
mu4e-server-name mu4e-server-name
|
||||||
|
mu4e-mu-binary args))
|
||||||
;; register a function for (:info ...) sexps
|
;; register a function for (:info ...) sexps
|
||||||
(setq mm/proc-info-func 'mm/proc-info-handler)
|
(setq mu4e-proc-info-func 'mu4e-proc-info-handler)
|
||||||
(when mm/mu-proc
|
(when mu4e-mu-proc
|
||||||
(set-process-coding-system mm/mu-proc 'binary 'utf-8-unix)
|
(set-process-coding-system mu4e-mu-proc 'binary 'utf-8-unix)
|
||||||
(set-process-filter mm/mu-proc 'mm/proc-filter)
|
(set-process-filter mu4e-mu-proc 'mu4e-proc-filter)
|
||||||
(set-process-sentinel mm/mu-proc 'mm/proc-sentinel))))
|
(set-process-sentinel mu4e-mu-proc 'mu4e-proc-sentinel))))
|
||||||
|
|
||||||
(defun mm/kill-proc ()
|
(defun mu4e-kill-proc ()
|
||||||
"Kill the mu server process."
|
"Kill the mu server process."
|
||||||
(let* ((buf (get-buffer mm/server-name))
|
(let* ((buf (get-buffer mu4e-server-name))
|
||||||
(proc (and buf (get-buffer-process buf))))
|
(proc (and buf (get-buffer-process buf))))
|
||||||
(when proc
|
(when proc
|
||||||
(let ((delete-exited-processes t))
|
(let ((delete-exited-processes t))
|
||||||
;; the mu server signal handler will make it quit after 'quit'
|
;; the mu server signal handler will make it quit after 'quit'
|
||||||
(mm/proc-send-command "quit"))
|
(mu4e-proc-send-command "quit"))
|
||||||
;; try sending SIGINT (C-c) to process, so it can exit gracefully
|
;; try sending SIGINT (C-c) to process, so it can exit gracefully
|
||||||
(ignore-errors
|
(ignore-errors
|
||||||
(signal-process proc 'SIGINT))))
|
(signal-process proc 'SIGINT))))
|
||||||
(setq
|
(setq
|
||||||
mm/mu-proc nil
|
mu4e-mu-proc nil
|
||||||
mm/buf nil))
|
mu4e-buf nil))
|
||||||
|
|
||||||
(defun mm/proc-is-running ()
|
(defun mu4e-proc-is-running ()
|
||||||
(and mm/mu-proc (eq (process-status mm/mu-proc) 'run)))
|
(and mu4e-mu-proc (eq (process-status mu4e-mu-proc) 'run)))
|
||||||
|
|
||||||
(defun mm/proc-eat-sexp-from-buf ()
|
(defun mu4e-proc-eat-sexp-from-buf ()
|
||||||
"'Eat' the next s-expression from `mm/buf'. `mm/buf gets its
|
"'Eat' the next s-expression from `mu4e-buf'. `mu4e-buf gets its
|
||||||
contents from the mu-servers in the following form:
|
contents from the mu-servers in the following form:
|
||||||
\376<len-of-sexp>\376<sexp>
|
\376<len-of-sexp>\376<sexp>
|
||||||
Function returns this sexp, or nil if there was none. `mm/buf' is
|
Function returns this sexp, or nil if there was none. `mu4e-buf' is
|
||||||
updated as well, with all processed sexp data removed."
|
updated as well, with all processed sexp data removed."
|
||||||
(when mm/buf
|
(when mu4e-buf
|
||||||
;; TODO: maybe try a non-regexp solution?
|
;; TODO: maybe try a non-regexp solution?
|
||||||
(let* ((b (string-match "\376\\([0-9]+\\)\376" mm/buf))
|
(let* ((b (string-match "\376\\([0-9]+\\)\376" mu4e-buf))
|
||||||
(sexp-len
|
(sexp-len
|
||||||
(when b (string-to-number (match-string 1 mm/buf)))))
|
(when b (string-to-number (match-string 1 mu4e-buf)))))
|
||||||
;; does mm/buf contain the full sexp?
|
;; does mu4e-buf contain the full sexp?
|
||||||
(when (and b (>= (length mm/buf) (+ sexp-len (match-end 0))))
|
(when (and b (>= (length mu4e-buf) (+ sexp-len (match-end 0))))
|
||||||
;; clear-up start
|
;; clear-up start
|
||||||
(setq mm/buf (substring mm/buf (match-end 0)))
|
(setq mu4e-buf (substring mu4e-buf (match-end 0)))
|
||||||
;; note: we read the input in binary mode -- here, we take the part that
|
;; note: we read the input in binary mode -- here, we take the part that
|
||||||
;; is the sexp, and convert that to utf-8, before we interpret it.
|
;; is the sexp, and convert that to utf-8, before we interpret it.
|
||||||
(let ((objcons
|
(let ((objcons
|
||||||
(ignore-errors ;; note: this may fail if we killed the process
|
(ignore-errors ;; note: this may fail if we killed the process
|
||||||
;; in the middle
|
;; in the middle
|
||||||
(read-from-string
|
(read-from-string
|
||||||
(decode-coding-string (substring mm/buf 0 sexp-len) 'utf-8)))))
|
(decode-coding-string (substring mu4e-buf 0 sexp-len) 'utf-8)))))
|
||||||
(when objcons
|
(when objcons
|
||||||
(setq mm/buf (substring mm/buf sexp-len))
|
(setq mu4e-buf (substring mu4e-buf sexp-len))
|
||||||
(car objcons)))))))
|
(car objcons)))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/proc-filter (proc str)
|
(defun mu4e-proc-filter (proc str)
|
||||||
"A process-filter for the 'mu server' output; it accumulates the
|
"A process-filter for the 'mu server' output; it accumulates the
|
||||||
strings into valid sexps by checking of the ';;eox' end-of-sexp
|
strings into valid sexps by checking of the ';;eox' end-of-sexp
|
||||||
marker, and then evaluating them.
|
marker, and then evaluating them.
|
||||||
@ -195,7 +196,7 @@ updated as well, with all processed sexp data removed."
|
|||||||
1. an error
|
1. an error
|
||||||
(:error 2 :error-message \"unknown command\")
|
(:error 2 :error-message \"unknown command\")
|
||||||
;; eox
|
;; eox
|
||||||
=> this will be passed to `mm/proc-error-func'.
|
=> this will be passed to `mu4e-proc-error-func'.
|
||||||
|
|
||||||
2a. a message sexp looks something like:
|
2a. a message sexp looks something like:
|
||||||
\(
|
\(
|
||||||
@ -216,87 +217,87 @@ updated as well, with all processed sexp data removed."
|
|||||||
:body-txt \" <message body>\"
|
:body-txt \" <message body>\"
|
||||||
\)
|
\)
|
||||||
;; eox
|
;; eox
|
||||||
=> this will be passed to `mm/proc-header-func'.
|
=> this will be passed to `mu4e-proc-header-func'.
|
||||||
|
|
||||||
2b. After the list of message sexps has been returned (see 2a.),
|
2b. After the list of message sexps has been returned (see 2a.),
|
||||||
we'll receive a sexp that looks like
|
we'll receive a sexp that looks like
|
||||||
(:found <n>) with n the number of messages found. The <n> will be
|
(:found <n>) with n the number of messages found. The <n> will be
|
||||||
passed to `mm/proc-found-func'.
|
passed to `mu4e-proc-found-func'.
|
||||||
|
|
||||||
3. a view looks like:
|
3. a view looks like:
|
||||||
(:view <msg-sexp>)
|
(:view <msg-sexp>)
|
||||||
=> the <msg-sexp> (see 2.) will be passed to `mm/proc-view-func'.
|
=> the <msg-sexp> (see 2.) will be passed to `mu4e-proc-view-func'.
|
||||||
|
|
||||||
4. a database update looks like:
|
4. a database update looks like:
|
||||||
(:update <msg-sexp> :move <nil-or-t>)
|
(:update <msg-sexp> :move <nil-or-t>)
|
||||||
|
|
||||||
=> the <msg-sexp> (see 2.) will be passed to
|
=> the <msg-sexp> (see 2.) will be passed to
|
||||||
`mm/proc-update-func', :move tells us whether this is a move to
|
`mu4e-proc-update-func', :move tells us whether this is a move to
|
||||||
another maildir, or merely a flag change.
|
another maildir, or merely a flag change.
|
||||||
|
|
||||||
5. a remove looks like:
|
5. a remove looks like:
|
||||||
(:remove <docid>)
|
(:remove <docid>)
|
||||||
=> the docid will be passed to `mm/proc-remove-func'
|
=> the docid will be passed to `mu4e-proc-remove-func'
|
||||||
|
|
||||||
6. a compose looks like:
|
6. a compose looks like:
|
||||||
(:compose <msg-sexp> :action <reply|forward>) => the <msg-sexp>
|
(:compose <msg-sexp> :action <reply|forward>) => the <msg-sexp>
|
||||||
and either 'reply or 'forward will be passed
|
and either 'reply or 'forward will be passed
|
||||||
`mm/proc-compose-func'."
|
`mu4e-proc-compose-func'."
|
||||||
(mm/proc-log "* Received %d byte(s)" (length str))
|
(mu4e-proc-log "* Received %d byte(s)" (length str))
|
||||||
(setq mm/buf (concat mm/buf str)) ;; update our buffer
|
(setq mu4e-buf (concat mu4e-buf str)) ;; update our buffer
|
||||||
(let ((sexp (mm/proc-eat-sexp-from-buf)))
|
(let ((sexp (mu4e-proc-eat-sexp-from-buf)))
|
||||||
(while sexp
|
(while sexp
|
||||||
(mm/proc-log "<- %S" sexp)
|
(mu4e-proc-log "<- %S" sexp)
|
||||||
(cond
|
(cond
|
||||||
;; a header plist can be recognized by the existence of a :date field
|
;; a header plist can be recognized by the existence of a :date field
|
||||||
((plist-get sexp :date)
|
((plist-get sexp :date)
|
||||||
(funcall mm/proc-header-func sexp))
|
(funcall mu4e-proc-header-func sexp))
|
||||||
|
|
||||||
;; the found sexp, we receive after getting all the headers
|
;; the found sexp, we receive after getting all the headers
|
||||||
((plist-get sexp :found)
|
((plist-get sexp :found)
|
||||||
(funcall mm/proc-found-func (plist-get sexp :found)))
|
(funcall mu4e-proc-found-func (plist-get sexp :found)))
|
||||||
|
|
||||||
;; viewin a specific message
|
;; viewin a specific message
|
||||||
((plist-get sexp :view)
|
((plist-get sexp :view)
|
||||||
(funcall mm/proc-view-func (plist-get sexp :view)))
|
(funcall mu4e-proc-view-func (plist-get sexp :view)))
|
||||||
|
|
||||||
;; receive a pong message
|
;; receive a pong message
|
||||||
((plist-get sexp :pong)
|
((plist-get sexp :pong)
|
||||||
(funcall mm/proc-pong-func
|
(funcall mu4e-proc-pong-func
|
||||||
(plist-get sexp :version) (plist-get sexp :doccount)))
|
(plist-get sexp :version) (plist-get sexp :doccount)))
|
||||||
|
|
||||||
;; something got moved/flags changed
|
;; something got moved/flags changed
|
||||||
((plist-get sexp :update)
|
((plist-get sexp :update)
|
||||||
(funcall mm/proc-update-func
|
(funcall mu4e-proc-update-func
|
||||||
(plist-get sexp :update) (plist-get sexp :move)))
|
(plist-get sexp :update) (plist-get sexp :move)))
|
||||||
|
|
||||||
;; a message got removed
|
;; a message got removed
|
||||||
((plist-get sexp :remove)
|
((plist-get sexp :remove)
|
||||||
(funcall mm/proc-remove-func (plist-get sexp :remove)))
|
(funcall mu4e-proc-remove-func (plist-get sexp :remove)))
|
||||||
|
|
||||||
;; start composing a new message
|
;; start composing a new message
|
||||||
((plist-get sexp :compose)
|
((plist-get sexp :compose)
|
||||||
(funcall mm/proc-compose-func
|
(funcall mu4e-proc-compose-func
|
||||||
(plist-get sexp :compose-type)
|
(plist-get sexp :compose-type)
|
||||||
(plist-get sexp :compose)))
|
(plist-get sexp :compose)))
|
||||||
|
|
||||||
;; get some info
|
;; get some info
|
||||||
((plist-get sexp :info)
|
((plist-get sexp :info)
|
||||||
(funcall mm/proc-info-func sexp))
|
(funcall mu4e-proc-info-func sexp))
|
||||||
|
|
||||||
;; receive an error
|
;; receive an error
|
||||||
((plist-get sexp :error)
|
((plist-get sexp :error)
|
||||||
(funcall mm/proc-error-func sexp))
|
(funcall mu4e-proc-error-func sexp))
|
||||||
(t (message "Unexpected data from server [%S]" sexp)))
|
(t (message "Unexpected data from server [%S]" sexp)))
|
||||||
(setq sexp (mm/proc-eat-sexp-from-buf)))))
|
(setq sexp (mu4e-proc-eat-sexp-from-buf)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/proc-sentinel (proc msg)
|
(defun mu4e-proc-sentinel (proc msg)
|
||||||
"Function that will be called when the mu-server process
|
"Function that will be called when the mu-server process
|
||||||
terminates."
|
terminates."
|
||||||
(let ((status (process-status proc)) (code (process-exit-status proc)))
|
(let ((status (process-status proc)) (code (process-exit-status proc)))
|
||||||
(setq mm/mu-proc nil)
|
(setq mu4e-mu-proc nil)
|
||||||
(setq mm/buf "") ;; clear any half-received sexps
|
(setq mu4e-buf "") ;; clear any half-received sexps
|
||||||
(cond
|
(cond
|
||||||
((eq status 'signal)
|
((eq status 'signal)
|
||||||
(cond
|
(cond
|
||||||
@ -316,44 +317,44 @@ terminates."
|
|||||||
(message "something bad happened to the mu server process")))))
|
(message "something bad happened to the mu server process")))))
|
||||||
|
|
||||||
|
|
||||||
(defconst mm/proc-log-buffer-name "*mm-log*"
|
(defconst mu4e-proc-log-buffer-name "*mu4e-log*"
|
||||||
"*internal* Name of the logging buffer.")
|
"*internal* Name of the logging buffer.")
|
||||||
|
|
||||||
(defun mm/proc-log (frm &rest args)
|
(defun mu4e-proc-log (frm &rest args)
|
||||||
"Write something in the *mm-log* buffer - mainly useful for debugging."
|
"Write something in the *mu4e-log* buffer - mainly useful for debugging."
|
||||||
(when mm/debug
|
(when mu4e-debug
|
||||||
(with-current-buffer (get-buffer-create mm/proc-log-buffer-name)
|
(with-current-buffer (get-buffer-create mu4e-proc-log-buffer-name)
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(insert (apply 'format (concat (format-time-string "%Y-%m-%d %T "
|
(insert (apply 'format (concat (format-time-string "%Y-%m-%d %T "
|
||||||
(current-time)) frm "\n") args)))))
|
(current-time)) frm "\n") args)))))
|
||||||
|
|
||||||
(defun mm/proc-send-command (frm &rest args)
|
(defun mu4e-proc-send-command (frm &rest args)
|
||||||
"Send as command to the mu server process; start the process if needed."
|
"Send as command to the mu server process; start the process if needed."
|
||||||
(unless (mm/proc-is-running)
|
(unless (mu4e-proc-is-running)
|
||||||
(mm/start-proc))
|
(mu4e-start-proc))
|
||||||
(let ((cmd (apply 'format frm args)))
|
(let ((cmd (apply 'format frm args)))
|
||||||
(mm/proc-log (concat "-> " cmd))
|
(mu4e-proc-log (concat "-> " cmd))
|
||||||
(process-send-string mm/mu-proc (concat cmd "\n"))))
|
(process-send-string mu4e-mu-proc (concat cmd "\n"))))
|
||||||
|
|
||||||
(defun mm/proc-remove-msg (docid)
|
(defun mu4e-proc-remove-msg (docid)
|
||||||
"Remove message identified by DOCID. The results are reporter
|
"Remove message identified by DOCID. The results are reporter
|
||||||
through either (:update ... ) or (:error ) sexp, which are handled
|
through either (:update ... ) or (:error ) sexp, which are handled
|
||||||
my `mm/proc-update-func' and `mm/proc-error-func', respectively."
|
my `mu4e-proc-update-func' and `mu4e-proc-error-func', respectively."
|
||||||
(mm/proc-send-command "remove %d" docid))
|
(mu4e-proc-send-command "remove %d" docid))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/proc-find (expr &optional maxnum)
|
(defun mu4e-proc-find (expr &optional maxnum)
|
||||||
"Start a database query for EXPR, getting up to MAXNUM
|
"Start a database query for EXPR, getting up to MAXNUM
|
||||||
results (or -1 for unlimited). For each result found, a function is
|
results (or -1 for unlimited). For each result found, a function is
|
||||||
called, depending on the kind of result. The variables
|
called, depending on the kind of result. The variables
|
||||||
`mm/proc-header-func' and `mm/proc-error-func' contain the function
|
`mu4e-proc-header-func' and `mu4e-proc-error-func' contain the function
|
||||||
that will be called for, resp., a message (header row) or an
|
that will be called for, resp., a message (header row) or an
|
||||||
error."
|
error."
|
||||||
(mm/proc-send-command "find \"%s\" %d"
|
(mu4e-proc-send-command "find \"%s\" %d"
|
||||||
expr (if maxnum maxnum -1)))
|
expr (if maxnum maxnum -1)))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/proc-move-msg (docid targetmdir &optional flags)
|
(defun mu4e-proc-move-msg (docid targetmdir &optional flags)
|
||||||
"Move message identified by DOCID to TARGETMDIR, optionally
|
"Move message identified by DOCID to TARGETMDIR, optionally
|
||||||
setting FLAGS in the process.
|
setting FLAGS in the process.
|
||||||
|
|
||||||
@ -369,82 +370,82 @@ The FLAGS parameter can have the following forms:
|
|||||||
|
|
||||||
The flags are any of `deleted', `flagged', `new', `passed', `replied' `seen' or
|
The flags are any of `deleted', `flagged', `new', `passed', `replied' `seen' or
|
||||||
`trashed', or the corresponding \"DFNPRST\" as defined in [1]. See
|
`trashed', or the corresponding \"DFNPRST\" as defined in [1]. See
|
||||||
`mm/string-to-flags' and `mm/flags-to-string'.
|
`mu4e-string-to-flags' and `mu4e-flags-to-string'.
|
||||||
The server reports the results for the operation through
|
The server reports the results for the operation through
|
||||||
`mm/proc-update-func'.
|
`mu4e-proc-update-func'.
|
||||||
The results are reported through either (:update ... )
|
The results are reported through either (:update ... )
|
||||||
or (:error ) sexp, which are handled my `mm/proc-update-func' and
|
or (:error ) sexp, which are handled my `mu4e-proc-update-func' and
|
||||||
`mm/proc-error-func', respectively."
|
`mu4e-proc-error-func', respectively."
|
||||||
(let
|
(let
|
||||||
((flagstr (if (stringp flags) flags (mm/flags-to-string flags)))
|
((flagstr (if (stringp flags) flags (mu4e-flags-to-string flags)))
|
||||||
(fullpath (concat mm/maildir targetmdir)))
|
(fullpath (concat mu4e-maildir targetmdir)))
|
||||||
(unless (and (file-directory-p fullpath) (file-writable-p fullpath))
|
(unless (and (file-directory-p fullpath) (file-writable-p fullpath))
|
||||||
(error "Not a writable directory: %s" fullpath))
|
(error "Not a writable directory: %s" fullpath))
|
||||||
;; note, we send the maildir, *not* the full path
|
;; note, we send the maildir, *not* the full path
|
||||||
(mm/proc-send-command "move %d \"%s\" %s" docid
|
(mu4e-proc-send-command "move %d \"%s\" %s" docid
|
||||||
targetmdir flagstr)))
|
targetmdir flagstr)))
|
||||||
|
|
||||||
(defun mm/proc-flag (docid-or-msgid flags)
|
(defun mu4e-proc-flag (docid-or-msgid flags)
|
||||||
"Set FLAGS for the message identified by either DOCID-OR-MSGID."
|
"Set FLAGS for the message identified by either DOCID-OR-MSGID."
|
||||||
(let ((flagstr (if (stringp flags) flags (mm/flags-to-string flags))))
|
(let ((flagstr (if (stringp flags) flags (mu4e-flags-to-string flags))))
|
||||||
(mm/proc-send-command "flag %S %s" docid-or-msgid flagstr)))
|
(mu4e-proc-send-command "flag %S %s" docid-or-msgid flagstr)))
|
||||||
|
|
||||||
(defun mm/proc-index (maildir)
|
(defun mu4e-proc-index (maildir)
|
||||||
"Update the message database for MAILDIR."
|
"Update the message database for MAILDIR."
|
||||||
(mm/proc-send-command "index \"%s\"" maildir))
|
(mu4e-proc-send-command "index \"%s\"" maildir))
|
||||||
|
|
||||||
(defun mm/proc-add (path maildir)
|
(defun mu4e-proc-add (path maildir)
|
||||||
"Add the message at PATH to the database, with MAILDIR
|
"Add the message at PATH to the database, with MAILDIR
|
||||||
set to e.g. '/drafts'; if this works, we will receive (:info :path
|
set to e.g. '/drafts'; if this works, we will receive (:info :path
|
||||||
<path> :docid <docid>)."
|
<path> :docid <docid>)."
|
||||||
(mm/proc-send-command "add \"%s\" \"%s\"" path maildir))
|
(mu4e-proc-send-command "add \"%s\" \"%s\"" path maildir))
|
||||||
|
|
||||||
(defun mm/proc-save (docid partidx path)
|
(defun mu4e-proc-save (docid partidx path)
|
||||||
"Save attachment PARTIDX from message with DOCID to PATH."
|
"Save attachment PARTIDX from message with DOCID to PATH."
|
||||||
(mm/proc-send-command "save %d %d \"%s\"" docid partidx path))
|
(mu4e-proc-send-command "save %d %d \"%s\"" docid partidx path))
|
||||||
|
|
||||||
(defun mm/proc-open (docid partidx)
|
(defun mu4e-proc-open (docid partidx)
|
||||||
"Open attachment PARTIDX from message with DOCID."
|
"Open attachment PARTIDX from message with DOCID."
|
||||||
(mm/proc-send-command "open %d %d" docid partidx))
|
(mu4e-proc-send-command "open %d %d" docid partidx))
|
||||||
|
|
||||||
(defun mm/proc-ping ()
|
(defun mu4e-proc-ping ()
|
||||||
"Sends a ping to the mu server, expecting a (:pong ...) in
|
"Sends a ping to the mu server, expecting a (:pong ...) in
|
||||||
response."
|
response."
|
||||||
(mm/proc-send-command "ping"))
|
(mu4e-proc-send-command "ping"))
|
||||||
|
|
||||||
(defun mm/proc-view-msg (docid)
|
(defun mu4e-proc-view-msg (docid)
|
||||||
"Get one particular message based on its DOCID. The result will
|
"Get one particular message based on its DOCID. The result will
|
||||||
be delivered to the function registered as `mm/proc-message-func'."
|
be delivered to the function registered as `mu4e-proc-message-func'."
|
||||||
(mm/proc-send-command "view %d" docid))
|
(mu4e-proc-send-command "view %d" docid))
|
||||||
|
|
||||||
(defun mm/proc-compose (compose-type docid)
|
(defun mu4e-proc-compose (compose-type docid)
|
||||||
"Start composing a message with DOCID and COMPOSE-TYPE (a symbol,
|
"Start composing a message with DOCID and COMPOSE-TYPE (a symbol,
|
||||||
either `forward', `reply' or `edit'.
|
either `forward', `reply' or `edit'.
|
||||||
The result will be delivered to the function registered as
|
The result will be delivered to the function registered as
|
||||||
`mm/proc-compose-func'."
|
`mu4e-proc-compose-func'."
|
||||||
(unless (member compose-type '(forward reply edit))
|
(unless (member compose-type '(forward reply edit))
|
||||||
(error "Unsupported compose-type"))
|
(error "Unsupported compose-type"))
|
||||||
(mm/proc-send-command "compose %s %d" (symbol-name compose-type) docid))
|
(mu4e-proc-send-command "compose %s %d" (symbol-name compose-type) docid))
|
||||||
|
|
||||||
(defconst mm/update-buffer-name "*update*"
|
(defconst mu4e-update-buffer-name "*update*"
|
||||||
"*internal* Name of the buffer to download mail")
|
"*internal* Name of the buffer to download mail")
|
||||||
|
|
||||||
(defun mm/proc-retrieve-mail-update-db ()
|
(defun mu4e-proc-retrieve-mail-update-db ()
|
||||||
"Try to retrieve mail (using the user-provided shell command),
|
"Try to retrieve mail (using the user-provided shell command),
|
||||||
and update the database afterwards."
|
and update the database afterwards."
|
||||||
(unless mm/get-mail-command
|
(unless mu4e-get-mail-command
|
||||||
(error "`mm/get-mail-command' is not defined"))
|
(error "`mu4e-get-mail-command' is not defined"))
|
||||||
(let ((buf (get-buffer-create mm/update-buffer-name)))
|
(let ((buf (get-buffer-create mu4e-update-buffer-name)))
|
||||||
(split-window-vertically -8)
|
(split-window-vertically -8)
|
||||||
(switch-to-buffer-other-window buf)
|
(switch-to-buffer-other-window buf)
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(erase-buffer))
|
(erase-buffer))
|
||||||
(message "Retrieving mail...")
|
(message "Retrieving mail...")
|
||||||
(call-process mm/get-mail-command nil buf t)
|
(call-process mu4e-get-mail-command nil buf t)
|
||||||
(message "Updating the database...")
|
(message "Updating the database...")
|
||||||
(mm/proc-index mm/maildir)
|
(mu4e-proc-index mu4e-maildir)
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(kill-buffer-and-window))))
|
(kill-buffer-and-window))))
|
||||||
|
|
||||||
|
|
||||||
(provide 'mm-proc)
|
(provide 'mu4e-proc)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
;; mm-send.el -- part of mm, the mu mail user agent
|
;; mu4e-send.el -- part of mm, the mu mail user agent
|
||||||
;;
|
;;
|
||||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||||
|
|
||||||
@ -39,23 +39,23 @@
|
|||||||
|
|
||||||
|
|
||||||
;; internal variables / constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; internal variables / constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defconst mm/msg-draft-name "*mm-draft*"
|
(defconst mu4e-msg-draft-name "*mu4e-draft*"
|
||||||
"Name for draft messages.")
|
"Name for draft messages.")
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; FIXME
|
;; FIXME
|
||||||
(defun mm/mu-binary-version () "0.98pre")
|
(defun mu4e-mu-binary-version () "0.98pre")
|
||||||
|
|
||||||
|
|
||||||
(defun mm/msg-user-agent ()
|
(defun mu4e-msg-user-agent ()
|
||||||
"Return the User-Agent string for mm. This is either the value
|
"Return the User-Agent string for mm. This is either the value
|
||||||
of `mm/user-agent', or, if not set, a string based on the
|
of `mu4e-user-agent', or, if not set, a string based on the
|
||||||
version of mm and emacs."
|
version of mm and emacs."
|
||||||
(or mm/user-agent
|
(or mu4e-user-agent
|
||||||
(format "mu %s; emacs %s" (mm/mu-binary-version) emacs-version)))
|
(format "mu %s; emacs %s" (mu4e-mu-binary-version) emacs-version)))
|
||||||
|
|
||||||
(defun mm/view-body (msg)
|
(defun mu4e-view-body (msg)
|
||||||
"Get the body for this message, which is either :body-txt,
|
"Get the body for this message, which is either :body-txt,
|
||||||
or if not available, :body-html converted to text)."
|
or if not available, :body-html converted to text)."
|
||||||
(or (plist-get msg :body-txt)
|
(or (plist-get msg :body-txt)
|
||||||
@ -65,12 +65,12 @@ or if not available, :body-html converted to text)."
|
|||||||
(buffer-string))
|
(buffer-string))
|
||||||
"No body found"))
|
"No body found"))
|
||||||
|
|
||||||
(defun mm/msg-cite-original (msg)
|
(defun mu4e-msg-cite-original (msg)
|
||||||
"Cite the body text of MSG, with a \"On %s, %s wrote:\"
|
"Cite the body text of MSG, with a \"On %s, %s wrote:\"
|
||||||
line (with the %s's replaced with the date of MSG and the name
|
line (with the %s's replaced with the date of MSG and the name
|
||||||
or e-mail address of its sender (or 'someone' if nothing
|
or e-mail address of its sender (or 'someone' if nothing
|
||||||
else)), followed of the quoted body of MSG, constructed by by
|
else)), followed of the quoted body of MSG, constructed by by
|
||||||
prepending `mm/msg-citation-prefix' to each line. If there is
|
prepending `mu4e-msg-citation-prefix' to each line. If there is
|
||||||
no body in MSG, return nil."
|
no body in MSG, return nil."
|
||||||
(let* ((from (plist-get msg :from))
|
(let* ((from (plist-get msg :from))
|
||||||
;; first try plain-text, then html
|
;; first try plain-text, then html
|
||||||
@ -90,7 +90,7 @@ or if not available, :body-html converted to text)."
|
|||||||
"\n\n"
|
"\n\n"
|
||||||
(replace-regexp-in-string "^" " > " body)))))
|
(replace-regexp-in-string "^" " > " body)))))
|
||||||
|
|
||||||
(defun mm/msg-recipients-remove (lst email-to-remove)
|
(defun mu4e-msg-recipients-remove (lst email-to-remove)
|
||||||
"Remove the recipient with EMAIL from the recipient list (of form
|
"Remove the recipient with EMAIL from the recipient list (of form
|
||||||
'( (\"A\" . \"a@example.com\") (\"B\" . \"B@example.com\"))."
|
'( (\"A\" . \"a@example.com\") (\"B\" . \"B@example.com\"))."
|
||||||
(remove-if
|
(remove-if
|
||||||
@ -98,7 +98,7 @@ or if not available, :body-html converted to text)."
|
|||||||
(let ((email (cdr name-email)))
|
(let ((email (cdr name-email)))
|
||||||
(when email (string= email-to-remove (downcase email))))) lst))
|
(when email (string= email-to-remove (downcase email))))) lst))
|
||||||
|
|
||||||
(defun mm/msg-recipients-to-string (lst)
|
(defun mu4e-msg-recipients-to-string (lst)
|
||||||
"Convert a recipient list (of form '( (\"A\"
|
"Convert a recipient list (of form '( (\"A\"
|
||||||
. \"a@example.com\") (\"B\" . \"B@example.com\") (nil
|
. \"a@example.com\") (\"B\" . \"B@example.com\") (nil
|
||||||
. \"c@example.com\")) into a string of form \"A <@aexample.com>, B
|
. \"c@example.com\")) into a string of form \"A <@aexample.com>, B
|
||||||
@ -112,12 +112,12 @@ or if not available, :body-html converted to text)."
|
|||||||
(format "%s" email)))) lst ", ")))
|
(format "%s" email)))) lst ", ")))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/msg-header (hdr val)
|
(defun mu4e-msg-header (hdr val)
|
||||||
"Return a header line of the form HDR: VAL\n. If VAL is nil,
|
"Return a header line of the form HDR: VAL\n. If VAL is nil,
|
||||||
return nil."
|
return nil."
|
||||||
(when val (format "%s: %s\n" hdr val)))
|
(when val (format "%s: %s\n" hdr val)))
|
||||||
|
|
||||||
(defun mm/msg-references-create (msg)
|
(defun mu4e-msg-references-create (msg)
|
||||||
"Construct the value of the References: header based on MSG as a
|
"Construct the value of the References: header based on MSG as a
|
||||||
comma-separated string. Normally, this the concatenation of the
|
comma-separated string. Normally, this the concatenation of the
|
||||||
existing References (which may be empty) and the message-id. If the
|
existing References (which may be empty) and the message-id. If the
|
||||||
@ -131,7 +131,7 @@ return nil."
|
|||||||
(lambda (msgid) (format "<%s>" msgid))
|
(lambda (msgid) (format "<%s>" msgid))
|
||||||
refs ","))))
|
refs ","))))
|
||||||
|
|
||||||
(defun mm/msg-to-create (msg)
|
(defun mu4e-msg-to-create (msg)
|
||||||
"Construct the To: header for a reply-message based on some
|
"Construct the To: header for a reply-message based on some
|
||||||
message MSG. This takes the Reply-To address of MSG if it exist, or
|
message MSG. This takes the Reply-To address of MSG if it exist, or
|
||||||
the From:-address otherwise. The result is either nil or a string
|
the From:-address otherwise. The result is either nil or a string
|
||||||
@ -140,10 +140,10 @@ Reply-To contains a string of one or more addresses,
|
|||||||
comma-separated."
|
comma-separated."
|
||||||
(or
|
(or
|
||||||
(plist-get msg :reply-to)
|
(plist-get msg :reply-to)
|
||||||
(mm/msg-recipients-to-string (plist-get msg :from))))
|
(mu4e-msg-recipients-to-string (plist-get msg :from))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/msg-cc-create (msg reply-all)
|
(defun mu4e-msg-cc-create (msg reply-all)
|
||||||
"Get the list of Cc-addresses for the reply to MSG. If REPLY-ALL
|
"Get the list of Cc-addresses for the reply to MSG. If REPLY-ALL
|
||||||
is nil this is simply empty, otherwise it is the old CC-list
|
is nil this is simply empty, otherwise it is the old CC-list
|
||||||
together with the old TO-list, minus `user-mail-address'. The
|
together with the old TO-list, minus `user-mail-address'. The
|
||||||
@ -154,11 +154,11 @@ the Cc: field."
|
|||||||
(when reply-all
|
(when reply-all
|
||||||
(setq cc-lst (append cc-lst to-lst)))
|
(setq cc-lst (append cc-lst to-lst)))
|
||||||
;; remove myself from cc
|
;; remove myself from cc
|
||||||
(setq cc-lst (mm/msg-recipients-remove cc-lst user-mail-address))
|
(setq cc-lst (mu4e-msg-recipients-remove cc-lst user-mail-address))
|
||||||
(mm/msg-recipients-to-string cc-lst)))
|
(mu4e-msg-recipients-to-string cc-lst)))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/msg-from-create ()
|
(defun mu4e-msg-from-create ()
|
||||||
"Construct a value for the From:-field of the reply to MSG,
|
"Construct a value for the From:-field of the reply to MSG,
|
||||||
based on `user-full-name' and `user-mail-address'; if the latter is
|
based on `user-full-name' and `user-mail-address'; if the latter is
|
||||||
nil, function returns nil."
|
nil, function returns nil."
|
||||||
@ -167,25 +167,25 @@ nil, function returns nil."
|
|||||||
(format "%s <%s>" user-full-name user-mail-address)
|
(format "%s <%s>" user-full-name user-mail-address)
|
||||||
(format "%s" user-mail-address))))
|
(format "%s" user-mail-address))))
|
||||||
|
|
||||||
(defun mm/msg-create-reply (msg)
|
(defun mu4e-msg-create-reply (msg)
|
||||||
"Create a draft message as a reply to MSG.
|
"Create a draft message as a reply to MSG.
|
||||||
|
|
||||||
A reply message has fields:
|
A reply message has fields:
|
||||||
From: - see `mu-msg-from-create'
|
From: - see `mu-msg-from-create'
|
||||||
To: - see `mm/msg-to-create'
|
To: - see `mu4e-msg-to-create'
|
||||||
Cc: - see `mm/msg-cc-create'
|
Cc: - see `mu4e-msg-cc-create'
|
||||||
Subject: - `mm/msg-reply-prefix' + subject of MSG
|
Subject: - `mu4e-msg-reply-prefix' + subject of MSG
|
||||||
|
|
||||||
then, the following fields, normally hidden from user:
|
then, the following fields, normally hidden from user:
|
||||||
Reply-To: - if `mail-reply-to' has been set
|
Reply-To: - if `mail-reply-to' has been set
|
||||||
References: - see `mm/msg-references-create'
|
References: - see `mu4e-msg-references-create'
|
||||||
In-Reply-To: - message-id of MSG
|
In-Reply-To: - message-id of MSG
|
||||||
User-Agent - see `mm/msg-user-agent'
|
User-Agent - see `mu4e-msg-user-agent'
|
||||||
|
|
||||||
Then follows `mail-header-separator' (for `message-mode' to separate
|
Then follows `mail-header-separator' (for `message-mode' to separate
|
||||||
body from headers)
|
body from headers)
|
||||||
|
|
||||||
And finally, the cited body of MSG, as per `mm/msg-cite-original'."
|
And finally, the cited body of MSG, as per `mu4e-msg-cite-original'."
|
||||||
(let* ((recipnum (+ (length (plist-get msg :to))
|
(let* ((recipnum (+ (length (plist-get msg :to))
|
||||||
(length (plist-get msg :cc))))
|
(length (plist-get msg :cc))))
|
||||||
(reply-all (when (> recipnum 1)
|
(reply-all (when (> recipnum 1)
|
||||||
@ -193,60 +193,60 @@ And finally, the cited body of MSG, as per `mm/msg-cite-original'."
|
|||||||
(format "Reply to all ~%d recipients? "
|
(format "Reply to all ~%d recipients? "
|
||||||
(+ recipnum))))))
|
(+ recipnum))))))
|
||||||
(concat
|
(concat
|
||||||
(mm/msg-header "From" (or (mm/msg-from-create) ""))
|
(mu4e-msg-header "From" (or (mu4e-msg-from-create) ""))
|
||||||
(when (boundp 'mail-reply-to)
|
(when (boundp 'mail-reply-to)
|
||||||
(mm/msg-header "Reply-To" mail-reply-to))
|
(mu4e-msg-header "Reply-To" mail-reply-to))
|
||||||
|
|
||||||
(mm/msg-header "To" (or (mm/msg-to-create msg) ""))
|
(mu4e-msg-header "To" (or (mu4e-msg-to-create msg) ""))
|
||||||
(mm/msg-header "Cc" (mm/msg-cc-create msg reply-all))
|
(mu4e-msg-header "Cc" (mu4e-msg-cc-create msg reply-all))
|
||||||
|
|
||||||
(mm/msg-header "User-agent" (mm/msg-user-agent))
|
(mu4e-msg-header "User-agent" (mu4e-msg-user-agent))
|
||||||
(mm/msg-header "References" (mm/msg-references-create msg))
|
(mu4e-msg-header "References" (mu4e-msg-references-create msg))
|
||||||
|
|
||||||
(mm/msg-header "In-reply-to" (format "<%s>" (plist-get msg :message-id)))
|
(mu4e-msg-header "In-reply-to" (format "<%s>" (plist-get msg :message-id)))
|
||||||
|
|
||||||
(mm/msg-header "Subject"
|
(mu4e-msg-header "Subject"
|
||||||
(concat mm/msg-reply-prefix (plist-get msg :subject)))
|
(concat mu4e-msg-reply-prefix (plist-get msg :subject)))
|
||||||
|
|
||||||
(propertize mail-header-separator 'read-only t 'intangible t) '"\n"
|
(propertize mail-header-separator 'read-only t 'intangible t) '"\n"
|
||||||
|
|
||||||
"\n\n"
|
"\n\n"
|
||||||
(mm/msg-cite-original msg))))
|
(mu4e-msg-cite-original msg))))
|
||||||
|
|
||||||
;; TODO: attachments
|
;; TODO: attachments
|
||||||
(defun mm/msg-create-forward (msg)
|
(defun mu4e-msg-create-forward (msg)
|
||||||
"Create a draft forward message for MSG.
|
"Create a draft forward message for MSG.
|
||||||
|
|
||||||
A forward message has fields:
|
A forward message has fields:
|
||||||
From: - see `mm/msg-from-create'
|
From: - see `mu4e-msg-from-create'
|
||||||
To: - empty
|
To: - empty
|
||||||
Subject: - `mm/msg-forward-prefix' + subject of MSG
|
Subject: - `mu4e-msg-forward-prefix' + subject of MSG
|
||||||
|
|
||||||
then, the following fields, normally hidden from user:
|
then, the following fields, normally hidden from user:
|
||||||
Reply-To: - if `mail-reply-to' has been set
|
Reply-To: - if `mail-reply-to' has been set
|
||||||
References: - see `mm/msg-references-create'
|
References: - see `mu4e-msg-references-create'
|
||||||
User-Agent - see `mm/msg-user-agent'
|
User-Agent - see `mu4e-msg-user-agent'
|
||||||
|
|
||||||
Then follows `mail-header-separator' (for `message-mode' to separate
|
Then follows `mail-header-separator' (for `message-mode' to separate
|
||||||
body from headers)
|
body from headers)
|
||||||
|
|
||||||
And finally, the cited body of MSG, as per `mm/msg-cite-original'."
|
And finally, the cited body of MSG, as per `mu4e-msg-cite-original'."
|
||||||
(concat
|
(concat
|
||||||
(mm/msg-header "From" (or (mm/msg-from-create) ""))
|
(mu4e-msg-header "From" (or (mu4e-msg-from-create) ""))
|
||||||
(when (boundp 'mail-reply-to)
|
(when (boundp 'mail-reply-to)
|
||||||
(mm/msg-header "Reply-To" mail-reply-to))
|
(mu4e-msg-header "Reply-To" mail-reply-to))
|
||||||
|
|
||||||
(mm/msg-header "To" "")
|
(mu4e-msg-header "To" "")
|
||||||
(mm/msg-header "User-agent" (mm/msg-user-agent))
|
(mu4e-msg-header "User-agent" (mu4e-msg-user-agent))
|
||||||
(mm/msg-header "References" (mm/msg-references-create msg))
|
(mu4e-msg-header "References" (mu4e-msg-references-create msg))
|
||||||
(mm/msg-header"Subject"
|
(mu4e-msg-header"Subject"
|
||||||
(concat mm/msg-forward-prefix (plist-get msg :subject)))
|
(concat mu4e-msg-forward-prefix (plist-get msg :subject)))
|
||||||
(propertize mail-header-separator 'read-only t 'intangible t) "\n"
|
(propertize mail-header-separator 'read-only t 'intangible t) "\n"
|
||||||
|
|
||||||
"\n\n"
|
"\n\n"
|
||||||
(mm/msg-cite-original msg)))
|
(mu4e-msg-cite-original msg)))
|
||||||
|
|
||||||
(defun mm/msg-create-new ()
|
(defun mu4e-msg-create-new ()
|
||||||
"Create a new message.
|
"Create a new message.
|
||||||
|
|
||||||
A new draft message has fields:
|
A new draft message has fields:
|
||||||
@ -256,24 +256,24 @@ A new draft message has fields:
|
|||||||
|
|
||||||
then, the following fields, normally hidden from user:
|
then, the following fields, normally hidden from user:
|
||||||
Reply-To: - if `mail-reply-to' has been set
|
Reply-To: - if `mail-reply-to' has been set
|
||||||
User-Agent - see `mm/msg-user-agent'
|
User-Agent - see `mu4e-msg-user-agent'
|
||||||
|
|
||||||
Then follows `mail-header-separator' (for `message-mode' to separate
|
Then follows `mail-header-separator' (for `message-mode' to separate
|
||||||
body from headers)."
|
body from headers)."
|
||||||
(concat
|
(concat
|
||||||
(mm/msg-header "From" (or (mm/msg-from-create) ""))
|
(mu4e-msg-header "From" (or (mu4e-msg-from-create) ""))
|
||||||
(when (boundp 'mail-reply-to)
|
(when (boundp 'mail-reply-to)
|
||||||
(mm/msg-header "Reply-To" mail-reply-to))
|
(mu4e-msg-header "Reply-To" mail-reply-to))
|
||||||
(mm/msg-header "To" "")
|
(mu4e-msg-header "To" "")
|
||||||
(mm/msg-header "User-agent" (mm/msg-user-agent))
|
(mu4e-msg-header "User-agent" (mu4e-msg-user-agent))
|
||||||
(mm/msg-header "Subject" "")
|
(mu4e-msg-header "Subject" "")
|
||||||
(propertize mail-header-separator 'read-only t 'intangible t) "\n"))
|
(propertize mail-header-separator 'read-only t 'intangible t) "\n"))
|
||||||
|
|
||||||
(defun mm/msg-open-draft (compose-type &optional msg)
|
(defun mu4e-msg-open-draft (compose-type &optional msg)
|
||||||
"Open a draft file for a new message, creating it if it does not
|
"Open a draft file for a new message, creating it if it does not
|
||||||
already exist, and optionally fill it with STR. Function also adds
|
already exist, and optionally fill it with STR. Function also adds
|
||||||
the new message to the database. When the draft message is added to
|
the new message to the database. When the draft message is added to
|
||||||
the database, `mm/path-docid-map' will be updated, so that we can
|
the database, `mu4e-path-docid-map' will be updated, so that we can
|
||||||
use the new docid. Returns the full path to the new message."
|
use the new docid. Returns the full path to the new message."
|
||||||
(let* ((hostname
|
(let* ((hostname
|
||||||
(downcase
|
(downcase
|
||||||
@ -281,14 +281,14 @@ use the new docid. Returns the full path to the new message."
|
|||||||
(substring system-name
|
(substring system-name
|
||||||
(string-match "^[^.]+" system-name) (match-end 0)))))
|
(string-match "^[^.]+" system-name) (match-end 0)))))
|
||||||
(draft
|
(draft
|
||||||
(concat mm/maildir mm/drafts-folder "/cur/"
|
(concat mu4e-maildir mu4e-drafts-folder "/cur/"
|
||||||
(format "%s-%x%x.%s:2,D" ;; 'D': rarely used, but hey, it's available
|
(format "%s-%x%x.%s:2,D" ;; 'D': rarely used, but hey, it's available
|
||||||
(format-time-string "%Y%m%d" (current-time))
|
(format-time-string "%Y%m%d" (current-time))
|
||||||
(emacs-pid) (random t) hostname)))
|
(emacs-pid) (random t) hostname)))
|
||||||
(str (case compose-type
|
(str (case compose-type
|
||||||
(reply (mm/msg-create-reply msg))
|
(reply (mu4e-msg-create-reply msg))
|
||||||
(forward (mm/msg-create-forward msg))
|
(forward (mu4e-msg-create-forward msg))
|
||||||
(new (mm/msg-create-new))
|
(new (mu4e-msg-create-new))
|
||||||
(t (error "unsupported compose-type %S" compose-type)))))
|
(t (error "unsupported compose-type %S" compose-type)))))
|
||||||
(when str
|
(when str
|
||||||
(with-temp-file draft
|
(with-temp-file draft
|
||||||
@ -296,12 +296,12 @@ use the new docid. Returns the full path to the new message."
|
|||||||
(write-file draft)))
|
(write-file draft)))
|
||||||
|
|
||||||
;; save our file immediately, add add it to the db; thus, we can retrieve
|
;; save our file immediately, add add it to the db; thus, we can retrieve
|
||||||
;; the new docid from `mm/path-docid-map'.
|
;; the new docid from `mu4e-path-docid-map'.
|
||||||
(mm/proc-add draft mm/drafts-folder)
|
(mu4e-proc-add draft mu4e-drafts-folder)
|
||||||
draft))
|
draft))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/send-compose-handler (compose-type &optional msg)
|
(defun mu4e-send-compose-handler (compose-type &optional msg)
|
||||||
"Create a new draft message, or open an existing one.
|
"Create a new draft message, or open an existing one.
|
||||||
|
|
||||||
COMPOSE-TYPE determines the kind of message to compose and is a
|
COMPOSE-TYPE determines the kind of message to compose and is a
|
||||||
@ -312,20 +312,20 @@ When COMPOSE-TYPE is `reply' or `forward', MSG should be a message
|
|||||||
plist. If COMPOSE-TYPE is `new', MSG should be nil.
|
plist. If COMPOSE-TYPE is `new', MSG should be nil.
|
||||||
|
|
||||||
The name of the draft folder is constructed from the concatenation
|
The name of the draft folder is constructed from the concatenation
|
||||||
of `mm/maildir' and `mm/drafts-folder' (therefore, these must be
|
of `mu4e-maildir' and `mu4e-drafts-folder' (therefore, these must be
|
||||||
set).
|
set).
|
||||||
|
|
||||||
The message file name is a unique name determined by
|
The message file name is a unique name determined by
|
||||||
`mm/msg-draft-file-name'.
|
`mu4e-msg-draft-file-name'.
|
||||||
|
|
||||||
The initial STR would be created from either `mm/msg-create-reply',
|
The initial STR would be created from either `mu4e-msg-create-reply',
|
||||||
ar`mm/msg-create-forward' or `mm/msg-create-new'. The editing buffer is
|
ar`mu4e-msg-create-forward' or `mu4e-msg-create-new'. The editing buffer is
|
||||||
using Gnus' `message-mode'."
|
using Gnus' `message-mode'."
|
||||||
(unless mm/maildir (error "mm/maildir not set"))
|
(unless mu4e-maildir (error "mu4e-maildir not set"))
|
||||||
(unless mm/drafts-folder (error "mm/drafts-folder not set"))
|
(unless mu4e-drafts-folder (error "mu4e-drafts-folder not set"))
|
||||||
(let ((draft
|
(let ((draft
|
||||||
(if (member compose-type '(reply forward new))
|
(if (member compose-type '(reply forward new))
|
||||||
(mm/msg-open-draft compose-type msg)
|
(mu4e-msg-open-draft compose-type msg)
|
||||||
(if (eq compose-type 'edit)
|
(if (eq compose-type 'edit)
|
||||||
(plist-get msg :path)
|
(plist-get msg :path)
|
||||||
(error "unsupported compose-type %S" compose-type)))))
|
(error "unsupported compose-type %S" compose-type)))))
|
||||||
@ -340,11 +340,11 @@ using Gnus' `message-mode'."
|
|||||||
|
|
||||||
;; update the db when the file is saved...]
|
;; update the db when the file is saved...]
|
||||||
(add-to-list 'write-file-functions
|
(add-to-list 'write-file-functions
|
||||||
(lambda() (mm/proc-add (buffer-file-name) mm/drafts-folder)))
|
(lambda() (mu4e-proc-add (buffer-file-name) mu4e-drafts-folder)))
|
||||||
|
|
||||||
;; hook our functions up with sending of the message
|
;; hook our functions up with sending of the message
|
||||||
(add-hook 'message-sent-hook 'mm/msg-save-to-sent nil t)
|
(add-hook 'message-sent-hook 'mu4e-msg-save-to-sent nil t)
|
||||||
(add-hook 'message-sent-hook 'mm/send-set-parent-flag nil t)
|
(add-hook 'message-sent-hook 'mu4e-send-set-parent-flag nil t)
|
||||||
|
|
||||||
(let ((message-hidden-headers
|
(let ((message-hidden-headers
|
||||||
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:"
|
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:"
|
||||||
@ -356,10 +356,10 @@ using Gnus' `message-mode'."
|
|||||||
(message-goto-body))))
|
(message-goto-body))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/msg-save-to-sent ()
|
(defun mu4e-msg-save-to-sent ()
|
||||||
"Move the message in this buffer to the sent folder. This is
|
"Move the message in this buffer to the sent folder. This is
|
||||||
meant to be called from message mode's `message-sent-hook'."
|
meant to be called from message mode's `message-sent-hook'."
|
||||||
(unless mm/sent-folder (error "mm/sent-folder not set"))
|
(unless mu4e-sent-folder (error "mu4e-sent-folder not set"))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
;; remove the --text follows this line-- separator
|
;; remove the --text follows this line-- separator
|
||||||
@ -368,10 +368,10 @@ using Gnus' `message-mode'."
|
|||||||
(error "cannot find mail-header-separator"))
|
(error "cannot find mail-header-separator"))
|
||||||
|
|
||||||
(save-buffer)
|
(save-buffer)
|
||||||
(let ((docid (gethash (buffer-file-name) mm/path-docid-map)))
|
(let ((docid (gethash (buffer-file-name) mu4e-path-docid-map)))
|
||||||
(unless docid (error "unknown message (%S)" (buffer-file-name)))
|
(unless docid (error "unknown message (%S)" (buffer-file-name)))
|
||||||
;; ok, all seems well, well move the message to the sent-folder
|
;; ok, all seems well, well move the message to the sent-folder
|
||||||
(mm/proc-move-msg docid mm/sent-folder "-T-D+S")
|
(mu4e-proc-move-msg docid mu4e-sent-folder "-T-D+S")
|
||||||
;; we can remove the value from the hash now, if we can establish there
|
;; we can remove the value from the hash now, if we can establish there
|
||||||
;; are not other compose buffers using this very same docid...
|
;; are not other compose buffers using this very same docid...
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ using Gnus' `message-mode'."
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defun mm/send-set-parent-flag ()
|
(defun mu4e-send-set-parent-flag ()
|
||||||
"Set the 'replied' flag on messages we replied to, and the
|
"Set the 'replied' flag on messages we replied to, and the
|
||||||
'passed' flag on message we have forwarded.
|
'passed' flag on message we have forwarded.
|
||||||
|
|
||||||
@ -413,8 +413,8 @@ This is meant to be called from message mode's
|
|||||||
(setq forwarded-from (car-safe (last refs)))))))
|
(setq forwarded-from (car-safe (last refs)))))))
|
||||||
;; remove the <>
|
;; remove the <>
|
||||||
(when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to))
|
(when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to))
|
||||||
(mm/proc-flag (match-string 1 in-reply-to) "+R"))
|
(mu4e-proc-flag (match-string 1 in-reply-to) "+R"))
|
||||||
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
|
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
|
||||||
(mm/proc-flag (match-string 1 forwarded-from) "+P"))))
|
(mu4e-proc-flag (match-string 1 forwarded-from) "+P"))))
|
||||||
|
|
||||||
(provide 'mm-send)
|
(provide 'mu4e-send)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
;; mm-view.el -- part of mm, the mu mail user agent
|
;; mu4e-view.el -- part of mm, the mu mail user agent
|
||||||
;;
|
;;
|
||||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||||
|
|
||||||
@ -36,20 +36,20 @@
|
|||||||
(require 'filladapt)
|
(require 'filladapt)
|
||||||
(require 'comint)
|
(require 'comint)
|
||||||
|
|
||||||
(defconst mm/view-buffer-name "*mm-view*"
|
(defconst mu4e-view-buffer-name "*mu4e-view*"
|
||||||
"*internal* Name for the message view buffer")
|
"*internal* Name for the message view buffer")
|
||||||
|
|
||||||
(defconst mm/view-raw-buffer-name "*mm-view-raw*"
|
(defconst mu4e-view-raw-buffer-name "*mu4e-view-raw*"
|
||||||
"*internal* Name for the raw message view buffer")
|
"*internal* Name for the raw message view buffer")
|
||||||
|
|
||||||
;; some buffer-local variables
|
;; some buffer-local variables
|
||||||
(defvar mm/hdrs-buffer nil
|
(defvar mu4e-hdrs-buffer nil
|
||||||
"*internal* Headers buffer connected to this view.")
|
"*internal* Headers buffer connected to this view.")
|
||||||
|
|
||||||
(defvar mm/current-msg nil
|
(defvar mu4e-current-msg nil
|
||||||
"*internal* The plist describing the current message.")
|
"*internal* The plist describing the current message.")
|
||||||
|
|
||||||
(defun mm/view (msg hdrsbuf &optional update)
|
(defun mu4e-view (msg hdrsbuf &optional update)
|
||||||
"Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
|
"Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
|
||||||
'In sync' here means that moving to the next/previous message in
|
'In sync' here means that moving to the next/previous message in
|
||||||
the the message view affects HDRSBUF, as does marking etc. If
|
the the message view affects HDRSBUF, as does marking etc. If
|
||||||
@ -57,72 +57,72 @@ UPDATE is non-nil, the current message will be (visually) updated.
|
|||||||
|
|
||||||
As a side-effect, a message that is being viewed loses its 'unread'
|
As a side-effect, a message that is being viewed loses its 'unread'
|
||||||
marking if it still had that."
|
marking if it still had that."
|
||||||
(let ((buf (get-buffer-create mm/view-buffer-name))
|
(let ((buf (get-buffer-create mu4e-view-buffer-name))
|
||||||
(inhibit-read-only t))
|
(inhibit-read-only t))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert
|
(insert
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (field)
|
(lambda (field)
|
||||||
(let ((fieldname (cdr (assoc field mm/header-names)))
|
(let ((fieldname (cdr (assoc field mu4e-header-names)))
|
||||||
(fieldval (plist-get msg field)))
|
(fieldval (plist-get msg field)))
|
||||||
(case field
|
(case field
|
||||||
|
|
||||||
(:subject (mm/view-header fieldname fieldval))
|
(:subject (mu4e-view-header fieldname fieldval))
|
||||||
(:path (mm/view-header fieldname fieldval))
|
(:path (mu4e-view-header fieldname fieldval))
|
||||||
(:maildir (mm/view-header fieldname fieldval))
|
(:maildir (mu4e-view-header fieldname fieldval))
|
||||||
(:flags (mm/view-header fieldname
|
(:flags (mu4e-view-header fieldname
|
||||||
(if fieldval (format "%S" fieldval) "")))
|
(if fieldval (format "%S" fieldval) "")))
|
||||||
;; contact fields
|
;; contact fields
|
||||||
(:to (mm/view-contacts msg field))
|
(:to (mu4e-view-contacts msg field))
|
||||||
(:from (mm/view-contacts msg field))
|
(:from (mu4e-view-contacts msg field))
|
||||||
(:cc (mm/view-contacts msg field))
|
(:cc (mu4e-view-contacts msg field))
|
||||||
(:bcc (mm/view-contacts msg field))
|
(:bcc (mu4e-view-contacts msg field))
|
||||||
|
|
||||||
;; if we (`user-mail-address' are the From, show To, otherwise,
|
;; if we (`user-mail-address' are the From, show To, otherwise,
|
||||||
;; show From
|
;; show From
|
||||||
(:from-or-to
|
(:from-or-to
|
||||||
(let* ((from (plist-get msg :from))
|
(let* ((from (plist-get msg :from))
|
||||||
(from (and from (cdar from))))
|
(from (and from (cdar from))))
|
||||||
(if (and from (string-match mm/user-mail-address-regexp from))
|
(if (and from (string-match mu4e-user-mail-address-regexp from))
|
||||||
(mm/view-contacts msg :to)
|
(mu4e-view-contacts msg :to)
|
||||||
(mm/view-contacts msg :from))))
|
(mu4e-view-contacts msg :from))))
|
||||||
|
|
||||||
;; date
|
;; date
|
||||||
(:date
|
(:date
|
||||||
(let ((datestr
|
(let ((datestr
|
||||||
(when fieldval (format-time-string mm/view-date-format fieldval))))
|
(when fieldval (format-time-string mu4e-view-date-format fieldval))))
|
||||||
(if datestr (mm/view-header fieldname datestr) "")))
|
(if datestr (mu4e-view-header fieldname datestr) "")))
|
||||||
;; size
|
;; size
|
||||||
(:size (mm/view-size msg)
|
(:size (mu4e-view-size msg)
|
||||||
(let ((sizestr (when size (format "%d bytes"))))
|
(let ((sizestr (when size (format "%d bytes"))))
|
||||||
(if sizestr (mm/view-header fieldname sizestr))))
|
(if sizestr (mu4e-view-header fieldname sizestr))))
|
||||||
;; attachments
|
;; attachments
|
||||||
(:attachments (mm/view-attachments msg))
|
(:attachments (mu4e-view-attachments msg))
|
||||||
(t (error "Unsupported field: %S" field)))))
|
(t (error "Unsupported field: %S" field)))))
|
||||||
mm/view-fields "")
|
mu4e-view-fields "")
|
||||||
"\n"
|
"\n"
|
||||||
(mm/view-body msg))
|
(mu4e-view-body msg))
|
||||||
|
|
||||||
;; initialize view-mode
|
;; initialize view-mode
|
||||||
(mm/view-mode)
|
(mu4e-view-mode)
|
||||||
(setq ;; these are buffer-local
|
(setq ;; these are buffer-local
|
||||||
mode-name (if (plist-get msg :subject)
|
mode-name (if (plist-get msg :subject)
|
||||||
(truncate-string-to-width (plist-get msg :subject) 16 0 nil t)
|
(truncate-string-to-width (plist-get msg :subject) 16 0 nil t)
|
||||||
(propertize "No subject" 'face 'mm/system-face))
|
(propertize "No subject" 'face 'mu4e-system-face))
|
||||||
mm/current-msg msg
|
mu4e-current-msg msg
|
||||||
mm/hdrs-buffer hdrsbuf
|
mu4e-hdrs-buffer hdrsbuf
|
||||||
mm/link-map (make-hash-table :size 32 :rehash-size 2 :weakness nil))
|
mu4e-link-map (make-hash-table :size 32 :rehash-size 2 :weakness nil))
|
||||||
|
|
||||||
(switch-to-buffer buf)
|
(switch-to-buffer buf)
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(mm/view-beautify)
|
(mu4e-view-beautify)
|
||||||
|
|
||||||
(unless update
|
(unless update
|
||||||
(mm/view-mark-as-read-maybe)))))
|
(mu4e-view-mark-as-read-maybe)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-body (msg)
|
(defun mu4e-view-body (msg)
|
||||||
"Get the body for this message, which is either :body-txt,
|
"Get the body for this message, which is either :body-txt,
|
||||||
or if not available, :body-html converted to text)."
|
or if not available, :body-html converted to text)."
|
||||||
(or (plist-get msg :body-txt)
|
(or (plist-get msg :body-txt)
|
||||||
@ -133,22 +133,22 @@ or if not available, :body-html converted to text)."
|
|||||||
"No body found"))
|
"No body found"))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-header (key val &optional dont-propertize-val)
|
(defun mu4e-view-header (key val &optional dont-propertize-val)
|
||||||
"Show header FIELD for MSG with KEY. ie. <KEY>: value-of-FIELD."
|
"Show header FIELD for MSG with KEY. ie. <KEY>: value-of-FIELD."
|
||||||
(if val
|
(if val
|
||||||
(concat
|
(concat
|
||||||
(propertize key 'face 'mm/view-header-key-face) ": "
|
(propertize key 'face 'mu4e-view-header-key-face) ": "
|
||||||
(if dont-propertize-val
|
(if dont-propertize-val
|
||||||
val
|
val
|
||||||
(propertize val 'face 'mm/view-header-value-face))
|
(propertize val 'face 'mu4e-view-header-value-face))
|
||||||
"\n")
|
"\n")
|
||||||
""))
|
""))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-contacts (msg field)
|
(defun mu4e-view-contacts (msg field)
|
||||||
"Add a header for a contact field (ie., :to, :from, :cc, :bcc)."
|
"Add a header for a contact field (ie., :to, :from, :cc, :bcc)."
|
||||||
(let* ((lst (plist-get msg field))
|
(let* ((lst (plist-get msg field))
|
||||||
(fieldname (cdr (assoc field mm/header-names)))
|
(fieldname (cdr (assoc field mu4e-header-names)))
|
||||||
(contacts
|
(contacts
|
||||||
(and lst
|
(and lst
|
||||||
(mapconcat
|
(mapconcat
|
||||||
@ -158,20 +158,20 @@ or if not available, :body-html converted to text)."
|
|||||||
(format "%s <%s>" name email)
|
(format "%s <%s>" name email)
|
||||||
(format "%s" email)))) lst ", "))))
|
(format "%s" email)))) lst ", "))))
|
||||||
(if contacts
|
(if contacts
|
||||||
(mm/view-header fieldname contacts)
|
(mu4e-view-header fieldname contacts)
|
||||||
"")))
|
"")))
|
||||||
|
|
||||||
(defvar mm/attach-map nil
|
(defvar mu4e-attach-map nil
|
||||||
"*internal* Hash which maps a number to a (part-id name mime-type).")
|
"*internal* Hash which maps a number to a (part-id name mime-type).")
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-attachments (msg)
|
(defun mu4e-view-attachments (msg)
|
||||||
"Display attachment information; the field looks like something like:
|
"Display attachment information; the field looks like something like:
|
||||||
:attachments ((:index 4 :name \"test123.doc\"
|
:attachments ((:index 4 :name \"test123.doc\"
|
||||||
:mime-type \"application/msword\" :size 1234))."
|
:mime-type \"application/msword\" :size 1234))."
|
||||||
(let ((atts (plist-get msg :attachments)))
|
(let ((atts (plist-get msg :attachments)))
|
||||||
(when atts
|
(when atts
|
||||||
(setq mm/attach-map
|
(setq mu4e-attach-map
|
||||||
(make-hash-table :size 32 :rehash-size 2 :weakness nil))
|
(make-hash-table :size 32 :rehash-size 2 :weakness nil))
|
||||||
(let* ((id 0)
|
(let* ((id 0)
|
||||||
(vals
|
(vals
|
||||||
@ -182,42 +182,42 @@ or if not available, :body-html converted to text)."
|
|||||||
(mime-type (plist-get att :mime-type))
|
(mime-type (plist-get att :mime-type))
|
||||||
(size (plist-get att :size)))
|
(size (plist-get att :size)))
|
||||||
(incf id)
|
(incf id)
|
||||||
(puthash id att mm/attach-map)
|
(puthash id att mu4e-attach-map)
|
||||||
(concat
|
(concat
|
||||||
(propertize (format "[%d]" id) 'face 'mm/view-attach-number-face)
|
(propertize (format "[%d]" id) 'face 'mu4e-view-attach-number-face)
|
||||||
(propertize name 'face 'mm/view-link-face)
|
(propertize name 'face 'mu4e-view-link-face)
|
||||||
(if size
|
(if size
|
||||||
(concat
|
(concat
|
||||||
"(" (propertize (mm/display-size size) 'face 'mm/view-header-key-face)
|
"(" (propertize (mu4e-display-size size) 'face 'mu4e-view-header-key-face)
|
||||||
")")
|
")")
|
||||||
"")
|
"")
|
||||||
)))
|
)))
|
||||||
atts ", ")))
|
atts ", ")))
|
||||||
(mm/view-header (format "Attachments(%d)" id) vals t)))))
|
(mu4e-view-header (format "Attachments(%d)" id) vals t)))))
|
||||||
|
|
||||||
|
|
||||||
(defvar mm/view-mode-map nil
|
(defvar mu4e-view-mode-map nil
|
||||||
"Keymap for \"*mm-view*\" buffers.")
|
"Keymap for \"*mu4e-view*\" buffers.")
|
||||||
(unless mm/view-mode-map
|
(unless mu4e-view-mode-map
|
||||||
(setq mm/view-mode-map
|
(setq mu4e-view-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
(define-key map "q" 'mm/view-quit-buffer)
|
(define-key map "q" 'mu4e-view-quit-buffer)
|
||||||
|
|
||||||
(define-key map "s" 'mm/search)
|
(define-key map "s" 'mu4e-search)
|
||||||
(define-key map "S" 'mm/search-full)
|
(define-key map "S" 'mu4e-search-full)
|
||||||
|
|
||||||
(define-key map "b" 'mm/search-bookmark)
|
(define-key map "b" 'mu4e-search-bookmark)
|
||||||
(define-key map "j" 'mm/jump-to-maildir)
|
(define-key map "j" 'mu4e-jump-to-maildir)
|
||||||
|
|
||||||
(define-key map "g" 'mm/view-go-to-url)
|
(define-key map "g" 'mu4e-view-go-to-url)
|
||||||
(define-key map "f" 'mm/compose-forward)
|
(define-key map "f" 'mu4e-compose-forward)
|
||||||
(define-key map "r" 'mm/compose-reply)
|
(define-key map "r" 'mu4e-compose-reply)
|
||||||
(define-key map "c" 'mm/compose-new)
|
(define-key map "c" 'mu4e-compose-new)
|
||||||
(define-key map "e" 'mm/edit-draft)
|
(define-key map "e" 'mu4e-edit-draft)
|
||||||
|
|
||||||
(define-key map "." 'mm/view-raw)
|
(define-key map "." 'mu4e-view-raw)
|
||||||
(define-key map "|" 'mm/view-pipe)
|
(define-key map "|" 'mu4e-view-pipe)
|
||||||
;; (define-key map "I" 'mm/inspect-message)
|
;; (define-key map "I" 'mu4e-inspect-message)
|
||||||
|
|
||||||
;; intra-message navigation
|
;; intra-message navigation
|
||||||
(define-key map (kbd "SPC") 'scroll-up)
|
(define-key map (kbd "SPC") 'scroll-up)
|
||||||
@ -232,109 +232,109 @@ or if not available, :body-html converted to text)."
|
|||||||
|
|
||||||
|
|
||||||
;; navigation between messages
|
;; navigation between messages
|
||||||
(define-key map "n" 'mm/view-next-header)
|
(define-key map "n" 'mu4e-view-next-header)
|
||||||
(define-key map "p" 'mm/view-prev-header)
|
(define-key map "p" 'mu4e-view-prev-header)
|
||||||
|
|
||||||
;; attachments
|
;; attachments
|
||||||
(define-key map "e" 'mm/view-extract-attachment)
|
(define-key map "e" 'mu4e-view-extract-attachment)
|
||||||
(define-key map "o" 'mm/view-open-attachment)
|
(define-key map "o" 'mu4e-view-open-attachment)
|
||||||
|
|
||||||
;; marking/unmarking
|
;; marking/unmarking
|
||||||
(define-key map (kbd "<backspace>") 'mm/mark-for-trash)
|
(define-key map (kbd "<backspace>") 'mu4e-mark-for-trash)
|
||||||
(define-key map "d" 'mm/view-mark-for-trash)
|
(define-key map "d" 'mu4e-view-mark-for-trash)
|
||||||
|
|
||||||
(define-key map (kbd "<delete>") 'mm/view-mark-for-delete)
|
(define-key map (kbd "<delete>") 'mu4e-view-mark-for-delete)
|
||||||
(define-key map "D" 'mm/view-mark-for-delete)
|
(define-key map "D" 'mu4e-view-mark-for-delete)
|
||||||
(define-key map "a" 'mm/mark-for-move-quick)
|
(define-key map "a" 'mu4e-mark-for-move-quick)
|
||||||
|
|
||||||
(define-key map "m" 'mm/view-mark-for-move)
|
(define-key map "m" 'mu4e-view-mark-for-move)
|
||||||
|
|
||||||
;; misc
|
;; misc
|
||||||
(define-key map "w" 'mm/view-toggle-wrap-lines)
|
(define-key map "w" 'mu4e-view-toggle-wrap-lines)
|
||||||
(define-key map "h" 'mm/view-toggle-hide-cited)
|
(define-key map "h" 'mu4e-view-toggle-hide-cited)
|
||||||
|
|
||||||
(define-key map "R" 'mm/view-refresh)
|
(define-key map "R" 'mu4e-view-refresh)
|
||||||
|
|
||||||
;; next 3 only warn user when attempt in the message view
|
;; next 3 only warn user when attempt in the message view
|
||||||
(define-key map "u" 'mm/view-unmark)
|
(define-key map "u" 'mu4e-view-unmark)
|
||||||
(define-key map "U" 'mm/view-unmark)
|
(define-key map "U" 'mu4e-view-unmark)
|
||||||
(define-key map "x" 'mm/view-marked-execute)
|
(define-key map "x" 'mu4e-view-marked-execute)
|
||||||
|
|
||||||
;; menu
|
;; menu
|
||||||
(define-key map [menu-bar] (make-sparse-keymap))
|
(define-key map [menu-bar] (make-sparse-keymap))
|
||||||
(let ((menumap (make-sparse-keymap "View")))
|
(let ((menumap (make-sparse-keymap "View")))
|
||||||
(define-key map [menu-bar headers] (cons "View" menumap))
|
(define-key map [menu-bar headers] (cons "View" menumap))
|
||||||
|
|
||||||
(define-key menumap [quit-buffer] '("Quit view" . mm/view-quit-buffer))
|
(define-key menumap [quit-buffer] '("Quit view" . mu4e-view-quit-buffer))
|
||||||
|
|
||||||
(define-key menumap [sepa0] '("--"))
|
(define-key menumap [sepa0] '("--"))
|
||||||
(define-key menumap [wrap-lines]
|
(define-key menumap [wrap-lines]
|
||||||
'("Toggle wrap lines" . mm/view-toggle-wrap-lines))
|
'("Toggle wrap lines" . mu4e-view-toggle-wrap-lines))
|
||||||
(define-key menumap [hide-cited]
|
(define-key menumap [hide-cited]
|
||||||
'("Toggle hide cited" . mm/view-toggle-hide-cited))
|
'("Toggle hide cited" . mu4e-view-toggle-hide-cited))
|
||||||
(define-key menumap [view-raw]
|
(define-key menumap [view-raw]
|
||||||
'("View raw message" . mm/view-raw))
|
'("View raw message" . mu4e-view-raw))
|
||||||
(define-key menumap [pipe]
|
(define-key menumap [pipe]
|
||||||
'("Pipe through shell" . mm/view-pipe))
|
'("Pipe through shell" . mu4e-view-pipe))
|
||||||
(define-key menumap [inspect]
|
(define-key menumap [inspect]
|
||||||
'("Inspect with guile" . mm/inspect-message))
|
'("Inspect with guile" . mu4e-inspect-message))
|
||||||
|
|
||||||
(define-key menumap [sepa8] '("--"))
|
(define-key menumap [sepa8] '("--"))
|
||||||
(define-key menumap [open-att]
|
(define-key menumap [open-att]
|
||||||
'("Open attachment" . mm/view-open-attachment))
|
'("Open attachment" . mu4e-view-open-attachment))
|
||||||
(define-key menumap [extract-att]
|
(define-key menumap [extract-att]
|
||||||
'("Extract attachment" . mm/view-extract-attachment))
|
'("Extract attachment" . mu4e-view-extract-attachment))
|
||||||
(define-key menumap [goto-url]
|
(define-key menumap [goto-url]
|
||||||
'("Visit URL" . mm/view-go-to-url))
|
'("Visit URL" . mu4e-view-go-to-url))
|
||||||
|
|
||||||
(define-key menumap [sepa1] '("--"))
|
(define-key menumap [sepa1] '("--"))
|
||||||
(define-key menumap [mark-delete]
|
(define-key menumap [mark-delete]
|
||||||
'("Mark for deletion" . mm/view-mark-for-delete))
|
'("Mark for deletion" . mu4e-view-mark-for-delete))
|
||||||
(define-key menumap [mark-trash]
|
(define-key menumap [mark-trash]
|
||||||
'("Mark for trash" . mm/view-mark-for-trash))
|
'("Mark for trash" . mu4e-view-mark-for-trash))
|
||||||
(define-key menumap [mark-move]
|
(define-key menumap [mark-move]
|
||||||
'("Mark for move" . mm/view-mark-for-move))
|
'("Mark for move" . mu4e-view-mark-for-move))
|
||||||
|
|
||||||
(define-key menumap [sepa2] '("--"))
|
(define-key menumap [sepa2] '("--"))
|
||||||
(define-key menumap [compose-new] '("Compose new" . mm/compose-new))
|
(define-key menumap [compose-new] '("Compose new" . mu4e-compose-new))
|
||||||
(define-key menumap [forward] '("Forward" . mm/compose-forward))
|
(define-key menumap [forward] '("Forward" . mu4e-compose-forward))
|
||||||
(define-key menumap [reply] '("Reply" . mm/compose-reply))
|
(define-key menumap [reply] '("Reply" . mu4e-compose-reply))
|
||||||
(define-key menumap [sepa3] '("--"))
|
(define-key menumap [sepa3] '("--"))
|
||||||
|
|
||||||
(define-key menumap [search] '("Search" . mm/search))
|
(define-key menumap [search] '("Search" . mu4e-search))
|
||||||
(define-key menumap [jump] '("Jump to maildir" . mm/jump-to-maildir))
|
(define-key menumap [jump] '("Jump to maildir" . mu4e-jump-to-maildir))
|
||||||
|
|
||||||
(define-key menumap [sepa4] '("--"))
|
(define-key menumap [sepa4] '("--"))
|
||||||
(define-key menumap [next] '("Next" . mm/view-next-header))
|
(define-key menumap [next] '("Next" . mu4e-view-next-header))
|
||||||
(define-key menumap [previous] '("Previous" . mm/view-prev-header)))
|
(define-key menumap [previous] '("Previous" . mu4e-view-prev-header)))
|
||||||
map)))
|
map)))
|
||||||
|
|
||||||
(fset 'mm/view-mode-map mm/view-mode-map)
|
(fset 'mu4e-view-mode-map mu4e-view-mode-map)
|
||||||
|
|
||||||
|
|
||||||
(defvar mm/wrap-lines nil
|
(defvar mu4e-wrap-lines nil
|
||||||
"*internal* Whether to wrap lines or not (variable controlled by
|
"*internal* Whether to wrap lines or not (variable controlled by
|
||||||
`mm/view-toggle-wrap-lines').")
|
`mu4e-view-toggle-wrap-lines').")
|
||||||
|
|
||||||
(defvar mm/hide-cited nil
|
(defvar mu4e-hide-cited nil
|
||||||
"*internal* Whether to hide cited lines or not (the variable can
|
"*internal* Whether to hide cited lines or not (the variable can
|
||||||
be changed with `mm/view-toggle-hide-cited').")
|
be changed with `mu4e-view-toggle-hide-cited').")
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-mode ()
|
(defun mu4e-view-mode ()
|
||||||
"Major mode for viewing an e-mail message."
|
"Major mode for viewing an e-mail message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(kill-all-local-variables)
|
(kill-all-local-variables)
|
||||||
(use-local-map mm/view-mode-map)
|
(use-local-map mu4e-view-mode-map)
|
||||||
|
|
||||||
(make-local-variable 'mm/hdrs-buffer)
|
(make-local-variable 'mu4e-hdrs-buffer)
|
||||||
(make-local-variable 'mm/current-msg)
|
(make-local-variable 'mu4e-current-msg)
|
||||||
(make-local-variable 'mm/link-map)
|
(make-local-variable 'mu4e-link-map)
|
||||||
|
|
||||||
(make-local-variable 'mm/wrap-lines)
|
(make-local-variable 'mu4e-wrap-lines)
|
||||||
(make-local-variable 'mm/hide-cited)
|
(make-local-variable 'mu4e-hide-cited)
|
||||||
|
|
||||||
(setq major-mode 'mm/view-mode mode-name mm/view-buffer-name)
|
(setq major-mode 'mu4e-view-mode mode-name mu4e-view-buffer-name)
|
||||||
(setq truncate-lines t buffer-read-only t))
|
(setq truncate-lines t buffer-read-only t))
|
||||||
|
|
||||||
;;;;;;
|
;;;;;;
|
||||||
@ -343,21 +343,21 @@ or if not available, :body-html converted to text)."
|
|||||||
;; we mark messages are as read when we leave the message; ie., when skipping to
|
;; we mark messages are as read when we leave the message; ie., when skipping to
|
||||||
;; the next/previous one, or leaving the view buffer altogether.
|
;; the next/previous one, or leaving the view buffer altogether.
|
||||||
|
|
||||||
(defun mm/view-mark-as-read-maybe ()
|
(defun mu4e-view-mark-as-read-maybe ()
|
||||||
"Clear the current message's New/Unread status and set it to
|
"Clear the current message's New/Unread status and set it to
|
||||||
Seen; if the message is not New/Unread, do nothing."
|
Seen; if the message is not New/Unread, do nothing."
|
||||||
(when mm/current-msg
|
(when mu4e-current-msg
|
||||||
(let ((flags (plist-get mm/current-msg :flags))
|
(let ((flags (plist-get mu4e-current-msg :flags))
|
||||||
(docid (plist-get mm/current-msg :docid)))
|
(docid (plist-get mu4e-current-msg :docid)))
|
||||||
;; is it a new message?
|
;; is it a new message?
|
||||||
(when (or (member 'unread flags) (member 'new flags))
|
(when (or (member 'unread flags) (member 'new flags))
|
||||||
(mm/proc-flag docid "+S-u-N")))))
|
(mu4e-proc-flag docid "+S-u-N")))))
|
||||||
|
|
||||||
|
|
||||||
(defvar mm/link-map nil
|
(defvar mu4e-link-map nil
|
||||||
"*internal* A map of some number->url so we can jump to url by number.")
|
"*internal* A map of some number->url so we can jump to url by number.")
|
||||||
|
|
||||||
(defun mm/view-beautify ()
|
(defun mu4e-view-beautify ()
|
||||||
"Improve the message view a bit, by making URLs clickable,
|
"Improve the message view a bit, by making URLs clickable,
|
||||||
removing '^M' etc."
|
removing '^M' etc."
|
||||||
(let ((num 0))
|
(let ((num 0))
|
||||||
@ -370,47 +370,47 @@ removing '^M' etc."
|
|||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(let ((p (search-forward "\n-- \n" nil t)))
|
(let ((p (search-forward "\n-- \n" nil t)))
|
||||||
(when p
|
(when p
|
||||||
(add-text-properties p (point-max) '(face mm/view-footer-face))))
|
(add-text-properties p (point-max) '(face mu4e-view-footer-face))))
|
||||||
;; this is fairly simplistic...
|
;; this is fairly simplistic...
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (re-search-forward "\\(https?://[-a-zA-Z0-9?_.$%/=+&#@!~,:;]*\\)\\>"
|
(while (re-search-forward "\\(https?://[-a-zA-Z0-9?_.$%/=+&#@!~,:;]*\\)\\>"
|
||||||
nil t)
|
nil t)
|
||||||
(let ((subst (propertize (match-string-no-properties 0)
|
(let ((subst (propertize (match-string-no-properties 0)
|
||||||
'face 'mm/view-link-face)))
|
'face 'mu4e-view-link-face)))
|
||||||
(incf num)
|
(incf num)
|
||||||
(puthash num (match-string-no-properties 0) mm/link-map)
|
(puthash num (match-string-no-properties 0) mu4e-link-map)
|
||||||
(replace-match (concat subst
|
(replace-match (concat subst
|
||||||
(propertize (format "[%d]" num)
|
(propertize (format "[%d]" num)
|
||||||
'face 'mm/view-url-number-face))))))))
|
'face 'mu4e-view-url-number-face))))))))
|
||||||
|
|
||||||
|
|
||||||
;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; some buffer-local variables
|
;; some buffer-local variables
|
||||||
(defvar mm/view-buffer nil
|
(defvar mu4e-view-buffer nil
|
||||||
"*internal* View buffer connected to this raw view.")
|
"*internal* View buffer connected to this raw view.")
|
||||||
|
|
||||||
(defun mm/view-raw-mode ()
|
(defun mu4e-view-raw-mode ()
|
||||||
"Major mode for viewing of raw e-mail message."
|
"Major mode for viewing of raw e-mail message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(kill-all-local-variables)
|
(kill-all-local-variables)
|
||||||
(use-local-map mm/view-raw-mode-map)
|
(use-local-map mu4e-view-raw-mode-map)
|
||||||
|
|
||||||
(make-local-variable 'mm/view-buffer)
|
(make-local-variable 'mu4e-view-buffer)
|
||||||
|
|
||||||
(setq major-mode 'mm/view-raw-mode
|
(setq major-mode 'mu4e-view-raw-mode
|
||||||
mode-name "mm: raw view")
|
mode-name "mm: raw view")
|
||||||
(setq truncate-lines t buffer-read-only t))
|
(setq truncate-lines t buffer-read-only t))
|
||||||
|
|
||||||
(defvar mm/view-raw-mode-map nil
|
(defvar mu4e-view-raw-mode-map nil
|
||||||
"Keymap for \"*mm-view-raw*\" buffers.")
|
"Keymap for \"*mu4e-view-raw*\" buffers.")
|
||||||
|
|
||||||
(unless mm/view-raw-mode-map
|
(unless mu4e-view-raw-mode-map
|
||||||
(setq mm/view-raw-mode-map
|
(setq mu4e-view-raw-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
|
|
||||||
(define-key map "q" 'mm/view-raw-quit-buffer)
|
(define-key map "q" 'mu4e-view-raw-quit-buffer)
|
||||||
(define-key map "." 'mm/view-raw-quit-buffer)
|
(define-key map "." 'mu4e-view-raw-quit-buffer)
|
||||||
|
|
||||||
;; intra-message navigation
|
;; intra-message navigation
|
||||||
(define-key map (kbd "SPC") 'scroll-up)
|
(define-key map (kbd "SPC") 'scroll-up)
|
||||||
@ -428,15 +428,15 @@ removing '^M' etc."
|
|||||||
(let ((menumap (make-sparse-keymap "Raw view")))
|
(let ((menumap (make-sparse-keymap "Raw view")))
|
||||||
(define-key map [menu-bar headers] (cons "Raw view" menumap))
|
(define-key map [menu-bar headers] (cons "Raw view" menumap))
|
||||||
(define-key menumap [quit-buffer] '("Quit" .
|
(define-key menumap [quit-buffer] '("Quit" .
|
||||||
mm/view-raw-quit-buffer))
|
mu4e-view-raw-quit-buffer))
|
||||||
map))))
|
map))))
|
||||||
|
|
||||||
(fset 'mm/view-raw-mode-map mm/view-raw-mode-map)
|
(fset 'mu4e-view-raw-mode-map mu4e-view-raw-mode-map)
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-raw-message (msg view-buffer)
|
(defun mu4e-view-raw-message (msg view-buffer)
|
||||||
"Display the raw contents of message MSG in a new buffer."
|
"Display the raw contents of message MSG in a new buffer."
|
||||||
(let ((buf (get-buffer-create mm/view-raw-buffer-name))
|
(let ((buf (get-buffer-create mu4e-view-raw-buffer-name))
|
||||||
(inhibit-read-only t)
|
(inhibit-read-only t)
|
||||||
(file (plist-get msg :path)))
|
(file (plist-get msg :path)))
|
||||||
(unless (and file (file-readable-p file))
|
(unless (and file (file-readable-p file))
|
||||||
@ -445,15 +445,15 @@ removing '^M' etc."
|
|||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert-file file)
|
(insert-file file)
|
||||||
;; initialize view-mode
|
;; initialize view-mode
|
||||||
(mm/view-raw-mode)
|
(mu4e-view-raw-mode)
|
||||||
(setq mm/view-buffer view-buffer)
|
(setq mu4e-view-buffer view-buffer)
|
||||||
(switch-to-buffer buf)
|
(switch-to-buffer buf)
|
||||||
(goto-char (point-min)))))
|
(goto-char (point-min)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-shell-command-on-raw-message (msg view-buffer cmd)
|
(defun mu4e-view-shell-command-on-raw-message (msg view-buffer cmd)
|
||||||
"Process the raw message with shell command CMD."
|
"Process the raw message with shell command CMD."
|
||||||
(let ((buf (get-buffer-create mm/view-raw-buffer-name))
|
(let ((buf (get-buffer-create mu4e-view-raw-buffer-name))
|
||||||
(inhibit-read-only t)
|
(inhibit-read-only t)
|
||||||
(file (plist-get msg :path)))
|
(file (plist-get msg :path)))
|
||||||
(unless (and file (file-readable-p file))
|
(unless (and file (file-readable-p file))
|
||||||
@ -461,41 +461,41 @@ removing '^M' etc."
|
|||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(process-file-shell-command cmd file buf)
|
(process-file-shell-command cmd file buf)
|
||||||
(mm/view-raw-mode)
|
(mu4e-view-raw-mode)
|
||||||
(setq mm/view-buffer view-buffer)
|
(setq mu4e-view-buffer view-buffer)
|
||||||
(switch-to-buffer buf)
|
(switch-to-buffer buf)
|
||||||
(goto-char (point-min)))))
|
(goto-char (point-min)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-raw-quit-buffer ()
|
(defun mu4e-view-raw-quit-buffer ()
|
||||||
"Quit the raw view and return to the message."
|
"Quit the raw view and return to the message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(if (buffer-live-p mm/view-buffer)
|
(if (buffer-live-p mu4e-view-buffer)
|
||||||
(switch-to-buffer mm/view-buffer)
|
(switch-to-buffer mu4e-view-buffer)
|
||||||
(kill-buffer)))
|
(kill-buffer)))
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; functions for org-contacts
|
;; functions for org-contacts
|
||||||
|
|
||||||
(defun mm/org-contacts-from (name-or-email)
|
(defun mu4e-org-contacts-from (name-or-email)
|
||||||
"Get a message field if we are in view mode; NAME-OR-EMAIL should
|
"Get a message field if we are in view mode; NAME-OR-EMAIL should
|
||||||
be either 'name or 'email to get the corresponding field. If the
|
be either 'name or 'email to get the corresponding field. If the
|
||||||
field is not found, \"\" is returned. Use this with org-contact
|
field is not found, \"\" is returned. Use this with org-contact
|
||||||
with a template like:
|
with a template like:
|
||||||
|
|
||||||
(\"c\" \"Contacts\" entry (file \"~/Org/contacts.org\")
|
(\"c\" \"Contacts\" entry (file \"~/Org/contacts.org\")
|
||||||
\"* %(mm/org-contacts-from 'name)
|
\"* %(mu4e-org-contacts-from 'name)
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:EMAIL: %(mm/org-contacts-from 'email)
|
:EMAIL: %(mu4e-org-contacts-from 'email)
|
||||||
:END:\")))
|
:END:\")))
|
||||||
|
|
||||||
See the `org-contacts' documentation for more details."
|
See the `org-contacts' documentation for more details."
|
||||||
(with-current-buffer mm/view-buffer-name ;; hackish...
|
(with-current-buffer mu4e-view-buffer-name ;; hackish...
|
||||||
(unless (eq major-mode 'mm/view-mode)
|
(unless (eq major-mode 'mu4e-view-mode)
|
||||||
(error "Not in mm/view mode."))
|
(error "Not in mu4e-view mode."))
|
||||||
(unless mm/current-msg
|
(unless mu4e-current-msg
|
||||||
(error "No current message."))
|
(error "No current message."))
|
||||||
(let ((from (car-safe (plist-get mm/current-msg :from))))
|
(let ((from (car-safe (plist-get mu4e-current-msg :from))))
|
||||||
(cond
|
(cond
|
||||||
((not from) "") ;; nothing found
|
((not from) "") ;; nothing found
|
||||||
((eq name-or-email 'name)
|
((eq name-or-email 'name)
|
||||||
@ -511,85 +511,85 @@ See the `org-contacts' documentation for more details."
|
|||||||
|
|
||||||
;; Interactive functions
|
;; Interactive functions
|
||||||
|
|
||||||
(defun mm/view-toggle-wrap-lines ()
|
(defun mu4e-view-toggle-wrap-lines ()
|
||||||
"Toggle line wrap in the message body."
|
"Toggle line wrap in the message body."
|
||||||
(interactive)
|
(interactive)
|
||||||
(if mm/wrap-lines
|
(if mu4e-wrap-lines
|
||||||
(progn
|
(progn
|
||||||
(setq mm/wrap-lines nil)
|
(setq mu4e-wrap-lines nil)
|
||||||
(mm/view-refresh)) ;; back to normal
|
(mu4e-view-refresh)) ;; back to normal
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
(setq mm/wrap-lines t)
|
(setq mu4e-wrap-lines t)
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(when (search-forward "\n\n") ;; search for the message body
|
(when (search-forward "\n\n") ;; search for the message body
|
||||||
(fill-region (point) (point-max)))))))
|
(fill-region (point) (point-max)))))))
|
||||||
|
|
||||||
(defun mm/view-toggle-hide-cited ()
|
(defun mu4e-view-toggle-hide-cited ()
|
||||||
"Toggle hiding of cited lines in the message body."
|
"Toggle hiding of cited lines in the message body."
|
||||||
(interactive)
|
(interactive)
|
||||||
(if mm/hide-cited
|
(if mu4e-hide-cited
|
||||||
(progn
|
(progn
|
||||||
(setq mm/hide-cited nil)
|
(setq mu4e-hide-cited nil)
|
||||||
(mm/view-refresh))
|
(mu4e-view-refresh))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(flush-lines "^[:blank:]*>")
|
(flush-lines "^[:blank:]*>")
|
||||||
(setq mm/hide-cited t)))))
|
(setq mu4e-hide-cited t)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-refresh ()
|
(defun mu4e-view-refresh ()
|
||||||
"Redisplay the current message."
|
"Redisplay the current message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(mm/view mm/current-msg mm/hdrs-buffer t))
|
(mu4e-view mu4e-current-msg mu4e-hdrs-buffer t))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-quit-buffer ()
|
(defun mu4e-view-quit-buffer ()
|
||||||
"Quit the message view and return to the headers."
|
"Quit the message view and return to the headers."
|
||||||
(interactive)
|
(interactive)
|
||||||
(if (buffer-live-p mm/hdrs-buffer)
|
(if (buffer-live-p mu4e-hdrs-buffer)
|
||||||
(switch-to-buffer mm/hdrs-buffer)
|
(switch-to-buffer mu4e-hdrs-buffer)
|
||||||
(kill-buffer)))
|
(kill-buffer)))
|
||||||
|
|
||||||
(defun mm/view-next-header ()
|
(defun mu4e-view-next-header ()
|
||||||
"View the next header."
|
"View the next header."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/next-header)
|
(when (mu4e-next-header)
|
||||||
(mm/view-message)))
|
(mu4e-view-message)))
|
||||||
|
|
||||||
(defun mm/view-prev-header ()
|
(defun mu4e-view-prev-header ()
|
||||||
"View the previous header."
|
"View the previous header."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/prev-header)
|
(when (mu4e-prev-header)
|
||||||
(mm/view-message)))
|
(mu4e-view-message)))
|
||||||
|
|
||||||
(defun mm/view-mark-for-move ()
|
(defun mu4e-view-mark-for-move ()
|
||||||
"Mark the current message for moving."
|
"Mark the current message for moving."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/mark-for-move)
|
(when (mu4e-mark-for-move)
|
||||||
(mm/view-message)))
|
(mu4e-view-message)))
|
||||||
|
|
||||||
(defun mm/view-mark-for-trash ()
|
(defun mu4e-view-mark-for-trash ()
|
||||||
"Mark the current message for moving to the trash folder."
|
"Mark the current message for moving to the trash folder."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/mark-for-trash)
|
(when (mu4e-mark-for-trash)
|
||||||
(mm/view-message)))
|
(mu4e-view-message)))
|
||||||
|
|
||||||
(defun mm/view-mark-for-delete ()
|
(defun mu4e-view-mark-for-delete ()
|
||||||
"Mark the current message for deletion."
|
"Mark the current message for deletion."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (mm/mark-for-delete)
|
(when (mu4e-mark-for-delete)
|
||||||
(mm/view-message)))
|
(mu4e-view-message)))
|
||||||
|
|
||||||
(defun mm/view-extract-attachment (attnum)
|
(defun mu4e-view-extract-attachment (attnum)
|
||||||
"Extract the attachment with ATTNUM."
|
"Extract the attachment with ATTNUM."
|
||||||
(unless mm/attachment-dir (error "`mm/attachment-dir' is not set"))
|
(unless mu4e-attachment-dir (error "`mu4e-attachment-dir' is not set"))
|
||||||
(when (or (null mm/attach-map) (zerop (hash-table-count mm/attach-map)))
|
(when (or (null mu4e-attach-map) (zerop (hash-table-count mu4e-attach-map)))
|
||||||
(error "No attachments for this message"))
|
(error "No attachments for this message"))
|
||||||
(interactive "nAttachment to extract:")
|
(interactive "nAttachment to extract:")
|
||||||
(let* ((att (gethash attnum mm/attach-map))
|
(let* ((att (gethash attnum mu4e-attach-map))
|
||||||
(path (and att (concat mm/attachment-dir
|
(path (and att (concat mu4e-attachment-dir
|
||||||
"/" (plist-get att :name))))
|
"/" (plist-get att :name))))
|
||||||
(id (and att (plist-get att :index)))
|
(id (and att (plist-get att :index)))
|
||||||
(retry t))
|
(retry t))
|
||||||
@ -599,74 +599,74 @@ See the `org-contacts' documentation for more details."
|
|||||||
(setq retry
|
(setq retry
|
||||||
(and (file-exists-p path)
|
(and (file-exists-p path)
|
||||||
(not (y-or-n-p (concat "Overwrite " path "?"))))))
|
(not (y-or-n-p (concat "Overwrite " path "?"))))))
|
||||||
(mm/proc-save (plist-get mm/current-msg :docid) id path)))
|
(mu4e-proc-save (plist-get mu4e-current-msg :docid) id path)))
|
||||||
|
|
||||||
(defun mm/view-open-attachment (attnum)
|
(defun mu4e-view-open-attachment (attnum)
|
||||||
"Extract the attachment with ATTNUM"
|
"Extract the attachment with ATTNUM"
|
||||||
(unless mm/attach-map
|
(unless mu4e-attach-map
|
||||||
(error "No attachments for this message"))
|
(error "No attachments for this message"))
|
||||||
(interactive "nAttachment to open:")
|
(interactive "nAttachment to open:")
|
||||||
(let* ((att (gethash attnum mm/attach-map))
|
(let* ((att (gethash attnum mu4e-attach-map))
|
||||||
(id (and att (plist-get att :index))))
|
(id (and att (plist-get att :index))))
|
||||||
(unless id (error "Not a valid attachment number"))
|
(unless id (error "Not a valid attachment number"))
|
||||||
(mm/proc-open (plist-get mm/current-msg :docid) id)))
|
(mu4e-proc-open (plist-get mu4e-current-msg :docid) id)))
|
||||||
|
|
||||||
(defun mm/view-unmark ()
|
(defun mu4e-view-unmark ()
|
||||||
"Warn user that unmarking only works in the header list."
|
"Warn user that unmarking only works in the header list."
|
||||||
(interactive)
|
(interactive)
|
||||||
(message "Unmarking needs to be done in the header list view"))
|
(message "Unmarking needs to be done in the header list view"))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/view-marked-execute ()
|
(defun mu4e-view-marked-execute ()
|
||||||
"Warn user that execution can only take place in n the header
|
"Warn user that execution can only take place in n the header
|
||||||
list."
|
list."
|
||||||
(interactive)
|
(interactive)
|
||||||
(message "Execution needs to be done in the header list view"))
|
(message "Execution needs to be done in the header list view"))
|
||||||
|
|
||||||
(defun mm/view-go-to-url (num)
|
(defun mu4e-view-go-to-url (num)
|
||||||
"Go to a numbered url."
|
"Go to a numbered url."
|
||||||
(interactive "nGo to url with number: ")
|
(interactive "nGo to url with number: ")
|
||||||
(let ((url (gethash num mm/link-map)))
|
(let ((url (gethash num mu4e-link-map)))
|
||||||
(unless url (error "Invalid number for URL"))
|
(unless url (error "Invalid number for URL"))
|
||||||
(browse-url url)))
|
(browse-url url)))
|
||||||
|
|
||||||
(defun mm/view-raw ()
|
(defun mu4e-view-raw ()
|
||||||
"Show the the raw text of the current message."
|
"Show the the raw text of the current message."
|
||||||
(interactive)
|
(interactive)
|
||||||
(unless mm/current-msg
|
(unless mu4e-current-msg
|
||||||
(error "No current message"))
|
(error "No current message"))
|
||||||
(mm/view-raw-message mm/current-msg (current-buffer)))
|
(mu4e-view-raw-message mu4e-current-msg (current-buffer)))
|
||||||
|
|
||||||
(defun mm/view-pipe (cmd)
|
(defun mu4e-view-pipe (cmd)
|
||||||
"Pipe the message through shell command CMD, and display the
|
"Pipe the message through shell command CMD, and display the
|
||||||
results."
|
results."
|
||||||
(interactive "sShell command: ")
|
(interactive "sShell command: ")
|
||||||
(unless mm/current-msg
|
(unless mu4e-current-msg
|
||||||
(error "No current message"))
|
(error "No current message"))
|
||||||
(mm/view-shell-command-on-raw-message mm/current-msg (current-buffer) cmd))
|
(mu4e-view-shell-command-on-raw-message mu4e-current-msg (current-buffer) cmd))
|
||||||
|
|
||||||
(defconst mm/muile-buffer-name "*muile*"
|
(defconst mu4e-muile-buffer-name "*muile*"
|
||||||
"Name of the buffer to execute muile.")
|
"Name of the buffer to execute muile.")
|
||||||
|
|
||||||
(defconst mm/muile-process-name "*muile*"
|
(defconst mu4e-muile-process-name "*muile*"
|
||||||
"Name of the muile process.")
|
"Name of the muile process.")
|
||||||
|
|
||||||
;; note, implementation is very basic/primitive; we probably need comint to do
|
;; note, implementation is very basic/primitive; we probably need comint to do
|
||||||
;; something like geiser does (http://www.nongnu.org/geiser/). Desirable
|
;; something like geiser does (http://www.nongnu.org/geiser/). Desirable
|
||||||
;; features: a) the output is not editable b) tab-completions work
|
;; features: a) the output is not editable b) tab-completions work
|
||||||
(defun mm/inspect-message ()
|
(defun mu4e-inspect-message ()
|
||||||
"Inspect the current message in the Guile/Muile shell."
|
"Inspect the current message in the Guile/Muile shell."
|
||||||
(interactive)
|
(interactive)
|
||||||
(unless mm/muile-binary (error "`mm/muile-binary' is not defined"))
|
(unless mu4e-muile-binary (error "`mu4e-muile-binary' is not defined"))
|
||||||
(unless (or (file-executable-p mm/muile-binary)
|
(unless (or (file-executable-p mu4e-muile-binary)
|
||||||
(executable-find mm/muile-binary))
|
(executable-find mu4e-muile-binary))
|
||||||
(error "%S not found" mm/muile-binary))
|
(error "%S not found" mu4e-muile-binary))
|
||||||
(unless mm/current-msg
|
(unless mu4e-current-msg
|
||||||
(error "No current message"))
|
(error "No current message"))
|
||||||
(get-buffer-create mm/muile-buffer-name)
|
(get-buffer-create mu4e-muile-buffer-name)
|
||||||
(start-process mm/muile-buffer-name mm/muile-process-name
|
(start-process mu4e-muile-buffer-name mu4e-muile-process-name
|
||||||
mm/muile-binary "--msg" (plist-get mm/current-msg :path))
|
mu4e-muile-binary "--msg" (plist-get mu4e-current-msg :path))
|
||||||
(switch-to-buffer mm/muile-buffer-name)
|
(switch-to-buffer mu4e-muile-buffer-name)
|
||||||
(shell-mode))
|
(shell-mode))
|
||||||
|
|
||||||
(provide 'mm-view)
|
(provide 'mu4e-view)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
;;; mm.el -- part of mm, the mu mail user agent
|
;;; mu4e.el -- part of mu4e, the mu mail user agent
|
||||||
;;
|
;;
|
||||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||||
|
|
||||||
@ -28,75 +28,75 @@
|
|||||||
|
|
||||||
(eval-when-compile (require 'cl))
|
(eval-when-compile (require 'cl))
|
||||||
|
|
||||||
(require 'mm-hdrs)
|
(require 'mu4e-hdrs)
|
||||||
(require 'mm-view)
|
(require 'mu4e-view)
|
||||||
(require 'mm-main)
|
(require 'mu4e-main)
|
||||||
(require 'mm-send)
|
(require 'mu4e-send)
|
||||||
(require 'mm-proc)
|
(require 'mu4e-proc)
|
||||||
|
|
||||||
(require 'mm-version) ;; auto-generated
|
(require 'mu4e-version) ;; auto-generated
|
||||||
|
|
||||||
;; mm-version.el is autogenerated, and defines mm/mu-version
|
;; mu4e-version.el is autogenerated, and defines mu4e-mu-version
|
||||||
(require 'mm-version)
|
(require 'mu4e-version)
|
||||||
|
|
||||||
;; Customization
|
;; Customization
|
||||||
|
|
||||||
(defgroup mm nil
|
(defgroup mu4e nil
|
||||||
"mm - the mu mail client"
|
"mu4e - mu for emacs"
|
||||||
:group 'local)
|
:group 'local)
|
||||||
|
|
||||||
(defcustom mm/mu-home nil
|
(defcustom mu4e-mu-home nil
|
||||||
"Location of the mu homedir, or nil for the default."
|
"Location of the mu homedir, or nil for the default."
|
||||||
:type 'directory
|
:type 'directory
|
||||||
:group 'mm
|
:group 'mu4e
|
||||||
:safe 'stringp)
|
:safe 'stringp)
|
||||||
|
|
||||||
(defcustom mm/mu-binary "mu"
|
(defcustom mu4e-mu-binary "mu"
|
||||||
"Name of the mu-binary to use; if it cannot be found in your
|
"Name of the mu-binary to use; if it cannot be found in your
|
||||||
PATH, you can specify the full path."
|
PATH, you can specify the full path."
|
||||||
:type 'file
|
:type 'file
|
||||||
:group 'mm
|
:group 'mu4e
|
||||||
:safe 'stringp)
|
:safe 'stringp)
|
||||||
|
|
||||||
(defcustom mm/maildir nil
|
(defcustom mu4e-maildir nil
|
||||||
"Your Maildir directory. When `nil', mu will try to find it."
|
"Your Maildir directory. When `nil', mu will try to find it."
|
||||||
:type 'directory
|
:type 'directory
|
||||||
:safe 'stringp
|
:safe 'stringp
|
||||||
:group 'mm)
|
:group 'mu4e)
|
||||||
|
|
||||||
(defcustom mm/get-mail-command nil
|
(defcustom mu4e-get-mail-command nil
|
||||||
"Shell command to run to retrieve new mail; e.g. 'offlineimap' or
|
"Shell command to run to retrieve new mail; e.g. 'offlineimap' or
|
||||||
'fetchmail'."
|
'fetchmail'."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm
|
:group 'mu4e
|
||||||
:safe 'stringp)
|
:safe 'stringp)
|
||||||
|
|
||||||
(defcustom mm/attachment-dir (expand-file-name "~/")
|
(defcustom mu4e-attachment-dir (expand-file-name "~/")
|
||||||
"Default directory for saving attachments."
|
"Default directory for saving attachments."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm
|
:group 'mu4e
|
||||||
:safe 'stringp)
|
:safe 'stringp)
|
||||||
|
|
||||||
(defvar mm/user-mail-address-regexp "$^"
|
(defvar mu4e-user-mail-address-regexp "$^"
|
||||||
"Regular expression matching the user's mail address(es). This is
|
"Regular expression matching the user's mail address(es). This is
|
||||||
used to distinguish ourselves from others, e.g. when replying and
|
used to distinguish ourselves from others, e.g. when replying and
|
||||||
in :from-or-to headers. By default, match nothing.")
|
in :from-or-to headers. By default, match nothing.")
|
||||||
|
|
||||||
(defvar mm/date-format-long "%c"
|
(defvar mu4e-date-format-long "%c"
|
||||||
"Date format to use in the message view, in the format of
|
"Date format to use in the message view, in the format of
|
||||||
`format-time-string'.")
|
`format-time-string'.")
|
||||||
|
|
||||||
(defvar mm/search-results-limit 500
|
(defvar mu4e-search-results-limit 500
|
||||||
"Maximum number of search results (or -1 for unlimited). Since
|
"Maximum number of search results (or -1 for unlimited). Since
|
||||||
limiting search results speeds up searches significantly, it's
|
limiting search results speeds up searches significantly, it's
|
||||||
useful to limit this. Note, to ignore the limit, use a prefix
|
useful to limit this. Note, to ignore the limit, use a prefix
|
||||||
argument (C-u) before invoking the search.")
|
argument (C-u) before invoking the search.")
|
||||||
|
|
||||||
|
|
||||||
(defvar mm/debug nil
|
(defvar mu4e-debug nil
|
||||||
"When set to non-nil, log debug information to the *mm-log* buffer.")
|
"When set to non-nil, log debug information to the *mu4e-log* buffer.")
|
||||||
|
|
||||||
(defvar mm/bookmarks
|
(defvar mu4e-bookmarks
|
||||||
'( ("flag:unread AND NOT flag:trashed" "Unread messages" ?u)
|
'( ("flag:unread AND NOT flag:trashed" "Unread messages" ?u)
|
||||||
("date:today..now" "Today's messages" ?t)
|
("date:today..now" "Today's messages" ?t)
|
||||||
("date:7d..now" "Last 7 days" ?w)
|
("date:7d..now" "Last 7 days" ?w)
|
||||||
@ -110,56 +110,56 @@ show up in the UI), and KEY is a shortcut key for the query.")
|
|||||||
|
|
||||||
;; Folders
|
;; Folders
|
||||||
|
|
||||||
(defgroup mm/folders nil
|
(defgroup mu4e-folders nil
|
||||||
"Special folders for mm."
|
"Special folders for mm."
|
||||||
:group 'mm)
|
:group 'mu4e)
|
||||||
|
|
||||||
;; (defcustom mm/inbox-folder nil
|
;; (defcustom mu4e-inbox-folder nil
|
||||||
;; "Your Inbox folder, relative to `mm/maildir', e.g. \"/Inbox\"."
|
;; "Your Inbox folder, relative to `mu4e-maildir', e.g. \"/Inbox\"."
|
||||||
;; :type 'string
|
;; :type 'string
|
||||||
;; :safe 'stringp
|
;; :safe 'stringp
|
||||||
;; :group 'mm/folders)
|
;; :group 'mu4e-folders)
|
||||||
|
|
||||||
(defcustom mm/sent-folder nil
|
(defcustom mu4e-sent-folder nil
|
||||||
"Your folder for sent messages, relative to `mm/maildir',
|
"Your folder for sent messages, relative to `mu4e-maildir',
|
||||||
e.g. \"/Sent Items\"."
|
e.g. \"/Sent Items\"."
|
||||||
:type 'string
|
:type 'string
|
||||||
:safe 'stringp
|
:safe 'stringp
|
||||||
:group 'mm/folders)
|
:group 'mu4e-folders)
|
||||||
|
|
||||||
(defcustom mm/draft-folder nil
|
(defcustom mu4e-draft-folder nil
|
||||||
"Your folder for draft messages, relative to `mm/maildir',
|
"Your folder for draft messages, relative to `mu4e-maildir',
|
||||||
e.g. \"/drafts\""
|
e.g. \"/drafts\""
|
||||||
:type 'string
|
:type 'string
|
||||||
:safe 'stringp
|
:safe 'stringp
|
||||||
:group 'mm/folders)
|
:group 'mu4e-folders)
|
||||||
|
|
||||||
(defcustom mm/trash-folder nil
|
(defcustom mu4e-trash-folder nil
|
||||||
"Your folder for trashed messages, relative to `mm/maildir',
|
"Your folder for trashed messages, relative to `mu4e-maildir',
|
||||||
e.g. \"/trash\"."
|
e.g. \"/trash\"."
|
||||||
:type 'string
|
:type 'string
|
||||||
:safe 'stringp
|
:safe 'stringp
|
||||||
:group 'mm/folders)
|
:group 'mu4e-folders)
|
||||||
|
|
||||||
|
|
||||||
(defcustom mm/maildir-shortcuts nil
|
(defcustom mu4e-maildir-shortcuts nil
|
||||||
"A list of maildir shortcuts to enable quickly going to the
|
"A list of maildir shortcuts to enable quickly going to the
|
||||||
particular for, or quickly moving messages towards them (i.e.,
|
particular for, or quickly moving messages towards them (i.e.,
|
||||||
archiving or refiling). The list contains elements of the form
|
archiving or refiling). The list contains elements of the form
|
||||||
(maildir . shortcut), where MAILDIR is a maildir (such as
|
(maildir . shortcut), where MAILDIR is a maildir (such as
|
||||||
\"/archive/\"), and shortcut a single shortcut character. With
|
\"/archive/\"), and shortcut a single shortcut character. With
|
||||||
this, in the header buffer and view buffer you can execute
|
this, in the header buffer and view buffer you can execute
|
||||||
`mm/mark-for-move-quick' (or 'm', by default) or
|
`mu4e-mark-for-move-quick' (or 'm', by default) or
|
||||||
`mm/jump-to-maildir-quick' (or 'j', by default), followed by the
|
`mu4e-jump-to-maildir-quick' (or 'j', by default), followed by the
|
||||||
designated shortcut character for the maildir.")
|
designated shortcut character for the maildir.")
|
||||||
|
|
||||||
;; the headers view
|
;; the headers view
|
||||||
(defgroup mm/headers nil
|
(defgroup mu4e-headers nil
|
||||||
"Settings for the headers view."
|
"Settings for the headers view."
|
||||||
:group 'mm)
|
:group 'mu4e)
|
||||||
|
|
||||||
|
|
||||||
(defcustom mm/headers-fields
|
(defcustom mu4e-headers-fields
|
||||||
'( (:date . 25)
|
'( (:date . 25)
|
||||||
(:flags . 6)
|
(:flags . 6)
|
||||||
(:from . 22)
|
(:from . 22)
|
||||||
@ -167,152 +167,152 @@ designated shortcut character for the maildir.")
|
|||||||
"A list of header fields to show in the headers buffer, and their
|
"A list of header fields to show in the headers buffer, and their
|
||||||
respective widths in characters. A width of `nil' means
|
respective widths in characters. A width of `nil' means
|
||||||
'unrestricted', and this is best reserved fo the rightmost (last)
|
'unrestricted', and this is best reserved fo the rightmost (last)
|
||||||
field. For the complete list of available headers, see `mm/header-names'"
|
field. For the complete list of available headers, see `mu4e-header-names'"
|
||||||
:type (list 'symbol)
|
:type (list 'symbol)
|
||||||
:group 'mm/headers)
|
:group 'mu4e-headers)
|
||||||
|
|
||||||
(defcustom mm/headers-date-format "%x %X"
|
(defcustom mu4e-headers-date-format "%x %X"
|
||||||
"Date format to use in the headers view, in the format of
|
"Date format to use in the headers view, in the format of
|
||||||
`format-time-string'."
|
`format-time-string'."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm/headers)
|
:group 'mu4e-headers)
|
||||||
|
|
||||||
|
|
||||||
;; the message view
|
;; the message view
|
||||||
(defgroup mm/view nil
|
(defgroup mu4e-view nil
|
||||||
"Settings for the message view."
|
"Settings for the message view."
|
||||||
:group 'mm)
|
:group 'mu4e)
|
||||||
|
|
||||||
(defcustom mm/view-fields
|
(defcustom mu4e-view-fields
|
||||||
'(:from :to :cc :subject :flags :date :maildir :path :attachments)
|
'(:from :to :cc :subject :flags :date :maildir :path :attachments)
|
||||||
"Header fields to display in the message view buffer. For the
|
"Header fields to display in the message view buffer. For the
|
||||||
complete list of available headers, see `mm/header-names'."
|
complete list of available headers, see `mu4e-header-names'."
|
||||||
:type (list 'symbol)
|
:type (list 'symbol)
|
||||||
:group 'mm/view)
|
:group 'mu4e-view)
|
||||||
|
|
||||||
(defcustom mm/view-date-format "%c"
|
(defcustom mu4e-view-date-format "%c"
|
||||||
"Date format to use in the message view, in the format of
|
"Date format to use in the message view, in the format of
|
||||||
`format-time-string'."
|
`format-time-string'."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm/headers)
|
:group 'mu4e-headers)
|
||||||
|
|
||||||
;; Composing / Sending messages
|
;; Composing / Sending messages
|
||||||
(defgroup mm/compose nil
|
(defgroup mu4e-compose nil
|
||||||
"Customizations for composing/sending messages."
|
"Customizations for composing/sending messages."
|
||||||
:group 'mm)
|
:group 'mu4e)
|
||||||
|
|
||||||
(defcustom mm/msg-citation-prefix "> "
|
(defcustom mu4e-msg-citation-prefix "> "
|
||||||
"String to prefix cited message parts with."
|
"String to prefix cited message parts with."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm/compose)
|
:group 'mu4e-compose)
|
||||||
|
|
||||||
(defcustom mm/msg-reply-prefix "Re: "
|
(defcustom mu4e-msg-reply-prefix "Re: "
|
||||||
"String to prefix the subject of replied messages with."
|
"String to prefix the subject of replied messages with."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm/compose)
|
:group 'mu4e-compose)
|
||||||
|
|
||||||
(defcustom mm/msg-forward-prefix "Fwd: "
|
(defcustom mu4e-msg-forward-prefix "Fwd: "
|
||||||
"String to prefix the subject of forwarded messages with."
|
"String to prefix the subject of forwarded messages with."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm/compose)
|
:group 'mu4e-compose)
|
||||||
|
|
||||||
(defcustom mm/user-agent nil
|
(defcustom mu4e-user-agent nil
|
||||||
"The user-agent string; leave at `nil' for the default."
|
"The user-agent string; leave at `nil' for the default."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'mm/compose)
|
:group 'mu4e-compose)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Faces
|
;; Faces
|
||||||
|
|
||||||
(defgroup mm/faces nil
|
(defgroup mu4e-faces nil
|
||||||
"Faces used in by mm."
|
"Faces used in by mm."
|
||||||
:group 'mm
|
:group 'mu4e
|
||||||
:group 'faces)
|
:group 'faces)
|
||||||
|
|
||||||
(defface mm/unread-face
|
(defface mu4e-unread-face
|
||||||
'((t :inherit font-lock-keyword-face :bold t))
|
'((t :inherit font-lock-keyword-face :bold t))
|
||||||
"Face for an unread mm message header."
|
"Face for an unread mm message header."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/moved-face
|
(defface mu4e-moved-face
|
||||||
'((t :inherit font-lock-comment-face :slant italic))
|
'((t :inherit font-lock-comment-face :slant italic))
|
||||||
"Face for an mm message header that has been moved to some
|
"Face for an mm message header that has been moved to some
|
||||||
folder (it's still visible in the search results, since we cannot
|
folder (it's still visible in the search results, since we cannot
|
||||||
be sure it no longer matches)."
|
be sure it no longer matches)."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/trashed-face
|
(defface mu4e-trashed-face
|
||||||
'((t :inherit font-lock-comment-face :strike-through t))
|
'((t :inherit font-lock-comment-face :strike-through t))
|
||||||
"Face for an message header in the trash folder."
|
"Face for an message header in the trash folder."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/draft-face
|
(defface mu4e-draft-face
|
||||||
'((t :inherit font-lock-string-face))
|
'((t :inherit font-lock-string-face))
|
||||||
"Face for a draft message header (i.e., a message with the draft
|
"Face for a draft message header (i.e., a message with the draft
|
||||||
flag set)."
|
flag set)."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/header-face
|
(defface mu4e-header-face
|
||||||
'((t :inherit default))
|
'((t :inherit default))
|
||||||
"Face for an mm header without any special flags."
|
"Face for an mm header without any special flags."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/title-face
|
(defface mu4e-title-face
|
||||||
'((t :inherit font-lock-type-face))
|
'((t :inherit font-lock-type-face))
|
||||||
"Face for an mm title."
|
"Face for an mm title."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/view-header-key-face
|
(defface mu4e-view-header-key-face
|
||||||
'((t :inherit font-lock-builtin-face))
|
'((t :inherit font-lock-builtin-face))
|
||||||
"Face for the header title (such as \"Subject\" in the message view)."
|
"Face for the header title (such as \"Subject\" in the message view)."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/view-header-value-face
|
(defface mu4e-view-header-value-face
|
||||||
'((t :inherit font-lock-doc-face))
|
'((t :inherit font-lock-doc-face))
|
||||||
"Face for the header value (such as \"Re: Hello!\" in the message view)."
|
"Face for the header value (such as \"Re: Hello!\" in the message view)."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/view-link-face
|
(defface mu4e-view-link-face
|
||||||
'((t :inherit font-lock-type-face :underline t))
|
'((t :inherit font-lock-type-face :underline t))
|
||||||
"Face for showing URLs and attachments in the message view."
|
"Face for showing URLs and attachments in the message view."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/highlight-face
|
(defface mu4e-highlight-face
|
||||||
'((t :inherit font-lock-pseudo-keyword-face :bold t))
|
'((t :inherit font-lock-pseudo-keyword-face :bold t))
|
||||||
"Face for highlighting things."
|
"Face for highlighting things."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/view-url-number-face
|
(defface mu4e-view-url-number-face
|
||||||
'((t :inherit font-lock-reference-face :bold t))
|
'((t :inherit font-lock-reference-face :bold t))
|
||||||
"Face for the number tags for URLs."
|
"Face for the number tags for URLs."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/view-attach-number-face
|
(defface mu4e-view-attach-number-face
|
||||||
'((t :inherit font-lock-variable-name-face :bold t))
|
'((t :inherit font-lock-variable-name-face :bold t))
|
||||||
"Face for the number tags for attachments."
|
"Face for the number tags for attachments."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/view-footer-face
|
(defface mu4e-view-footer-face
|
||||||
'((t :inherit font-lock-comment-face))
|
'((t :inherit font-lock-comment-face))
|
||||||
"Face for message footers (signatures)."
|
"Face for message footers (signatures)."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/hdrs-marks-face
|
(defface mu4e-hdrs-marks-face
|
||||||
'((t :inherit font-lock-preprocessor-face))
|
'((t :inherit font-lock-preprocessor-face))
|
||||||
"Face for the mark in the headers list."
|
"Face for the mark in the headers list."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
(defface mm/system-face
|
(defface mu4e-system-face
|
||||||
'((t :inherit font-lock-comment-face :slant italic))
|
'((t :inherit font-lock-comment-face :slant italic))
|
||||||
"Face for system message (such as the footers for message
|
"Face for system message (such as the footers for message
|
||||||
headers)."
|
headers)."
|
||||||
:group 'mm/faces)
|
:group 'mu4e-faces)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; internal variables / constants
|
;; internal variables / constants
|
||||||
|
|
||||||
(defconst mm/header-names
|
(defconst mu4e-header-names
|
||||||
'( (:attachments . "Attach")
|
'( (:attachments . "Attach")
|
||||||
(:bcc . "Bcc")
|
(:bcc . "Bcc")
|
||||||
(:cc . "Cc")
|
(:cc . "Cc")
|
||||||
@ -332,69 +332,69 @@ in which case it will be equal to `:to'.)")
|
|||||||
|
|
||||||
|
|
||||||
;; mm startup function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; mm startup function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
(defun mm ()
|
(defun mu4e ()
|
||||||
"Start mm. We do this by sending a 'ping' to the mu server
|
"Start mm. We do this by sending a 'ping' to the mu server
|
||||||
process, and start the main view if the 'pong' we receive from the
|
process, and start the main view if the 'pong' we receive from the
|
||||||
server has the expected values."
|
server has the expected values."
|
||||||
(interactive)
|
(interactive)
|
||||||
(if (buffer-live-p mm/main-buffer-name)
|
(if (buffer-live-p mu4e-main-buffer-name)
|
||||||
(switch-to-buffer mm/main-buffer-name)
|
(switch-to-buffer mu4e-main-buffer-name)
|
||||||
(setq mm/proc-pong-func
|
(setq mu4e-proc-pong-func
|
||||||
(lambda (version doccount)
|
(lambda (version doccount)
|
||||||
(unless (string= version mm/mu-version)
|
(unless (string= version mu4e-mu-version)
|
||||||
(error "mu server has version %s, but we need %s"
|
(error "mu server has version %s, but we need %s"
|
||||||
version mm/mu-version))
|
version mu4e-mu-version))
|
||||||
(mm/main-view)))
|
(mu4e-main-view)))
|
||||||
(mm/proc-ping)))
|
(mu4e-proc-ping)))
|
||||||
|
|
||||||
(defun mm/ask-maildir (prompt)
|
(defun mu4e-ask-maildir (prompt)
|
||||||
"Ask the user for a shortcut (using PROMPT) as defined in
|
"Ask the user for a shortcut (using PROMPT) as defined in
|
||||||
`mm/maildir-shortcuts', then return the corresponding folder
|
`mu4e-maildir-shortcuts', then return the corresponding folder
|
||||||
name. If the special shortcut 'o' (for _o_ther) is used, or if
|
name. If the special shortcut 'o' (for _o_ther) is used, or if
|
||||||
`mm/maildir-shortcuts is not defined, let user choose from all
|
`mu4e-maildir-shortcuts is not defined, let user choose from all
|
||||||
maildirs under `mm/maildir."
|
maildirs under `mu4e-maildir."
|
||||||
(unless mm/maildir (error "`mm/maildir' is not defined"))
|
(unless mu4e-maildir (error "`mu4e-maildir' is not defined"))
|
||||||
(if (not mm/maildir-shortcuts)
|
(if (not mu4e-maildir-shortcuts)
|
||||||
(ido-completing-read prompt (mm/get-sub-maildirs mm/maildir))
|
(ido-completing-read prompt (mu4e-get-sub-maildirs mu4e-maildir))
|
||||||
(let* ((mlist (append mm/maildir-shortcuts '(("ther" . ?o))))
|
(let* ((mlist (append mu4e-maildir-shortcuts '(("ther" . ?o))))
|
||||||
(fnames
|
(fnames
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (item)
|
(lambda (item)
|
||||||
(concat
|
(concat
|
||||||
"["
|
"["
|
||||||
(propertize (make-string 1 (cdr item)) 'face 'mm/view-link-face)
|
(propertize (make-string 1 (cdr item)) 'face 'mu4e-view-link-face)
|
||||||
"]"
|
"]"
|
||||||
(car item)))
|
(car item)))
|
||||||
mlist ", "))
|
mlist ", "))
|
||||||
(kar (read-char (concat prompt fnames))))
|
(kar (read-char (concat prompt fnames))))
|
||||||
(if (= kar ?o) ;; user chose 'other'?
|
(if (= kar ?o) ;; user chose 'other'?
|
||||||
(ido-completing-read prompt (mm/get-sub-maildirs mm/maildir))
|
(ido-completing-read prompt (mu4e-get-sub-maildirs mu4e-maildir))
|
||||||
(or
|
(or
|
||||||
(car-safe (find-if (lambda (item) (= kar (cdr item))) mm/maildir-shortcuts))
|
(car-safe (find-if (lambda (item) (= kar (cdr item))) mu4e-maildir-shortcuts))
|
||||||
(error "Invalid shortcut '%c'" kar))))))
|
(error "Invalid shortcut '%c'" kar))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defun mm/ask-bookmark (prompt)
|
(defun mu4e-ask-bookmark (prompt)
|
||||||
"Ask the user for a bookmark (using PROMPT) as defined in
|
"Ask the user for a bookmark (using PROMPT) as defined in
|
||||||
`mm/bookmarks', then return the corresponding query."
|
`mu4e-bookmarks', then return the corresponding query."
|
||||||
(unless mm/bookmarks (error "`mm/bookmarks' is not defined"))
|
(unless mu4e-bookmarks (error "`mu4e-bookmarks' is not defined"))
|
||||||
(let* ((bmarks
|
(let* ((bmarks
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (bm)
|
(lambda (bm)
|
||||||
(let ((query (nth 0 bm)) (title (nth 1 bm)) (key (nth 2 bm)))
|
(let ((query (nth 0 bm)) (title (nth 1 bm)) (key (nth 2 bm)))
|
||||||
(concat
|
(concat
|
||||||
"[" (propertize (make-string 1 key) 'face 'mm/view-link-face) "]"
|
"[" (propertize (make-string 1 key) 'face 'mu4e-view-link-face) "]"
|
||||||
title))) mm/bookmarks ", "))
|
title))) mu4e-bookmarks ", "))
|
||||||
(kar (read-char (concat prompt bmarks)))
|
(kar (read-char (concat prompt bmarks)))
|
||||||
(chosen-bm
|
(chosen-bm
|
||||||
(find-if (lambda (bm) (= kar (nth 2 bm))) mm/bookmarks)))
|
(find-if (lambda (bm) (= kar (nth 2 bm))) mu4e-bookmarks)))
|
||||||
(unless chosen-bm (error "Invalid shortcut '%c'" kar))
|
(unless chosen-bm (error "Invalid shortcut '%c'" kar))
|
||||||
(nth 0 chosen-bm)))
|
(nth 0 chosen-bm)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defun mm/new-buffer (bufname)
|
(defun mu4e-new-buffer (bufname)
|
||||||
"Return a new buffer BUFNAME; if such already exists, kill the
|
"Return a new buffer BUFNAME; if such already exists, kill the
|
||||||
old one first."
|
old one first."
|
||||||
(when (get-buffer bufname)
|
(when (get-buffer bufname)
|
||||||
@ -407,19 +407,19 @@ old one first."
|
|||||||
|
|
||||||
;;; converting flags->string and vice-versa ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; converting flags->string and vice-versa ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defun mm/flags-to-string (flags)
|
(defun mu4e-flags-to-string (flags)
|
||||||
"Remove duplicates and sort the output of `mm/flags-to-string-raw'."
|
"Remove duplicates and sort the output of `mu4e-flags-to-string-raw'."
|
||||||
(concat
|
(concat
|
||||||
(sort (remove-duplicates (append (mm/flags-to-string-raw flags) nil)) '>)))
|
(sort (remove-duplicates (append (mu4e-flags-to-string-raw flags) nil)) '>)))
|
||||||
|
|
||||||
(defun mm/flags-to-string-raw (flags)
|
(defun mu4e-flags-to-string-raw (flags)
|
||||||
"Convert a list of flags into a string as seen in Maildir
|
"Convert a list of flags into a string as seen in Maildir
|
||||||
message files; flags are symbols draft, flagged, new, passed,
|
message files; flags are symbols draft, flagged, new, passed,
|
||||||
replied, seen, trashed and the string is the concatenation of the
|
replied, seen, trashed and the string is the concatenation of the
|
||||||
uppercased first letters of these flags, as per [1]. Other flags
|
uppercased first letters of these flags, as per [1]. Other flags
|
||||||
than the ones listed here are ignored.
|
than the ones listed here are ignored.
|
||||||
|
|
||||||
Also see `mm/flags-to-string'.
|
Also see `mu4e-flags-to-string'.
|
||||||
|
|
||||||
\[1\]: http://cr.yp.to/proto/maildir.html"
|
\[1\]: http://cr.yp.to/proto/maildir.html"
|
||||||
(when flags
|
(when flags
|
||||||
@ -436,14 +436,14 @@ Also see `mm/flags-to-string'.
|
|||||||
('signed ?s)
|
('signed ?s)
|
||||||
('unread ?u))))
|
('unread ?u))))
|
||||||
(concat (and kar (string kar))
|
(concat (and kar (string kar))
|
||||||
(mm/flags-to-string-raw (cdr flags))))))
|
(mu4e-flags-to-string-raw (cdr flags))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/string-to-flags (str)
|
(defun mu4e-string-to-flags (str)
|
||||||
"Remove duplicates from the output of `mm/string-to-flags-1'"
|
"Remove duplicates from the output of `mu4e-string-to-flags-1'"
|
||||||
(remove-duplicates (mm/string-to-flags-1 str)))
|
(remove-duplicates (mu4e-string-to-flags-1 str)))
|
||||||
|
|
||||||
(defun mm/string-to-flags-1 (str)
|
(defun mu4e-string-to-flags-1 (str)
|
||||||
"Convert a string with message flags as seen in Maildir
|
"Convert a string with message flags as seen in Maildir
|
||||||
messages into a list of flags in; flags are symbols draft,
|
messages into a list of flags in; flags are symbols draft,
|
||||||
flagged, new, passed, replied, seen, trashed and the string is
|
flagged, new, passed, replied, seen, trashed and the string is
|
||||||
@ -462,10 +462,10 @@ Also see `mu/flags-to-string'.
|
|||||||
(?S 'seen)
|
(?S 'seen)
|
||||||
(?T 'trashed))))
|
(?T 'trashed))))
|
||||||
(append (when flag (list flag))
|
(append (when flag (list flag))
|
||||||
(mm/string-to-flags-1 (substring str 1))))))
|
(mu4e-string-to-flags-1 (substring str 1))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mm/display-size (size)
|
(defun mu4e-display-size (size)
|
||||||
"Get a string representation of SIZE (in bytes)."
|
"Get a string representation of SIZE (in bytes)."
|
||||||
(cond
|
(cond
|
||||||
((>= size 1000000) (format "%2.1fM" (/ size 1000000.0)))
|
((>= size 1000000) (format "%2.1fM" (/ size 1000000.0)))
|
||||||
@ -476,4 +476,4 @@ Also see `mu/flags-to-string'.
|
|||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(provide 'mm)
|
(provide 'mu4e)
|
||||||
Reference in New Issue
Block a user