From: David Bremner Date: Wed, 12 Oct 2016 01:42:26 +0000 (-0300) Subject: merge buttonise-links patch to master X-Git-Tag: 0.24_rc0~125 X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=commitdiff_plain;h=5d05523659912c6b4221fe5246261df601ea41c8;hp=f575a346df09c82691bb9e7c462836d982fe31f7 merge buttonise-links patch to master --- diff --git a/devel/nmbug/nmbug b/devel/nmbug/nmbug index 1dd5f14f..6febf16f 100755 --- a/devel/nmbug/nmbug +++ b/devel/nmbug/nmbug @@ -475,7 +475,7 @@ def log(args=()): 'nmbug log HEAD..@{upstream}'. """ # we don't want output trapping here, because we want the pager. - args = ['log', '--name-status'] + list(args) + args = ['log', '--name-status', '--no-renames'] + list(args) with _git(args=args, expect=(0, 1, -13)) as p: p.wait() diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index 10eaab19..b2e1fba7 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -194,7 +194,14 @@ external commands." (t (funcall notmuch-address-selection-function (format "Address (%s matches): " num-options) - (cdr options) (car options)))))) + ;; We put the first match as the initial + ;; input; we put all the matches as + ;; possible completions, moving the + ;; first match to the end of the list + ;; makes cursor up/down in the list work + ;; better. + (append (cdr options) (list (car options))) + (car options)))))) (if chosen (progn (push chosen notmuch-address-history) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 2f015b0d..b2cdace9 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -57,6 +57,10 @@ (custom-add-to-group 'notmuch-send 'message 'custom-group) +(defgroup notmuch-tag nil + "Tags and tagging in Notmuch." + :group 'notmuch) + (defgroup notmuch-crypto nil "Processing and display of cryptographic MIME parts." :group 'notmuch) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 55bc2672..c5671731 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -490,15 +490,64 @@ will be addressed to all recipients of the source message." (notmuch-mua-reply query-string sender reply-all) (deactivate-mark))) +(defun notmuch-mua-check-no-misplaced-secure-tag () + "Query user if there is a misplaced secure mml tag. + +Emacs message-send will (probably) ignore a secure mml tag unless +it is at the start of the body. Returns t if there is no such +tag, or the user confirms they mean it." + (save-excursion + (let ((body-start (progn (message-goto-body) (point)))) + (goto-char (point-max)) + (or + ;; We are always fine if there is no secure tag. + (not (search-backward "<#secure" nil 't)) + ;; There is a secure tag, so it must be at the start of the + ;; body, with no secure tag earlier (i.e., in the headers). + (and (= (point) body-start) + (not (search-backward "<#secure" nil 't))) + ;; The user confirms they means it. + (yes-or-no-p "\ +There is a <#secure> tag not at the start of the body. It is +likely that the message will be sent unsigned and unencrypted. +Really send? "))))) + +(defun notmuch-mua-check-secure-tag-has-newline () + "Query if the secure mml tag has a newline following it. + +Emacs message-send will (probably) ignore a correctly placed +secure mml tag unless it is followed by a newline. Returns t if +any secure tag is followed by a newline, or the user confirms +they mean it." + (save-excursion + (message-goto-body) + (or + ;; There is no (correctly placed) secure tag. + (not (looking-at "<#secure")) + ;; The secure tag is followed by a newline. + (looking-at "<#secure[^\n>]*>\n") + ;; The user confirms they means it. + (yes-or-no-p "\ +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? ")))) + +(defun notmuch-mua-send-common (arg &optional exit) + (interactive "P") + (when (and (notmuch-mua-check-no-misplaced-secure-tag) + (notmuch-mua-check-secure-tag-has-newline)) + (letf (((symbol-function 'message-do-fcc) #'notmuch-maildir-message-do-fcc)) + (if exit + (message-send-and-exit arg) + (message-send arg))))) + (defun notmuch-mua-send-and-exit (&optional arg) (interactive "P") - (letf (((symbol-function 'message-do-fcc) #'notmuch-maildir-message-do-fcc)) - (message-send-and-exit arg))) + (notmuch-mua-send-common arg 't)) (defun notmuch-mua-send (&optional arg) (interactive "P") - (letf (((symbol-function 'message-do-fcc) #'notmuch-maildir-message-do-fcc)) - (message-send arg))) + (notmuch-mua-send-common arg)) (defun notmuch-mua-kill-buffer () (interactive) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index e7d16f81..643dee6e 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1433,6 +1433,7 @@ reset based on the original query." (define-key map "V" 'notmuch-show-view-raw-message) (define-key map "c" 'notmuch-show-stash-map) (define-key map "h" 'notmuch-show-toggle-visibility-headers) + (define-key map "k" 'notmuch-tag-jump) (define-key map "*" 'notmuch-show-tag-all) (define-key map "-" 'notmuch-show-remove-tag) (define-key map "+" 'notmuch-show-add-tag) diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el index 6c8b6a75..c03027f7 100644 --- a/emacs/notmuch-tag.el +++ b/emacs/notmuch-tag.el @@ -28,6 +28,54 @@ (require 'crm) (require 'notmuch-lib) +(declare-function notmuch-search-tag "notmuch" tag-changes) +(declare-function notmuch-show-tag "notmuch-show" tag-changes) +(declare-function notmuch-tree-tag "notmuch-tree" tag-changes) + +(autoload 'notmuch-jump "notmuch-jump") + +(define-widget 'notmuch-tag-key-type 'list + "A single key tagging binding." + :format "%v" + :args '((list :inline t + :format "%v" + (key-sequence :tag "Key") + (radio :tag "Tag operations" (repeat :tag "Tag list" (string :format "%v" :tag "change")) + (variable :tag "Tag variable")) + (string :tag "Name")))) + +(defcustom notmuch-tagging-keys + `((,(kbd "a") notmuch-archive-tags "Archive") + (,(kbd "u") notmuch-show-mark-read-tags "Mark read") + (,(kbd "f") ("+flagged") "Flag") + (,(kbd "s") ("+spam" "-inbox") "Mark as spam") + (,(kbd "d") ("+deleted" "-inbox") "Delete")) + "A list of keys and corresponding tagging operations. + +For each key (or key sequence) you can specify a sequence of +tagging operations to apply, or a variable which contains a list +of tagging operations such as `notmuch-archive-tags'. The final +element is a name for this tagging operation. If the name is +omitted or empty then the list of tag changes, or the variable +name is used as the name. The key `r` should not be used as that +is already bound: it switches the menu to a menu of the reverse +tagging operations. The reverse of a tagging operation is the +same list of individual tag-ops but with `+tag` replaced by +`-tag` and vice versa. + +If setting this variable outside of customize then it should be a +list of triples (lists of three elements). Each triple should be +of the form (key-binding tagging-operations name). KEY-BINDING +can be a single character or a key sequence; TAGGING-OPERATIONS +should either be a list of individual tag operations each of the +form `+tag` or `-tag`, or the variable name of a variable that is +a list of tagging operations; NAME should be a name for the +tagging operation, if omitted or empty than then name is taken +from TAGGING-OPERATIONS." + :tag "List of tagging bindings" + :type '(repeat notmuch-tag-key-type) + :group 'notmuch-tag) + (define-widget 'notmuch-tag-format-type 'lazy "Customize widget for notmuch-tag-format and friends" :type '(alist :key-type (regexp :tag "Tag") @@ -437,6 +485,55 @@ begin with a \"+\" or a \"-\". If REVERSE is non-nil, replace all s))) tags)) +(defvar notmuch-tag-jump-reverse-key "k" + "The key in tag-jump to switch to the reverse tag changes.") + +(defun notmuch-tag-jump (reverse) + "Create a jump menu for tagging operations. + +Creates and displays a jump menu for the tagging operations +specified in `notmuch-tagging-keys'. If REVERSE is set then it +offers a menu of the reverses of the operations specified in +`notmuch-tagging-keys'; i.e. each `+tag` is replaced by `-tag` +and vice versa." + ;; In principle this function is simple, but it has to deal with + ;; lots of cases: different modes (search/show/tree), whether a name + ;; is specified, whether the tagging operations is a list of + ;; tag-ops, or a symbol that evaluates to such a list, and whether + ;; REVERSE is specified. + (interactive "P") + (let (action-map) + (dolist (binding notmuch-tagging-keys) + (let* ((tag-function (case major-mode + (notmuch-search-mode #'notmuch-search-tag) + (notmuch-show-mode #'notmuch-show-tag) + (notmuch-tree-mode #'notmuch-tree-tag))) + (key (first binding)) + (forward-tag-change (if (symbolp (second binding)) + (symbol-value (second binding)) + (second binding))) + (tag-change (if reverse + (notmuch-tag-change-list forward-tag-change 't) + forward-tag-change)) + (name (or (and (not (string= (third binding) "")) + (third binding)) + (and (symbolp (second binding)) + (symbol-name (second binding))))) + (name-string (if name + (if reverse (concat "Reverse " name) + name) + (mapconcat #'identity tag-change " ")))) + (push (list key name-string + `(lambda () (,tag-function ',tag-change))) + action-map))) + (push (list notmuch-tag-jump-reverse-key + (if reverse + "Forward tag changes " + "Reverse tag changes") + (apply-partially 'notmuch-tag-jump (not reverse))) + action-map) + (setq action-map (nreverse action-map)) + (notmuch-jump action-map "Tag: "))) ;; diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 658c4f90..1555812c 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -279,6 +279,7 @@ FUNC." (define-key map "P" 'notmuch-tree-prev-message) (define-key map (kbd "M-p") 'notmuch-tree-prev-thread) (define-key map (kbd "M-n") 'notmuch-tree-next-thread) + (define-key map "k" 'notmuch-tag-jump) (define-key map "-" 'notmuch-tree-remove-tag) (define-key map "+" 'notmuch-tree-add-tag) (define-key map "*" 'notmuch-tree-tag-thread) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 8e146924..6c36ad8a 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -169,6 +169,7 @@ there will be called at other points of notmuch execution." (define-key map "t" 'notmuch-search-filter-by-tag) (define-key map "l" 'notmuch-search-filter) (define-key map [mouse-1] 'notmuch-search-show-thread) + (define-key map "k" 'notmuch-tag-jump) (define-key map "*" 'notmuch-search-tag-all) (define-key map "a" 'notmuch-search-archive-thread) (define-key map "-" 'notmuch-search-remove-tag) @@ -891,9 +892,10 @@ PROMPT is the string to prompt with." (process-lines notmuch-command "search" "--output=tags" "*"))) (completions (append (list "folder:" "path:" "thread:" "id:" "date:" "from:" "to:" - "subject:" "attachment:" "mimetype:") + "subject:" "attachment:") (mapcar (lambda (tag) (concat "tag:" tag)) all-tags) - (mapcar (lambda (tag) (concat "is:" tag)) all-tags)))) + (mapcar (lambda (tag) (concat "is:" tag)) all-tags) + (mapcar (lambda (mimetype) (concat "mimetype:" mimetype)) (mailcap-mime-types))))) (let ((keymap (copy-keymap minibuffer-local-map)) (current-query (case major-mode (notmuch-search-mode (notmuch-search-get-query))