Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / d0 / cb10633d0014a8fe5bb3b79bb744e716f79e02
1 Return-Path: <dmitry.kurochkin@gmail.com>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 0EBB3429E5B\r
6         for <notmuch@notmuchmail.org>; Mon, 30 Jan 2012 20:55:57 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.799\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5\r
12         tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
13         FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
14 Received: from olra.theworths.org ([127.0.0.1])\r
15         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
16         with ESMTP id 3lOl3lG5rFnc for <notmuch@notmuchmail.org>;\r
17         Mon, 30 Jan 2012 20:55:52 -0800 (PST)\r
18 Received: from mail-bk0-f53.google.com (mail-bk0-f53.google.com\r
19         [209.85.214.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
20         (No client certificate requested)\r
21         by olra.theworths.org (Postfix) with ESMTPS id 291AF418C33\r
22         for <notmuch@notmuchmail.org>; Mon, 30 Jan 2012 20:55:51 -0800 (PST)\r
23 Received: by mail-bk0-f53.google.com with SMTP id 11so2152468bke.26\r
24         for <notmuch@notmuchmail.org>; Mon, 30 Jan 2012 20:55:50 -0800 (PST)\r
25 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;\r
26         h=from:to:subject:date:message-id:x-mailer:in-reply-to:references;\r
27         bh=RwdGtPHYub158ZfE1nWK+DQ63pIYlDQYrpATOoNIuJw=;\r
28         b=DIspABZxWaxtwGvteZWqrfz/ZCRmw941J4zDwftkOkUOT/mUsAg5UOxteuejYomwop\r
29         PBGNlkbyUiIrhlZA86oOHbKHPr+MqZFqxHGcU7QiO1pdAqsBGqDO5K2CCJfJvp0XbVOO\r
30         ZtofY4QGhCy6gXsVNeAExhSGf/upz2ii82ylI=\r
31 Received: by 10.204.136.197 with SMTP id s5mr10140431bkt.9.1327985750778;\r
32         Mon, 30 Jan 2012 20:55:50 -0800 (PST)\r
33 Received: from localhost ([91.144.186.21])\r
34         by mx.google.com with ESMTPS id d2sm42464658bky.11.2012.01.30.20.55.49\r
35         (version=TLSv1/SSLv3 cipher=OTHER);\r
36         Mon, 30 Jan 2012 20:55:50 -0800 (PST)\r
37 From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>\r
38 To: notmuch@notmuchmail.org\r
39 Subject: [PATCH v4 03/12] emacs: make "+" and "-" tagging operations in\r
40         notmuch-search more flexible\r
41 Date: Tue, 31 Jan 2012 08:54:17 +0400\r
42 Message-Id: <1327985666-29191-4-git-send-email-dmitry.kurochkin@gmail.com>\r
43 X-Mailer: git-send-email 1.7.9\r
44 In-Reply-To: <1327985666-29191-1-git-send-email-dmitry.kurochkin@gmail.com>\r
45 References: <1327901644-15799-1-git-send-email-dmitry.kurochkin@gmail.com>\r
46         <1327985666-29191-1-git-send-email-dmitry.kurochkin@gmail.com>\r
47 X-BeenThere: notmuch@notmuchmail.org\r
48 X-Mailman-Version: 2.1.13\r
49 Precedence: list\r
50 List-Id: "Use and development of the notmuch mail system."\r
51         <notmuch.notmuchmail.org>\r
52 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
53         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
54 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
55 List-Post: <mailto:notmuch@notmuchmail.org>\r
56 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
57 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
58         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
59 X-List-Received-Date: Tue, 31 Jan 2012 04:55:57 -0000\r
60 \r
61 Before the change, "+" and "-" tagging operations in notmuch-search\r
62 view accepted only a single tag.  The patch makes them use the\r
63 recently added `notmuch-read-tag-changes' function (renamed\r
64 `notmuch-select-tags-with-completion'), which allows to enter multiple\r
65 tags with "+" and "-" prefixes.  So after the change, "+" and "-"\r
66 bindings in notmuch-search view allow to both add and remove multiple\r
67 tags.  The only difference between "+" and "-" is the minibuffer\r
68 initial input ("+" and "-" respectively).\r
69 ---\r
70  emacs/notmuch.el |  163 +++++++++++++++++++++++++++---------------------------\r
71  1 files changed, 81 insertions(+), 82 deletions(-)\r
72 \r
73 diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
74 index ff46617..ce8bef6 100644\r
75 --- a/emacs/notmuch.el\r
76 +++ b/emacs/notmuch.el\r
77 @@ -76,38 +76,56 @@ For example:\r
78  (defvar notmuch-query-history nil\r
79    "Variable to store minibuffer history for notmuch queries")\r
80  \r
81 -(defun notmuch-tag-completions (&optional prefixes search-terms)\r
82 -  (let ((tag-list\r
83 -        (split-string\r
84 -         (with-output-to-string\r
85 -           (with-current-buffer standard-output\r
86 -             (apply 'call-process notmuch-command nil t\r
87 -                    nil "search-tags" search-terms)))\r
88 -         "\n+" t)))\r
89 -    (if (null prefixes)\r
90 -       tag-list\r
91 -      (apply #'append\r
92 -            (mapcar (lambda (tag)\r
93 -                      (mapcar (lambda (prefix)\r
94 -                                (concat prefix tag)) prefixes))\r
95 -                    tag-list)))))\r
96 +(defun notmuch-tag-completions (&optional search-terms)\r
97 +  (split-string\r
98 +   (with-output-to-string\r
99 +     (with-current-buffer standard-output\r
100 +       (apply 'call-process notmuch-command nil t\r
101 +             nil "search-tags" search-terms)))\r
102 +   "\n+" t))\r
103  \r
104  (defun notmuch-select-tag-with-completion (prompt &rest search-terms)\r
105 -  (let ((tag-list (notmuch-tag-completions nil search-terms)))\r
106 +  (let ((tag-list (notmuch-tag-completions search-terms)))\r
107      (completing-read prompt tag-list)))\r
108  \r
109 -(defun notmuch-select-tags-with-completion (prompt &optional prefixes &rest search-terms)\r
110 -  (let ((tag-list (notmuch-tag-completions prefixes search-terms))\r
111 -       (crm-separator " ")\r
112 -       ;; By default, space is bound to "complete word" function.\r
113 -       ;; Re-bind it to insert a space instead.  Note that <tab>\r
114 -       ;; still does the completion.\r
115 -       (crm-local-completion-map\r
116 -        (let ((map (make-sparse-keymap)))\r
117 -          (set-keymap-parent map crm-local-completion-map)\r
118 -          (define-key map " " 'self-insert-command)\r
119 -          map)))\r
120 -    (delete "" (completing-read-multiple prompt tag-list))))\r
121 +(defun notmuch-read-tag-changes (&optional initial-input &rest search-terms)\r
122 +  (let* ((all-tag-list (notmuch-tag-completions))\r
123 +        (add-tag-list (mapcar (apply-partially 'concat "+") all-tag-list))\r
124 +        (remove-tag-list (mapcar (apply-partially 'concat "-")\r
125 +                                 (if (null search-terms)\r
126 +                                     all-tag-list\r
127 +                                   (notmuch-tag-completions search-terms))))\r
128 +        (tag-list (append add-tag-list remove-tag-list))\r
129 +        (crm-separator " ")\r
130 +        ;; By default, space is bound to "complete word" function.\r
131 +        ;; Re-bind it to insert a space instead.  Note that <tab>\r
132 +        ;; still does the completion.\r
133 +        (crm-local-completion-map\r
134 +         (let ((map (make-sparse-keymap)))\r
135 +           (set-keymap-parent map crm-local-completion-map)\r
136 +           (define-key map " " 'self-insert-command)\r
137 +           map)))\r
138 +    (delete "" (completing-read-multiple "Tags (+add -drop): "\r
139 +               tag-list nil nil initial-input))))\r
140 +\r
141 +(defun notmuch-update-tags (tags tag-changes)\r
142 +  "Return a copy of TAGS with additions and removals from TAG-CHANGES.\r
143 +\r
144 +TAG-CHANGES must be a list of tags names, each prefixed with\r
145 +either a \"+\" to indicate the tag should be added to TAGS if not\r
146 +present or a \"-\" to indicate that the tag should be removed\r
147 +from TAGS if present."\r
148 +  (let ((result-tags (copy-sequence tags)))\r
149 +    (dolist (tag-change tag-changes)\r
150 +      (let ((op (string-to-char tag-change))\r
151 +           (tag (unless (string= tag-change "") (substring tag-change 1))))\r
152 +       (case op\r
153 +         (?+ (unless (member tag result-tags)\r
154 +               (push tag result-tags)))\r
155 +         (?- (setq result-tags (delete tag result-tags)))\r
156 +         (otherwise\r
157 +          (error "Changed tag must be of the form `+this_tag' or `-that_tag'")))))\r
158 +    (sort result-tags 'string<)))\r
159  \r
160  (defun notmuch-foreach-mime-part (function mm-handle)\r
161    (cond ((stringp (car mm-handle))\r
162 @@ -447,6 +465,10 @@ Complete list of currently available key bindings:\r
163    "Return a list of threads for the current region"\r
164    (notmuch-search-properties-in-region 'notmuch-search-thread-id beg end))\r
165  \r
166 +(defun notmuch-search-find-thread-id-region-search (beg end)\r
167 +  "Return a search string for threads for the current region"\r
168 +  (mapconcat 'identity (notmuch-search-find-thread-id-region beg end) " or "))\r
169 +\r
170  (defun notmuch-search-find-authors ()\r
171    "Return the authors for the current thread"\r
172    (get-text-property (point) 'notmuch-search-authors))\r
173 @@ -590,74 +612,53 @@ the messages that were tagged"\r
174         (forward-line 1))\r
175        output)))\r
176  \r
177 -(defun notmuch-search-add-tag-thread (tag)\r
178 -  (notmuch-search-add-tag-region tag (point) (point)))\r
179 +(defun notmuch-search-tag-thread (&rest tags)\r
180 +  "Change tags for the currently selected thread.\r
181  \r
182 -(defun notmuch-search-add-tag-region (tag beg end)\r
183 -  (let ((search-id-string (mapconcat 'identity (notmuch-search-find-thread-id-region beg end) " or ")))\r
184 -    (notmuch-tag search-id-string (concat "+" tag))\r
185 -    (save-excursion\r
186 -      (let ((last-line (line-number-at-pos end))\r
187 -           (max-line (- (line-number-at-pos (point-max)) 2)))\r
188 -       (goto-char beg)\r
189 -       (while (<= (line-number-at-pos) (min last-line max-line))\r
190 -         (notmuch-search-set-tags (delete-dups (sort (cons tag (notmuch-search-get-tags)) 'string<)))\r
191 -         (forward-line))))))\r
192 +See `notmuch-search-tag-region' for details."\r
193 +  (apply 'notmuch-search-tag-region (point) (point) tags))\r
194  \r
195 -(defun notmuch-search-remove-tag-thread (tag)\r
196 -  (notmuch-search-remove-tag-region tag (point) (point)))\r
197 +(defun notmuch-search-tag-region (beg end &rest tags)\r
198 +  "Change tags for threads in the given region.\r
199  \r
200 -(defun notmuch-search-remove-tag-region (tag beg end)\r
201 -  (let ((search-id-string (mapconcat 'identity (notmuch-search-find-thread-id-region beg end) " or ")))\r
202 -    (notmuch-tag search-id-string (concat "-" tag))\r
203 +TAGS is a list of tag operations for `notmuch-tag'.  The tags are\r
204 +added or removed for all threads in the region from BEG to END."\r
205 +  (let ((search-string (notmuch-search-find-thread-id-region-search beg end)))\r
206 +    (apply 'notmuch-tag search-string tags)\r
207      (save-excursion\r
208        (let ((last-line (line-number-at-pos end))\r
209             (max-line (- (line-number-at-pos (point-max)) 2)))\r
210         (goto-char beg)\r
211         (while (<= (line-number-at-pos) (min last-line max-line))\r
212 -         (notmuch-search-set-tags (delete tag (notmuch-search-get-tags)))\r
213 +         (notmuch-search-set-tags\r
214 +          (notmuch-update-tags (notmuch-search-get-tags) tags))\r
215           (forward-line))))))\r
216  \r
217 -(defun notmuch-search-add-tag (tag)\r
218 -  "Add a tag to the currently selected thread or region.\r
219 -\r
220 -The tag is added to all messages in the currently selected thread\r
221 -or threads in the current region."\r
222 -  (interactive\r
223 -   (list (notmuch-select-tag-with-completion "Tag to add: ")))\r
224 -  (save-excursion\r
225 -    (if (region-active-p)\r
226 -       (let* ((beg (region-beginning))\r
227 -              (end (region-end)))\r
228 -         (notmuch-search-add-tag-region tag beg end))\r
229 -      (notmuch-search-add-tag-thread tag))))\r
230 -\r
231 -(defun notmuch-search-remove-tag (tag)\r
232 -  "Remove a tag from the currently selected thread or region.\r
233 +(defun notmuch-search-tag (&optional initial-input)\r
234 +  "Change tags for the currently selected thread or region."\r
235 +  (interactive)\r
236 +  (let* ((beg (if (region-active-p) (region-beginning) (point)))\r
237 +        (end (if (region-active-p) (region-end) (point)))\r
238 +        (search-string (notmuch-search-find-thread-id-region-search beg end))\r
239 +        (tags (notmuch-read-tag-changes initial-input search-string)))\r
240 +    (apply 'notmuch-search-tag-region beg end tags)))\r
241 +\r
242 +(defun notmuch-search-add-tag ()\r
243 +  "Same as `notmuch-search-tag' but sets initial input to '+'."\r
244 +  (interactive)\r
245 +  (notmuch-search-tag "+"))\r
246  \r
247 -The tag is removed from all messages in the currently selected\r
248 -thread or threads in the current region."\r
249 -  (interactive\r
250 -   (list (notmuch-select-tag-with-completion\r
251 -         "Tag to remove: "\r
252 -         (if (region-active-p)\r
253 -             (mapconcat 'identity\r
254 -                        (notmuch-search-find-thread-id-region (region-beginning) (region-end))\r
255 -                        " ")\r
256 -           (notmuch-search-find-thread-id)))))\r
257 -  (save-excursion\r
258 -    (if (region-active-p)\r
259 -       (let* ((beg (region-beginning))\r
260 -              (end (region-end)))\r
261 -         (notmuch-search-remove-tag-region tag beg end))\r
262 -      (notmuch-search-remove-tag-thread tag))))\r
263 +(defun notmuch-search-remove-tag ()\r
264 +  "Same as `notmuch-search-tag' but sets initial input to '-'."\r
265 +  (interactive)\r
266 +  (notmuch-search-tag "-"))\r
267  \r
268  (defun notmuch-search-archive-thread ()\r
269    "Archive the currently selected thread (remove its \"inbox\" tag).\r
270  \r
271  This function advances the next thread when finished."\r
272    (interactive)\r
273 -  (notmuch-search-remove-tag-thread "inbox")\r
274 +  (notmuch-search-tag-thread "-inbox")\r
275    (notmuch-search-next-thread))\r
276  \r
277  (defvar notmuch-search-process-filter-data nil\r
278 @@ -893,9 +894,7 @@ will prompt for tags to be added or removed. Tags prefixed with\r
279  Each character of the tag name may consist of alphanumeric\r
280  characters as well as `_.+-'.\r
281  "\r
282 -  (interactive (notmuch-select-tags-with-completion\r
283 -               "Operations (+add -drop): notmuch tag "\r
284 -               '("+" "-")))\r
285 +  (interactive (notmuch-read-tag-changes))\r
286    (apply 'notmuch-tag notmuch-search-query-string actions))\r
287  \r
288  (defun notmuch-search-buffer-title (query)\r
289 -- \r
290 1.7.9\r
291 \r