diff options
| author | Gnus developers | 2012-09-05 22:35:32 +0000 |
|---|---|---|
| committer | Katsumi Yamaoka | 2012-09-05 22:35:32 +0000 |
| commit | 350a188850c4eeceab0220ba1f6fdf98f0f57e93 (patch) | |
| tree | ef47da20a533cc6bb63e46b6a6d1b08f28d0fc1e | |
| parent | 20ef56dbc88f517ebf60d89577fc89870d9fe888 (diff) | |
| download | emacs-350a188850c4eeceab0220ba1f6fdf98f0f57e93.tar.gz emacs-350a188850c4eeceab0220ba1f6fdf98f0f57e93.zip | |
Merge changes made in Gnus master
2012-09-05 Julien Danjou <julien@danjou.info>
* gnus-srvr.el (gnus-server-open-server): Don't message on failure:
this hide the real reason with a message giving absolutely no hint.
2012-09-05 Lars Ingebrigtsen <larsi@gnus.org>
* gnus-group.el (gnus-group-mark-article-read): Propagate the read mark
to the backend (bug#11804).
* message.el (message-insert-newsgroups): Don't insert newsgroup
duplicates (bug#12275).
2012-09-05 John Wiegley <johnw@newartisans.com>
* gnus.el (gnus-expand-group-parameters): Allow regexp substitutions in
sieve rules.
2012-09-05 Jan Tatarik <jan.tatarik@gmail.com>
* gnus-score.el (gnus-score-decode-text-parts): Use #' for the local
function.
* gnus-logic.el (gnus-advanced-body): Allow scoring on decoded bodies.
* gnus-score.el (gnus-score-decode-text-parts): Ditto.
2012-09-05 Magnus Henoch <magnus.henoch@gmail.com>
* nnmaildir.el: Make nnmaildir understand and write maildir flags.
That is, rename files from "unique:2," to "unique:2,S" for "seen", etc.
This should make nnmaildir more usable with offlineimap.
| -rw-r--r-- | lisp/gnus/ChangeLog | 33 | ||||
| -rw-r--r-- | lisp/gnus/gnus-group.el | 2 | ||||
| -rw-r--r-- | lisp/gnus/gnus-logic.el | 73 | ||||
| -rw-r--r-- | lisp/gnus/gnus-score.el | 231 | ||||
| -rw-r--r-- | lisp/gnus/gnus-srvr.el | 3 | ||||
| -rw-r--r-- | lisp/gnus/gnus.el | 45 | ||||
| -rw-r--r-- | lisp/gnus/message.el | 32 | ||||
| -rw-r--r-- | lisp/gnus/nnmaildir.el | 286 |
8 files changed, 487 insertions, 218 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 0587469a08e..c6220204511 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,36 @@ | |||
| 1 | 2012-09-05 Julien Danjou <julien@danjou.info> | ||
| 2 | |||
| 3 | * gnus-srvr.el (gnus-server-open-server): Don't message on failure: | ||
| 4 | this hide the real reason with a message giving absolutely no hint. | ||
| 5 | |||
| 6 | 2012-09-05 Lars Ingebrigtsen <larsi@gnus.org> | ||
| 7 | |||
| 8 | * gnus-group.el (gnus-group-mark-article-read): Propagate the read mark | ||
| 9 | to the backend (bug#11804). | ||
| 10 | |||
| 11 | * message.el (message-insert-newsgroups): Don't insert newsgroup | ||
| 12 | duplicates (bug#12275). | ||
| 13 | |||
| 14 | 2012-09-05 John Wiegley <johnw@newartisans.com> | ||
| 15 | |||
| 16 | * gnus.el (gnus-expand-group-parameters): Allow regexp substitutions in | ||
| 17 | sieve rules. | ||
| 18 | |||
| 19 | 2012-09-05 Jan Tatarik <jan.tatarik@gmail.com> | ||
| 20 | |||
| 21 | * gnus-score.el (gnus-score-decode-text-parts): Use #' for the local | ||
| 22 | function. | ||
| 23 | |||
| 24 | * gnus-logic.el (gnus-advanced-body): Allow scoring on decoded bodies. | ||
| 25 | |||
| 26 | * gnus-score.el (gnus-score-decode-text-parts): Ditto. | ||
| 27 | |||
| 28 | 2012-09-05 Magnus Henoch <magnus.henoch@gmail.com> | ||
| 29 | |||
| 30 | * nnmaildir.el: Make nnmaildir understand and write maildir flags. | ||
| 31 | That is, rename files from "unique:2," to "unique:2,S" for "seen", etc. | ||
| 32 | This should make nnmaildir more usable with offlineimap. | ||
| 33 | |||
| 1 | 2012-09-03 Lars Ingebrigtsen <larsi@gnus.org> | 34 | 2012-09-03 Lars Ingebrigtsen <larsi@gnus.org> |
| 2 | 35 | ||
| 3 | * gnus-notifications.el (gnus-notifications-notify): Use it. | 36 | * gnus-notifications.el (gnus-notifications-notify): Use it. |
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index 2f6fc0ccd19..37e4470239e 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el | |||
| @@ -4670,6 +4670,8 @@ you the groups that have both dormant articles and cached articles." | |||
| 4670 | (setq mark gnus-expirable-mark)) | 4670 | (setq mark gnus-expirable-mark)) |
| 4671 | (setq mark (gnus-request-update-mark | 4671 | (setq mark (gnus-request-update-mark |
| 4672 | group article mark)) | 4672 | group article mark)) |
| 4673 | (gnus-request-set-mark | ||
| 4674 | group (list (list (list article) 'add '(read)))) | ||
| 4673 | (gnus-mark-article-as-read article mark) | 4675 | (gnus-mark-article-as-read article mark) |
| 4674 | (setq gnus-newsgroup-active (gnus-active group)) | 4676 | (setq gnus-newsgroup-active (gnus-active group)) |
| 4675 | (when active | 4677 | (when active |
diff --git a/lisp/gnus/gnus-logic.el b/lisp/gnus/gnus-logic.el index 954295438c9..a440b779930 100644 --- a/lisp/gnus/gnus-logic.el +++ b/lisp/gnus/gnus-logic.el | |||
| @@ -180,46 +180,51 @@ | |||
| 180 | (setq header "article")) | 180 | (setq header "article")) |
| 181 | (with-current-buffer nntp-server-buffer | 181 | (with-current-buffer nntp-server-buffer |
| 182 | (let* ((request-func (cond ((string= "head" header) | 182 | (let* ((request-func (cond ((string= "head" header) |
| 183 | 'gnus-request-head) | 183 | 'gnus-request-head) |
| 184 | ((string= "body" header) | 184 | ;; We need to peek at the headers to detect the |
| 185 | 'gnus-request-body) | 185 | ;; content encoding |
| 186 | (t 'gnus-request-article))) | 186 | ((string= "body" header) |
| 187 | ofunc article) | 187 | 'gnus-request-article) |
| 188 | (t 'gnus-request-article))) | ||
| 189 | ofunc article handles) | ||
| 188 | ;; Not all backends support partial fetching. In that case, we | 190 | ;; Not all backends support partial fetching. In that case, we |
| 189 | ;; just fetch the entire article. | 191 | ;; just fetch the entire article. |
| 190 | (unless (gnus-check-backend-function | 192 | (unless (gnus-check-backend-function |
| 191 | (intern (concat "request-" header)) | 193 | (intern (concat "request-" header)) |
| 192 | gnus-newsgroup-name) | 194 | gnus-newsgroup-name) |
| 193 | (setq ofunc request-func) | 195 | (setq ofunc request-func) |
| 194 | (setq request-func 'gnus-request-article)) | 196 | (setq request-func 'gnus-request-article)) |
| 195 | (setq article (mail-header-number gnus-advanced-headers)) | 197 | (setq article (mail-header-number gnus-advanced-headers)) |
| 196 | (gnus-message 7 "Scoring article %s..." article) | 198 | (gnus-message 7 "Scoring article %s..." article) |
| 197 | (when (funcall request-func article gnus-newsgroup-name) | 199 | (when (funcall request-func article gnus-newsgroup-name) |
| 198 | (goto-char (point-min)) | 200 | (when (string= "body" header) |
| 199 | ;; If just parts of the article is to be searched and the | 201 | (setq handles (gnus-score-decode-text-parts))) |
| 200 | ;; backend didn't support partial fetching, we just narrow to | 202 | (goto-char (point-min)) |
| 201 | ;; the relevant parts. | 203 | ;; If just parts of the article is to be searched and the |
| 202 | (when ofunc | 204 | ;; backend didn't support partial fetching, we just narrow to |
| 203 | (if (eq ofunc 'gnus-request-head) | 205 | ;; the relevant parts. |
| 204 | (narrow-to-region | 206 | (when ofunc |
| 205 | (point) | 207 | (if (eq ofunc 'gnus-request-head) |
| 206 | (or (search-forward "\n\n" nil t) (point-max))) | 208 | (narrow-to-region |
| 207 | (narrow-to-region | 209 | (point) |
| 208 | (or (search-forward "\n\n" nil t) (point)) | 210 | (or (search-forward "\n\n" nil t) (point-max))) |
| 209 | (point-max)))) | 211 | (narrow-to-region |
| 210 | (let* ((case-fold-search (not (eq (downcase (symbol-name type)) | 212 | (or (search-forward "\n\n" nil t) (point)) |
| 211 | (symbol-name type)))) | 213 | (point-max)))) |
| 212 | (search-func | 214 | (let* ((case-fold-search (not (eq (downcase (symbol-name type)) |
| 213 | (cond ((memq type '(r R regexp Regexp)) | 215 | (symbol-name type)))) |
| 214 | 're-search-forward) | 216 | (search-func |
| 215 | ((memq type '(s S string String)) | 217 | (cond ((memq type '(r R regexp Regexp)) |
| 216 | 'search-forward) | 218 | 're-search-forward) |
| 217 | (t | 219 | ((memq type '(s S string String)) |
| 218 | (error "Invalid match type: %s" type))))) | 220 | 'search-forward) |
| 219 | (goto-char (point-min)) | 221 | (t |
| 220 | (prog1 | 222 | (error "Invalid match type: %s" type))))) |
| 221 | (funcall search-func match nil t) | 223 | (goto-char (point-min)) |
| 222 | (widen))))))) | 224 | (prog1 |
| 225 | (funcall search-func match nil t) | ||
| 226 | (widen))) | ||
| 227 | (when handles (mm-destroy-parts handles)))))) | ||
| 223 | 228 | ||
| 224 | (provide 'gnus-logic) | 229 | (provide 'gnus-logic) |
| 225 | 230 | ||
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el index f24d889216e..bc35cf3dea5 100644 --- a/lisp/gnus/gnus-score.el +++ b/lisp/gnus/gnus-score.el | |||
| @@ -1717,105 +1717,140 @@ score in `gnus-newsgroup-scored' by SCORE." | |||
| 1717 | (setq entries rest))))) | 1717 | (setq entries rest))))) |
| 1718 | nil) | 1718 | nil) |
| 1719 | 1719 | ||
| 1720 | (defun gnus-score-decode-text-parts () | ||
| 1721 | (labels ((mm-text-parts (handle) | ||
| 1722 | (cond ((stringp (car handle)) | ||
| 1723 | (let ((parts (mapcan 'mm-text-parts (cdr handle)))) | ||
| 1724 | (if (equal "multipart/alternative" (car handle)) | ||
| 1725 | ;; pick the first supported alternative | ||
| 1726 | (list (car parts)) | ||
| 1727 | parts))) | ||
| 1728 | |||
| 1729 | ((bufferp (car handle)) | ||
| 1730 | (when (string-match "^text/" (mm-handle-media-type handle)) | ||
| 1731 | (list handle))) | ||
| 1732 | |||
| 1733 | (t (mapcan 'mm-text-parts handle)))) | ||
| 1734 | (my-mm-display-part (handle) | ||
| 1735 | (when handle | ||
| 1736 | (save-restriction | ||
| 1737 | (narrow-to-region (point) (point)) | ||
| 1738 | (mm-display-inline handle) | ||
| 1739 | (goto-char (point-max)))))) | ||
| 1740 | |||
| 1741 | (let (;(mm-text-html-renderer 'w3m-standalone) | ||
| 1742 | (handles (mm-dissect-buffer t))) | ||
| 1743 | (save-excursion | ||
| 1744 | (article-goto-body) | ||
| 1745 | (delete-region (point) (point-max)) | ||
| 1746 | (mapc #'my-mm-display-part (mm-text-parts handles)) | ||
| 1747 | handles)))) | ||
| 1748 | |||
| 1720 | (defun gnus-score-body (scores header now expire &optional trace) | 1749 | (defun gnus-score-body (scores header now expire &optional trace) |
| 1721 | (if gnus-agent-fetching | 1750 | (if gnus-agent-fetching |
| 1722 | nil | 1751 | nil |
| 1723 | (save-excursion | 1752 | (save-excursion |
| 1724 | (setq gnus-scores-articles | 1753 | (setq gnus-scores-articles |
| 1725 | (sort gnus-scores-articles | 1754 | (sort gnus-scores-articles |
| 1726 | (lambda (a1 a2) | 1755 | (lambda (a1 a2) |
| 1727 | (< (mail-header-number (car a1)) | 1756 | (< (mail-header-number (car a1)) |
| 1728 | (mail-header-number (car a2)))))) | 1757 | (mail-header-number (car a2)))))) |
| 1729 | (set-buffer nntp-server-buffer) | 1758 | (set-buffer nntp-server-buffer) |
| 1730 | (save-restriction | 1759 | (save-restriction |
| 1731 | (let* ((buffer-read-only nil) | 1760 | (let* ((buffer-read-only nil) |
| 1732 | (articles gnus-scores-articles) | 1761 | (articles gnus-scores-articles) |
| 1733 | (all-scores scores) | 1762 | (all-scores scores) |
| 1734 | (request-func (cond ((string= "head" header) | 1763 | (request-func (cond ((string= "head" header) |
| 1735 | 'gnus-request-head) | 1764 | 'gnus-request-head) |
| 1736 | ((string= "body" header) | 1765 | ;; We need to peek at the headers to detect |
| 1737 | 'gnus-request-body) | 1766 | ;; the content encoding |
| 1738 | (t 'gnus-request-article))) | 1767 | ((string= "body" header) |
| 1739 | entries alist ofunc article last) | 1768 | 'gnus-request-article) |
| 1740 | (when articles | 1769 | (t 'gnus-request-article))) |
| 1741 | (setq last (mail-header-number (caar (last articles)))) | 1770 | entries alist ofunc article last) |
| 1742 | ;; Not all backends support partial fetching. In that case, | 1771 | (when articles |
| 1743 | ;; we just fetch the entire article. | 1772 | (setq last (mail-header-number (caar (last articles)))) |
| 1744 | (unless (gnus-check-backend-function | 1773 | ;; Not all backends support partial fetching. In that case, |
| 1745 | (and (string-match "^gnus-" (symbol-name request-func)) | 1774 | ;; we just fetch the entire article. |
| 1746 | (intern (substring (symbol-name request-func) | 1775 | (unless (gnus-check-backend-function |
| 1747 | (match-end 0)))) | 1776 | (and (string-match "^gnus-" (symbol-name request-func)) |
| 1748 | gnus-newsgroup-name) | 1777 | (intern (substring (symbol-name request-func) |
| 1749 | (setq ofunc request-func) | 1778 | (match-end 0)))) |
| 1750 | (setq request-func 'gnus-request-article)) | 1779 | gnus-newsgroup-name) |
| 1751 | (while articles | 1780 | (setq ofunc request-func) |
| 1752 | (setq article (mail-header-number (caar articles))) | 1781 | (setq request-func 'gnus-request-article)) |
| 1753 | (gnus-message 7 "Scoring article %s of %s..." article last) | 1782 | (while articles |
| 1754 | (widen) | 1783 | (setq article (mail-header-number (caar articles))) |
| 1755 | (when (funcall request-func article gnus-newsgroup-name) | 1784 | (gnus-message 7 "Scoring article %s of %s..." article last) |
| 1756 | (goto-char (point-min)) | 1785 | (widen) |
| 1757 | ;; If just parts of the article is to be searched, but the | 1786 | (let (handles) |
| 1758 | ;; backend didn't support partial fetching, we just narrow | 1787 | (when (funcall request-func article gnus-newsgroup-name) |
| 1759 | ;; to the relevant parts. | 1788 | (when (string= "body" header) |
| 1760 | (when ofunc | 1789 | (setq handles (gnus-score-decode-text-parts))) |
| 1761 | (if (eq ofunc 'gnus-request-head) | 1790 | (goto-char (point-min)) |
| 1762 | (narrow-to-region | 1791 | ;; If just parts of the article is to be searched, but the |
| 1763 | (point) | 1792 | ;; backend didn't support partial fetching, we just narrow |
| 1764 | (or (search-forward "\n\n" nil t) (point-max))) | 1793 | ;; to the relevant parts. |
| 1765 | (narrow-to-region | 1794 | (when ofunc |
| 1766 | (or (search-forward "\n\n" nil t) (point)) | 1795 | (if (eq ofunc 'gnus-request-head) |
| 1767 | (point-max)))) | 1796 | (narrow-to-region |
| 1768 | (setq scores all-scores) | 1797 | (point) |
| 1769 | ;; Find matches. | 1798 | (or (search-forward "\n\n" nil t) (point-max))) |
| 1770 | (while scores | 1799 | (narrow-to-region |
| 1771 | (setq alist (pop scores) | 1800 | (or (search-forward "\n\n" nil t) (point)) |
| 1772 | entries (assoc header alist)) | 1801 | (point-max)))) |
| 1773 | (while (cdr entries) ;First entry is the header index. | 1802 | (setq scores all-scores) |
| 1774 | (let* ((rest (cdr entries)) | 1803 | ;; Find matches. |
| 1775 | (kill (car rest)) | 1804 | (while scores |
| 1776 | (match (nth 0 kill)) | 1805 | (setq alist (pop scores) |
| 1777 | (type (or (nth 3 kill) 's)) | 1806 | entries (assoc header alist)) |
| 1778 | (score (or (nth 1 kill) | 1807 | (while (cdr entries) ;First entry is the header index. |
| 1779 | gnus-score-interactive-default-score)) | 1808 | (let* ((rest (cdr entries)) |
| 1780 | (date (nth 2 kill)) | 1809 | (kill (car rest)) |
| 1781 | (found nil) | 1810 | (match (nth 0 kill)) |
| 1782 | (case-fold-search | 1811 | (type (or (nth 3 kill) 's)) |
| 1783 | (not (or (eq type 'R) (eq type 'S) | 1812 | (score (or (nth 1 kill) |
| 1784 | (eq type 'Regexp) (eq type 'String)))) | 1813 | gnus-score-interactive-default-score)) |
| 1785 | (search-func | 1814 | (date (nth 2 kill)) |
| 1786 | (cond ((or (eq type 'r) (eq type 'R) | 1815 | (found nil) |
| 1787 | (eq type 'regexp) (eq type 'Regexp)) | 1816 | (case-fold-search |
| 1788 | 're-search-forward) | 1817 | (not (or (eq type 'R) (eq type 'S) |
| 1789 | ((or (eq type 's) (eq type 'S) | 1818 | (eq type 'Regexp) (eq type 'String)))) |
| 1790 | (eq type 'string) (eq type 'String)) | 1819 | (search-func |
| 1791 | 'search-forward) | 1820 | (cond ((or (eq type 'r) (eq type 'R) |
| 1792 | (t | 1821 | (eq type 'regexp) (eq type 'Regexp)) |
| 1793 | (error "Invalid match type: %s" type))))) | 1822 | 're-search-forward) |
| 1794 | (goto-char (point-min)) | 1823 | ((or (eq type 's) (eq type 'S) |
| 1795 | (when (funcall search-func match nil t) | 1824 | (eq type 'string) (eq type 'String)) |
| 1796 | ;; Found a match, update scores. | 1825 | 'search-forward) |
| 1797 | (setcdr (car articles) (+ score (cdar articles))) | 1826 | (t |
| 1798 | (setq found t) | 1827 | (error "Invalid match type: %s" type))))) |
| 1799 | (when trace | 1828 | (goto-char (point-min)) |
| 1800 | (push | 1829 | (when (funcall search-func match nil t) |
| 1801 | (cons (car-safe (rassq alist gnus-score-cache)) | 1830 | ;; Found a match, update scores. |
| 1802 | kill) | 1831 | (setcdr (car articles) (+ score (cdar articles))) |
| 1803 | gnus-score-trace))) | 1832 | (setq found t) |
| 1804 | ;; Update expire date | 1833 | (when trace |
| 1805 | (unless trace | 1834 | (push |
| 1806 | (cond | 1835 | (cons (car-safe (rassq alist gnus-score-cache)) |
| 1807 | ((null date)) ;Permanent entry. | 1836 | kill) |
| 1808 | ((and found gnus-update-score-entry-dates) | 1837 | gnus-score-trace))) |
| 1809 | ;; Match, update date. | 1838 | ;; Update expire date |
| 1810 | (gnus-score-set 'touched '(t) alist) | 1839 | (unless trace |
| 1811 | (setcar (nthcdr 2 kill) now)) | 1840 | (cond |
| 1812 | ((and expire (< date expire)) ;Old entry, remove. | 1841 | ((null date)) ;Permanent entry. |
| 1813 | (gnus-score-set 'touched '(t) alist) | 1842 | ((and found gnus-update-score-entry-dates) |
| 1814 | (setcdr entries (cdr rest)) | 1843 | ;; Match, update date. |
| 1815 | (setq rest entries)))) | 1844 | (gnus-score-set 'touched '(t) alist) |
| 1816 | (setq entries rest))))) | 1845 | (setcar (nthcdr 2 kill) now)) |
| 1817 | (setq articles (cdr articles))))))) | 1846 | ((and expire (< date expire)) ;Old entry, remove. |
| 1818 | nil)) | 1847 | (gnus-score-set 'touched '(t) alist) |
| 1848 | (setcdr entries (cdr rest)) | ||
| 1849 | (setq rest entries)))) | ||
| 1850 | (setq entries rest)))) | ||
| 1851 | (when handles (mm-destroy-parts handles)))) | ||
| 1852 | (setq articles (cdr articles))))))) | ||
| 1853 | nil)) | ||
| 1819 | 1854 | ||
| 1820 | (defun gnus-score-thread (scores header now expire &optional trace) | 1855 | (defun gnus-score-thread (scores header now expire &optional trace) |
| 1821 | (gnus-score-followup scores header now expire trace t)) | 1856 | (gnus-score-followup scores header now expire trace t)) |
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el index 66509c939dc..f58cb80311a 100644 --- a/lisp/gnus/gnus-srvr.el +++ b/lisp/gnus/gnus-srvr.el | |||
| @@ -490,8 +490,7 @@ The following commands are available: | |||
| 490 | (error "No such server: %s" server)) | 490 | (error "No such server: %s" server)) |
| 491 | (gnus-server-set-status method 'ok) | 491 | (gnus-server-set-status method 'ok) |
| 492 | (prog1 | 492 | (prog1 |
| 493 | (or (gnus-open-server method) | 493 | (gnus-open-server method) |
| 494 | (progn (message "Couldn't open %s" server) nil)) | ||
| 495 | (gnus-server-update-server server) | 494 | (gnus-server-update-server server) |
| 496 | (gnus-server-position-point)))) | 495 | (gnus-server-position-point)))) |
| 497 | 496 | ||
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index 5862e7807a2..8fbde5c8ecc 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el | |||
| @@ -3824,12 +3824,28 @@ You should probably use `gnus-find-method-for-group' instead." | |||
| 3824 | "Go through PARAMETERS and expand them according to the match data." | 3824 | "Go through PARAMETERS and expand them according to the match data." |
| 3825 | (let (new) | 3825 | (let (new) |
| 3826 | (dolist (elem parameters) | 3826 | (dolist (elem parameters) |
| 3827 | (if (and (stringp (cdr elem)) | 3827 | (cond |
| 3828 | (string-match "\\\\[0-9&]" (cdr elem))) | 3828 | ((and (stringp (cdr elem)) |
| 3829 | (push (cons (car elem) | 3829 | (string-match "\\\\[0-9&]" (cdr elem))) |
| 3830 | (gnus-expand-group-parameter match (cdr elem) group)) | 3830 | (push (cons (car elem) |
| 3831 | new) | 3831 | (gnus-expand-group-parameter match (cdr elem) group)) |
| 3832 | (push elem new))) | 3832 | new)) |
| 3833 | ;; For `sieve' group parameters, perform substitutions for every | ||
| 3834 | ;; string within the match rule. This allows for parameters such | ||
| 3835 | ;; as: | ||
| 3836 | ;; ("list\\.\\(.*\\)" | ||
| 3837 | ;; (sieve header :is "list-id" "<\\1.domain.org>")) | ||
| 3838 | ((eq 'sieve (car elem)) | ||
| 3839 | (push (mapcar (lambda (sieve-elem) | ||
| 3840 | (if (and (stringp sieve-elem) | ||
| 3841 | (string-match "\\\\[0-9&]" sieve-elem)) | ||
| 3842 | (gnus-expand-group-parameter match sieve-elem | ||
| 3843 | group) | ||
| 3844 | sieve-elem)) | ||
| 3845 | (cdr elem)) | ||
| 3846 | new)) | ||
| 3847 | (t | ||
| 3848 | (push elem new)))) | ||
| 3833 | new)) | 3849 | new)) |
| 3834 | 3850 | ||
| 3835 | (defun gnus-group-fast-parameter (group symbol &optional allow-list) | 3851 | (defun gnus-group-fast-parameter (group symbol &optional allow-list) |
| @@ -3861,9 +3877,20 @@ The function `gnus-group-find-parameter' will do that for you." | |||
| 3861 | (when this-result | 3877 | (when this-result |
| 3862 | (setq result (car this-result)) | 3878 | (setq result (car this-result)) |
| 3863 | ;; Expand if necessary. | 3879 | ;; Expand if necessary. |
| 3864 | (if (and (stringp result) (string-match "\\\\[0-9&]" result)) | 3880 | (cond |
| 3865 | (setq result (gnus-expand-group-parameter | 3881 | ((and (stringp result) (string-match "\\\\[0-9&]" result)) |
| 3866 | (car head) result group))))))) | 3882 | (setq result (gnus-expand-group-parameter |
| 3883 | (car head) result group))) | ||
| 3884 | ;; For `sieve' group parameters, perform substitutions | ||
| 3885 | ;; for every string within the match rule (see above). | ||
| 3886 | ((eq symbol 'sieve) | ||
| 3887 | (setq result | ||
| 3888 | (mapcar (lambda (elem) | ||
| 3889 | (if (stringp elem) | ||
| 3890 | (gnus-expand-group-parameter (car head) | ||
| 3891 | elem group) | ||
| 3892 | elem)) | ||
| 3893 | result)))))))) | ||
| 3867 | ;; Done. | 3894 | ;; Done. |
| 3868 | result)))) | 3895 | result)))) |
| 3869 | 3896 | ||
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 18088423eb0..42911ce0648 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el | |||
| @@ -3292,11 +3292,33 @@ or in the synonym headers, defined by `message-header-synonyms'." | |||
| 3292 | (defun message-insert-newsgroups () | 3292 | (defun message-insert-newsgroups () |
| 3293 | "Insert the Newsgroups header from the article being replied to." | 3293 | "Insert the Newsgroups header from the article being replied to." |
| 3294 | (interactive) | 3294 | (interactive) |
| 3295 | (when (and (message-position-on-field "Newsgroups") | 3295 | (let ((old-newsgroups (mail-fetch-field "newsgroups")) |
| 3296 | (mail-fetch-field "newsgroups") | 3296 | (new-newsgroups (message-fetch-reply-field "newsgroups")) |
| 3297 | (not (string-match "\\` *\\'" (mail-fetch-field "newsgroups")))) | 3297 | (first t) |
| 3298 | (insert ",")) | 3298 | insert-newsgroups) |
| 3299 | (insert (or (message-fetch-reply-field "newsgroups") ""))) | 3299 | (message-position-on-field "Newsgroups") |
| 3300 | (cond | ||
| 3301 | ((not new-newsgroups) | ||
| 3302 | (error "No Newsgroups to insert")) | ||
| 3303 | ((not old-newsgroups) | ||
| 3304 | (insert new-newsgroups)) | ||
| 3305 | (t | ||
| 3306 | (setq new-newsgroups (split-string new-newsgroups "[, ]+") | ||
| 3307 | old-newsgroups (split-string old-newsgroups "[, ]+")) | ||
| 3308 | (dolist (group new-newsgroups) | ||
| 3309 | (unless (member group old-newsgroups) | ||
| 3310 | (push group insert-newsgroups))) | ||
| 3311 | (if (null insert-newsgroups) | ||
| 3312 | (error "Newgroup%s already in the header" | ||
| 3313 | (if (> (length new-newsgroups) 1) | ||
| 3314 | "s" "")) | ||
| 3315 | (when old-newsgroups | ||
| 3316 | (setq first nil)) | ||
| 3317 | (dolist (group insert-newsgroups) | ||
| 3318 | (unless first | ||
| 3319 | (insert ",")) | ||
| 3320 | (setq first nil) | ||
| 3321 | (insert group))))))) | ||
| 3300 | 3322 | ||
| 3301 | 3323 | ||
| 3302 | 3324 | ||
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el index 7139a528e11..caf28202f04 100644 --- a/lisp/gnus/nnmaildir.el +++ b/lisp/gnus/nnmaildir.el | |||
| @@ -77,6 +77,66 @@ | |||
| 77 | 77 | ||
| 78 | (defconst nnmaildir-version "Gnus") | 78 | (defconst nnmaildir-version "Gnus") |
| 79 | 79 | ||
| 80 | (defconst nnmaildir-flag-mark-mapping | ||
| 81 | '((?F . tick) | ||
| 82 | (?R . reply) | ||
| 83 | (?S . read)) | ||
| 84 | "Alist mapping Maildir filename flags to Gnus marks. | ||
| 85 | Maildir filenames are of the form \"unique-id:2,FLAGS\", | ||
| 86 | where FLAGS are a string of characters in ASCII order. | ||
| 87 | Some of the FLAGS correspond to Gnus marks.") | ||
| 88 | |||
| 89 | (defsubst nnmaildir--mark-to-flag (mark) | ||
| 90 | "Find the Maildir flag that corresponds to MARK (an atom). | ||
| 91 | Return a character, or `nil' if not found. | ||
| 92 | See `nnmaildir-flag-mark-mapping'." | ||
| 93 | (car (rassq mark nnmaildir-flag-mark-mapping))) | ||
| 94 | |||
| 95 | (defsubst nnmaildir--flag-to-mark (flag) | ||
| 96 | "Find the Gnus mark that corresponds to FLAG (a character). | ||
| 97 | Return an atom, or `nil' if not found. | ||
| 98 | See `nnmaildir-flag-mark-mapping'." | ||
| 99 | (cdr (assq flag nnmaildir-flag-mark-mapping))) | ||
| 100 | |||
| 101 | (defun nnmaildir--ensure-suffix (filename) | ||
| 102 | "Ensure that FILENAME contains the suffix \":2,\"." | ||
| 103 | (if (string-match-p ":2," filename) | ||
| 104 | filename | ||
| 105 | (concat filename ":2,"))) | ||
| 106 | |||
| 107 | (defun nnmaildir--add-flag (flag suffix) | ||
| 108 | "Return a copy of SUFFIX where FLAG is set. | ||
| 109 | SUFFIX should start with \":2,\"." | ||
| 110 | (unless (string-match-p "^:2," suffix) | ||
| 111 | (error "Invalid suffix `%s'" suffix)) | ||
| 112 | (let* ((flags (substring suffix 3)) | ||
| 113 | (flags-as-list (append flags nil)) | ||
| 114 | (new-flags | ||
| 115 | (concat (gnus-delete-duplicates | ||
| 116 | ;; maildir flags must be sorted | ||
| 117 | (sort (cons flag flags-as-list) '<))))) | ||
| 118 | (concat ":2," new-flags))) | ||
| 119 | |||
| 120 | (defun nnmaildir--remove-flag (flag suffix) | ||
| 121 | "Return a copy of SUFFIX where FLAG is cleared. | ||
| 122 | SUFFIX should start with \":2,\"." | ||
| 123 | (unless (string-match-p "^:2," suffix) | ||
| 124 | (error "Invalid suffix `%s'" suffix)) | ||
| 125 | (let* ((flags (substring suffix 3)) | ||
| 126 | (flags-as-list (append flags nil)) | ||
| 127 | (new-flags (concat (delq flag flags-as-list)))) | ||
| 128 | (concat ":2," new-flags))) | ||
| 129 | |||
| 130 | (defun nnmaildir--article-set-flags (article new-suffix curdir) | ||
| 131 | (let* ((prefix (nnmaildir--art-prefix article)) | ||
| 132 | (suffix (nnmaildir--art-suffix article)) | ||
| 133 | (article-file (concat curdir prefix suffix)) | ||
| 134 | (new-name (concat curdir prefix new-suffix))) | ||
| 135 | (unless (file-exists-p article-file) | ||
| 136 | (error "Couldn't find article file %s" article-file)) | ||
| 137 | (rename-file article-file new-name 'replace) | ||
| 138 | (setf (nnmaildir--art-suffix article) new-suffix))) | ||
| 139 | |||
| 80 | (defvar nnmaildir-article-file-name nil | 140 | (defvar nnmaildir-article-file-name nil |
| 81 | "*The filename of the most recently requested article. This variable is set | 141 | "*The filename of the most recently requested article. This variable is set |
| 82 | by nnmaildir-request-article.") | 142 | by nnmaildir-request-article.") |
| @@ -208,29 +268,33 @@ by nnmaildir-request-article.") | |||
| 208 | (eval param)) | 268 | (eval param)) |
| 209 | 269 | ||
| 210 | (defmacro nnmaildir--with-nntp-buffer (&rest body) | 270 | (defmacro nnmaildir--with-nntp-buffer (&rest body) |
| 271 | (declare (debug (body))) | ||
| 211 | `(with-current-buffer nntp-server-buffer | 272 | `(with-current-buffer nntp-server-buffer |
| 212 | ,@body)) | 273 | ,@body)) |
| 213 | (defmacro nnmaildir--with-work-buffer (&rest body) | 274 | (defmacro nnmaildir--with-work-buffer (&rest body) |
| 275 | (declare (debug (body))) | ||
| 214 | `(with-current-buffer (get-buffer-create " *nnmaildir work*") | 276 | `(with-current-buffer (get-buffer-create " *nnmaildir work*") |
| 215 | ,@body)) | 277 | ,@body)) |
| 216 | (defmacro nnmaildir--with-nov-buffer (&rest body) | 278 | (defmacro nnmaildir--with-nov-buffer (&rest body) |
| 279 | (declare (debug (body))) | ||
| 217 | `(with-current-buffer (get-buffer-create " *nnmaildir nov*") | 280 | `(with-current-buffer (get-buffer-create " *nnmaildir nov*") |
| 218 | ,@body)) | 281 | ,@body)) |
| 219 | (defmacro nnmaildir--with-move-buffer (&rest body) | 282 | (defmacro nnmaildir--with-move-buffer (&rest body) |
| 283 | (declare (debug (body))) | ||
| 220 | `(with-current-buffer (get-buffer-create " *nnmaildir move*") | 284 | `(with-current-buffer (get-buffer-create " *nnmaildir move*") |
| 221 | ,@body)) | 285 | ,@body)) |
| 222 | 286 | ||
| 223 | (defmacro nnmaildir--subdir (dir subdir) | 287 | (defsubst nnmaildir--subdir (dir subdir) |
| 224 | `(file-name-as-directory (concat ,dir ,subdir))) | 288 | (file-name-as-directory (concat dir subdir))) |
| 225 | (defmacro nnmaildir--srvgrp-dir (srv-dir gname) | 289 | (defsubst nnmaildir--srvgrp-dir (srv-dir gname) |
| 226 | `(nnmaildir--subdir ,srv-dir ,gname)) | 290 | (nnmaildir--subdir srv-dir gname)) |
| 227 | (defmacro nnmaildir--tmp (dir) `(nnmaildir--subdir ,dir "tmp")) | 291 | (defsubst nnmaildir--tmp (dir) (nnmaildir--subdir dir "tmp")) |
| 228 | (defmacro nnmaildir--new (dir) `(nnmaildir--subdir ,dir "new")) | 292 | (defsubst nnmaildir--new (dir) (nnmaildir--subdir dir "new")) |
| 229 | (defmacro nnmaildir--cur (dir) `(nnmaildir--subdir ,dir "cur")) | 293 | (defsubst nnmaildir--cur (dir) (nnmaildir--subdir dir "cur")) |
| 230 | (defmacro nnmaildir--nndir (dir) `(nnmaildir--subdir ,dir ".nnmaildir")) | 294 | (defsubst nnmaildir--nndir (dir) (nnmaildir--subdir dir ".nnmaildir")) |
| 231 | (defmacro nnmaildir--nov-dir (dir) `(nnmaildir--subdir ,dir "nov")) | 295 | (defsubst nnmaildir--nov-dir (dir) (nnmaildir--subdir dir "nov")) |
| 232 | (defmacro nnmaildir--marks-dir (dir) `(nnmaildir--subdir ,dir "marks")) | 296 | (defsubst nnmaildir--marks-dir (dir) (nnmaildir--subdir dir "marks")) |
| 233 | (defmacro nnmaildir--num-dir (dir) `(nnmaildir--subdir ,dir "num")) | 297 | (defsubst nnmaildir--num-dir (dir) (nnmaildir--subdir dir "num")) |
| 234 | 298 | ||
| 235 | (defmacro nnmaildir--unlink (file-arg) | 299 | (defmacro nnmaildir--unlink (file-arg) |
| 236 | `(let ((file ,file-arg)) | 300 | `(let ((file ,file-arg)) |
| @@ -305,6 +369,7 @@ by nnmaildir-request-article.") | |||
| 305 | string) | 369 | string) |
| 306 | 370 | ||
| 307 | (defmacro nnmaildir--condcase (errsym body &rest handler) | 371 | (defmacro nnmaildir--condcase (errsym body &rest handler) |
| 372 | (declare (debug (sexp form body))) | ||
| 308 | `(condition-case ,errsym | 373 | `(condition-case ,errsym |
| 309 | (let ((system-messages-locale "C")) ,body) | 374 | (let ((system-messages-locale "C")) ,body) |
| 310 | (error . ,handler))) | 375 | (error . ,handler))) |
| @@ -759,7 +824,7 @@ by nnmaildir-request-article.") | |||
| 759 | (dolist (file (funcall ls ndir nil "\\`[^.]" 'nosort)) | 824 | (dolist (file (funcall ls ndir nil "\\`[^.]" 'nosort)) |
| 760 | (setq x (concat ndir file)) | 825 | (setq x (concat ndir file)) |
| 761 | (and (time-less-p (nth 5 (file-attributes x)) (current-time)) | 826 | (and (time-less-p (nth 5 (file-attributes x)) (current-time)) |
| 762 | (rename-file x (concat cdir file ":2,")))) | 827 | (rename-file x (concat cdir (nnmaildir--ensure-suffix file))))) |
| 763 | (setf (nnmaildir--grp-new group) nattr)) | 828 | (setf (nnmaildir--grp-new group) nattr)) |
| 764 | (setq cattr (nth 5 (file-attributes cdir))) | 829 | (setq cattr (nth 5 (file-attributes cdir))) |
| 765 | (if (equal cattr (nnmaildir--grp-cur group)) | 830 | (if (equal cattr (nnmaildir--grp-cur group)) |
| @@ -784,11 +849,23 @@ by nnmaildir-request-article.") | |||
| 784 | cdir (nnmaildir--marks-dir nndir) | 849 | cdir (nnmaildir--marks-dir nndir) |
| 785 | ndir (nnmaildir--subdir cdir "tick") | 850 | ndir (nnmaildir--subdir cdir "tick") |
| 786 | cdir (nnmaildir--subdir cdir "read")) | 851 | cdir (nnmaildir--subdir cdir "read")) |
| 787 | (dolist (file files) | 852 | (dolist (prefix-suffix files) |
| 788 | (setq file (car file)) | 853 | (let ((prefix (car prefix-suffix)) |
| 789 | (if (or (not (file-exists-p (concat cdir file))) | 854 | (suffix (cdr prefix-suffix))) |
| 790 | (file-exists-p (concat ndir file))) | 855 | ;; increase num for each unread or ticked article |
| 791 | (setq num (1+ num))))) | 856 | (when (or |
| 857 | ;; first look for marks in suffix, if it's valid... | ||
| 858 | (when (and (stringp suffix) | ||
| 859 | (string-prefix-p ":2," suffix)) | ||
| 860 | (or | ||
| 861 | (not (string-match-p | ||
| 862 | (string (nnmaildir--mark-to-flag 'read)) suffix)) | ||
| 863 | (string-match-p | ||
| 864 | (string (nnmaildir--mark-to-flag 'tick)) suffix))) | ||
| 865 | ;; then look in marks directories | ||
| 866 | (not (file-exists-p (concat cdir prefix))) | ||
| 867 | (file-exists-p (concat ndir prefix))) | ||
| 868 | (incf num))))) | ||
| 792 | (setf (nnmaildir--grp-cache group) (make-vector num nil)) | 869 | (setf (nnmaildir--grp-cache group) (make-vector num nil)) |
| 793 | (let ((inhibit-quit t)) | 870 | (let ((inhibit-quit t)) |
| 794 | (set (intern gname groups) group)) | 871 | (set (intern gname groups) group)) |
| @@ -916,12 +993,15 @@ by nnmaildir-request-article.") | |||
| 916 | "\n"))))) | 993 | "\n"))))) |
| 917 | 'group) | 994 | 'group) |
| 918 | 995 | ||
| 919 | (defun nnmaildir-request-marks (gname info &optional server) | 996 | (defun nnmaildir-request-update-info (gname info &optional server) |
| 920 | (let ((group (nnmaildir--prepare server gname)) | 997 | (let* ((group (nnmaildir--prepare server gname)) |
| 921 | pgname flist always-marks never-marks old-marks dotfile num dir | 998 | (curdir (nnmaildir--cur |
| 922 | markdirs marks mark ranges markdir article read end new-marks ls | 999 | (nnmaildir--srvgrp-dir |
| 923 | old-mmth new-mmth mtime mark-sym existing missing deactivate-mark | 1000 | (nnmaildir--srv-dir nnmaildir--cur-server) gname))) |
| 924 | article-list) | 1001 | (curdir-mtime (nth 5 (file-attributes curdir))) |
| 1002 | pgname flist always-marks never-marks old-marks dotfile num dir | ||
| 1003 | all-marks marks mark ranges markdir read end new-marks ls | ||
| 1004 | old-mmth new-mmth mtime mark-sym existing missing deactivate-mark) | ||
| 925 | (catch 'return | 1005 | (catch 'return |
| 926 | (unless group | 1006 | (unless group |
| 927 | (setf (nnmaildir--srv-error nnmaildir--cur-server) | 1007 | (setf (nnmaildir--srv-error nnmaildir--cur-server) |
| @@ -950,34 +1030,71 @@ by nnmaildir-request-article.") | |||
| 950 | dir (nnmaildir--nndir dir) | 1030 | dir (nnmaildir--nndir dir) |
| 951 | dir (nnmaildir--marks-dir dir) | 1031 | dir (nnmaildir--marks-dir dir) |
| 952 | ls (nnmaildir--group-ls nnmaildir--cur-server pgname) | 1032 | ls (nnmaildir--group-ls nnmaildir--cur-server pgname) |
| 953 | markdirs (funcall ls dir nil "\\`[^.]" 'nosort) | 1033 | all-marks (gnus-delete-duplicates |
| 954 | new-mmth (nnmaildir--up2-1 (length markdirs)) | 1034 | ;; get mark names from mark dirs and from flag |
| 1035 | ;; mappings | ||
| 1036 | (append | ||
| 1037 | (mapcar 'cdr nnmaildir-flag-mark-mapping) | ||
| 1038 | (mapcar 'intern (funcall ls dir nil "\\`[^.]" 'nosort)))) | ||
| 1039 | new-mmth (nnmaildir--up2-1 (length all-marks)) | ||
| 955 | new-mmth (make-vector new-mmth 0) | 1040 | new-mmth (make-vector new-mmth 0) |
| 956 | old-mmth (nnmaildir--grp-mmth group)) | 1041 | old-mmth (nnmaildir--grp-mmth group)) |
| 957 | (dolist (mark markdirs) | 1042 | (dolist (mark all-marks) |
| 958 | (setq markdir (nnmaildir--subdir dir mark) | 1043 | (setq markdir (nnmaildir--subdir dir (symbol-name mark)) |
| 959 | mark-sym (intern mark) | ||
| 960 | ranges nil) | 1044 | ranges nil) |
| 961 | (catch 'got-ranges | 1045 | (catch 'got-ranges |
| 962 | (if (memq mark-sym never-marks) (throw 'got-ranges nil)) | 1046 | (if (memq mark never-marks) (throw 'got-ranges nil)) |
| 963 | (when (memq mark-sym always-marks) | 1047 | (when (memq mark always-marks) |
| 964 | (setq ranges existing) | 1048 | (setq ranges existing) |
| 965 | (throw 'got-ranges nil)) | 1049 | (throw 'got-ranges nil)) |
| 966 | (setq mtime (nth 5 (file-attributes markdir))) | 1050 | ;; Find the mtime for this mark. If this mark can be expressed as |
| 967 | (set (intern mark new-mmth) mtime) | 1051 | ;; a filename flag, get the later of the mtimes for markdir and |
| 968 | (when (equal mtime (symbol-value (intern-soft mark old-mmth))) | 1052 | ;; curdir, otherwise only the markdir counts. |
| 969 | (setq ranges (assq mark-sym old-marks)) | 1053 | (setq mtime |
| 1054 | (let ((markdir-mtime (nth 5 (file-attributes markdir)))) | ||
| 1055 | (cond | ||
| 1056 | ((null (nnmaildir--mark-to-flag mark)) | ||
| 1057 | markdir-mtime) | ||
| 1058 | ((null markdir-mtime) | ||
| 1059 | curdir-mtime) | ||
| 1060 | ((null curdir-mtime) | ||
| 1061 | ;; this should never happen... | ||
| 1062 | markdir-mtime) | ||
| 1063 | ((time-less-p markdir-mtime curdir-mtime) | ||
| 1064 | curdir-mtime) | ||
| 1065 | (t | ||
| 1066 | markdir-mtime)))) | ||
| 1067 | (set (intern (symbol-name mark) new-mmth) mtime) | ||
| 1068 | (when (equal mtime (symbol-value (intern-soft (symbol-name mark) old-mmth))) | ||
| 1069 | (setq ranges (assq mark old-marks)) | ||
| 970 | (if ranges (setq ranges (cdr ranges))) | 1070 | (if ranges (setq ranges (cdr ranges))) |
| 971 | (throw 'got-ranges nil)) | 1071 | (throw 'got-ranges nil)) |
| 972 | (setq article-list nil) | 1072 | (let ((article-list nil)) |
| 973 | (dolist (prefix (funcall ls markdir nil "\\`[^.]" 'nosort)) | 1073 | ;; Consider the article marked if it either has the flag in the |
| 974 | (setq article (nnmaildir--flist-art flist prefix)) | 1074 | ;; filename, or is in the markdir. As you'd rarely remove a |
| 975 | (if article | 1075 | ;; flag/mark, this should avoid losing information in the most |
| 976 | (setq article-list | 1076 | ;; common usage pattern. |
| 977 | (cons (nnmaildir--art-num article) article-list)))) | 1077 | (or |
| 978 | (setq ranges (gnus-add-to-range ranges (sort article-list '<)))) | 1078 | (let ((flag (nnmaildir--mark-to-flag mark))) |
| 979 | (if (eq mark-sym 'read) (setq read ranges) | 1079 | ;; If this mark has a corresponding maildir flag... |
| 980 | (if ranges (setq marks (cons (cons mark-sym ranges) marks))))) | 1080 | (when flag |
| 1081 | (let ((regexp | ||
| 1082 | (concat "\\`[^.].*:2,[A-Z]*" (string flag)))) | ||
| 1083 | ;; ...then find all files with that flag. | ||
| 1084 | (dolist (filename (funcall ls curdir nil regexp 'nosort)) | ||
| 1085 | (let* ((prefix (car (split-string filename ":2,"))) | ||
| 1086 | (article (nnmaildir--flist-art flist prefix))) | ||
| 1087 | (when article | ||
| 1088 | (push (nnmaildir--art-num article) article-list))))))) | ||
| 1089 | ;; Also check Gnus-specific mark directory, if it exists. | ||
| 1090 | (when (file-directory-p markdir) | ||
| 1091 | (dolist (prefix (funcall ls markdir nil "\\`[^.]" 'nosort)) | ||
| 1092 | (let ((article (nnmaildir--flist-art flist prefix))) | ||
| 1093 | (when article | ||
| 1094 | (push (nnmaildir--art-num article) article-list)))))) | ||
| 1095 | (setq ranges (gnus-add-to-range ranges (sort article-list '<))))) | ||
| 1096 | (if (eq mark 'read) (setq read ranges) | ||
| 1097 | (if ranges (setq marks (cons (cons mark ranges) marks))))) | ||
| 981 | (gnus-info-set-read info (gnus-range-add read missing)) | 1098 | (gnus-info-set-read info (gnus-range-add read missing)) |
| 982 | (gnus-info-set-marks info marks 'extend) | 1099 | (gnus-info-set-marks info marks 'extend) |
| 983 | (setf (nnmaildir--grp-mmth group) new-mmth) | 1100 | (setf (nnmaildir--grp-mmth group) new-mmth) |
| @@ -1525,39 +1642,63 @@ by nnmaildir-request-article.") | |||
| 1525 | didnt))) | 1642 | didnt))) |
| 1526 | 1643 | ||
| 1527 | (defun nnmaildir-request-set-mark (gname actions &optional server) | 1644 | (defun nnmaildir-request-set-mark (gname actions &optional server) |
| 1528 | (let ((group (nnmaildir--prepare server gname)) | 1645 | (let* ((group (nnmaildir--prepare server gname)) |
| 1529 | (coding-system-for-write nnheader-file-coding-system) | 1646 | (curdir (nnmaildir--cur |
| 1530 | (buffer-file-coding-system nil) | 1647 | (nnmaildir--srvgrp-dir |
| 1531 | (file-coding-system-alist nil) | 1648 | (nnmaildir--srv-dir nnmaildir--cur-server) |
| 1532 | del-mark del-action add-action set-action marksdir nlist | 1649 | gname))) |
| 1533 | ranges begin end article all-marks todo-marks mdir mfile | 1650 | (coding-system-for-write nnheader-file-coding-system) |
| 1534 | pgname ls permarkfile deactivate-mark) | 1651 | (buffer-file-coding-system nil) |
| 1652 | (file-coding-system-alist nil) | ||
| 1653 | del-mark del-action add-action set-action marksdir nlist | ||
| 1654 | ranges begin end article all-marks todo-marks mdir mfile | ||
| 1655 | pgname ls permarkfile deactivate-mark) | ||
| 1535 | (setq del-mark | 1656 | (setq del-mark |
| 1536 | (lambda (mark) | 1657 | (lambda (mark) |
| 1537 | (setq mfile (nnmaildir--subdir marksdir (symbol-name mark)) | 1658 | (let ((prefix (nnmaildir--art-prefix article)) |
| 1538 | mfile (concat mfile (nnmaildir--art-prefix article))) | 1659 | (suffix (nnmaildir--art-suffix article)) |
| 1539 | (nnmaildir--unlink mfile)) | 1660 | (flag (nnmaildir--mark-to-flag mark))) |
| 1661 | (when flag | ||
| 1662 | ;; If this mark corresponds to a flag, remove the flag from | ||
| 1663 | ;; the file name. | ||
| 1664 | (nnmaildir--article-set-flags | ||
| 1665 | article (nnmaildir--remove-flag flag suffix) curdir)) | ||
| 1666 | ;; We still want to delete the hardlink in the marks dir if | ||
| 1667 | ;; present, regardless of whether this mark has a maildir flag or | ||
| 1668 | ;; not, to avoid getting out of sync. | ||
| 1669 | (setq mfile (nnmaildir--subdir marksdir (symbol-name mark)) | ||
| 1670 | mfile (concat mfile prefix)) | ||
| 1671 | (nnmaildir--unlink mfile))) | ||
| 1540 | del-action (lambda (article) (mapcar del-mark todo-marks)) | 1672 | del-action (lambda (article) (mapcar del-mark todo-marks)) |
| 1541 | add-action | 1673 | add-action |
| 1542 | (lambda (article) | 1674 | (lambda (article) |
| 1543 | (mapcar | 1675 | (mapcar |
| 1544 | (lambda (mark) | 1676 | (lambda (mark) |
| 1545 | (setq mdir (nnmaildir--subdir marksdir (symbol-name mark)) | 1677 | (let ((prefix (nnmaildir--art-prefix article)) |
| 1546 | permarkfile (concat mdir ":") | 1678 | (suffix (nnmaildir--art-suffix article)) |
| 1547 | mfile (concat mdir (nnmaildir--art-prefix article))) | 1679 | (flag (nnmaildir--mark-to-flag mark))) |
| 1548 | (nnmaildir--condcase err (add-name-to-file permarkfile mfile) | 1680 | (if flag |
| 1549 | (cond | 1681 | ;; If there is a corresponding maildir flag, just rename |
| 1550 | ((nnmaildir--eexist-p err)) | 1682 | ;; the file. |
| 1551 | ((nnmaildir--enoent-p err) | 1683 | (nnmaildir--article-set-flags |
| 1552 | (nnmaildir--mkdir mdir) | 1684 | article (nnmaildir--add-flag flag suffix) curdir) |
| 1553 | (nnmaildir--mkfile permarkfile) | 1685 | ;; Otherwise, use nnmaildir-specific marks dir. |
| 1554 | (add-name-to-file permarkfile mfile)) | 1686 | (setq mdir (nnmaildir--subdir marksdir (symbol-name mark)) |
| 1555 | ((nnmaildir--emlink-p err) | 1687 | permarkfile (concat mdir ":") |
| 1556 | (let ((permarkfilenew (concat permarkfile "{new}"))) | 1688 | mfile (concat mdir prefix)) |
| 1557 | (nnmaildir--mkfile permarkfilenew) | 1689 | (nnmaildir--condcase err (add-name-to-file permarkfile mfile) |
| 1558 | (rename-file permarkfilenew permarkfile 'replace) | 1690 | (cond |
| 1559 | (add-name-to-file permarkfile mfile))) | 1691 | ((nnmaildir--eexist-p err)) |
| 1560 | (t (signal (car err) (cdr err)))))) | 1692 | ((nnmaildir--enoent-p err) |
| 1693 | (nnmaildir--mkdir mdir) | ||
| 1694 | (nnmaildir--mkfile permarkfile) | ||
| 1695 | (add-name-to-file permarkfile mfile)) | ||
| 1696 | ((nnmaildir--emlink-p err) | ||
| 1697 | (let ((permarkfilenew (concat permarkfile "{new}"))) | ||
| 1698 | (nnmaildir--mkfile permarkfilenew) | ||
| 1699 | (rename-file permarkfilenew permarkfile 'replace) | ||
| 1700 | (add-name-to-file permarkfile mfile))) | ||
| 1701 | (t (signal (car err) (cdr err)))))))) | ||
| 1561 | todo-marks)) | 1702 | todo-marks)) |
| 1562 | set-action (lambda (article) | 1703 | set-action (lambda (article) |
| 1563 | (funcall add-action article) | 1704 | (funcall add-action article) |
| @@ -1581,7 +1722,12 @@ by nnmaildir-request-article.") | |||
| 1581 | pgname (nnmaildir--pgname nnmaildir--cur-server gname) | 1722 | pgname (nnmaildir--pgname nnmaildir--cur-server gname) |
| 1582 | ls (nnmaildir--group-ls nnmaildir--cur-server pgname) | 1723 | ls (nnmaildir--group-ls nnmaildir--cur-server pgname) |
| 1583 | all-marks (funcall ls marksdir nil "\\`[^.]" 'nosort) | 1724 | all-marks (funcall ls marksdir nil "\\`[^.]" 'nosort) |
| 1584 | all-marks (mapcar 'intern all-marks)) | 1725 | all-marks (gnus-delete-duplicates |
| 1726 | ;; get mark names from mark dirs and from flag | ||
| 1727 | ;; mappings | ||
| 1728 | (append | ||
| 1729 | (mapcar 'cdr nnmaildir-flag-mark-mapping) | ||
| 1730 | (mapcar 'intern all-marks)))) | ||
| 1585 | (dolist (action actions) | 1731 | (dolist (action actions) |
| 1586 | (setq ranges (car action) | 1732 | (setq ranges (car action) |
| 1587 | todo-marks (caddr action)) | 1733 | todo-marks (caddr action)) |