diff --git a/emacs/coolj.el b/emacs/coolj.el index 0385872f..b3e314f0 100644 --- a/emacs/coolj.el +++ b/emacs/coolj.el @@ -25,13 +25,13 @@ ;;; Commentary: -;;; This is a simple derivative of some functionality from -;;; `longlines.el'. The key difference is that this version will -;;; insert a prefix at the head of each wrapped line. The prefix is -;;; calculated from the originating long line. +;; This is a simple derivative of some functionality from +;; `longlines.el'. The key difference is that this version will +;; insert a prefix at the head of each wrapped line. The prefix is +;; calculated from the originating long line. -;;; No minor-mode is provided, the caller is expected to call -;;; `coolj-wrap-region' to wrap the region of interest. +;; No minor-mode is provided, the caller is expected to call +;; `coolj-wrap-region' to wrap the region of interest. ;;; Code: diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index 71985ed7..bf29c3a0 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -25,9 +25,11 @@ (require 'notmuch-parser) (require 'notmuch-lib) (require 'notmuch-company) -;; + (declare-function company-manual-begin "company") +;;; Cache internals + (defvar notmuch-address-last-harvest 0 "Time of last address harvest.") @@ -47,6 +49,8 @@ If the hash is not present it attempts to load a saved hash." (or notmuch-address-full-harvest-finished (notmuch-address--load-address-hash))) +;;; Options + (defcustom notmuch-address-command 'internal "Determines how address completion candidates are generated. @@ -133,6 +137,14 @@ matching `notmuch-address-completion-headers-regexp'." :group 'notmuch-address :group 'notmuch-hooks) +(defcustom notmuch-address-use-company t + "If available, use company mode for address completion." + :type 'boolean + :group 'notmuch-send + :group 'notmuch-address) + +;;; Setup + (defun notmuch-address-selection-function (prompt collection initial-input) "Call (`completing-read' PROMPT COLLECTION nil nil INITIAL-INPUT 'notmuch-address-history)" @@ -147,12 +159,6 @@ matching `notmuch-address-completion-headers-regexp'." (defun notmuch-address-message-insinuate () (message "calling notmuch-address-message-insinuate is no longer needed")) -(defcustom notmuch-address-use-company t - "If available, use company mode for address completion." - :type 'boolean - :group 'notmuch-send - :group 'notmuch-address) - (defun notmuch-address-setup () (let* ((setup-company (and notmuch-address-use-company (require 'company nil t))) @@ -178,6 +184,8 @@ toggles the setting in this buffer." (kill-local-variable 'company-idle-delay) (setq-local company-idle-delay nil)))) +;;; Completion + (defun notmuch-address-matching (substring) "Returns a list of completion candidates matching SUBSTRING. The candidates are taken from `notmuch-address-completions'." @@ -250,6 +258,8 @@ requiring external commands." (ding)))) (t nil))) +;;; Harvest + (defun notmuch-address-harvest-addr (result) (let ((name-addr (plist-get result :name-addr))) (puthash name-addr t notmuch-address-completions))) @@ -406,7 +416,7 @@ appear to be an address savefile. Not overwriting." (setq notmuch-address-full-harvest-finished t)) (setq notmuch-address-last-harvest 0))))))) -;; +;;; Standalone completion (defun notmuch-address-from-minibuffer (prompt) (if (not notmuch-address-command) @@ -425,7 +435,7 @@ appear to be an address savefile. Not overwriting." (let ((minibuffer-local-map rmap)) (read-string prompt))))) -;; +;;; _ (provide 'notmuch-address) diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el index b50e73c8..4439cc15 100644 --- a/emacs/notmuch-company.el +++ b/emacs/notmuch-company.el @@ -102,7 +102,6 @@ (run-hook-with-args 'notmuch-address-post-completion-functions arg)) (no-cache t)))) - (provide 'notmuch-company) ;;; notmuch-company.el ends here diff --git a/emacs/notmuch-compat.el b/emacs/notmuch-compat.el index 2975f4c2..c4e07780 100644 --- a/emacs/notmuch-compat.el +++ b/emacs/notmuch-compat.el @@ -41,8 +41,6 @@ (unless (fboundp 'message--fold-long-headers) (add-hook 'message-header-hook 'notmuch-message--fold-long-headers)) -;; End of compatibility functions - (provide 'notmuch-compat) ;;; notmuch-compat.el ends here diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el index 9e6f3a9d..6d2d35a5 100644 --- a/emacs/notmuch-crypto.el +++ b/emacs/notmuch-crypto.el @@ -26,6 +26,8 @@ (declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) +;;; Options + (defcustom notmuch-crypto-process-mime t "Whether to process cryptographic MIME parts. @@ -55,6 +57,8 @@ mode." :type 'string :group 'notmuch-crypto) +;;; Faces + (defface notmuch-crypto-part-header '((((class color) (background dark)) @@ -96,6 +100,8 @@ mode." :group 'notmuch-crypto :group 'notmuch-faces) +;;; Functions + (define-button-type 'notmuch-crypto-status-button-type 'action (lambda (button) (message (button-get button 'help-echo))) 'follow-link t @@ -259,7 +265,7 @@ corresponding key when the status button is pressed." 'mouse-face 'notmuch-crypto-decryption) (insert "\n")) -;; +;;; _ (provide 'notmuch-crypto) diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index f928be87..9ce9e736 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -31,6 +31,8 @@ (declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) (declare-function notmuch-message-mode "notmuch-mua") +;;; Options + (defgroup notmuch-draft nil "Saving and editing drafts in Notmuch." :group 'notmuch) @@ -85,6 +87,8 @@ like they are intended to be sent encrypted :group 'notmuch-draft :group 'notmuch-crypto) +;;; Internal + (defvar notmuch-draft-encryption-tag-regex "<#\\(part encrypt\\|secure.*mode=.*encrypt>\\)" "Regular expression matching mml tags indicating encryption of part or message.") @@ -169,6 +173,8 @@ Really save and index an unencrypted copy? ") ;; but notmuch doesn't want that form, so remove them. (concat "draft-" (substring (message-make-message-id) 1 -1))) +;;; Commands + (defun notmuch-draft-save () "Save the current draft message in the notmuch database. @@ -226,6 +232,7 @@ applied to newly inserted messages)." (defun notmuch-draft-resume (id) "Resume editing of message with id ID." + ;; Used by command `notmuch-show-resume-message'. (let* ((tags (process-lines notmuch-command "search" "--output=tags" "--exclude=false" id)) (draft (equal tags (notmuch-update-tags tags notmuch-draft-tags)))) @@ -265,10 +272,10 @@ applied to newly inserted messages)." ;; message is resaved or sent. (setq notmuch-draft-id (and draft id))))) +;;; _ (add-hook 'message-send-hook 'notmuch-draft--mark-deleted) - (provide 'notmuch-draft) ;;; notmuch-draft.el ends here diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 7bc713f3..28ffedd9 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -37,6 +37,8 @@ (&optional query query-context target buffer-name open-target)) +;;; Options + (defun notmuch-saved-search-get (saved-search field) "Get FIELD from SAVED-SEARCH. @@ -192,6 +194,8 @@ fields of the search." (defvar notmuch-hello-indent 4 "How much to indent non-headers.") +(defimage notmuch-hello-logo ((:type png :file "notmuch-logo.png"))) + (defcustom notmuch-show-logo t "Should the notmuch logo be shown?" :type 'boolean @@ -367,23 +371,15 @@ supported for \"Customized queries section\" items." :group 'notmuch-hello :type 'boolean) +;;; Internal variables + (defvar notmuch-hello-hidden-sections nil "List of sections titles whose contents are hidden.") (defvar notmuch-hello-first-run t "True if `notmuch-hello' is run for the first time, set to nil afterwards.") -(defun notmuch-hello-nice-number (n) - (let (result) - (while (> n 0) - (push (% n 1000) result) - (setq n (/ n 1000))) - (setq result (or result '(0))) - (apply #'concat - (number-to-string (car result)) - (mapcar (lambda (elem) - (format "%s%03d" notmuch-hello-thousands-separator elem)) - (cdr result))))) +;;; Widgets for inserters (define-widget 'notmuch-search-item 'item "A recent search." @@ -419,6 +415,8 @@ supported for \"Customized queries section\" items." 1 ; for the space before the [del] button 5))) ; for the [del] button +;;; Widget actions + (defun notmuch-hello-search (widget &rest _event) (let ((search (widget-value widget))) (when search @@ -451,6 +449,13 @@ supported for \"Customized queries section\" items." (delete search notmuch-search-history))) (notmuch-hello-update))) +;;; Button utilities + +;; `notmuch-hello-query-counts', `notmuch-hello-nice-number' and +;; `notmuch-hello-insert-buttons' are used outside this section. +;; All other functions that are defined in this section are only +;; used by these two functions. + (defun notmuch-hello-longest-label (searches-alist) (or (cl-loop for elem in searches-alist maximize (length (notmuch-saved-search-get elem :name))) @@ -585,6 +590,18 @@ the CLI and emacs interface.")) (list (plist-put elem-plist :count message-count))))) query-list))) +(defun notmuch-hello-nice-number (n) + (let (result) + (while (> n 0) + (push (% n 1000) result) + (setq n (/ n 1000))) + (setq result (or result '(0))) + (apply #'concat + (number-to-string (car result)) + (mapcar (lambda (elem) + (format "%s%03d" notmuch-hello-thousands-separator elem)) + (cdr result))))) + (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. @@ -639,7 +656,7 @@ with `notmuch-hello-query-counts'." (unless (eq (% count tags-per-line) 0) (widget-insert "\n")))) -(defimage notmuch-hello-logo ((:type png :file "notmuch-logo.png"))) +;;; Mode (defun notmuch-hello-update () "Update the notmuch-hello buffer." @@ -723,6 +740,8 @@ Complete list of currently available key bindings: ;;(setq buffer-read-only t) ) +;;; Inserters + (defun notmuch-hello-generate-tag-alist (&optional hide-tags) "Return an alist from tags to queries to display in the all-tags section." (cl-mapcan (lambda (tag) @@ -922,6 +941,8 @@ following: (let ((fill-column (- (window-width) notmuch-hello-indent))) (center-region start (point))))) +;;; Hello! + ;;;###autoload (defun notmuch-hello (&optional no-display) "Run notmuch and display saved searches, known tags, etc." @@ -973,7 +994,7 @@ following: (run-hooks 'notmuch-hello-refresh-hook) (setq notmuch-hello-first-run nil)) -;; +;;; _ (provide 'notmuch-hello) diff --git a/emacs/notmuch-jump.el b/emacs/notmuch-jump.el index ff622055..7a27b6b3 100644 --- a/emacs/notmuch-jump.el +++ b/emacs/notmuch-jump.el @@ -198,8 +198,6 @@ buffer." (exit-minibuffer))))))) map)) -;; - (provide 'notmuch-jump) ;;; notmuch-jump.el ends here diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 0e235fa3..0b698d59 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -33,6 +33,8 @@ (defconst notmuch-emacs-version "unknown" "Placeholder variable when notmuch-version.el[c] is not available.")) +;;; Groups + (defgroup notmuch nil "Notmuch mail reader for Emacs." :group 'mail) @@ -78,6 +80,8 @@ "Graphical attributes for displaying text" :group 'notmuch) +;;; Options + (defcustom notmuch-command "notmuch" "Name of the notmuch binary. @@ -125,11 +129,6 @@ the user's needs: (string :tag "Custom script")) :group 'notmuch-external) -;; - -(defvar notmuch-search-history nil - "Variable to store notmuch searches history.") - (defcustom notmuch-archive-tags '("-inbox") "List of tag changes to apply to a message or a thread when it is archived. @@ -144,6 +143,11 @@ For example, if you wanted to remove an \"inbox\" tag and add an :group 'notmuch-search :group 'notmuch-show) +;;; Variables + +(defvar notmuch-search-history nil + "Variable to store notmuch searches history.") + (defvar notmuch-common-keymap (let ((map (make-sparse-keymap))) (define-key map "?" 'notmuch-help) @@ -177,6 +181,8 @@ For example, if you wanted to remove an \"inbox\" tag and add an (select-window (posn-window (event-start last-input-event))) (button-activate button))) +;;; CLI Utilities + (defun notmuch-command-to-string (&rest args) "Synchronously invoke \"notmuch\" with the given list of arguments. @@ -234,6 +240,8 @@ displays both values separately." (concat cli-version " (emacs mua version " notmuch-emacs-version ")"))))) +;;; Notmuch Configuration + (defun notmuch-config-get (item) "Return a value from the notmuch configuration." (let* ((val (notmuch-command-to-string "config" "get" item)) @@ -263,6 +271,8 @@ displays both values separately." (defun notmuch-user-emails () (cons (notmuch-user-primary-email) (notmuch-user-other-email))) +;;; Commands + (defun notmuch-poll () "Run \"notmuch new\" or an external script to import mail. @@ -287,6 +297,8 @@ it, in which case it is killed." (bury-buffer) (kill-buffer))) +;;; Describe Key Bindings + (defun notmuch-prefix-key-description (key) "Given a prefix key code, return a human-readable string representation. @@ -297,7 +309,6 @@ This is basically just `format-kbd-macro' but we also convert ESC to M-." "M-" (concat desc " ")))) - (defun notmuch-describe-key (actual-key binding prefix ua-keys tail) "Prepend cons cells describing prefix-arg ACTUAL-KEY and ACTUAL-KEY to TAIL. @@ -435,6 +446,8 @@ of its command symbol." (insert desc))) (pop-to-buffer (help-buffer))))) +;;; Refreshing Buffers + (defvar-local notmuch-buffer-refresh-function nil "Function to call to refresh the current buffer.") @@ -466,6 +479,8 @@ be displayed." (with-current-buffer buffer (notmuch-refresh-this-buffer)))))) +;;; String Utilities + (defun notmuch-prettify-subject (subject) ;; This function is used by `notmuch-search-process-filter' which ;; requires that we not disrupt its' matching state. @@ -509,8 +524,6 @@ This replaces spaces, percents, and double quotes in STR with (replace-regexp-in-string "[ %\"]" (lambda (match) (format "%%%02x" (aref match 0))) str)) -;; - (defun notmuch-common-do-stash (text) "Common function to stash text in kill ring, and display in minibuffer." (if text @@ -522,7 +535,7 @@ This replaces spaces, percents, and double quotes in STR with (kill-new "") (message "Nothing to stash!"))) -;; +;;; Generic Utilities (defun notmuch-plist-delete (plist property) (let* ((xplist (cons nil plist)) @@ -533,6 +546,8 @@ This replaces spaces, percents, and double quotes in STR with (setq pred (cddr pred))) (cdr xplist))) +;;; MML Utilities + (defun notmuch-match-content-type (t1 t2) "Return t if t1 and t2 are matching content types, taking wildcards into account." (let ((st1 (split-string t1 "/")) @@ -673,6 +688,8 @@ current buffer, if possible." (mm-display-part handle) t)))))) +;;; Generic Utilities + ;; Converts a plist of headers to an alist of headers. The input plist should ;; have symbols of the form :Header as keys, and the resulting alist will have ;; symbols of the form 'Header as keys. @@ -739,6 +756,8 @@ returned by FUNC." (put-text-property start next prop (funcall func value) object) (setq start next)))) +;;; Running Notmuch + (defun notmuch-logged-error (msg &optional extra) "Log MSG and EXTRA to *Notmuch errors* and signal MSG. @@ -967,6 +986,8 @@ status." (defvar-local notmuch-show-process-crypto nil) +;;; Generic Utilities + (defun notmuch-interactive-region () "Return the bounds of the current interactive region. @@ -981,6 +1002,8 @@ region if the region is active, or both `point' otherwise." 'notmuch-interactive-region "notmuch 0.29") +;;; _ + (provide 'notmuch-lib) ;;; notmuch-lib.el ends here diff --git a/emacs/notmuch-maildir-fcc.el b/emacs/notmuch-maildir-fcc.el index 32b8100e..5de03cc2 100644 --- a/emacs/notmuch-maildir-fcc.el +++ b/emacs/notmuch-maildir-fcc.el @@ -29,6 +29,8 @@ (defvar notmuch-maildir-fcc-count 0) +;;; Options + (defcustom notmuch-fcc-dirs "sent" "Determines the Fcc Header which says where to save outgoing mail. @@ -83,8 +85,7 @@ directory if it does not exist yet when sending a mail." (const :tag "Use simple fcc" nil)) :group 'notmuch-send) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions which set up the fcc header in the message buffer. +;;; Functions which set up the fcc header in the message buffer. (defun notmuch-fcc-header-setup () "Add an Fcc header to the current message buffer. @@ -142,9 +143,7 @@ Insert header anyway? " subdir))) subdir (concat (notmuch-database-path) "/" subdir)))))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions for saving a message either using notmuch insert or file -;; fcc. First functions common to the two cases. +;;; Functions for saving a message using either method. (defmacro with-temporary-notmuch-message-buffer (&rest body) "Set-up a temporary copy of the current message-mode buffer." @@ -204,8 +203,7 @@ normal fcc." (notmuch-maildir-fcc-with-notmuch-insert fcc-header) (notmuch-maildir-fcc-file-fcc fcc-header))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions for saving a message using notmuch insert. +;;; Functions for saving a message using notmuch insert. (defun notmuch-maildir-notmuch-insert-current-buffer (folder &optional create tags) "Use notmuch insert to put the current buffer in the database. @@ -251,9 +249,7 @@ If CREATE is non-nil then create the folder if necessary." (?e (notmuch-maildir-fcc-with-notmuch-insert (read-from-minibuffer "Fcc header: " fcc-header))))))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions for saving a message using file fcc. +;;; Functions for saving a message using file fcc. (defun notmuch-maildir-fcc-host-fixer (hostname) (replace-regexp-in-string "/\\|:" @@ -362,6 +358,8 @@ return t if successful, and nil otherwise." (delete-file (concat destdir "/tmp/" msg-id)))) t))) +;;; _ + (provide 'notmuch-maildir-fcc) ;;; notmuch-maildir-fcc.el ends here diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index c38cb5aa..6fe5f6d0 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -38,7 +38,7 @@ (declare-function notmuch-draft-postpone "notmuch-draft" ()) (declare-function notmuch-draft-save "notmuch-draft" ()) -;; +;;; Options (defcustom notmuch-mua-send-hook nil "Hook run before sending messages." @@ -120,7 +120,7 @@ to `notmuch-mua-send-hook'." :type 'regexp :group 'notmuch-send) -;; +;;; Various functions (defun notmuch-mua-attachment-check () "Signal an error if the message text indicates that an @@ -215,6 +215,8 @@ Typically this is added to `notmuch-mua-send-hook'." (funcall original-func header references) (unless (bolp) (insert "\n"))) +;;; Mua reply + (defun notmuch-mua-reply (query-string &optional sender reply-all) (let ((args '("reply" "--format=sexp" "--format-version=4")) (process-crypto notmuch-show-process-crypto) @@ -318,6 +320,8 @@ Typically this is added to `notmuch-mua-send-hook'." (message-goto-body) (set-buffer-modified-p nil)) +;;; Mode and keymap + (defvar notmuch-message-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-c C-c") #'notmuch-mua-send-and-exit) @@ -333,6 +337,8 @@ Typically this is added to `notmuch-mua-send-hook'." (put 'notmuch-message-mode 'flyspell-mode-predicate 'mail-mode-flyspell-verify) +;;; New messages + (defun notmuch-mua-pop-to-buffer (name switch-function) "Pop to buffer NAME, and warn if it already exists and is modified. Like `message-pop-to-buffer' but enable `notmuch-message-mode' @@ -528,6 +534,8 @@ will be addressed to all recipients of the source message." (notmuch-mua-reply query-string sender reply-all) (deactivate-mark))) +;;; Checks + (defun notmuch-mua-check-no-misplaced-secure-tag () "Query user if there is a misplaced secure mml tag. @@ -570,6 +578,8 @@ The <#secure> tag at the start of the body is not followed by a newline. It is likely that the message will be sent unsigned and unencrypted. Really send? ")))) +;;; Finishing commands + (defun notmuch-mua-send-common (arg &optional exit) (interactive "P") (run-hooks 'notmuch-mua-send-hook) @@ -593,7 +603,7 @@ unencrypted. Really send? ")))) (interactive) (message-kill-buffer)) -;; +;;; _ (define-mail-user-agent 'notmuch-user-agent 'notmuch-mua-mail 'notmuch-mua-send-and-exit @@ -603,8 +613,6 @@ unencrypted. Really send? ")))) ;; composing a message. (notmuch-mua-add-more-hidden-headers) -;; - (provide 'notmuch-mua) ;;; notmuch-mua.el ends here diff --git a/emacs/notmuch-print.el b/emacs/notmuch-print.el index 6dd9f775..d7b2fcce 100644 --- a/emacs/notmuch-print.el +++ b/emacs/notmuch-print.el @@ -25,6 +25,8 @@ (declare-function notmuch-show-get-prop "notmuch-show" (prop &optional props)) +;;; Options + (defcustom notmuch-print-mechanism 'notmuch-print-lpr "How should printing be done?" :group 'notmuch-show @@ -36,7 +38,7 @@ (function :tag "Use muttprint then evince" notmuch-print-muttprint/evince) (function :tag "Using a custom function"))) -;; Utility functions: +;;; Utility functions (defun notmuch-print-run-evince (file) "View FILE using 'evince'." @@ -54,7 +56,7 @@ Optional OUTPUT allows passing a list of flags to muttprint." "--printed-headers" "Date_To_From_CC_Newsgroups_*Subject*_/Tags/" output)) -;; User-visible functions: +;;; User-visible functions (defun notmuch-print-lpr (msg) "Print a message buffer using lpr." @@ -91,6 +93,8 @@ Optional OUTPUT allows passing a list of flags to muttprint." (set-buffer-modified-p nil) (funcall notmuch-print-mechanism msg)) +;;; _ + (provide 'notmuch-print) ;;; notmuch-print.el ends here diff --git a/emacs/notmuch-query.el b/emacs/notmuch-query.el index 3cfccbc3..72ddd2ce 100644 --- a/emacs/notmuch-query.el +++ b/emacs/notmuch-query.el @@ -23,6 +23,8 @@ (require 'notmuch-lib) +;;; Basic query function + (defun notmuch-query-get-threads (search-terms) "Return a list of threads of messages matching SEARCH-TERMS. @@ -35,8 +37,7 @@ is a possibly empty forest of replies." (setq args (append args search-terms)) (apply #'notmuch-call-notmuch-sexp args))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Mapping functions across collections of messages. +;;; Mapping functions across collections of messages (defun notmuch-query-map-aux (mapper function seq) "Private function to do the actual mapping and flattening." @@ -64,8 +65,7 @@ Flatten results to a list. See the function `notmuch-query-get-threads' for more information." (cons (funcall fn (car tree)) (notmuch-query-map-forest fn (cadr tree)))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Predefined queries +;;; Predefined queries (defun notmuch-query-get-message-ids (&rest search-terms) "Return a list of message-ids of messages that match SEARCH-TERMS." diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 056c4e30..7dfbb327 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -59,6 +59,8 @@ (declare-function notmuch-read-query "notmuch" (prompt)) (declare-function notmuch-draft-resume "notmuch-draft" (id)) +;;; Options + (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date") "Headers that should be shown in a message, in this order. @@ -162,6 +164,8 @@ indentation." :type '(choice (const nil) regexp) :group 'notmuch-show) +;;; Variables + (defvar-local notmuch-show-thread-id nil) (defvar-local notmuch-show-parent-buffer nil) @@ -182,6 +186,8 @@ handlers is discarded. When set to t the stdout and stderr from each attachment handler is logged in buffers with names beginning \" *notmuch-part*\".") +;;; Options + (defcustom notmuch-show-stash-mlarchive-link-alist '(("Gmane" . "https://mid.gmane.org/") ("MARC" . "https://marc.info/?i=") @@ -260,6 +266,8 @@ position of the message in the thread." :type 'boolean :group 'notmuch-show) +;;; Utilities + (defmacro with-current-notmuch-show-message (&rest body) "Evaluate body with current buffer set to the text of current message." `(save-excursion @@ -275,6 +283,8 @@ position of the message in the thread." "Enable Visual Line mode." (visual-line-mode t)) +;;; Commands + ;; DEPRECATED in Notmuch 0.16 since we now have convenient part ;; commands. We'll keep the command around for a version or two in ;; case people want to bind it themselves. @@ -355,6 +365,8 @@ operation on the contents of the current buffer." (interactive) (notmuch-show-with-message-as-text 'notmuch-print-message)) +;;; Headers + (defun notmuch-show-fontify-header () (let ((face (cond ((looking-at "[Tt]o:") @@ -493,6 +505,8 @@ message at DEPTH in the current thread." (narrow-to-region start (point-max)) (run-hooks 'notmuch-show-markup-headers-hook))))) +;;; Parts + (define-button-type 'notmuch-show-part-button-type 'action 'notmuch-show-part-button-default 'follow-link t @@ -548,7 +562,7 @@ message at DEPTH in the current thread." (overlay-put overlay 'invisible (not show)) t))))))) -;; Part content ID handling +;;; Part content ID handling (defvar notmuch-show--cids nil "Alist from raw content ID to (MSG PART).") @@ -811,7 +825,8 @@ will return nil if the CID is unknown or cannot be retrieved." (gnus-blocked-images notmuch-show-text/html-blocked-images)) (notmuch-show-insert-part-*/* msg part content-type nth depth button)))) -;; These functions are used by notmuch-show--insert-part-text/html-shr +;;; Functions used by notmuch-show--insert-part-text/html-shr + (declare-function libxml-parse-html-region "xml.c") (declare-function shr-insert-document "shr") @@ -836,7 +851,7 @@ will return nil if the CID is unknown or cannot be retrieved." (notmuch-mm-display-part-inline msg part content-type notmuch-show-process-crypto) t) -;; Functions for determining how to handle MIME parts. +;;; Functions for determining how to handle MIME parts. (defun notmuch-show-handlers-for (content-type) "Return a list of content handlers for a part of type CONTENT-TYPE." @@ -852,7 +867,7 @@ will return nil if the CID is unknown or cannot be retrieved." (intern (concat "notmuch-show-insert-part-" content-type)))) result)) -;; +;;; Parts (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth button) ;; Run the handlers until one of them succeeds. @@ -1098,6 +1113,8 @@ is t, hide the part initially and show the button." (notmuch-show-message-visible msg (and (plist-get msg :match) (not (plist-get msg :excluded)))))) +;;; Toggle commands + (defun notmuch-show-toggle-process-crypto () "Toggle the processing of cryptographic MIME parts." (interactive) @@ -1126,6 +1143,8 @@ is t, hide the part initially and show the button." "Content is not indented.")) (notmuch-show-refresh-view)) +;;; Main insert functions + (defun notmuch-show-insert-tree (tree depth) "Insert the message tree TREE at depth DEPTH in the current thread." (let ((msg (car tree)) @@ -1143,6 +1162,8 @@ is t, hide the part initially and show the button." "Insert the forest of threads FOREST." (mapc (lambda (thread) (notmuch-show-insert-thread thread 0)) forest)) +;;; Link buttons + (defvar notmuch-id-regexp (concat ;; Match the id: prefix only if it begins a word (to disallow, for @@ -1203,6 +1224,8 @@ buttons for a corresponding notmuch search." 'help-echo "Mouse-1, RET: search for this message" 'face goto-address-mail-face))))) +;;; Show command + ;;;###autoload (defun notmuch-show (thread-id &optional elide-toggle parent-buffer query-context buffer-name) "Run \"notmuch show\" with the given thread ID and display results. @@ -1325,6 +1348,8 @@ If no messages match the query return NIL." ;; Report back to the caller whether any messages matched. forest)) +;;; Refresh command + (defun notmuch-show-capture-state () "Capture the state of the current buffer. @@ -1399,6 +1424,8 @@ reset based on the original query." (ding) (message "Refreshing the buffer resulted in no messages!")))) +;;; Keymaps + (defvar notmuch-show-stash-map (let ((map (make-sparse-keymap))) (define-key map "c" 'notmuch-show-stash-cc) @@ -1479,6 +1506,8 @@ reset based on the original query." map) "Keymap for \"notmuch show\" buffers.") +;;; Mode + (define-derived-mode notmuch-show-mode fundamental-mode "notmuch-show" "Major mode for viewing a thread with notmuch. @@ -1515,6 +1544,8 @@ All currently available key bindings: (setq imenu-extract-index-name-function #'notmuch-show-imenu-extract-index-name-function)) +;;; Tree commands + (defun notmuch-tree-from-show-current-query () "Call notmuch tree with the current query." (interactive) @@ -1529,17 +1560,14 @@ All currently available key bindings: notmuch-show-query-context (notmuch-show-get-message-id))) +;;; Movement related functions. + (defun notmuch-show-move-to-message-top () (goto-char (notmuch-show-message-top))) (defun notmuch-show-move-to-message-bottom () (goto-char (notmuch-show-message-bottom))) -(defun notmuch-show-message-adjust () - (recenter 0)) - -;; Movement related functions. - ;; There's some strangeness here where a text property applied to a ;; region a->b is not found when point is at b. We walk backwards ;; until finding the property. @@ -1583,8 +1611,7 @@ effects." (cl-loop do (funcall function) while (notmuch-show-goto-message-next)))) -;; Functions relating to the visibility of messages and their -;; components. +;;; Functions relating to the visibility of messages and their components. (defun notmuch-show-message-visible (props visible-p) (overlay-put (plist-get props :message-overlay) 'invisible (not visible-p)) @@ -1594,8 +1621,7 @@ effects." (overlay-put (plist-get props :headers-overlay) 'invisible (not visible-p)) (notmuch-show-set-prop :headers-visible visible-p props)) -;; Functions for setting and getting attributes of the current -;; message. +;;; Functions for setting and getting attributes of the current message. (defun notmuch-show-set-message-properties (props) (save-excursion @@ -1768,8 +1794,7 @@ Reshows the current thread with matches defined by the new query-string." (notmuch-show-refresh-view t) (notmuch-show-goto-message msg-id))) -;; Functions for getting attributes of several messages in the current -;; thread. +;;; Functions for getting attributes of several messages in the current thread. (defun notmuch-show-get-message-ids-for-open-messages () "Return a list of all id: queries for open messages in the current thread." @@ -1783,7 +1808,7 @@ Reshows the current thread with matches defined by the new query-string." (setq done (not (notmuch-show-goto-message-next)))) message-ids))) -;; Commands typically bound to keys. +;;; Commands typically bound to keys. (defun notmuch-show-advance () "Advance through thread. @@ -1911,6 +1936,9 @@ any effects from previous calls to (message-resend addresses) (notmuch-bury-or-kill-this-buffer))) +(defun notmuch-show-message-adjust () + (recenter 0)) + (defun notmuch-show-next-message (&optional pop-at-end) "Show the next message. @@ -2381,7 +2409,7 @@ omit --in-reply-to=." (list (notmuch-show-get-message-id t)) "--in-reply-to=")))) " "))) -;; Interactive part functions and their helpers +;;; Interactive part functions and their helpers (defun notmuch-show-generate-part-buffer (msg part) "Return a temporary buffer containing the specified part's content." @@ -2528,6 +2556,8 @@ browsing." (funcall fn (completing-read prompt urls nil nil nil nil (car urls))) (message "No URLs found.")))) +;;; _ + (provide 'notmuch-show) ;;; notmuch-show.el ends here diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el index 925de78c..817ea99f 100644 --- a/emacs/notmuch-tag.el +++ b/emacs/notmuch-tag.el @@ -37,6 +37,8 @@ (declare-function notmuch-tree-tag "notmuch-tree" (tag-changes)) (declare-function notmuch-jump "notmuch-jump" (action-map prompt)) +;;; Keys + (define-widget 'notmuch-tag-key-type 'list "A single key tagging binding." :format "%v" @@ -84,6 +86,8 @@ from TAGGING-OPERATIONS." :type '(repeat notmuch-tag-key-type) :group 'notmuch-tag) +;;; Faces and Formats + (define-widget 'notmuch-tag-format-type 'lazy "Customize widget for notmuch-tag-format and friends." :type '(alist :key-type (regexp :tag "Tag") @@ -217,6 +221,8 @@ See `notmuch-tag-formats' for full documentation." :group 'notmuch-faces :type 'notmuch-tag-format-type) +;;; Icons + (defun notmuch-tag-format-image-data (tag data) "Replace TAG with image DATA, if available. @@ -270,6 +276,8 @@ This can be used with `notmuch-tag-format-image-data'." ") +;;; Format Handling + (defvar notmuch-tag--format-cache (make-hash-table :test 'equal) "Cache of tag format lookup. Internal to `notmuch-tag-format-tag'.") @@ -347,6 +355,8 @@ changed (the normal case) are shown using formats from face t))) +;;; Hooks + (defcustom notmuch-before-tag-hook nil "Hooks that are run before tags of a message are modified. @@ -369,6 +379,8 @@ the messages that were tagged." :options '(notmuch-hl-line-mode) :group 'notmuch-hooks) +;;; User Input + (defvar notmuch-select-tag-history nil "Variable to store minibuffer history for `notmuch-select-tag-with-completion' function.") @@ -429,6 +441,8 @@ initial input in the minibuffer." nil nil initial-input 'notmuch-read-tag-changes-history)))) +;;; Tagging + (defun notmuch-update-tags (tags tag-changes) "Return a copy of TAGS with additions and removals from TAG-CHANGES. @@ -547,7 +561,7 @@ and vice versa." (setq action-map (nreverse action-map)) (notmuch-jump action-map "Tag: "))) -;; +;;; _ (provide 'notmuch-tag) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 17863f6a..713b00da 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -54,6 +54,8 @@ (defvar-local notmuch-tree-unthreaded nil "A buffer local copy of argument unthreaded to the function notmuch-tree.") +;;; Options + (defgroup notmuch-tree nil "Showing message and thread structure." :group 'notmuch) @@ -118,7 +120,9 @@ For example: notmuch-unthreaded-result-format notmuch-tree-result-format)) -;; Faces for messages that match the query. +;;; Faces +;;;; Faces for messages that match the query + (defface notmuch-tree-match-face '((t :inherit default)) "Default face used in tree mode face for matching messages" @@ -169,7 +173,8 @@ For example: :group 'notmuch-tree :group 'notmuch-faces) -;; Faces for messages that do not match the query. +;;;; Faces for messages that do not match the query + (defface notmuch-tree-no-match-face '((t (:foreground "gray"))) "Default face used in tree mode face for non-matching messages." @@ -206,6 +211,8 @@ For example: :group 'notmuch-tree :group 'notmuch-faces) +;;; Variables + (defvar-local notmuch-tree-previous-subject "The subject of the most recent result shown during the async display.") @@ -238,6 +245,8 @@ This is used to try and make sure we don't close the message pane if the user has loaded a different buffer in that window.") (put 'notmuch-tree-message-buffer 'permanent-local t) +;;; Tree wrapper commands + (defmacro notmuch-tree--define-do-in-message-window (name cmd) "Define NAME as a command that calls CMD interactively in the message window. If the message pane is closed then this command does nothing. @@ -305,6 +314,8 @@ then NAME behaves like CMD." notmuch-tree-view-raw-message notmuch-show-view-raw-message) +;;; Keymap + (defvar notmuch-tree-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map notmuch-common-keymap) @@ -363,6 +374,8 @@ then NAME behaves like CMD." map) "Keymap for \"notmuch tree\" buffers.") +;;; Message properties + (defun notmuch-tree-get-message-properties () "Return the properties of the current message as a plist. @@ -414,6 +427,8 @@ Some useful entries are: (interactive) (notmuch-tree-get-prop :match)) +;;; Update display + (defun notmuch-tree-refresh-result () "Redisplay the current message line. @@ -456,6 +471,8 @@ NOT change the database." (when (string= tree-msg-id (notmuch-show-get-message-id)) (notmuch-show-update-tags new-tags))))))) +;;; Commands (and some helper functions used by them) + (defun notmuch-tree-tag (tag-changes) "Change tags for the current message." (interactive @@ -835,7 +852,7 @@ buffer." (notmuch-tree-tag-thread (notmuch-tag-change-list notmuch-archive-tags unarchive)))) -;; Functions below here display the tree buffer itself. +;;; Functions for displaying the tree buffer itself (defun notmuch-tree-clean-address (address) "Try to clean a single email ADDRESS for display. Return @@ -1142,7 +1159,7 @@ The arguments are: (interactive) (notmuch-tree query query-context target buffer-name open-target t)) -;; +;;; _ (provide 'notmuch-tree) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index ce4b9637..f371cc4c 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -30,7 +30,7 @@ (msg part depth &optional hide)) (defvar notmuch-show-indent-messages-width) -;; +;;; Options (defgroup notmuch-wash nil "Cleaning up messages for display." @@ -130,6 +130,8 @@ or at the window width (whichever one is lower)." (integer :tag "number of characters")) :group 'notmuch-wash) +;;; Faces + (defface notmuch-wash-toggle-button '((t (:inherit font-lock-comment-face))) "Face used for buttons toggling the visibility of washed away @@ -143,6 +145,8 @@ message parts." :group 'notmuch-wash :group 'notmuch-faces) +;;; Buttons + (defun notmuch-wash-toggle-invisible-action (cite-button) ;; Toggle overlay visibility (let ((overlay (button-get cite-button 'overlay))) @@ -225,6 +229,8 @@ that PREFIX should not include a newline." :type button-type))) (overlay-put overlay 'notmuch-wash-button button)))))) +;;; Hook functions + (defun notmuch-wash-excerpt-citations (msg depth) "Excerpt citations and up to one signature." (goto-char (point-min)) @@ -270,8 +276,6 @@ that PREFIX should not include a newline." msg sig-start-marker sig-end-marker "signature")))))) -;; - (defun notmuch-wash-elide-blank-lines (msg depth) "Elide leading, trailing and successive blank lines." ;; Algorithm derived from `article-strip-multiple-blank-lines' in @@ -293,8 +297,6 @@ that PREFIX should not include a newline." (when (looking-at "\n") (delete-region (match-beginning 0) (match-end 0)))) -;; - (defun notmuch-wash-tidy-citations (msg depth) "Improve the display of cited regions of a message. @@ -319,8 +321,6 @@ Perform several transformations on the message body: (while (re-search-forward "\\(^>[> ]*\n\\)\\(^$\\|^[^>].*\\)" nil t) (replace-match "\\2"))) -;; - (defun notmuch-wash-wrap-long-lines (msg depth) "Wrap long lines in the message. @@ -342,7 +342,7 @@ the wrapped text are maintained." 2))) (coolj-wrap-region (point-min) (point-max)))) -;; +;;;; Convert Inline Patches (require 'diff-mode) @@ -417,7 +417,7 @@ for error." (delete-region (point-min) (point-max)) (notmuch-show-insert-bodypart nil part depth))))) -;; +;;; _ (provide 'notmuch-wash) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index bba4ca03..6a09dd38 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -80,6 +80,8 @@ (require 'notmuch-message) (require 'notmuch-parser) +;;; Options + (defcustom notmuch-search-result-format `(("date" . "%12s ") ("count" . "%-7s ") @@ -115,6 +117,8 @@ there will be called at other points of notmuch execution." (defvar notmuch-query-history nil "Variable to store minibuffer history for notmuch queries.") +;;; Mime Utilities + (defun notmuch-foreach-mime-part (function mm-handle) (cond ((stringp (car mm-handle)) (dolist (part (cdr mm-handle)) @@ -151,6 +155,8 @@ there will be called at other points of notmuch execution." (mm-save-part p)))) mm-handle)) +;;; Integrations + (require 'hl-line) (defun notmuch-hl-line-mode () @@ -158,6 +164,8 @@ there will be called at other points of notmuch execution." (when hl-line-overlay (overlay-put hl-line-overlay 'priority 1)))) +;;; Options + (defcustom notmuch-search-hook '(notmuch-hl-line-mode) "List of functions to call when notmuch displays the search results." :type 'hook @@ -165,6 +173,8 @@ there will be called at other points of notmuch execution." :group 'notmuch-search :group 'notmuch-hooks) +;;; Keymap + (defvar notmuch-search-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map notmuch-common-keymap) @@ -195,6 +205,8 @@ there will be called at other points of notmuch execution." map) "Keymap for \"notmuch search\" buffers.") +;;; Stashing + (defvar notmuch-search-stash-map (let ((map (make-sparse-keymap))) (define-key map "i" 'notmuch-search-stash-thread-id) @@ -214,12 +226,16 @@ there will be called at other points of notmuch execution." (interactive) (notmuch-common-do-stash (notmuch-search-get-query))) +;;; Variables + (defvar notmuch-search-query-string) (defvar notmuch-search-target-thread) (defvar notmuch-search-target-line) (defvar notmuch-search-disjunctive-regexp "\\<[oO][rR]\\>") +;;; Movement + (defun notmuch-search-scroll-up () "Move forward through search results by one window's worth." (interactive) @@ -271,6 +287,8 @@ there will be called at other points of notmuch execution." (interactive) (goto-char (point-min))) +;;; Faces + (defface notmuch-message-summary-face `((((class color) (background light)) ,@(and (>= emacs-major-version 27) '(:extend t)) @@ -356,6 +374,8 @@ This face is the default value for the \"unread\" tag in :group 'notmuch-search :group 'notmuch-faces) +;;; Mode + (define-derived-mode notmuch-search-mode fundamental-mode "notmuch-search" "Major mode displaying results of a notmuch search. @@ -400,6 +420,8 @@ Complete list of currently available key bindings: (setq imenu-extract-index-name-function #'notmuch-search-imenu-extract-index-name-function)) +;;; Search Results + (defun notmuch-search-get-result (&optional pos) "Return the result object for the thread at POS (or point). @@ -558,6 +580,8 @@ thread." (let ((message-id (notmuch-search-find-thread-id))) (notmuch-mua-new-reply message-id prompt-for-sender nil))) +;;; Tags + (defun notmuch-search-set-tags (tags &optional pos) (let ((new-result (plist-put (notmuch-search-get-result pos) :tags tags))) (notmuch-search-update-result new-result pos))) @@ -639,6 +663,8 @@ This function advances the next thread when finished." (when (eq beg end) (notmuch-search-next-thread))) +;;; Search Results + (defun notmuch-search-update-result (result &optional pos) "Replace the result object of the thread at POS (or point) by RESULT and redraw it. @@ -881,6 +907,8 @@ sets the :orig-tag property." (notmuch-sexp-parse-partial-list 'notmuch-search-append-result results-buf))))) +;;; Commands (and some helper functions used by them) + (defun notmuch-search-tag-all (tag-changes) "Add/remove tags from all messages in current search buffer. @@ -1132,7 +1160,7 @@ notmuch buffers exist, run `notmuch'." (pop-to-buffer-same-window first)) (notmuch)))) -;;;; Imenu Support +;;; Imenu Support (defun notmuch-search-imenu-prev-index-position-function () "Move point to previous message in notmuch-search buffer. @@ -1149,6 +1177,8 @@ beginning of the line." (author (notmuch-search-find-authors))) (format "%s (%s)" subject author))) +;;; _ + (setq mail-user-agent 'notmuch-user-agent) (provide 'notmuch) diff --git a/test/test-lib.el b/test/test-lib.el index ec16c59c..4de5b292 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -1,4 +1,4 @@ -;; test-lib.el --- auxiliary stuff for Notmuch Emacs tests. +;;; test-lib.el --- auxiliary stuff for Notmuch Emacs tests ;; ;; Copyright © Carl Worth ;; Copyright © David Edmondson @@ -20,6 +20,8 @@ ;; ;; Authors: Dmitry Kurochkin +;;; Code: + (require 'cl-lib) ;; Ensure that the dynamic variables that are defined by this library