diff --git a/Makefile.am b/Makefile.am index f23ef4e0..73ef0033 100644 --- a/Makefile.am +++ b/Makefile.am @@ -29,7 +29,13 @@ else guile= endif -SUBDIRS=m4 man src $(widgets) $(guile) emacs contrib toys +if HAVE_EMACS +emacs=emacs +else +emacs= +endif + +SUBDIRS=m4 man src $(widgets) $(guile) $(emacs) contrib toys ACLOCAL_AMFLAGS=-I m4 diff --git a/configure.ac b/configure.ac index 03f33f07..799c931e 100644 --- a/configure.ac +++ b/configure.ac @@ -49,7 +49,9 @@ AC_SYS_LARGEFILE AC_CHECK_PROG(have_makeinfo,makeinfo,yes,no) AM_CONDITIONAL(HAVE_MAKEINFO,test "x$have_makeinfo" = "xyes") - +# we need emacs for byte-compiling mu4e +AM_PATH_LISPDIR +AM_CONDITIONAL(HAVE_EMACS,test "x$lispdir" != "xno") # we need some special tricks for filesystems that don't have d_type; # e.g. Solaris. See mu-maildir.c. Explicitly disabling it is for @@ -281,6 +283,7 @@ src/Makefile src/tests/Makefile widgets/Makefile emacs/Makefile +emacs/mu4e-version.el guile/Makefile guile/mu/Makefile guile/examples/Makefile diff --git a/emacs/Makefile.am b/emacs/Makefile.am index 90edccf3..df3c7769 100644 --- a/emacs/Makefile.am +++ b/emacs/Makefile.am @@ -17,28 +17,24 @@ include $(top_srcdir)/gtest.mk SUBDIRS= - -BUILT_SOURCES=mu4e-version.el - -mu4e-version.el: $(top_srcdir)/configure.ac - @echo -e ";; auto-generated\n\ -(defconst mu4e-mu-version \"$(VERSION)\" \"Required mu binary version.\")\n\ -(provide 'mu4e-version)\n" >$@ - + info_TEXINFOS=mu4e.texi mu4e_TEXINFOS=fdl.texi -elispdir= ${prefix}/share/emacs/site-lisp/mu4e/ -elisp_DATA= \ - mu4e.el \ +lispdir=${prefix}/share/emacs/site-lisp/mu4e/ + +dist_lisp_LISP= \ + mu4e-utils.el \ mu4e-hdrs.el \ - mu4e-view.el \ - mu4e-proc.el \ mu4e-main.el \ + mu4e-proc.el \ + mu4e-raw-view.el \ mu4e-send.el \ mu4e-speedbar.el \ - mu4e-utils.el \ + mu4e-vars.el \ mu4e-version.el \ + mu4e-view.el \ + mu4e.el \ org-mu4e.el EXTRA_DIST=$(elisp_DATA) diff --git a/emacs/mu4e-hdrs.el b/emacs/mu4e-hdrs.el index 126d8884..fe15a01a 100644 --- a/emacs/mu4e-hdrs.el +++ b/emacs/mu4e-hdrs.el @@ -27,19 +27,13 @@ ;; headers like 'To:' or 'Subject:') ;; Code: - -(eval-when-compile (require 'cl)) - (require 'hl-line) + (require 'mu4e-proc) (require 'mu4e-utils) ;; utility functions - +(require 'mu4e-vars) ;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defvar mu4e-last-expr nil "*internal* The most recent search expression.") -(defconst mu4e-hdrs-buffer-name "*mu4e-headers*" - "*internal* Name of the buffer for message headers.") -(defvar mu4e-hdrs-buffer nil "*internal* Buffer for message headers") (defconst mu4e-hdrs-fringe " " "*internal* The space on the left of message headers to put marks.") @@ -120,7 +114,9 @@ headers." (when (and viewbuf (buffer-live-p viewbuf)) (with-current-buffer viewbuf (when (eq docid (plist-get mu4e-current-msg :docid)) - (setq mu4e-current-msg msg))))) + (setq mu4e-current-msg msg) + ;; and re-highlight this message + (mu4e-hdrs-highlight docid))))) ;; 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 @@ -234,7 +230,9 @@ after the end of the search results." (insert (propertize str 'face 'mu4e-system-face 'intangible t)) (unless (= 0 count) (message "Found %d matching message%s" - count (if (= 1 count) "" "s")))))))) + count (if (= 1 count) "" "s")) + ;; highlight the first message + (mu4e-hdrs-highlight (mu4e--docid-at-point (point-min))))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -336,7 +334,6 @@ after the end of the search results." (define-key menumap [next] '("Next" . mu4e-next-header)) (define-key menumap [previous] '("Previous" . mu4e-prev-header)) (define-key menumap [sepa4] '("--"))) - map))) (fset 'mu4e-hdrs-mode-map mu4e-hdrs-mode-map) @@ -376,7 +373,7 @@ after the end of the search results." hl-line-face 'mu4e-header-highlight-face) (hl-line-mode 1) - + (setq header-line-format (cons (make-string @@ -394,7 +391,27 @@ after the end of the search results." mu4e-headers-fields)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (defun mu4e-select-headers-window-if-visible () +;;; higlighting +(defvar mu4e--highlighted-docid nil + "*internal* The highlighted docid") + +(defun mu4e-hdrs-highlight (docid) + "Highlight the header with DOCID, or do nothing if it's not +found. Also, unhighlight any previously highlighted headers." + (with-current-buffer mu4e-hdrs-buffer + (save-excursion + ;; first, unhighlight the previously highlighted docid, if any + (when (and mu4e--highlighted-docid + (mu4e--goto-docid mu4e--highlighted-docid)) + (hl-line-unhighlight)) + ;; now, highlight the new one + (when (mu4e--goto-docid docid) + (hl-line-highlight))) + (setq mu4e--highlighted-docid docid))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defun mu4e-select-headers-window-if-visible () "When there is a visible window for the headers buffer, make sure to select it. This is needed when adding new headers, otherwise adding a lot of new headers looks really choppy." @@ -436,8 +453,6 @@ of the beginning of the line." (setq newpoint (point))))) newpoint)) ;; return the point, or nil if not found - - (defun mu4e--docid-pos (docid) "Return the pos of the beginning of the line with the header with docid DOCID, or nil if it cannot be found." @@ -482,11 +497,7 @@ at (point-max) otherwise. If MSG is not nil, add it as the text-property `msg'." (concat (mu4e--docid-cookie docid) mu4e-hdrs-fringe str "\n") - 'docid docid 'msg msg)) - ;; if it's the first header, highlight it - (when is-first-header - (goto-char (point-min)) - (hl-line-highlight))))))) + 'docid docid 'msg msg))))))) (defun mu4e-hdrs-remove-header (docid) "Remove header with DOCID at POINT." @@ -746,7 +757,7 @@ do a new search." (when (mu4e-handle-marks) (if mu4e-last-expr (mu4e-hdrs-search mu4e-last-expr) - (mu4e-search)))) + (call-interactively 'mu4e-search)))) (defun mu4e--hdrs-move (lines) "Move point LINES lines forward (if LINES is positive) or @@ -756,12 +767,11 @@ docid. Otherwise, return nil." (unless (buffer-live-p mu4e-hdrs-buffer) (error "Headers buffer is not alive %S" (current-buffer))) (set-window-point (get-buffer-window mu4e-hdrs-buffer) (point)) - (hl-line-unhighlight) (let ((succeeded (= 0 (forward-line lines))) (docid (mu4e--docid-at-point))) ;; trick to move point, even if this function is called when this window ;; is not visible - (hl-line-highlight) + (mu4e-hdrs-highlight docid) ;; return the docid only if the move succeeded (when succeeded docid)))) @@ -803,7 +813,7 @@ not provided, function asks for it." (concat "/" target))) (fulltarget (concat mu4e-maildir target))) (when (or (file-directory-p fulltarget) - (and (yes-or-no-(point) + (and (yes-or-no-p (format "%s does not exist. Create now?" fulltarget)) (mu4e-proc-mkdir fulltarget))) (mu4e-hdrs-mark 'move target) diff --git a/emacs/mu4e-proc.el b/emacs/mu4e-proc.el index e9f46983..6121ce9b 100644 --- a/emacs/mu4e-proc.el +++ b/emacs/mu4e-proc.el @@ -23,9 +23,11 @@ ;;; Commentary: ;;; Code: -(eval-when-compile (require 'cl)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(require 'mu4e-vars) +(require 'mu4e-utils) +(require 'mu4e-version) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; internal vars (defvar mu4e-mu-proc nil @@ -106,10 +108,6 @@ process." ;; add draft messages to the db, so when we're sending them, we can move ;; to the sent folder using the `mu4e-proc-move'. (puthash (plist-get info :path) (plist-get info :docid) mu4e-path-docid-map)) - ((eq type 'version) - (setq - mu4e-version (plist-get info :version) - mu4e-doccount (plist-get-info :doccount))) ((eq type 'index) (if (eq (plist-get info :status) 'running) (message (format "Indexing... processed %d, updated %d" diff --git a/emacs/mu4e-raw-view.el b/emacs/mu4e-raw-view.el new file mode 100644 index 00000000..b42a2654 --- /dev/null +++ b/emacs/mu4e-raw-view.el @@ -0,0 +1,110 @@ +;;; mu4e-raw-view.el -- part of mu4e, the mu mail user agent +;; +;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema + +;; Author: Dirk-Jan C. Binnema +;; Maintainer: Dirk-Jan C. Binnema + +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; In this file we define mu4e-view-mode (+ helper functions), which is used for +;; viewing e-mail messages + +;;; Code: +(eval-when-compile (require 'cl)) + +(require 'mu4e-utils) ;; utility functions + +;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; some buffer-local variables +(defconst mu4e-raw-view-buffer-name "*mu4e-raw-view*" + "*internal* Name for the raw message view buffer") + +(defvar mu4e-raw-view-buffer nil "*internal* The raw view buffer.") + +(defvar mu4e-raw-view-mode-map nil + "Keymap for \"*mu4e-raw-view*\" buffers.") + +(unless mu4e-raw-view-mode-map + (setq mu4e-raw-view-mode-map + (let ((map (make-sparse-keymap))) + + (define-key map "q" 'mu4e-raw-view-quit-buffer) + (define-key map "." 'mu4e-raw-view-quit-buffer) + + ;; intra-message navigation + (define-key map (kbd "SPC") 'scroll-up) + (define-key map (kbd "") + '(lambda () (interactive) (goto-char (point-min)))) + (define-key map (kbd "") + '(lambda () (interactive) (goto-char (point-max)))) + (define-key map (kbd "RET") + '(lambda () (interactive) (scroll-up 1))) + (define-key map (kbd "") + '(lambda () (interactive) (scroll-up -1))) + map))) + +(fset 'mu4e-raw-view-mode-map mu4e-raw-view-mode-map) + +(define-derived-mode mu4e-raw-view-mode special-mode + "mu4e:raw" + "Major mode for viewing of raw e-mail message in mu4e. +\\{mu4e-raw-view-mode-map}.") + + +(defun mu4e-raw-view-message (msg view-buffer) + "Display the raw contents of message MSG in a new buffer." + (let ((buf (get-buffer-create mu4e-raw-view-buffer-name)) + (inhibit-read-only t) + (file (plist-get msg :path))) + (unless (and file (file-readable-p file)) + (error "Not a readable file: %S" file)) + (with-current-buffer buf + (erase-buffer) + (insert-file-contents file) + ;; initialize view-mode + (mu4e-raw-view-mode) + (setq mu4e-raw-view-buffer view-buffer) + (switch-to-buffer buf) + (goto-char (point-min))))) + + +(defun mu4e-view-shell-command-on-raw-message (msg view-buffer cmd) + "Process the raw message with shell command CMD." + (let ((buf (get-buffer-create mu4e-raw-view-buffer-name)) + (inhibit-read-only t) + (file (plist-get msg :path))) + (unless (and file (file-readable-p file)) + (error "Not a readable file: %S" file)) + (with-current-buffer buf + (erase-buffer) + (process-file-shell-command cmd file buf) + (mu4e-raw-view-mode) + (setq mu4e-raw-view-buffer view-buffer) + (switch-to-buffer buf) + (goto-char (point-min))))) + + +(defun mu4e-raw-view-quit-buffer () + "Quit the raw view and return to the message." + (interactive) + (kill-buffer)) + +(provide 'mu4e-raw-view) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/emacs/mu4e-send.el b/emacs/mu4e-send.el index 15576f7e..1685b737 100644 --- a/emacs/mu4e-send.el +++ b/emacs/mu4e-send.el @@ -26,10 +26,11 @@ ;; gnus' message mode ;;; Code: + ;; we use some stuff from gnus.. +(require 'cl) -(eval-when-compile (require 'cl)) - -;; we use some stuff from gnus... +(require 'mu4e-utils) +(require 'mu4e-vars) (require 'message) (require 'mail-parse) (require 'smtpmail) @@ -159,7 +160,7 @@ separator is never written to file. Also see (replace-match (propertize mail-header-separator 'read-only t 'intangible t)) ;; no empty line? then append one - ((progn ) + (progn (goto-char (point-max)) (insert (concat "\n" mail-header-separator "\n")))))) diff --git a/emacs/mu4e-speedbar.el b/emacs/mu4e-speedbar.el index 83fd8450..3b8f6d7c 100644 --- a/emacs/mu4e-speedbar.el +++ b/emacs/mu4e-speedbar.el @@ -39,6 +39,8 @@ ;;; Code: +(require 'speedbar) + (defvar mu4e-main-speedbar-key-map nil "Keymap used when in mu4e display mode.") diff --git a/emacs/mu4e-utils.el b/emacs/mu4e-utils.el index f51fe1fc..cd5b9770 100644 --- a/emacs/mu4e-utils.el +++ b/emacs/mu4e-utils.el @@ -25,10 +25,9 @@ ;; Utility functions used in the mu4e ;;; Code: +(require 'cl) (require 'html2text) -(eval-when-compile (require 'cl)) - (defun mu4e-create-maildir-maybe (dir) "Offer to create DIR if it does not exist yet. Return t if the dir already existed, or has been created, nil otherwise." @@ -303,7 +302,7 @@ point in eiter the headers buffer or the view buffer." ((eq major-mode 'mu4e-hdrs-mode) (get-text-property (point) 'msg)) ((eq major-mode 'mu4e-view-mode) - mu4e--current-msg)))) + mu4e-current-msg)))) (unless msg (error "No message at point")) (plist-get msg field))) @@ -318,7 +317,6 @@ instead of erroring out." (delete-windows-on buf) ;; destroy all windows for this buffer (kill-buffer)))) - (defun mu4e-select-other-view () "When the headers view is selected, select the message view (if that has a live window), and vice versa." @@ -334,6 +332,48 @@ that has a live window), and vice versa." (select-window other-win) (message "No window to switch to")))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar mu4e-update-timer nil + "*internal* The mu4e update timer.") + +(defun mu4e () + "Start mu4e. We do this by sending a 'ping' to the mu server +process, and start the main view if the 'pong' we receive from the +server has the expected values." + (interactive) + (if (buffer-live-p (get-buffer mu4e-main-buffer-name)) + (switch-to-buffer mu4e-main-buffer-name) + (mu4e-check-requirements) + ;; explicit version checks are a bit questionable, + ;; better to check for specific features + (if (< emacs-major-version 23) + (error "Emacs >= 23.x is required for mu4e") + (progn + (setq mu4e-proc-pong-func + (lambda (version doccount) + (unless (string= version mu4e-mu-version) + (error "mu server has version %s, but we need %s" + version mu4e-mu-version)) + (mu4e-main-view) + (when (and mu4e-update-interval (null mu4e-update-timer)) + (setq mu4e-update-timer + (run-at-time + 0 mu4e-update-interval + 'mu4e-update-mail))) + (message "Started mu4e with %d message%s in store" + doccount (if (= doccount 1) "" "s")))) + (mu4e-proc-ping))))) + +(defun mu4e-quit() + "Quit the mu4e session." + (interactive) + (when (y-or-n-p "Are you sure you want to quit? ") + (message nil) + (when mu4e-update-timer + (cancel-timer mu4e-update-timer) + (setq mu4e-update-timer nil)) + (mu4e-kill-proc) + (kill-buffer))) (provide 'mu4e-utils) ;;; End of mu4e-utils.el diff --git a/emacs/mu4e-vars.el b/emacs/mu4e-vars.el new file mode 100644 index 00000000..c37cfb0d --- /dev/null +++ b/emacs/mu4e-vars.el @@ -0,0 +1,472 @@ +;;; mu4e-vars.el -- part of mu4e, the mu mail user agent +;; +;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema + +;; Author: Dirk-Jan C. Binnema +;; Maintainer: Dirk-Jan C. Binnema + +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Customization + +(defgroup mu4e nil + "mu4e - mu for emacs" + :group 'local) + +(defcustom mu4e-mu-home nil + "Location of the mu homedir, or nil for the default." + :type 'directory + :group 'mu4e + :safe 'stringp) + +(defcustom mu4e-mu-binary (executable-find "mu") + "Name of the mu-binary to use; if it cannot be found in your +PATH, you can specify the full path." + :type 'file + :group 'mu4e + :safe 'stringp) + +(defcustom mu4e-maildir (expand-file-name "~/Maildir") + "Your Maildir directory; by default, mu4e assumes +~/Maildir." + :type 'directory + :safe 'stringp + :group 'mu4e) + +(defcustom mu4e-get-mail-command nil + "Shell command to run to retrieve new mail; e.g. 'offlineimap' or +'fetchmail'." + :type 'string + :group 'mu4e + :safe 'stringp) + +(defcustom mu4e-update-interval nil + "Number of seconds between automatic calls to retrieve mail and +update the database. If nil, don't update automatically. Note, +changes in `mu4e-update-interval' only take effect after restarting +mu4d." + :type 'integer + :group 'mu4e + :safe 'integerp) + +(defcustom mu4e-attachment-dir (expand-file-name "~/") + "Default directory for saving attachments." + :type 'string + :group 'mu4e + :safe 'stringp) + +(defvar mu4e-user-mail-address-regexp "$^" + "Regular expression matching the user's mail address(es). This is +used to distinguish ourselves from others, e.g. when replying and +in :from-or-to headers. By default, match nothing.") + +(defvar mu4e-date-format-long "%c" + "Date format to use in the message view, in the format of + `format-time-string'.") + +(defvar mu4e-search-results-limit 1000 + "Maximum number of search results (or -1 for unlimited). Since +limiting search results speeds up searches significantly, it's +useful to limit this. Note, to ignore the limit, use a prefix +argument (C-u) before invoking the search.") + +(defvar mu4e-debug nil + "When set to non-nil, log debug information to the *mu4e-log* buffer.") + +(defvar mu4e-bookmarks + '( ("flag:unread AND NOT flag:trashed" "Unread messages" ?u) + ("date:today..now" "Today's messages" ?t) + ("date:7d..now" "Last 7 days" ?w) + ("mime:image/*" "Messages with images" ?p)) + "A list of pre-defined queries; these will show up in the main +screen. Each of the list elements is a three-element list of the +form (QUERY DESCRIPTION KEY), where QUERY is a string with a mu +query, DESCRIPTION is a short description of the query (this will +show up in the UI), and KEY is a shortcut key for the query.") + +(defvar mu4e-split-view 'horizontal + "How to show messages / headers; a symbol which is either: + * a symbol 'horizontal: split horizontally (headers on top) + * a symbol 'vertical: split vertically (headers on the left). + * anything else: don't split (show either headers or messages, not both) +Also see `mu4e-headers-visible-lines' and `mu4e-headers-visible-columns'.") + +;; Sending +(defgroup mu4e-sending nil + "E-mail-sending related settings for mu4e." + :group 'mu4e) + +(defcustom mu4e-sent-messages-behavior 'sent + "Determines what mu4e does with sent messages - this is a symbol +which can be either: +'sent --> move the sent message to the Sent-folder (`mu4e-sent-folder') +'trash --> move the sent message to the Trash-folder (`mu4e-trash-folder') +'delete --> delete the sent message. +Note, when using GMail/IMAP, you should set this to either 'trash +or 'delete, since GMail already takes care of keeping copies in the +sent folder." + :type 'symbol + :safe 'symbolp + :group 'mu4e-sending) + +;; Folders + +(defgroup mu4e-folders nil + "Special folders." + :group 'mu4e) + +(defcustom mu4e-sent-folder "/sent" + "Your folder for sent messages, relative to `mu4e-maildir', + e.g. \"/Sent Items\"." + :type 'string + :safe 'stringp + :group 'mu4e-folders) + +(defcustom mu4e-drafts-folder "/drafts" + "Your folder for draft messages, relative to `mu4e-maildir', + e.g. \"/drafts\"" + :type 'string + :safe 'stringp + :group 'mu4e-folders) + +(defcustom mu4e-trash-folder "/trash" + "Your folder for trashed messages, relative to `mu4e-maildir', + e.g. \"/trash\"." + :type 'string + :safe 'stringp + :group 'mu4e-folders) + + +(defcustom mu4e-maildir-shortcuts nil + "A list of maildir shortcuts to enable quickly going to the + particular for, or quickly moving messages towards them (i.e., + archiving or refiling). The list contains elements of the form + (maildir . shortcut), where MAILDIR is a maildir (such as +\"/archive/\"), and shortcut a single shortcut character. With +this, in the header buffer and view buffer you can execute +`mu4e-mark-for-move-quick' (or 'm', by default) or +`mu4e-jump-to-maildir' (or 'j', by default), followed by the +designated shortcut character for the maildir.") + +;; the headers view +(defgroup mu4e-headers nil + "Settings for the headers view." + :group 'mu4e) + + +(defcustom mu4e-headers-fields + '( (:date . 25) + (:flags . 6) + (:from . 22) + (:subject . nil)) + "A list of header fields to show in the headers buffer, and their + respective widths in characters. A width of `nil' means + 'unrestricted', and this is best reserved fo the rightmost (last) + field. For the complete list of available headers, see + `mu4e-header-names'" + :type (list 'symbol) + :group 'mu4e-headers) + +(defcustom mu4e-headers-date-format "%x %X" + "Date format to use in the headers view, in the format of + `format-time-string'." + :type 'string + :group 'mu4e-headers) + +(defcustom mu4e-headers-leave-behavior 'ask + "What to do when user leaves the headers view (e.g. quits, + refreshes or does a new search). Value is one of the following + symbols: +- ask (ask the user whether to ignore the marks) +- apply (automatically apply the marks before doing anything else) +- ignore (automatically ignore the marks without asking)." + :type 'symbol + :group 'mu4e-headers) + + +(defcustom mu4e-headers-visible-lines 10 + "Number of lines to display in the header view when using the +horizontal split-view. This includes the header-line at the top, +and the mode-line." + :type 'integer + :group 'mu4e-headers) + + +(defcustom mu4e-headers-visible-columns 30 + "Number of columns to display for the header view when using the +vertical split-view." + :type 'integer + :group 'mu4e-headers) + +;; the message view +(defgroup mu4e-view nil + "Settings for the message view." + :group 'mu4e) + +(defcustom mu4e-view-fields + '(:from :to :cc :subject :flags :date :maildir :attachments) + "Header fields to display in the message view buffer. For the +complete list of available headers, see `mu4e-header-names'." + :type (list 'symbol) + :group 'mu4e-view) + +(defcustom mu4e-view-date-format "%c" + "Date format to use in the message view, in the format of + `format-time-string'." + :type 'string + :group 'mu4e-view) + +(defcustom mu4e-view-prefer-html nil + "Whether to base the body display on the HTML-version of the +e-mail message (if there is any." + :type 'boolean + :group 'mu4e-view) + +(defcustom mu4e-html2text-command nil + "Shel command that converts HTML from stdin into plain text on +stdout. If this is not defined, the emacs `html2text' tool will be +used when faced with html-only message. If you use htmltext, it's +recommended you use \"html2text -utf8 -width 72\"." + :type 'string + :group 'mu4e-view + :safe 'stringp) + + +(defcustom mu4e-view-wrap-lines nil + "Whether to automatically wrap lines in the body of messages when +viewing them. Note that wrapping does not work well with all +messages, but you can always toggle between wrapped/unwrapped +display with `mu4e-view-toggle-wrap-lines (default keybinding: )." + :group 'mu4e-view) + +(defcustom mu4e-view-wrap-lines nil + "Whether to automatically wrap lines in the body of messages when +viewing them. Note that wrapping does not work well with all +messages, but you can always toggle between wrapped/unwrapped +display with `mu4e-view-toggle-wrap-lines (default keybinding: )." + :group 'mu4e-view) + + +(defcustom mu4e-view-hide-cited nil + "Whether to automatically hide cited parts of messages (as +determined by the presence of '> ' at the beginning of the +line). Note that you can always toggle between hidden/unhidden +display with `mu4e-view-toggle-hide-cited (default keybinding: +)." + :group 'mu4e-view) + + +;; Composing / Sending messages +(defgroup mu4e-compose nil + "Customizations for composing/sending messages." + :group 'mu4e) + +(defcustom mu4e-send-citation-prefix "> " + "String to prefix cited message parts with." + :type 'string + :group 'mu4e-compose) + +(defcustom mu4e-send-reply-prefix "Re: " + "String to prefix the subject of replied messages with." + :type 'string + :group 'mu4e-compose) + +(defcustom mu4e-send-forward-prefix "Fwd: " + "String to prefix the subject of forwarded messages with." + :type 'string + :group 'mu4e-compose) + +(defcustom mu4e-user-agent nil + "The user-agent string; leave at `nil' for the default." + :type 'string + :group 'mu4e-compose) + +(defcustom mu4e-sent-messages-behavior 'sent + "Determines what mu4e does with sent messages - this is a symbol +which can be either: +'sent --> move the sent message to the Sent-folder (`mu4e-sent-folder') +'trash --> move the sent message to the Trash-folder (`mu4e-trash-folder') +'delete --> delete the sent message. +Note, when using GMail/IMAP, you should set this to either 'trash +or 'delete, since GMail already takes care of keeping copies in the +sent folder." + :type 'symbol + :safe 'symbolp + :group 'mu4e-compose) + + +;; Faces + +(defgroup mu4e-faces nil + "Type faces (fonts) used in mu4e." + :group 'mu4e + :group 'faces) + + +(defface mu4e-unread-face + '((t :inherit font-lock-keyword-face :bold t)) + "Face for an unread message header." + :group 'mu4e-faces) + +(defface mu4e-moved-face + '((t :inherit font-lock-comment-face :slant italic)) + "Face for a message header that has been moved to some +folder (it's still visible in the search results, since we cannot +be sure it no longer matches)." + :group 'mu4e-faces) + +(defface mu4e-trashed-face + '((t :inherit font-lock-comment-face :strike-through t)) + "Face for an message header in the trash folder." + :group 'mu4e-faces) + +(defface mu4e-draft-face + '((t :inherit font-lock-string-face)) + "Face for a draft message header (i.e., a message with the draft +flag set)." + :group 'mu4e-faces) + +(defface mu4e-header-face + '((t :inherit default)) + "Face for a header without any special flags." + :group 'mu4e-faces) + +(defface mu4e-header-title-face + '((t :inherit font-lock-type-face)) + "Face for a header title in the headers view." + :group 'mu4e-faces) + +(defface mu4e-view-header-key-face + '((t :inherit font-lock-builtin-face :bold t)) + "Face for a header title (such as \"Subject\") in the message + view." + :group 'mu4e-faces) + +(defface mu4e-header-highlight-face + '((t :inherit default :weight bold :underline t)) + "Face for the header at point." + :group 'mu4e-faces) + +(defface mu4e-view-header-value-face + '((t :inherit font-lock-doc-face)) + "Face for a header value (such as \"Re: Hello!\") in the message + view." + :group 'mu4e-faces) + +(defface mu4e-view-link-face + '((t :inherit font-lock-type-face :underline t)) + "Face for showing URLs and attachments in the message view." + :group 'mu4e-faces) + +(defface mu4e-highlight-face + '((t :inherit font-lock-pseudo-keyword-face :bold t)) + "Face for highlighting things." + :group 'mu4e-faces) + +(defface mu4e-title-face + '((t :inherit font-lock-type-face :bold t)) + "Face for a header title in the headers view." + :group 'mu4e-faces) + +(defface mu4e-view-url-number-face + '((t :inherit font-lock-reference-face :bold t)) + "Face for the number tags for URLs." + :group 'mu4e-faces) + +(defface mu4e-view-attach-number-face + '((t :inherit font-lock-variable-name-face :bold t)) + "Face for the number tags for attachments." + :group 'mu4e-faces) + +(defface mu4e-cited-1-face + '((t :inherit font-lock-builtin-face :bold nil :italic t)) + "Face for cited message parts (level 1)." + :group 'mu4e-faces) + +(defface mu4e-cited-2-face + '((t :inherit font-lock-type-face :bold nil :italic t)) + "Face for cited message parts (level 2)." + :group 'mu4e-faces) + +(defface mu4e-cited-3-face + '((t :inherit font-lock-variable-name-face :bold nil :italic t)) + "Face for cited message parts (level 3)." + :group 'mu4e-faces) + +(defface mu4e-cited-4-face + '((t :inherit font-lock-pseudo-keyword-face :bold nil :italic t)) + "Face for cited message parts (level 4)." + :group 'mu4e-faces) + +(defface mu4e-view-footer-face + '((t :inherit font-lock-comment-face)) + "Face for message footers (signatures)." + :group 'mu4e-faces) + +(defface mu4e-hdrs-marks-face + '((t :inherit font-lock-preprocessor-face)) + "Face for the mark in the headers list." + :group 'mu4e-faces) + +(defface mu4e-system-face + '((t :inherit font-lock-comment-face :slant italic)) + "Face for system message (such as the footers for message +headers)." + :group 'mu4e-faces) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; internal variables / constants + +(defconst mu4e-header-names + '( (:attachments . "Attach") + (:bcc . "Bcc") + (:cc . "Cc") + (:date . "Date") + (:flags . "Flgs") + (:from . "From") + (:from-or-to . "From/To") + (:maildir . "Maildir") + (:path . "Path") + (:subject . "Subject") + (:to . "To")) +"A alist of all possible header fields; this is used in the UI (the +column headers in the header list, and the fields the message +view). Most fields should be self-explanatory. A special one is +`:from-or-to', which is equal to `:from' unless `:from' matches , +in which case it will be equal to `:to'.)") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; run-time vars used in multiple places + +;; headers +(defvar mu4e-last-expr nil "*internal* The most recent search expression.") +(defconst mu4e-hdrs-buffer-name "*mu4e-headers*" + "*internal* Name of the buffer for message headers.") +(defvar mu4e-hdrs-buffer nil "*internal* Buffer for message headers") + +;; view +(defconst mu4e-view-buffer-name "*mu4e-view*" + "*internal* Name for the message view buffer") +(defvar mu4e-view-buffer nil "*internal* The view buffer.") +(defvar mu4e-current-msg nil + "*internal* The plist describing the currently viewed message.") + +(provide 'mu4e-vars) diff --git a/emacs/mu4e-version.el.in b/emacs/mu4e-version.el.in new file mode 100644 index 00000000..421dea16 --- /dev/null +++ b/emacs/mu4e-version.el.in @@ -0,0 +1,7 @@ +;; auto-generated +(defconst mu4e-mu-version "@PACKAGE_STRING@" + "Required mu binary version; mu4e's verson must agree with + this.") + +(provide 'mu4e-version) + diff --git a/emacs/mu4e-view.el b/emacs/mu4e-view.el index da710344..b2a9d725 100644 --- a/emacs/mu4e-view.el +++ b/emacs/mu4e-view.el @@ -26,25 +26,18 @@ ;; viewing e-mail messages ;;; Code: -(eval-when-compile (require 'cl)) - (require 'mu4e-utils) ;; utility functions +(require 'mu4e-vars) +(require 'mu4e-raw-view) + ;; we prefer the improved fill-region (require 'filladapt nil 'noerror) (require 'comint) -(defconst mu4e-view-buffer-name "*mu4e-view*" - "*internal* Name for the message view buffer") - -(defvar mu4e-view-buffer nil "*internal* The view buffer.") - ;; some buffer-local variables (defvar mu4e-hdrs-buffer nil "*internal* Headers buffer connected to this view.") -(defvar mu4e-current-msg nil - "*internal* The plist describing the current message.") - (defun mu4e-view-message-with-msgid (msgid) "View message with MSGID. This is meant for external programs wanting to show specific messages - for example, `mu4e-org'." @@ -98,8 +91,9 @@ marking if it still had that." fieldval)))) (if datestr (mu4e-view-header fieldname datestr) ""))) ;; size - (:size (mu4e-view-size msg) - (let ((sizestr (when size (format "%d bytes")))) + (:size + (let* (size (mu4e-view-size msg) + (sizestr (when size (format "%d bytes" size)))) (if sizestr (mu4e-view-header fieldname sizestr)))) ;; attachments (:attachments (mu4e-view-attachments msg)) @@ -464,82 +458,7 @@ number them so they can be opened using `mu4e-view-go-to-url'." 'face 'mu4e-view-url-number-face)))))))) -;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; some buffer-local variables -(defconst mu4e-raw-view-buffer-name "*mu4e-raw-view*" - "*internal* Name for the raw message view buffer") - -(defvar mu4e-raw-view-buffer nil "*internal* The raw view buffer.") - -(defvar mu4e-raw-view-mode-map nil - "Keymap for \"*mu4e-raw-view*\" buffers.") - -(unless mu4e-raw-view-mode-map - (setq mu4e-raw-view-mode-map - (let ((map (make-sparse-keymap))) - - (define-key map "q" 'mu4e-raw-view-quit-buffer) - (define-key map "." 'mu4e-raw-view-quit-buffer) - - ;; intra-message navigation - (define-key map (kbd "SPC") 'scroll-up) - (define-key map (kbd "") - '(lambda () (interactive) (goto-char (point-min)))) - (define-key map (kbd "") - '(lambda () (interactive) (goto-char (point-max)))) - (define-key map (kbd "RET") - '(lambda () (interactive) (scroll-up 1))) - (define-key map (kbd "") - '(lambda () (interactive) (scroll-up -1))) - map))) - -(fset 'mu4e-raw-view-mode-map mu4e-raw-view-mode-map) - -(define-derived-mode mu4e-raw-view-mode special-mode - "mu4e:raw" - "Major mode for viewing of raw e-mail message in mu4e. -\\{mu4e-raw-view-mode-map}.") - - -(defun mu4e-raw-view-message (msg view-buffer) - "Display the raw contents of message MSG in a new buffer." - (let ((buf (get-buffer-create mu4e-raw-view-buffer-name)) - (inhibit-read-only t) - (file (plist-get msg :path))) - (unless (and file (file-readable-p file)) - (error "Not a readable file: %S" file)) - (with-current-buffer buf - (erase-buffer) - (insert-file file) - ;; initialize view-mode - (mu4e-raw-view-mode) - (setq mu4e-raw-view-buffer view-buffer) - (switch-to-buffer buf) - (goto-char (point-min))))) - - -(defun mu4e-view-shell-command-on-raw-message (msg view-buffer cmd) - "Process the raw message with shell command CMD." - (let ((buf (get-buffer-create mu4e-raw-view-buffer-name)) - (inhibit-read-only t) - (file (plist-get msg :path))) - (unless (and file (file-readable-p file)) - (error "Not a readable file: %S" file)) - (with-current-buffer buf - (erase-buffer) - (process-file-shell-command cmd file buf) - (mu4e-raw-view-mode) - (setq mu4e-raw-view-buffer view-buffer) - (switch-to-buffer buf) - (goto-char (point-min))))) - - -(defun mu4e-raw-view-quit-buffer () - "Quit the raw view and return to the message." - (interactive) - (kill-buffer)) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; functions for org-contacts @@ -658,10 +577,10 @@ citations." (defun mu4e-view-extract-attachment (attnum) "Extract the attachment with ATTNUM." + (interactive "nAttachment to extract:") (unless mu4e-attachment-dir (error "`mu4e-attachment-dir' is not set")) (when (or (null mu4e-attach-map) (zerop (hash-table-count mu4e-attach-map))) (error "No attachments for this message")) - (interactive "nAttachment to extract:") (let* ((att (gethash attnum mu4e-attach-map)) (path (and att (concat mu4e-attachment-dir "/" (plist-get att :name)))) @@ -677,9 +596,9 @@ citations." (defun mu4e-view-open-attachment (attnum) "Extract the attachment with ATTNUM" + (interactive "nAttachment to open:") (unless mu4e-attach-map (error "No attachments for this message")) - (interactive "nAttachment to open:") (let* ((att (gethash attnum mu4e-attach-map)) (id (and att (plist-get att :index)))) (unless id (error "Not a valid attachment number")) diff --git a/emacs/mu4e.el b/emacs/mu4e.el index 01f846ab..32309921 100644 --- a/emacs/mu4e.el +++ b/emacs/mu4e.el @@ -40,476 +40,5 @@ ;; mu4e-version.el is autogenerated, and defines mu4e-mu-version (require 'mu4e-version) -;; Customization - -(defgroup mu4e nil - "mu4e - mu for emacs" - :group 'local) - -(defcustom mu4e-mu-home nil - "Location of the mu homedir, or nil for the default." - :type 'directory - :group 'mu4e - :safe 'stringp) - -(defcustom mu4e-mu-binary (executable-find "mu") - "Name of the mu-binary to use; if it cannot be found in your -PATH, you can specify the full path." - :type 'file - :group 'mu4e - :safe 'stringp) - -(defcustom mu4e-maildir (expand-file-name "~/Maildir") - "Your Maildir directory; by default, mu4e assumes -~/Maildir." - :type 'directory - :safe 'stringp - :group 'mu4e) - -(defcustom mu4e-get-mail-command nil - "Shell command to run to retrieve new mail; e.g. 'offlineimap' or -'fetchmail'." - :type 'string - :group 'mu4e - :safe 'stringp) - -(defcustom mu4e-update-interval nil - "Number of seconds between automatic calls to retrieve mail and -update the database. If nil, don't update automatically. Note, -changes in `mu4e-update-interval' only take effect after restarting -mu4d." - :type 'integer - :group 'mu4e - :safe 'integerp) - -(defcustom mu4e-attachment-dir (expand-file-name "~/") - "Default directory for saving attachments." - :type 'string - :group 'mu4e - :safe 'stringp) - -(defvar mu4e-user-mail-address-regexp "$^" - "Regular expression matching the user's mail address(es). This is -used to distinguish ourselves from others, e.g. when replying and -in :from-or-to headers. By default, match nothing.") - -(defvar mu4e-date-format-long "%c" - "Date format to use in the message view, in the format of - `format-time-string'.") - -(defvar mu4e-search-results-limit 1000 - "Maximum number of search results (or -1 for unlimited). Since -limiting search results speeds up searches significantly, it's -useful to limit this. Note, to ignore the limit, use a prefix -argument (C-u) before invoking the search.") - -(defvar mu4e-debug nil - "When set to non-nil, log debug information to the *mu4e-log* buffer.") - -(defvar mu4e-bookmarks - '( ("flag:unread AND NOT flag:trashed" "Unread messages" ?u) - ("date:today..now" "Today's messages" ?t) - ("date:7d..now" "Last 7 days" ?w) - ("mime:image/*" "Messages with images" ?p)) - "A list of pre-defined queries; these will show up in the main -screen. Each of the list elements is a three-element list of the -form (QUERY DESCRIPTION KEY), where QUERY is a string with a mu -query, DESCRIPTION is a short description of the query (this will -show up in the UI), and KEY is a shortcut key for the query.") - -(defvar mu4e-split-view 'horizontal - "How to show messages / headers; a symbol which is either: - * a symbol 'horizontal: split horizontally (headers on top) - * a symbol 'vertical: split vertically (headers on the left). - * anything else: don't split (show either headers or messages, not both) -Also see `mu4e-headers-visible-lines' and `mu4e-headers-visible-columns'.") - -;; Sending -(defgroup mu4e-sending nil - "E-mail-sending related settings for mu4e.") - -(defcustom mu4e-sent-messages-behavior 'sent - "Determines what mu4e does with sent messages - this is a symbol -which can be either: -'sent --> move the sent message to the Sent-folder (`mu4e-sent-folder') -'trash --> move the sent message to the Trash-folder (`mu4e-trash-folder') -'delete --> delete the sent message. -Note, when using GMail/IMAP, you should set this to either 'trash -or 'delete, since GMail already takes care of keeping copies in the -sent folder." - :type 'symbol - :safe 'symbolp - :group 'mu4e-sending) - -;; Folders - -(defgroup mu4e-folders nil - "Special folders." - :group 'mu4e) - -(defcustom mu4e-sent-folder "/sent" - "Your folder for sent messages, relative to `mu4e-maildir', - e.g. \"/Sent Items\"." - :type 'string - :safe 'stringp - :group 'mu4e-folders) - -(defcustom mu4e-drafts-folder "/drafts" - "Your folder for draft messages, relative to `mu4e-maildir', - e.g. \"/drafts\"" - :type 'string - :safe 'stringp - :group 'mu4e-folders) - -(defcustom mu4e-trash-folder "/trash" - "Your folder for trashed messages, relative to `mu4e-maildir', - e.g. \"/trash\"." - :type 'string - :safe 'stringp - :group 'mu4e-folders) - - -(defcustom mu4e-maildir-shortcuts nil - "A list of maildir shortcuts to enable quickly going to the - particular for, or quickly moving messages towards them (i.e., - archiving or refiling). The list contains elements of the form - (maildir . shortcut), where MAILDIR is a maildir (such as -\"/archive/\"), and shortcut a single shortcut character. With -this, in the header buffer and view buffer you can execute -`mu4e-mark-for-move-quick' (or 'm', by default) or -`mu4e-jump-to-maildir' (or 'j', by default), followed by the -designated shortcut character for the maildir.") - -;; the headers view -(defgroup mu4e-headers nil - "Settings for the headers view." - :group 'mu4e) - - -(defcustom mu4e-headers-fields - '( (:date . 25) - (:flags . 6) - (:from . 22) - (:subject . nil)) - "A list of header fields to show in the headers buffer, and their - respective widths in characters. A width of `nil' means - 'unrestricted', and this is best reserved fo the rightmost (last) - field. For the complete list of available headers, see - `mu4e-header-names'" - :type (list 'symbol) - :group 'mu4e-headers) - -(defcustom mu4e-headers-date-format "%x %X" - "Date format to use in the headers view, in the format of - `format-time-string'." - :type 'string - :group 'mu4e-headers) - -(defcustom mu4e-headers-leave-behavior 'ask - "What to do when user leaves the headers view (e.g. quits, - refreshes or does a new search). Value is one of the following - symbols: -- ask (ask the user whether to ignore the marks) -- apply (automatically apply the marks before doing anything else) -- ignore (automatically ignore the marks without asking)." - :type 'symbol - :group 'mu4e-headers) - - -(defcustom mu4e-headers-visible-lines 8 - "Number of lines to display in the header view when using the -horizontal split-view." - :type 'integer - :group 'mu4e-headers) - - -(defcustom mu4e-headers-visible-columns 30 - "Number of columns to display for the header view when using the -vertical split-view." - :type 'integer - :group 'mu4e-headers) - -;; the message view -(defgroup mu4e-view nil - "Settings for the message view." - :group 'mu4e) - -(defcustom mu4e-view-fields - '(:from :to :cc :subject :flags :date :maildir :attachments) - "Header fields to display in the message view buffer. For the -complete list of available headers, see `mu4e-header-names'." - :type (list 'symbol) - :group 'mu4e-view) - -(defcustom mu4e-view-date-format "%c" - "Date format to use in the message view, in the format of - `format-time-string'." - :type 'string - :group 'mu4e-view) - -(defcustom mu4e-view-prefer-html nil - "Whether to base the body display on the HTML-version of the -e-mail message (if there is any." - :type 'boolean - :group 'mu4e-view) - -(defcustom mu4e-html2text-command nil - "Shel command that converts HTML from stdin into plain text on -stdout. If this is not defined, the emacs `html2text' tool will be -used when faced with html-only message. If you use htmltext, it's -recommended you use \"html2text -utf8 -width 72\"." - :type 'string - :group 'mu4e-view - :safe 'stringp) - - -(defcustom mu4e-view-wrap-lines nil - "Whether to automatically wrap lines in the body of messages when -viewing them. Note that wrapping does not work well with all -messages, but you can always toggle between wrapped/unwrapped -display with `mu4e-view-toggle-wrap-lines (default keybinding: )." - :group 'mu4e-view) - -(defcustom mu4e-view-wrap-lines nil - "Whether to automatically wrap lines in the body of messages when -viewing them. Note that wrapping does not work well with all -messages, but you can always toggle between wrapped/unwrapped -display with `mu4e-view-toggle-wrap-lines (default keybinding: )." - :group 'mu4e-view) - - -(defcustom mu4e-view-hide-cited nil - "Whether to automatically hide cited parts of messages (as -determined by the presence of '> ' at the beginning of the -line). Note that you can always toggle between hidden/unhidden -display with `mu4e-view-toggle-hide-cited (default keybinding: -)." - :group 'mu4e-view) - - -;; Composing / Sending messages -(defgroup mu4e-compose nil - "Customizations for composing/sending messages." - :group 'mu4e) - -(defcustom mu4e-send-citation-prefix "> " - "String to prefix cited message parts with." - :type 'string - :group 'mu4e-compose) - -(defcustom mu4e-send-reply-prefix "Re: " - "String to prefix the subject of replied messages with." - :type 'string - :group 'mu4e-compose) - -(defcustom mu4e-send-forward-prefix "Fwd: " - "String to prefix the subject of forwarded messages with." - :type 'string - :group 'mu4e-compose) - -(defcustom mu4e-user-agent nil - "The user-agent string; leave at `nil' for the default." - :type 'string - :group 'mu4e-compose) - -(defcustom mu4e-sent-messages-behavior 'sent - "Determines what mu4e does with sent messages - this is a symbol -which can be either: -'sent --> move the sent message to the Sent-folder (`mu4e-sent-folder') -'trash --> move the sent message to the Trash-folder (`mu4e-trash-folder') -'delete --> delete the sent message. -Note, when using GMail/IMAP, you should set this to either 'trash -or 'delete, since GMail already takes care of keeping copies in the -sent folder." - :type 'symbol - :safe 'symbolp - :group 'mu4e-compose) - - -;; Faces - -(defgroup mu4e-faces nil - "Type faces (fonts) used in mu4e." - :group 'mu4e - :group 'faces) - - -(defface mu4e-unread-face - '((t :inherit font-lock-keyword-face :bold t)) - "Face for an unread message header." - :group 'mu4e-faces) - -(defface mu4e-moved-face - '((t :inherit font-lock-comment-face :slant italic)) - "Face for a message header that has been moved to some -folder (it's still visible in the search results, since we cannot -be sure it no longer matches)." - :group 'mu4e-faces) - -(defface mu4e-trashed-face - '((t :inherit font-lock-comment-face :strike-through t)) - "Face for an message header in the trash folder." - :group 'mu4e-faces) - -(defface mu4e-draft-face - '((t :inherit font-lock-string-face)) - "Face for a draft message header (i.e., a message with the draft -flag set)." - :group 'mu4e-faces) - -(defface mu4e-header-face - '((t :inherit default)) - "Face for a header without any special flags." - :group 'mu4e-faces) - -(defface mu4e-header-title-face - '((t :inherit font-lock-type-face)) - "Face for a header title in the headers view." - :group 'mu4e-faces) - -(defface mu4e-view-header-key-face - '((t :inherit font-lock-builtin-face :bold t)) - "Face for a header title (such as \"Subject\") in the message - view." - :group 'mu4e-faces) - -(defface mu4e-header-highlight-face - '((t :inherit default :weight bold :underline t)) - "Face for the header at point." - :group 'mu4e-faces) - -(defface mu4e-view-header-value-face - '((t :inherit font-lock-doc-face)) - "Face for a header value (such as \"Re: Hello!\") in the message - view." - :group 'mu4e-faces) - -(defface mu4e-view-link-face - '((t :inherit font-lock-type-face :underline t)) - "Face for showing URLs and attachments in the message view." - :group 'mu4e-faces) - -(defface mu4e-highlight-face - '((t :inherit font-lock-pseudo-keyword-face :bold t)) - "Face for highlighting things." - :group 'mu4e-faces) - -(defface mu4e-title-face - '((t :inherit font-lock-type-face :bold t)) - "Face for a header title in the headers view." - :group 'mu4e-faces) - -(defface mu4e-view-url-number-face - '((t :inherit font-lock-reference-face :bold t)) - "Face for the number tags for URLs." - :group 'mu4e-faces) - -(defface mu4e-view-attach-number-face - '((t :inherit font-lock-variable-name-face :bold t)) - "Face for the number tags for attachments." - :group 'mu4e-faces) - -(defface mu4e-cited-1-face - '((t :inherit font-lock-builtin-face :bold nil :italic t)) - "Face for cited message parts (level 1)." - :group 'mu4e-faces) - -(defface mu4e-cited-2-face - '((t :inherit font-lock-type-face :bold nil :italic t)) - "Face for cited message parts (level 2)." - :group 'mu4e-faces) - -(defface mu4e-cited-3-face - '((t :inherit font-lock-variable-name-face :bold nil :italic t)) - "Face for cited message parts (level 3)." - :group 'mu4e-faces) - -(defface mu4e-cited-4-face - '((t :inherit font-lock-pseudo-keyword-face :bold nil :italic t)) - "Face for cited message parts (level 4)." - :group 'mu4e-faces) - -(defface mu4e-view-footer-face - '((t :inherit font-lock-comment-face)) - "Face for message footers (signatures)." - :group 'mu4e-faces) - -(defface mu4e-hdrs-marks-face - '((t :inherit font-lock-preprocessor-face)) - "Face for the mark in the headers list." - :group 'mu4e-faces) - -(defface mu4e-system-face - '((t :inherit font-lock-comment-face :slant italic)) - "Face for system message (such as the footers for message -headers)." - :group 'mu4e-faces) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; internal variables / constants - -(defconst mu4e-header-names - '( (:attachments . "Attach") - (:bcc . "Bcc") - (:cc . "Cc") - (:date . "Date") - (:flags . "Flgs") - (:from . "From") - (:from-or-to . "From/To") - (:maildir . "Maildir") - (:path . "Path") - (:subject . "Subject") - (:to . "To")) -"A alist of all possible header fields; this is used in the UI (the -column headers in the header list, and the fields the message -view). Most fields should be self-explanatory. A special one is -`:from-or-to', which is equal to `:from' unless `:from' matches , -in which case it will be equal to `:to'.)") - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defvar mu4e-update-timer nil - "*internal* The mu4e update timer.") - -(defun mu4e () - "Start mu4e. We do this by sending a 'ping' to the mu server -process, and start the main view if the 'pong' we receive from the -server has the expected values." - (interactive) - (if (buffer-live-p (get-buffer mu4e-main-buffer-name)) - (switch-to-buffer mu4e-main-buffer-name) - (mu4e-check-requirements) - ;; explicit version checks are a bit questionable, - ;; better to check for specific features - (if (< emacs-major-version 23) - (error "Emacs >= 23.x is required for mu4e") - (progn - (setq mu4e-proc-pong-func - (lambda (version doccount) - (unless (string= version mu4e-mu-version) - (error "mu server has version %s, but we need %s" - version mu4e-mu-version)) - (mu4e-main-view) - (when (and mu4e-update-interval (null mu4e-update-timer)) - (setq mu4e-update-timer - (run-at-time - 0 mu4e-update-interval - 'mu4e-update-mail))) - (message "Started mu4e with %d message%s in store" - doccount (if (= doccount 1) "" "s")))) - (mu4e-proc-ping))))) - -(defun mu4e-quit() - "Quit the mu4e session." - (interactive) - (when (y-or-n-p "Are you sure you want to quit? ") - (message nil) - (when mu4e-update-timer - (cancel-timer mu4e-update-timer) - (setq mu4e-update-timer nil)) - (mu4e-kill-proc) - (kill-buffer))) - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (provide 'mu4e)