X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=emacs%2Fnotmuch-lib.el;h=6ff351d71bb1a0e7b4658b0a62dbd3e20233c54c;hp=5dc6797068c876619bc36f57cd2ffa4c9ae5e9ab;hb=177cd31fbdff93254d576b737b55656d3a6086b5;hpb=71012e81098dce71cbd69479ecdee375a24db79c diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 5dc67970..6ff351d7 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -23,10 +23,12 @@ ;;; Code: +(require 'cl-lib) + (require 'mm-util) (require 'mm-view) (require 'mm-decode) -(require 'cl) + (require 'notmuch-compat) (unless (require 'notmuch-version nil t) @@ -74,6 +76,10 @@ "Running external commands from within Notmuch." :group 'notmuch) +(defgroup notmuch-address nil + "Address completion." + :group 'notmuch) + (defgroup notmuch-faces nil "Graphical attributes for displaying text" :group 'notmuch) @@ -149,8 +155,11 @@ For example, if you wanted to remove an \"inbox\" tag and add an (define-key map "?" 'notmuch-help) (define-key map "q" 'notmuch-bury-or-kill-this-buffer) (define-key map "s" 'notmuch-search) + (define-key map "t" 'notmuch-search-by-tag) (define-key map "z" 'notmuch-tree) + (define-key map "u" 'notmuch-unthreaded) (define-key map "m" 'notmuch-mua-new-mail) + (define-key map "g" 'notmuch-refresh-this-buffer) (define-key map "=" 'notmuch-refresh-this-buffer) (define-key map (kbd "M-=") 'notmuch-refresh-all-buffers) (define-key map "G" 'notmuch-poll-and-refresh-this-buffer) @@ -180,7 +189,7 @@ If notmuch exits with a non-zero status, output from the process will appear in a buffer named \"*Notmuch errors*\" and an error will be signaled. -Otherwise the output will be returned" +Otherwise the output will be returned." (with-temp-buffer (let* ((status (apply #'call-process notmuch-command nil t nil args)) (output (buffer-string))) @@ -202,7 +211,7 @@ Otherwise the output will be returned" (unless (notmuch-cli-sane-p) (notmuch-logged-error "notmuch cli seems misconfigured or unconfigured." -"Perhaps you haven't run \"notmuch setup\" yet? Try running this + "Perhaps you haven't run \"notmuch setup\" yet? Try running this on the command line, and then retry your notmuch command"))) (defun notmuch-cli-version () @@ -250,11 +259,13 @@ on the command line, and then retry your notmuch command"))) Invokes `notmuch-poll-script', \"notmuch new\", or does nothing depending on the value of `notmuch-poll-script'." (interactive) + (message "Polling mail...") (if (stringp notmuch-poll-script) (unless (string= notmuch-poll-script "") (unless (equal (call-process notmuch-poll-script nil nil) 0) (error "Notmuch: poll script `%s' failed!" notmuch-poll-script))) - (notmuch-call-notmuch-process "new"))) + (notmuch-call-notmuch-process "new")) + (message "Polling mail...done")) (defun notmuch-bury-or-kill-this-buffer () "Undisplay the current buffer. @@ -290,10 +301,10 @@ This is basically just `format-kbd-macro' but we also convert ESC to M-." (defun notmuch-describe-key (actual-key binding prefix ua-keys tail) - "Prepend cons cells describing prefix-arg ACTUAL-KEY and ACTUAL-KEY to TAIL + "Prepend cons cells describing prefix-arg ACTUAL-KEY and ACTUAL-KEY to TAIL. It does not prepend if ACTUAL-KEY is already listed in TAIL." - (let ((key-string (concat prefix (format-kbd-macro actual-key)))) + (let ((key-string (concat prefix (key-description actual-key)))) ;; We don't include documentation if the key-binding is ;; over-ridden. Note, over-riding a binding automatically hides the ;; prefixed version too. @@ -307,10 +318,12 @@ It does not prepend if ACTUAL-KEY is already listed in TAIL." tail))) ;; Documentation for command (push (cons key-string - (or (and (symbolp binding) (get binding 'notmuch-doc)) - (notmuch-documentation-first-line binding))) + (or (and (symbolp binding) + (get binding 'notmuch-doc)) + (and (functionp binding) + (notmuch-documentation-first-line binding)))) tail))) - tail) + tail) (defun notmuch-describe-remaps (remap-keymap ua-keys base-keymap prefix tail) ;; Remappings are represented as a binding whose first "event" is @@ -318,13 +331,13 @@ It does not prepend if ACTUAL-KEY is already listed in TAIL." ;; binding whose "key" is 'remap, and whose "binding" is itself a ;; keymap that maps not from keys to commands, but from old (remapped) ;; functions to the commands to use in their stead. - (map-keymap - (lambda (command binding) - (mapc - (lambda (actual-key) - (setq tail (notmuch-describe-key actual-key binding prefix ua-keys tail))) - (where-is-internal command base-keymap))) - remap-keymap) + (map-keymap (lambda (command binding) + (mapc (lambda (actual-key) + (setq tail + (notmuch-describe-key actual-key binding + prefix ua-keys tail))) + (where-is-internal command base-keymap))) + remap-keymap) tail) (defun notmuch-describe-keymap (keymap ua-keys base-keymap &optional prefix tail) @@ -347,9 +360,13 @@ prefix argument. PREFIX and TAIL are used internally." (notmuch-describe-remaps binding ua-keys base-keymap prefix tail) (notmuch-describe-keymap - binding ua-keys base-keymap (notmuch-prefix-key-description key) tail)))) + binding ua-keys base-keymap + (notmuch-prefix-key-description key) + tail)))) (binding - (setq tail (notmuch-describe-key (vector key) binding prefix ua-keys tail))))) + (setq tail + (notmuch-describe-key (vector key) + binding prefix ua-keys tail))))) keymap) tail) @@ -359,11 +376,15 @@ prefix argument. PREFIX and TAIL are used internally." (while (string-match "\\\\{\\([^}[:space:]]*\\)}" doc beg) (let ((desc (save-match-data - (let* ((keymap-name (substring doc (match-beginning 1) (match-end 1))) + (let* ((keymap-name (substring doc + (match-beginning 1) + (match-end 1))) (keymap (symbol-value (intern keymap-name))) (ua-keys (where-is-internal 'universal-argument keymap t)) (desc-alist (notmuch-describe-keymap keymap ua-keys keymap)) - (desc-list (mapcar (lambda (arg) (concat (car arg) "\t" (cdr arg))) desc-alist))) + (desc-list (mapcar (lambda (arg) + (concat (car arg) "\t" (cdr arg))) + desc-alist))) (mapconcat #'identity desc-list "\n"))))) (setq doc (replace-match desc 1 1 doc))) (setq beg (match-end 0))) @@ -382,7 +403,8 @@ its prefixed behavior by setting the 'notmuch-prefix-doc property of its command symbol." (interactive) (let* ((mode major-mode) - (doc (substitute-command-keys (notmuch-substitute-command-keys (documentation mode t))))) + (doc (substitute-command-keys + (notmuch-substitute-command-keys (documentation mode t))))) (with-current-buffer (generate-new-buffer "*notmuch-help*") (insert doc) (goto-char (point-min)) @@ -393,17 +415,18 @@ of its command symbol." "Show help for a subkeymap." (interactive) (let* ((key (this-command-keys-vector)) - (prefix (make-vector (1- (length key)) nil)) - (i 0)) + (prefix (make-vector (1- (length key)) nil)) + (i 0)) (while (< i (length prefix)) (aset prefix i (aref key i)) (setq i (1+ i))) - (let* ((subkeymap (key-binding prefix)) (ua-keys (where-is-internal 'universal-argument nil t)) (prefix-string (notmuch-prefix-key-description prefix)) - (desc-alist (notmuch-describe-keymap subkeymap ua-keys subkeymap prefix-string)) - (desc-list (mapcar (lambda (arg) (concat (car arg) "\t" (cdr arg))) desc-alist)) + (desc-alist (notmuch-describe-keymap + subkeymap ua-keys subkeymap prefix-string)) + (desc-list (mapcar (lambda (arg) (concat (car arg) "\t" (cdr arg))) + desc-alist)) (desc (mapconcat #'identity desc-list "\n"))) (with-help-window (help-buffer) (with-current-buffer standard-output @@ -464,7 +487,6 @@ This includes newlines, tabs, and other funny characters." The caller is responsible for prepending the term prefix and a colon. This performs minimal escaping in order to produce user-friendly queries." - (save-match-data (if (or (equal term "") ;; To be pessimistic, only pass through terms composed @@ -507,7 +529,7 @@ This replaces spaces, percents, and double quotes in STR with (let (out) (while list (when (funcall predicate (car list)) - (push (car list) out)) + (push (car list) out)) (setq list (cdr list))) (nreverse out))) @@ -521,11 +543,11 @@ This replaces spaces, percents, and double quotes in STR with (cdr xplist))) (defun notmuch-split-content-type (content-type) - "Split content/type into 'content' and 'type'" + "Split content/type into 'content' and 'type'." (split-string content-type "/")) (defun notmuch-match-content-type (t1 t2) - "Return t if t1 and t2 are matching content types, taking wildcards into account" + "Return t if t1 and t2 are matching content types, taking wildcards into account." (let ((st1 (notmuch-split-content-type t1)) (st2 (notmuch-split-content-type t2))) (if (or (string= (cadr st1) "*") @@ -535,12 +557,11 @@ This replaces spaces, percents, and double quotes in STR with (string= (downcase t1) (downcase t2))))) (defvar notmuch-multipart/alternative-discouraged - '( - ;; Avoid HTML parts. + '(;; Avoid HTML parts. "text/html" - ;; multipart/related usually contain a text/html part and some associated graphics. - "multipart/related" - )) + ;; multipart/related usually contain a text/html part and some + ;; associated graphics. + "multipart/related")) (defun notmuch-multipart/alternative-determine-discouraged (msg) "Return the discouraged alternatives for the specified message." @@ -567,7 +588,7 @@ for this message, if present." (defun notmuch-parts-filter-by-type (parts type) "Given a list of message parts, return a list containing the ones matching the given type." - (remove-if-not + (cl-remove-if-not (lambda (part) (notmuch-match-content-type (plist-get part :content-type) type)) parts)) @@ -589,12 +610,14 @@ the given type." (set-buffer-multibyte nil)) (let ((args `("show" "--format=raw" ,(format "--part=%s" (plist-get part :id)) - ,@(when process-crypto '("--decrypt")) + ,@(and process-crypto '("--decrypt=true")) ,(notmuch-id-to-query (plist-get msg :id)))) (coding-system-for-read - (if binaryp 'no-conversion - (let ((coding-system (mm-charset-to-coding-system - (plist-get part :content-charset)))) + (if binaryp + 'no-conversion + (let ((coding-system + (mm-charset-to-coding-system + (plist-get part :content-charset)))) ;; Sadly, ;; `mm-charset-to-coding-system' seems ;; to return things that are not @@ -606,7 +629,8 @@ the given type." ;; charset is US-ASCII. RFC6657 ;; complicates this somewhat. 'us-ascii))))) - (apply #'call-process notmuch-command nil '(t nil) nil args) + (apply #'call-process + notmuch-command nil '(t nil) nil args) (buffer-string)))))) (when (and cache data) (plist-put part plist-elem data)) @@ -643,11 +667,11 @@ MSG (if it isn't already)." ;; first loading gnus-art, which defines it, resulting in a ;; void-variable error. Hence, we advise `mm-shr' to ensure gnus-art ;; is loaded. -(if (>= emacs-major-version 24) - (defadvice mm-shr (before load-gnus-arts activate) - (require 'gnus-art nil t) - (ad-disable-advice 'mm-shr 'before 'load-gnus-arts) - (ad-activate 'mm-shr))) +(when (>= emacs-major-version 24) + (defadvice mm-shr (before load-gnus-arts activate) + (require 'gnus-art nil t) + (ad-disable-advice 'mm-shr 'before 'load-gnus-arts) + (ad-activate 'mm-shr))) (defun notmuch-mm-display-part-inline (msg part content-type process-crypto) "Use the mm-decode/mm-view functions to display a part in the @@ -659,9 +683,11 @@ current buffer, if possible." ;; `gnus-decoded' charset. Otherwise, we'll fetch the binary ;; part content and let mm-* decode it. (let* ((have-content (plist-member part :content)) - (charset (if have-content 'gnus-decoded + (charset (if have-content + 'gnus-decoded (plist-get part :content-charset))) - (handle (mm-make-handle (current-buffer) `(,content-type (charset . ,charset))))) + (handle (mm-make-handle (current-buffer) + `(,content-type (charset . ,charset))))) ;; If the user wants the part inlined, insert the content and ;; test whether we are able to inline it (which includes both ;; capability and suitability tests). @@ -678,8 +704,8 @@ current buffer, if possible." ;; have symbols of the form :Header as keys, and the resulting alist will have ;; symbols of the form 'Header as keys. (defun notmuch-headers-plist-to-alist (plist) - (loop for (key value . rest) on plist by #'cddr - collect (cons (intern (substring (symbol-name key) 1)) value))) + (cl-loop for (key value . rest) on plist by #'cddr + collect (cons (intern (substring (symbol-name key) 1)) value))) (defun notmuch-face-ensure-list-form (face) "Return FACE in face list form. @@ -705,7 +731,6 @@ must be a face name (a symbol or string), a property list of face attributes, or a list of these. If START and/or END are omitted, they default to the beginning/end of OBJECT. For convenience when applied to strings, this returns OBJECT." - ;; A face property can have three forms: a face name (a string or ;; symbol), a property list, or a list of these two forms. In the ;; list case, the faces will be combined, with the earlier faces @@ -748,7 +773,6 @@ This logs MSG and EXTRA to the *Notmuch errors* buffer and signals MSG as an error. If EXTRA is non-nil, text referring the user to the *Notmuch errors* buffer will be appended to the signaled error. This function does not return." - (with-current-buffer (get-buffer-create "*Notmuch errors*") (goto-char (point-max)) (unless (bobp) @@ -761,26 +785,27 @@ signaled error. This function does not return." (insert extra) (unless (bolp) (newline))))) - (error "%s" (concat msg (when extra - " (see *Notmuch errors* for more details)")))) + (error "%s" + (concat msg (and extra " (see *Notmuch errors* for more details)")))) -(defun notmuch-check-async-exit-status (proc msg &optional command err-file) +(defun notmuch-check-async-exit-status (proc msg &optional command err) "If PROC exited abnormally, pop up an error buffer and signal an error. This is a wrapper around `notmuch-check-exit-status' for asynchronous process sentinels. PROC and MSG must be the -arguments passed to the sentinel. COMMAND and ERR-FILE, if -provided, are passed to `notmuch-check-exit-status'. If COMMAND -is not provided, it is taken from `process-command'." +arguments passed to the sentinel. COMMAND and ERR, if provided, +are passed to `notmuch-check-exit-status'. If COMMAND is not +provided, it is taken from `process-command'." (let ((exit-status - (case (process-status proc) + (cl-case (process-status proc) ((exit) (process-exit-status proc)) ((signal) msg)))) (when exit-status - (notmuch-check-exit-status exit-status (or command (process-command proc)) - nil err-file)))) + (notmuch-check-exit-status exit-status + (or command (process-command proc)) + nil err)))) -(defun notmuch-check-exit-status (exit-status command &optional output err-file) +(defun notmuch-check-exit-status (exit-status command &optional output err) "If EXIT-STATUS is non-zero, pop up an error buffer and signal an error. If EXIT-STATUS is non-zero, pop up a notmuch error buffer @@ -789,10 +814,9 @@ be a number indicating the exit status code of a process or a string describing the signal that terminated the process (such as returned by `call-process'). COMMAND must be a list giving the command and its arguments. OUTPUT, if provided, is a string -giving the output of command. ERR-FILE, if provided, is the name -of a file containing the error output of command. OUTPUT and the -contents of ERR-FILE will be included in the error message." - +giving the output of command. ERR, if provided, is the error +output of command. OUTPUT and ERR will be included in the error +message." (cond ((eq exit-status 0) t) ((eq exit-status 20) @@ -804,12 +828,7 @@ You may need to restart Emacs or upgrade your notmuch Emacs package.")) Emacs requested a newer output format than supported by the notmuch CLI. You may need to restart Emacs or upgrade your notmuch package.")) (t - (let* ((err (when err-file - (with-temp-buffer - (insert-file-contents err-file) - (unless (eobp) - (buffer-string))))) - (command-string + (let* ((command-string (mapconcat (lambda (arg) (shell-quote-argument (cond ((stringp arg) arg) @@ -818,24 +837,22 @@ You may need to restart Emacs or upgrade your notmuch package.")) command " ")) (extra (concat "command: " command-string "\n" - (if (integerp exit-status) - (format "exit status: %s\n" exit-status) - (format "exit signal: %s\n" exit-status)) - (when err - (concat "stderr:\n" err)) - (when output - (concat "stdout:\n" output))))) - (if err - ;; We have an error message straight from the CLI. - (notmuch-logged-error - (replace-regexp-in-string "[ \n\r\t\f]*\\'" "" err) extra) - ;; We only have combined output from the CLI; don't inundate - ;; the user with it. Mimic `process-lines'. - (notmuch-logged-error (format "%s exited with status %s" - (car command) exit-status) - extra)) - ;; `notmuch-logged-error' does not return. - )))) + (if (integerp exit-status) + (format "exit status: %s\n" exit-status) + (format "exit signal: %s\n" exit-status)) + (and err (concat "stderr:\n" err)) + (and output (concat "stdout:\n" output))))) + (if err + ;; We have an error message straight from the CLI. + (notmuch-logged-error + (replace-regexp-in-string "[ \n\r\t\f]*\\'" "" err) extra) + ;; We only have combined output from the CLI; don't inundate + ;; the user with it. Mimic `process-lines'. + (notmuch-logged-error (format "%s exited with status %s" + (car command) exit-status) + extra)) + ;; `notmuch-logged-error' does not return. + )))) (defun notmuch-call-notmuch--helper (destination args) "Helper for synchronous notmuch invocation commands. @@ -843,12 +860,11 @@ You may need to restart Emacs or upgrade your notmuch package.")) This wraps `call-process'. DESTINATION has the same meaning as for `call-process'. ARGS is as described for `notmuch-call-notmuch-process'." - (let (stdin-string) (while (keywordp (car args)) - (case (car args) - (:stdin-string (setq stdin-string (cadr args) - args (cddr args))) + (cl-case (car args) + (:stdin-string (setq stdin-string (cadr args)) + (setq args (cddr args))) (otherwise (error "Unknown keyword argument: %s" (car args))))) (if (null stdin-string) @@ -881,13 +897,16 @@ notmuch's output as an S-expression and returns the parsed value. Like `notmuch-call-notmuch-process', if notmuch exits with a non-zero status, this will report its output and signal an error." - (with-temp-buffer (let ((err-file (make-temp-file "nmerr"))) (unwind-protect - (let ((status (notmuch-call-notmuch--helper (list t err-file) args))) + (let ((status (notmuch-call-notmuch--helper (list t err-file) args)) + (err (with-temp-buffer + (insert-file-contents err-file) + (unless (eobp) + (buffer-string))))) (notmuch-check-exit-status status (cons notmuch-command args) - (buffer-string) err-file) + (buffer-string) err) (goto-char (point-min)) (read (current-buffer))) (delete-file err-file))))) @@ -905,31 +924,56 @@ when the process exits, or nil for none. The caller must *not* invoke `set-process-sentinel' directly on the returned process, as that will interfere with the handling of stderr and the exit status." - - ;; There is no way (as of Emacs 24.3) to capture stdout and stderr - ;; separately for asynchronous processes, or even to redirect stderr - ;; to a file, so we use a trivial shell wrapper to send stderr to a - ;; temporary file and clean things up in the sentinel. - (let* ((err-file (make-temp-file "nmerr")) - ;; Use a pipe - (process-connection-type nil) - ;; Find notmuch using Emacs' `exec-path' - (command (or (executable-find notmuch-command) - (error "command not found: %s" notmuch-command))) - (proc (apply #'start-process name buffer - "/bin/sh" "-c" - "exec 2>\"$1\"; shift; exec \"$0\" \"$@\"" - command err-file args))) - (process-put proc 'err-file err-file) + (let (err-file err-buffer proc err-proc + ;; Find notmuch using Emacs' `exec-path' + (command (or (executable-find notmuch-command) + (error "Command not found: %s" notmuch-command)))) + (if (fboundp 'make-process) + (progn + (setq err-buffer (generate-new-buffer " *notmuch-stderr*")) + ;; Emacs 25 and newer has `make-process', which allows + ;; redirecting stderr independently from stdout to a + ;; separate buffer. As this allows us to avoid using a + ;; temporary file and shell invocation, use it when + ;; available. + (setq proc (make-process + :name name + :buffer buffer + :command (cons command args) + :connection-type 'pipe + :stderr err-buffer)) + (setq err-proc (get-buffer-process err-buffer)) + (process-put proc 'err-buffer err-buffer) + + (process-put err-proc 'err-file err-file) + (process-put err-proc 'err-buffer err-buffer) + (set-process-sentinel err-proc #'notmuch-start-notmuch-error-sentinel)) + ;; On Emacs versions before 25, there is no way to capture + ;; stdout and stderr separately for asynchronous processes, or + ;; even to redirect stderr to a file, so we use a trivial shell + ;; wrapper to send stderr to a temporary file and clean things + ;; up in the sentinel. + (setq err-file (make-temp-file "nmerr")) + (let ((process-connection-type nil)) ;; Use a pipe + (setq proc (apply #'start-process name buffer + "/bin/sh" "-c" + "exec 2>\"$1\"; shift; exec \"$0\" \"$@\"" + command err-file args))) + (process-put proc 'err-file err-file)) (process-put proc 'sub-sentinel sentinel) (process-put proc 'real-command (cons notmuch-command args)) (set-process-sentinel proc #'notmuch-start-notmuch-sentinel) proc)) (defun notmuch-start-notmuch-sentinel (proc event) - (let ((err-file (process-get proc 'err-file)) - (sub-sentinel (process-get proc 'sub-sentinel)) - (real-command (process-get proc 'real-command))) + "Process sentinel function used by `notmuch-start-notmuch'." + (let* ((err-file (process-get proc 'err-file)) + (err-buffer (or (process-get proc 'err-buffer) + (find-file-noselect err-file))) + (err (and (not (zerop (buffer-size err-buffer))) + (with-current-buffer err-buffer (buffer-string)))) + (sub-sentinel (process-get proc 'sub-sentinel)) + (real-command (process-get proc 'real-command))) (condition-case err (progn ;; Invoke the sub-sentinel, if any @@ -941,36 +985,56 @@ status." ;; and there's no point in telling the user that (but we ;; still check for and report stderr output below). (when (buffer-live-p (process-buffer proc)) - (notmuch-check-async-exit-status proc event real-command err-file)) + (notmuch-check-async-exit-status proc event real-command err)) ;; If that didn't signal an error, then any error output was ;; really warning output. Show warnings, if any. (let ((warnings - (with-temp-buffer - (unless (= (second (insert-file-contents err-file)) 0) - (end-of-line) - ;; Show first line; stuff remaining lines in the - ;; errors buffer. - (let ((l1 (buffer-substring (point-min) (point)))) - (skip-chars-forward "\n") - (cons l1 (unless (eobp) - (buffer-substring (point) (point-max))))))))) + (and err + (with-current-buffer err-buffer + (goto-char (point-min)) + (end-of-line) + ;; Show first line; stuff remaining lines in the + ;; errors buffer. + (let ((l1 (buffer-substring (point-min) (point)))) + (skip-chars-forward "\n") + (cons l1 (and (not (eobp)) + (buffer-substring (point) + (point-max))))))))) (when warnings (notmuch-logged-error (car warnings) (cdr warnings))))) (error ;; Emacs behaves strangely if an error escapes from a sentinel, ;; so turn errors into messages. (message "%s" (error-message-string err)))) - (ignore-errors (delete-file err-file)))) + (when err-file (ignore-errors (delete-file err-file))))) + +(defun notmuch-start-notmuch-error-sentinel (proc event) + (let* ((err-file (process-get proc 'err-file)) + ;; When `make-process' is available, use the error buffer + ;; associated with the process, otherwise the error file. + (err-buffer (or (process-get proc 'err-buffer) + (find-file-noselect err-file)))) + (when err-buffer (kill-buffer err-buffer)))) ;; This variable is used only buffer local, but it needs to be ;; declared globally first to avoid compiler warnings. (defvar notmuch-show-process-crypto nil) (make-variable-buffer-local 'notmuch-show-process-crypto) -(provide 'notmuch-lib) +(defun notmuch-interactive-region () + "Return the bounds of the current interactive region. + +This returns (BEG END), where BEG and END are the bounds of the +region if the region is active, or both `point' otherwise." + (if (region-active-p) + (list (region-beginning) (region-end)) + (list (point) (point)))) -;; Local Variables: -;; byte-compile-warnings: (not cl-functions) -;; End: +(define-obsolete-function-alias + 'notmuch-search-interactive-region + 'notmuch-interactive-region + "notmuch 0.29") + +(provide 'notmuch-lib) ;;; notmuch-lib.el ends here