commit 0695f5383f67ebbe606e63e5349db63cf650e7da (HEAD, refs/remotes/origin/master) Author: Lars Ingebrigtsen Date: Sun Sep 29 09:56:31 2019 +0200 Add new Gnus summary commands and keystrokes for "unseen" navigation * doc/misc/gnus.texi (Choosing Commands): Document them. * lisp/gnus/gnus-sum.el (gnus-summary-next-unseen-article) (gnus-summary-prev-unseen-article): New commands and keystrokes (bug#35213). diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 4c69c69292..8ab1cf9f68 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -5347,6 +5347,20 @@ Go to the next article (@code{gnus-summary-next-article}). @findex gnus-summary-prev-article Go to the previous article (@code{gnus-summary-prev-article}). +@item G u +@itemx ] +@kindex ] @r{(Summary)} +@kindex G u @r{(Summary)} +@findex gnus-summary-next-unseen-article +Go to the next unseen article (@code{gnus-summary-next-unseen-article}). + +@item G U +@itemx [ +@kindex [ @r{(Summary)} +@kindex G U @r{(Summary)} +@findex gnus-summary-prev-unseen-article +Go to the previous unseen article (@code{gnus-summary-prev-unseen-article}). + @item G C-n @kindex G C-n @r{(Summary)} @findex gnus-summary-next-same-subject diff --git a/etc/NEWS b/etc/NEWS index 3d8480cb46..f858c95831 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1046,6 +1046,13 @@ Of course it will still find it if you have it in '~/.ecompleterc'. ** Gnus ++++ +*** Two new Gnus summary mode navigation commands have been added, +bound to the '[' and ']' keys: `gnus-summary-prev-unseen-article' and +`gnus-summary-next-unseen-article'. These take you (respectively) to +the previous unseen or next unseen article. (These are the ones that +are marked with "." in the summary mode lines.) + +++ *** The Gnus user variable 'nnimap-expunge' supports three new values: 'never' for never expunging messages, 'immediately' for immediately diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 20f338eda1..b5d744843f 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -1911,6 +1911,8 @@ increase the score of each group you read." "\M-p" gnus-summary-prev-unread-subject "." gnus-summary-first-unread-article "," gnus-summary-best-unread-article + "[" gnus-summary-prev-unseen-article + "]" gnus-summary-next-unseen-article "\M-s" gnus-summary-search-article-forward "\M-r" gnus-summary-search-article-backward "\M-S" gnus-summary-repeat-search-article-forward @@ -2088,6 +2090,8 @@ increase the score of each group you read." "\M-p" gnus-summary-prev-unread-subject "f" gnus-summary-first-unread-article "b" gnus-summary-best-unread-article + "u" gnus-summary-next-unseen-article + "U" gnus-summary-prev-unseen-article "j" gnus-summary-goto-article "g" gnus-summary-goto-subject "l" gnus-summary-goto-last-article @@ -2796,6 +2800,8 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs)))) ["Previous article same subject" gnus-summary-prev-same-subject t] ["First unread article" gnus-summary-first-unread-article t] ["Best unread article" gnus-summary-best-unread-article t] + ["Next unseen article" gnus-summary-next-unseen-article t] + ["Prev unseen article" gnus-summary-prev-unseen-article t] ["Go to subject number..." gnus-summary-goto-subject t] ["Go to article number..." gnus-summary-goto-article t] ["Go to the last article" gnus-summary-goto-last-article t] @@ -3175,6 +3181,9 @@ The following commands are available: (:type list)) number mark pos header level) +(defun gnus-data-unseen-p (data) + (memq (gnus-data-number data) gnus-newsgroup-unseen)) + (define-inline gnus-data-unread-p (data) (inline-quote (= (gnus-data-mark ,data) gnus-unread-mark))) @@ -8119,6 +8128,32 @@ Return nil if there are no unread articles." (gnus-summary-first-subject t)) (gnus-summary-position-point))) +(defun gnus-summary-next-unseen-article (&optional backward) + "Select the next unseen article." + (interactive) + (let* ((article (gnus-summary-article-number)) + (articles (gnus-data-find-list article (gnus-data-list backward)))) + (when (or (not gnus-summary-check-current) + (not (gnus-data-unseen-p (car articles))) + (not (gnus-data-unread-p (car articles)))) + (setq articles (cdr articles))) + (while (and articles + (or (not (gnus-data-unseen-p (car articles))) + (not (gnus-data-unread-p (car articles))))) + (setq articles (cdr articles))) + (if (not articles) + (if backward + (message "No previous unseen article") + (message "No next unseen article")) + (goto-char (gnus-data-pos (car articles))) + (gnus-summary-select-article) + (gnus-data-number (car articles))))) + +(defun gnus-summary-prev-unseen-article () + "Select the previous unseen article." + (interactive) + (gnus-summary-next-unseen-article t)) + (defun gnus-summary-first-unseen-subject () "Place the point on the subject line of the first unseen article. Return nil if there are no unseen articles." commit 82c79220f58caa8ee6b78c8704aa97191c2352c7 Author: Eli Zaretskii Date: Sun Sep 29 10:09:56 2019 +0300 Improve documentation of image conversion feature * lisp/image/image-converter.el (image-converter) (image-convert-p, image-convert): * lisp/image.el (convert-images-externally): * etc/NEWS: * doc/lispref/display.texi (Defining Images): Fix recently added documentation. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index ec288b1c47..a661eca13f 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6049,7 +6049,8 @@ If Emacs doesn't have native support for the image format in question, and @code{convert-images-externally} is non-@code{nil}, Emacs will try to determine whether there are external utilities that can be used to transform the image in question to @acronym{PNG} before displaying. -GraphicsMagick, ImageMagick and ffmpeg are currently supported. +GraphicsMagick, ImageMagick and @command{ffmpeg} are currently +supported for image conversions. The function returns @code{nil} if images of this type are not supported. Otherwise it returns an image descriptor. diff --git a/etc/NEWS b/etc/NEWS index 677b710e22..3d8480cb46 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2657,11 +2657,11 @@ data about creation times and orientation and the like. functions. *** New library image-converter. -To view exotic image formats that Emacs doesn't have native support -for, the new 'convert-images-externally' variable can be set to t. If -the system has GraphicsMagick, ImageMagick or ffmpeg installed, it -will be used to convert images automatically before displaying with -'create-image'. +If you need to view exotic image formats for which Emacs doesn't have +native support, customize the new variable 'convert-images-externally' +to t. If your system has GraphicsMagick, ImageMagick or 'ffmpeg' +installed, they will then be used to convert images automatically +before displaying them. *** 'image-mode' now uses this library to automatically rotate images according to the orientation in the Exif data, if any. diff --git a/lisp/image.el b/lisp/image.el index 3f953e65ae..07ffefcbc5 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -143,11 +143,11 @@ based on the font pixel size." (defcustom convert-images-externally nil "If non-nil, `create-image' will use external converters for exotic formats. -Emacs handles most of the common image formats (JPEG, PNG, GIF -and so on) internally, but images that doesn't have native -support in Emacs can still be displayed by Emacs if external -conversion programs (like ImageMagick \"convert\", GraphicsMagick -\"gm\" or \"ffmpeg\") are installed." +Emacs handles most of the common image formats (SVG, JPEG, PNG, GIF +and some others) internally, but images that don't have native +support in Emacs can still be displayed if an external conversion +program (like ImageMagick \"convert\", GraphicsMagick \"gm\" +or \"ffmpeg\") is installed." :type 'bool :version "27.1") diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el index f485c34842..25b49ff103 100644 --- a/lisp/image/image-converter.el +++ b/lisp/image/image-converter.el @@ -41,8 +41,11 @@ conversion programs (like ImageMagick \"convert\", GraphicsMagick :version "27.1") (defcustom image-converter nil - "What external converter to use. -`imagemagick', `graphicsmagick' and `ffmpeg' are supported." + "Type of the external image converter to use. +The value should a symbol, either `imagemagick', `graphicsmagick', +or `ffmpeg'. +If nil, Emacs will try to find one of the supported converters +installed on the system." :group 'image :type 'symbol :version "27.1") @@ -57,7 +60,7 @@ conversion programs (like ImageMagick \"convert\", GraphicsMagick "List of supported image converters to try.") (defun image-convert-p (file) - "Return `image-convert' if FILE can be converted." + "Return `image-convert' if FILE is an image file that can be converted." ;; Find an installed image converter. (unless image-converter (image-converter--find-converter)) @@ -66,7 +69,7 @@ conversion programs (like ImageMagick \"convert\", GraphicsMagick 'image-convert)) (defun image-convert (image) - "Convert IMAGE to a format Emacs can display. + "Convert IMAGE file to the PNG format. IMAGE can either be a file name, which will make the return value a string with the image data. It can also be an image object as returned by `create-image'. If so, it has to be an image object @@ -75,7 +78,7 @@ where created with DATA-P nil (i.e., it has to refer to a file)." (unless image-converter (image-converter--find-converter)) (unless image-converter - (error "No external image converters installed")) + (error "No external image converters available")) (when (and (listp image) (not (plist-get (cdr image) :file))) (error "Only images that refer to files can be converted")) commit 8b5e92921ed9748e13433acf176b03488bc8bedb Author: Lars Ingebrigtsen Date: Sun Sep 29 02:16:41 2019 +0200 Remove :group from a recent defcustom * lisp/image.el (convert-images-externally): Remove :group. diff --git a/lisp/image.el b/lisp/image.el index 00b4c487cd..3f953e65ae 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -148,7 +148,6 @@ and so on) internally, but images that doesn't have native support in Emacs can still be displayed by Emacs if external conversion programs (like ImageMagick \"convert\", GraphicsMagick \"gm\" or \"ffmpeg\") are installed." - :group 'image :type 'bool :version "27.1") commit 63f4f02aa78e6b48f7ee346d31a813ca0978651e Author: Lars Ingebrigtsen Date: Sun Sep 29 01:26:02 2019 +0200 If requested, use external image converters for exotic formats * doc/lispref/display.texi (Defining Images): Document it. * lisp/image.el (convert-images-externally): New variable. (image-type): Use it. (create-image): Convert images. * lisp/image/image-converter.el (image-converter--convert): New file. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index fd6820897f..ec288b1c47 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6044,6 +6044,13 @@ properties---for example, (create-image "foo.xpm" 'xpm nil :heuristic-mask t) @end example +@vindex convert-images-externally +If Emacs doesn't have native support for the image format in question, +and @code{convert-images-externally} is non-@code{nil}, Emacs will try +to determine whether there are external utilities that can be used to +transform the image in question to @acronym{PNG} before displaying. +GraphicsMagick, ImageMagick and ffmpeg are currently supported. + The function returns @code{nil} if images of this type are not supported. Otherwise it returns an image descriptor. @end defun diff --git a/etc/NEWS b/etc/NEWS index 34b7a5aa29..677b710e22 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2656,6 +2656,13 @@ data about creation times and orientation and the like. 'exif-parse-file' and 'exif-parse-buffer' are the main interface functions. +*** New library image-converter. +To view exotic image formats that Emacs doesn't have native support +for, the new 'convert-images-externally' variable can be set to t. If +the system has GraphicsMagick, ImageMagick or ffmpeg installed, it +will be used to convert images automatically before displaying with +'create-image'. + *** 'image-mode' now uses this library to automatically rotate images according to the orientation in the Exif data, if any. diff --git a/lisp/image.el b/lisp/image.el index b36a5138b1..00b4c487cd 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -141,6 +141,17 @@ based on the font pixel size." (const :tag "Automatically compute" auto)) :version "26.1") +(defcustom convert-images-externally nil + "If non-nil, `create-image' will use external converters for exotic formats. +Emacs handles most of the common image formats (JPEG, PNG, GIF +and so on) internally, but images that doesn't have native +support in Emacs can still be displayed by Emacs if external +conversion programs (like ImageMagick \"convert\", GraphicsMagick +\"gm\" or \"ffmpeg\") are installed." + :group 'image + :type 'bool + :version "27.1") + ;; Map put into text properties on images. (defvar image-map (let ((map (make-sparse-keymap))) @@ -357,6 +368,9 @@ be determined." ;; If nothing seems to be supported, return first type that matched. (or first (setq first type)))))))) +(declare-function image-convert-p "image-converter.el" (file)) +(declare-function image-convert "image-converter.el" (image)) + ;;;###autoload (defun image-type (source &optional type data-p) "Determine and return image type. @@ -372,10 +386,16 @@ Optional DATA-P non-nil means SOURCE is a string containing image data." (setq type (if data-p (image-type-from-data source) (or (image-type-from-file-header source) - (image-type-from-file-name source)))) - (or type (error "Cannot determine image type"))) - (or (memq type (and (boundp 'image-types) image-types)) - (error "Invalid image type `%s'" type)) + (image-type-from-file-name source) + (and convert-images-externally + (progn + (require 'image-converter) + (image-convert-p source)))))) + (unless type + (error "Cannot determine image type"))) + (when (and (not (eq type 'image-convert)) + (not (memq type (and (boundp 'image-types) image-types)))) + (error "Invalid image type `%s'" type)) type) @@ -438,6 +458,12 @@ Image file names that are not absolute are searched for in the `x-bitmap-file-path' (in that order)." ;; It is x_find_image_file in image.c that sets the search path. (setq type (image-type file-or-data type data-p)) + ;; If we have external image conversion switched on (for exotic, + ;; non-native image formats), then we convert the file. + (when (eq type 'image-convert) + (setq file-or-data (image-convert file-or-data) + type 'png + data-p t)) (when (image-type-available-p type) (append (list 'image :type type (if data-p :data :file) file-or-data) (and (not (plist-get props :scale)) diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el new file mode 100644 index 0000000000..f485c34842 --- /dev/null +++ b/lisp/image/image-converter.el @@ -0,0 +1,191 @@ +;;; image-converter.el --- Converting images from exotic formats -*- lexical-binding: t -*- + +;; Copyright (C) 2019 Free Software Foundation, Inc. + +;; Author: Lars Magne Ingebrigtsen +;; Keywords: images + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; The main interface function here is `image-convert'. + +;;; Code: + +(require 'cl-generic) +(eval-when-compile (require 'cl-lib)) + +(defcustom convert-external-images nil + "If non-nil, `create-image' will use external converters for exotic formats. +Emacs handles most of the common image formats (JPEG, PNG, GIF +and so on) internally, but images that doesn't have native +support in Emacs can still be displayed by Emacs if external +conversion programs (like ImageMagick \"convert\", GraphicsMagick +\"gm\" or \"ffmpeg\") are installed." + :group 'image + :type 'bool + :version "27.1") + +(defcustom image-converter nil + "What external converter to use. +`imagemagick', `graphicsmagick' and `ffmpeg' are supported." + :group 'image + :type 'symbol + :version "27.1") + +(defvar image-converter-regexp nil + "A regexp that matches the file name suffixes that can be converted.") + +(defvar image-converter--converters + '((graphicsmagick :command "gm convert" :probe "-list format") + (imagemagick :command "convert" :probe "-list format") + (ffmpeg :command "ffmpeg" :probe "-decoders")) + "List of supported image converters to try.") + +(defun image-convert-p (file) + "Return `image-convert' if FILE can be converted." + ;; Find an installed image converter. + (unless image-converter + (image-converter--find-converter)) + (and image-converter + (string-match image-converter-regexp file) + 'image-convert)) + +(defun image-convert (image) + "Convert IMAGE to a format Emacs can display. +IMAGE can either be a file name, which will make the return value +a string with the image data. It can also be an image object as +returned by `create-image'. If so, it has to be an image object +where created with DATA-P nil (i.e., it has to refer to a file)." + ;; Find an installed image converter. + (unless image-converter + (image-converter--find-converter)) + (unless image-converter + (error "No external image converters installed")) + (when (and (listp image) + (not (plist-get (cdr image) :file))) + (error "Only images that refer to files can be converted")) + (with-temp-buffer + (set-buffer-multibyte nil) + (when-let ((err (image-converter--convert + image-converter + (if (listp image) + (plist-get (cdr image) :file) + image)))) + (error "%s" err)) + (if (listp image) + ;; Return an image object that's the same as we were passed, + ;; but ignore the :type and :file values. + (apply #'create-image (buffer-string) 'png t + (cl-loop for (key val) on (cdr image) by #'cddr + unless (memq key '(:type :file)) + append (list key val))) + (buffer-string)))) + +(defun image-converter--value (type elem) + "Return the value of ELEM of image converter TYPE." + (plist-get (cdr (assq type image-converter--converters)) elem)) + +(cl-defmethod image-converter--probe ((type (eql graphicsmagick))) + "Check whether the system has GraphicsMagick installed." + (with-temp-buffer + (let ((command (split-string (image-converter--value type :command) " ")) + formats) + (when (zerop (apply #'call-process (car command) nil '(t nil) nil + (append (cdr command) + (split-string + (image-converter--value type :probe) " ")))) + (goto-char (point-min)) + (when (re-search-forward "^-" nil t) + (forward-line 1) + ;; Lines look like + ;; " 8BIM P rw- Photoshop resource format". + (while (re-search-forward "^ *\\([A-Z0-9]+\\) +. +r" nil t) + (push (downcase (match-string 1)) formats))) + (nreverse formats))))) + +(cl-defmethod image-converter--probe ((type (eql imagemagick))) + "Check whether the system has ImageMagick installed." + (with-temp-buffer + (let ((command (split-string (image-converter--value type :command) " ")) + formats) + ;; Can't check return value; ImageMagick convert usually returns + ;; a non-zero result on "-list format". + (apply #'call-process (car command) nil '(t nil) nil + (append (cdr command) + (split-string (image-converter--value type :probe) " "))) + (goto-char (point-min)) + (when (re-search-forward "^-" nil t) + (forward-line 1) + ;; Lines look like + ;; " WPG* r-- Word Perfect Graphics". + (while (re-search-forward "^ *\\([A-Z0-9]+\\)\\*? +r" nil t) + (push (downcase (match-string 1)) formats))) + (nreverse formats)))) + +(cl-defmethod image-converter--probe ((type (eql ffmpeg))) + "Check whether the system has ffmpeg installed." + (with-temp-buffer + (let ((command (image-converter--value type :command)) + formats) + (when (zerop (call-process command nil '(t nil) nil + (image-converter--value type :probe))) + (goto-char (point-min)) + (when (re-search-forward "^ *-" nil t) + (forward-line 1) + ;; Lines look like + ;; " V....D alias_pix Alias/Wavefront PIX image" + (while (re-search-forward "^ *V[^ ]+ +\\([a-z0-9_]+\\)" nil t) + (push (match-string 1) formats))) + (nreverse formats))))) + +(defun image-converter--find-converter () + "Find an installed image converter." + (dolist (elem image-converter--converters) + (when-let ((formats (image-converter--probe (car elem)))) + (setq image-converter (car elem) + image-converter-regexp (concat "\\." (regexp-opt formats) "\\'"))))) + +(cl-defmethod image-converter--convert ((type (eql graphicsmagick)) file) + "Convert using GraphicsMagick." + (image-converter--convert-magick type file)) + +(cl-defmethod image-converter--convert ((type (eql imagemagick)) file) + "Convert using ImageMagick." + (image-converter--convert-magick type file)) + +(defun image-converter--convert-magick (type file) + (let ((command (split-string (image-converter--value type :command) " "))) + (unless (zerop (apply #'call-process (car command) + nil t nil + (append (cdr command) + (list (expand-file-name file) "png:-")))) + ;; If the command failed, hopefully the buffer contains the + ;; error message. + (buffer-string)))) + +(cl-defmethod image-converter--convert ((type (eql ffmpeg)) file) + "Convert using ffmpeg." + (unless (zerop (call-process (image-converter--value type :command) + nil '(t nil) nil + "-i" (expand-file-name file) + "-c:v" "png" "-f" "image2pipe" "-")) + "ffmpeg error when converting")) + +(provide 'image-converter) + +;;; image-converter.el ends here commit c359782ae6441bba2fad2b6d53bcbcd5a8be7057 Author: Stephen Gildea Date: Sat Sep 28 15:46:27 2019 -0700 Reorganize time-stamp tests * time-stamp-tests.el: Group tests by when the format was or will be documented. Add tests for a few more undocumented, volatile formats. Change AM hours test time to be a different hour from PM test time. (Making these changes to the tests now will minimize test changes needed later with anticipated code changes.) diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el index 165b4f13c2..452d83ddba 100644 --- a/test/lisp/time-stamp-tests.el +++ b/test/lisp/time-stamp-tests.el @@ -31,7 +31,7 @@ (mail-host-address "test-mail-host-name") (ref-time '(17337 16613)) ;Monday, Jan 2, 2006, 3:04:05 PM (ref-time2 '(22574 61591)) ;Friday, Nov 18, 2016, 12:14:15 PM - (ref-time3 '(21377 23973 123456)) ;Sun, May 25, 2014, 03:04:05.123456am + (ref-time3 '(21377 34956)) ;Sunday, May 25, 2014, 06:07:08 AM (time-stamp-time-zone t)) ;use UTC (cl-letf (((symbol-function 'time-stamp-conv-warn) (lambda (old-format _new) @@ -57,181 +57,187 @@ ;;; Tests: -(ert-deftest time-stamp-test-day-of-week-documented () - "Test documented time-stamp formats for day of week." +(ert-deftest time-stamp-test-day-of-week () + "Test time-stamp formats for named day of week." (with-time-stamp-test-env + ;; implemented and documented since 1997 (should (equal (time-stamp-string "%3a" ref-time) "Mon")) + (should (equal (time-stamp-string "%#A" ref-time) "MONDAY")) (should (equal (time-stamp-string "%3A" ref-time) "MON")) (should (equal (time-stamp-string "%:a" ref-time) "Monday")) - (should (equal (time-stamp-string "%#A" ref-time) "MONDAY")) - (should (equal (time-stamp-string "%3a" ref-time2) "Fri")) - (should (equal (time-stamp-string "%3A" ref-time2) "FRI")) - (should (equal (time-stamp-string "%:a" ref-time2) "Friday")) - (should (equal (time-stamp-string "%#A" ref-time2) "FRIDAY")))) - -(ert-deftest time-stamp-test-day-of-week-future () - "Test implemented but as yet undocumented time-stamp formats for day of week." - (with-time-stamp-test-env + ;; implemented since 2001, undocumented future formats (should (equal (time-stamp-string "%#a" ref-time) "MON")) (should (equal (time-stamp-string "%:A" ref-time) "Monday")) - (should (equal (time-stamp-string "%#a" ref-time2) "FRI")) - (should (equal (time-stamp-string "%:A" ref-time2) "Friday")))) - -(ert-deftest time-stamp-test-day-of-week-volatile-warns () - "Test time-stamp formats for day of week that will change. -Test that each generates a warning." - (with-time-stamp-test-env + ;; warned since 1997, will change + (time-stamp-should-warn (equal + (time-stamp-string "%a" ref-time) "Monday")) (time-stamp-should-warn (equal - (time-stamp-string "%a" ref-time) "Monday")) + (time-stamp-string "%^a" ref-time) "Monday")) (time-stamp-should-warn (equal (time-stamp-string "%A" ref-time) "MONDAY")))) -(ert-deftest time-stamp-test-month-name-documented () - "Test documented time-stamp formats for month name." +(ert-deftest time-stamp-test-month-name () + "Test time-stamp formats for month name." (with-time-stamp-test-env + ;; implemented and documented since 1997 (should (equal (time-stamp-string "%3b" ref-time) "Jan")) + (should (equal (time-stamp-string "%#B" ref-time) "JANUARY")) (should (equal (time-stamp-string "%3B" ref-time) "JAN")) (should (equal (time-stamp-string "%:b" ref-time) "January")) - (should (equal (time-stamp-string "%#B" ref-time) "JANUARY")))) - -(ert-deftest time-stamp-test-month-name-future () - "Test implemented but as yet undocumented time-stamp formats for month name." - (with-time-stamp-test-env + ;; implemented since 2001, undocumented future formats (should (equal (time-stamp-string "%#b" ref-time) "JAN")) - (should (equal (time-stamp-string "%:B" ref-time) "January")))) - -(ert-deftest time-stamp-test-month-name-volatile-warns () - "Test time-stamp formats for month name that will change. -Test that each generates a warning." - (with-time-stamp-test-env + (should (equal (time-stamp-string "%:B" ref-time) "January")) + ;; warned since 1997, will change (time-stamp-should-warn (equal (time-stamp-string "%b" ref-time) "January")) + (time-stamp-should-warn (equal + (time-stamp-string "%^b" ref-time) "January")) (time-stamp-should-warn (equal (time-stamp-string "%B" ref-time) "JANUARY")))) (ert-deftest time-stamp-test-day-of-month () "Test time-stamp formats for day of month." (with-time-stamp-test-env - ;; documented 1-digit - (should (equal (time-stamp-string "%:d" ref-time) "2")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%2d" ref-time) " 2")) - (should (equal (time-stamp-string "%02d" ref-time) "02")) - ;; documented 2-digit - (should (equal (time-stamp-string "%:d" ref-time2) "18")) (should (equal (time-stamp-string "%2d" ref-time2) "18")) + (should (equal (time-stamp-string "%02d" ref-time) "02")) (should (equal (time-stamp-string "%02d" ref-time2) "18")) - ;; undocumented future formats + ;; implemented and documented since 1997 + (should (equal (time-stamp-string "%:d" ref-time) "2")) + (should (equal (time-stamp-string "%:d" ref-time2) "18")) + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%1d" ref-time) "2")) (should (equal (time-stamp-string "%1d" ref-time2) "18")) - ;; changing formats + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%_d" ref-time) "2")) + (time-stamp-should-warn (equal (time-stamp-string "%_d" ref-time2) "18")) (time-stamp-should-warn (equal (time-stamp-string "%d" ref-time) "2")) - (time-stamp-should-warn (equal (time-stamp-string "%_d" ref-time) "2")))) + (time-stamp-should-warn (equal (time-stamp-string "%d" ref-time2) "18")))) (ert-deftest time-stamp-test-hours-24 () "Test time-stamp formats for hour on a 24-hour clock." (with-time-stamp-test-env - ;; documented PM - (should (equal (time-stamp-string "%:H" ref-time) "15")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%2H" ref-time) "15")) - (should (equal (time-stamp-string "%02H" ref-time) "15")) - ;; documented AM - (should (equal (time-stamp-string "%:H" ref-time2) "12")) (should (equal (time-stamp-string "%2H" ref-time2) "12")) + (should (equal (time-stamp-string "%2H" ref-time3) " 6")) + (should (equal (time-stamp-string "%02H" ref-time) "15")) (should (equal (time-stamp-string "%02H" ref-time2) "12")) - ;; documented 1-digit - (should (equal (time-stamp-string "%:H" ref-time3) "3")) - (should (equal (time-stamp-string "%2H" ref-time3) " 3")) - (should (equal (time-stamp-string "%02H" ref-time3) "03")) - ;; undocumented future formats + (should (equal (time-stamp-string "%02H" ref-time3) "06")) + ;; implemented and documented since 1997 + (should (equal (time-stamp-string "%:H" ref-time) "15")) + (should (equal (time-stamp-string "%:H" ref-time2) "12")) + (should (equal (time-stamp-string "%:H" ref-time3) "6")) + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%1H" ref-time) "15")) (should (equal (time-stamp-string "%1H" ref-time2) "12")) - (should (equal (time-stamp-string "%1H" ref-time3) "3")) - ;; changing formats + (should (equal (time-stamp-string "%1H" ref-time3) "6")) + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%_H" ref-time) "15")) + (time-stamp-should-warn (equal (time-stamp-string "%_H" ref-time2) "12")) + (time-stamp-should-warn (equal (time-stamp-string "%_H" ref-time3) "6")) (time-stamp-should-warn (equal (time-stamp-string "%H" ref-time) "15")) - (time-stamp-should-warn (equal (time-stamp-string "%_H" ref-time) "15")))) + (time-stamp-should-warn (equal (time-stamp-string "%H" ref-time2) "12")) + (time-stamp-should-warn (equal (time-stamp-string "%H" ref-time3) "6")))) (ert-deftest time-stamp-test-hours-12 () "Test time-stamp formats for hour on a 12-hour clock." (with-time-stamp-test-env - ;; documented 1-digit, PM - (should (equal (time-stamp-string "%:I" ref-time) "3")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%2I" ref-time) " 3")) - (should (equal (time-stamp-string "%02I" ref-time) "03")) - ;; documented 2-digit - (should (equal (time-stamp-string "%:I" ref-time2) "12")) (should (equal (time-stamp-string "%2I" ref-time2) "12")) + (should (equal (time-stamp-string "%2I" ref-time3) " 6")) + (should (equal (time-stamp-string "%02I" ref-time) "03")) (should (equal (time-stamp-string "%02I" ref-time2) "12")) - ;; undocumented future formats + (should (equal (time-stamp-string "%02I" ref-time3) "06")) + ;; implemented and documented since 1997 + (should (equal (time-stamp-string "%:I" ref-time) "3")) ;PM + (should (equal (time-stamp-string "%:I" ref-time2) "12")) ;PM + (should (equal (time-stamp-string "%:I" ref-time3) "6")) ;AM + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%1I" ref-time) "3")) (should (equal (time-stamp-string "%1I" ref-time2) "12")) - ;; changing formats + (should (equal (time-stamp-string "%1I" ref-time3) "6")) + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%_I" ref-time) "3")) + (time-stamp-should-warn (equal (time-stamp-string "%_I" ref-time2) "12")) + (time-stamp-should-warn (equal (time-stamp-string "%_I" ref-time3) "6")) (time-stamp-should-warn (equal (time-stamp-string "%I" ref-time) "3")) - (time-stamp-should-warn (equal (time-stamp-string "%_I" ref-time) "3")))) + (time-stamp-should-warn (equal (time-stamp-string "%I" ref-time2) "12")) + (time-stamp-should-warn (equal (time-stamp-string "%I" ref-time3) "6")))) (ert-deftest time-stamp-test-month-number () "Test time-stamp formats for month number." (with-time-stamp-test-env - ;; documented 1-digit - (should (equal (time-stamp-string "%:m" ref-time) "1")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%2m" ref-time) " 1")) - (should (equal (time-stamp-string "%02m" ref-time) "01")) - ;; documented 2-digit - (should (equal (time-stamp-string "%:m" ref-time2) "11")) (should (equal (time-stamp-string "%2m" ref-time2) "11")) + (should (equal (time-stamp-string "%02m" ref-time) "01")) (should (equal (time-stamp-string "%02m" ref-time2) "11")) - ;; undocumented future formats + ;; implemented and documented since 1997 + (should (equal (time-stamp-string "%:m" ref-time) "1")) + (should (equal (time-stamp-string "%:m" ref-time2) "11")) + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%1m" ref-time) "1")) (should (equal (time-stamp-string "%1m" ref-time2) "11")) - ;; changing formats + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%_m" ref-time) "1")) + (time-stamp-should-warn (equal (time-stamp-string "%_m" ref-time2) "11")) (time-stamp-should-warn (equal (time-stamp-string "%m" ref-time) "1")) - (time-stamp-should-warn (equal (time-stamp-string "%_m" ref-time) "1")))) + (time-stamp-should-warn (equal (time-stamp-string "%m" ref-time2) "11")))) (ert-deftest time-stamp-test-minute () "Test time-stamp formats for minute." (with-time-stamp-test-env - ;; documented 1-digit - (should (equal (time-stamp-string "%:M" ref-time) "4")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%2M" ref-time) " 4")) - (should (equal (time-stamp-string "%02M" ref-time) "04")) - ;; documented 2-digit - (should (equal (time-stamp-string "%:M" ref-time2) "14")) (should (equal (time-stamp-string "%2M" ref-time2) "14")) + (should (equal (time-stamp-string "%02M" ref-time) "04")) (should (equal (time-stamp-string "%02M" ref-time2) "14")) - ;; undocumented future formats + ;; implemented and documented since 1997 + (should (equal (time-stamp-string "%:M" ref-time) "4")) + (should (equal (time-stamp-string "%:M" ref-time2) "14")) + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%1M" ref-time) "4")) (should (equal (time-stamp-string "%1M" ref-time2) "14")) - ;; changing formats + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%_M" ref-time) "4")) + (time-stamp-should-warn (equal (time-stamp-string "%_M" ref-time2) "14")) (time-stamp-should-warn (equal (time-stamp-string "%M" ref-time) "4")) - (time-stamp-should-warn (equal (time-stamp-string "%_M" ref-time) "4")))) + (time-stamp-should-warn (equal (time-stamp-string "%M" ref-time2) "14")))) (ert-deftest time-stamp-test-second () "Test time-stamp formats for second." (with-time-stamp-test-env - ;; documented 1-digit - (should (equal (time-stamp-string "%:S" ref-time) "5")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%2S" ref-time) " 5")) - (should (equal (time-stamp-string "%02S" ref-time) "05")) - ;; documented 2-digit - (should (equal (time-stamp-string "%:S" ref-time2) "15")) (should (equal (time-stamp-string "%2S" ref-time2) "15")) + (should (equal (time-stamp-string "%02S" ref-time) "05")) (should (equal (time-stamp-string "%02S" ref-time2) "15")) - ;; undocumented future formats + ;; implemented and documented since 1997 + (should (equal (time-stamp-string "%:S" ref-time) "5")) + (should (equal (time-stamp-string "%:S" ref-time2) "15")) + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%1S" ref-time) "5")) (should (equal (time-stamp-string "%1S" ref-time2) "15")) - ;; changing formats + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%_S" ref-time) "5")) + (time-stamp-should-warn (equal (time-stamp-string "%_S" ref-time2) "15")) (time-stamp-should-warn (equal (time-stamp-string "%S" ref-time) "5")) - (time-stamp-should-warn (equal (time-stamp-string "%_S" ref-time) "5")))) + (time-stamp-should-warn (equal (time-stamp-string "%S" ref-time2) "15")))) (ert-deftest time-stamp-test-am-pm () "Test time-stamp formats for AM and PM strings." (with-time-stamp-test-env - ;; documented + ;; implemented and documented since 1997 (should (equal (time-stamp-string "%#p" ref-time) "pm")) - (should (equal (time-stamp-string "%P" ref-time) "PM")) (should (equal (time-stamp-string "%#p" ref-time3) "am")) + (should (equal (time-stamp-string "%P" ref-time) "PM")) (should (equal (time-stamp-string "%P" ref-time3) "AM")) - ;; changing - (time-stamp-should-warn (equal (time-stamp-string "%p" ref-time) "pm")))) + ;; warned since 1997, will change + (time-stamp-should-warn (equal (time-stamp-string "%p" ref-time) "pm")) + (time-stamp-should-warn (equal (time-stamp-string "%p" ref-time3) "am")))) (ert-deftest time-stamp-test-day-number-in-week () "Test time-stamp formats for day number in week." @@ -243,40 +249,42 @@ Test that each generates a warning." (ert-deftest time-stamp-test-year () "Test time-stamp formats for year." (with-time-stamp-test-env - ;; documented + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%02y" ref-time) "06")) + ;; implemented and documented since 1997 (should (equal (time-stamp-string "%:y" ref-time) "2006")) - ;; undocumented future formats + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%Y" ref-time) "2006")) - ;; changing + ;; warned since 1997, will change (time-stamp-should-warn (equal (time-stamp-string "%y" ref-time) "2006")))) (ert-deftest time-stamp-test-time-zone () "Test time-stamp formats for time zone." (with-time-stamp-test-env - ;; documented - (should (equal (time-stamp-string "%z" ref-time) "gmt")) + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%Z" ref-time) "GMT")) - ;; undocumented future formats + (should (equal (time-stamp-string "%z" ref-time) "gmt")) + ;; implemented since 1997, undocumented future format (should (equal (time-stamp-string "%#Z" ref-time) "gmt")))) (ert-deftest time-stamp-test-non-date-conversions () "Test time-stamp formats for non-date items." (with-time-stamp-test-env - ;; documented + ;; implemented and documented since 1995 (should (equal (time-stamp-string "%%" ref-time) "%")) ;% last char (should (equal (time-stamp-string "%%P" ref-time) "%P")) ;% not last char (should (equal (time-stamp-string "%f" ref-time) "time-stamped-file")) (should (equal (time-stamp-string "%F" ref-time) "/emacs/test/time-stamped-file")) - (should - (equal (time-stamp-string "%s" ref-time) "test-system-name.example.org")) - (should (equal (time-stamp-string "%u" ref-time) "test-logname")) - (should (equal (time-stamp-string "%U" ref-time) "Time Stamp Tester")) (should (equal (time-stamp-string "%h" ref-time) "test-mail-host-name")) - ;; undocumented + (should (equal + (time-stamp-string "%s" ref-time) "test-system-name.example.org")) + (should (equal (time-stamp-string "%U" ref-time) "Time Stamp Tester")) + (should (equal (time-stamp-string "%u" ref-time) "test-logname")) + ;; implemented since 2001, undocumented future formats (should (equal (time-stamp-string "%L" ref-time) "Time Stamp Tester")) (should (equal (time-stamp-string "%l" ref-time) "test-logname")) + ;; implemented since 2007, undocumented future formats (should (equal (time-stamp-string "%Q" ref-time) "test-system-name.example.org")) (should (equal @@ -306,6 +314,7 @@ Test that each generates a warning." (should (equal (time-stamp-string "%0%" ref-time3) "")) (should (equal (time-stamp-string "%1%" ref-time3) "%")) (should (equal (time-stamp-string "%2%" ref-time3) " %")) - (should (equal (time-stamp-string "%#3a" ref-time3) "SUN")))) + (should (equal (time-stamp-string "%#3a" ref-time3) "SUN")) + (should (equal (time-stamp-string "%#3b" ref-time2) "NOV")))) ;;; time-stamp-tests.el ends here commit bc94e2dd4be04cbe7b5ab6749e30ef6c305c0588 Author: Lars Ingebrigtsen Date: Sat Sep 28 21:36:20 2019 +0200 Expunge INBOX messages after splitting * lisp/gnus/nnimap.el (nnimap-split-incoming-mail): Expunge articles after splitting (bug#37541). diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index baf2f9f477..d4681e2b43 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -1125,7 +1125,6 @@ If LIMIT, first try to limit the search to the N last articles." (defun nnimap-delete-article (articles) "Delete ARTICLES." - (debug articles) (with-current-buffer (nnimap-buffer) (nnimap-command "UID STORE %s +FLAGS.SILENT (\\Deleted)" (nnimap-article-ranges articles)) @@ -2175,9 +2174,14 @@ Return the server's response to the SELECT or EXAMINE command." (when (and (not can-move) sequences) (nnimap-wait-for-response (caar sequences)) ;; And then mark the successful copy actions as deleted, - ;; and possibly expunge them. - (nnimap-delete-article - (nnimap-parse-copied-articles sequences))) + ;; and possibly expunge them. Almost any non-nil + ;; setting of nnimap-expunge should lead to expunging + ;; here. + (let ((nnimap-expunge (and nnimap-expunge + (not (equal nnimap-expunge 'never)) + 'immediate))) + (nnimap-delete-article + (nnimap-parse-copied-articles sequences)))) (when junk-articles (nnimap-delete-article junk-articles)))))))) commit bb50aaa325aee980cdaeaa2358f4f54db5eb71fe Author: Lars Ingebrigtsen Date: Sat Sep 28 21:30:19 2019 +0200 Clean up nnimap-split-incoming-mail slightly * lisp/gnus/nnimap.el (nnimap-split-incoming-mail): Don't call -delete-articles on empty lists (bug#37541). diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 839399859d..baf2f9f477 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -1125,6 +1125,7 @@ If LIMIT, first try to limit the search to the N last articles." (defun nnimap-delete-article (articles) "Delete ARTICLES." + (debug articles) (with-current-buffer (nnimap-buffer) (nnimap-command "UID STORE %s +FLAGS.SILENT (\\Deleted)" (nnimap-article-ranges articles)) @@ -2177,7 +2178,8 @@ Return the server's response to the SELECT or EXAMINE command." ;; and possibly expunge them. (nnimap-delete-article (nnimap-parse-copied-articles sequences))) - (nnimap-delete-article junk-articles))))))) + (when junk-articles + (nnimap-delete-article junk-articles)))))))) (defun nnimap-parse-copied-articles (sequences) (let (sequence copied range) commit c49e36e67e127417782770d63afc378cd232344e Merge: fc3ba91a57 8cd2eee70a Author: Eli Zaretskii Date: Sat Sep 28 22:11:38 2019 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 8cd2eee70a6af700c0379e3e7126ef023293ee67 Author: Lars Ingebrigtsen Date: Sat Sep 28 21:09:30 2019 +0200 Copy edit nnimap-expunge doc string * lisp/gnus/nnimap.el (nnimap-expunge): Copy edit doc string. diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 2c91ba0bf5..839399859d 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -104,17 +104,17 @@ Possible choices are nil (use default methods), `anonymous', (defvoo nnimap-expunge 'on-exit "When to expunge deleted messages. -If 'never, deleted articles are marked with the IMAP \\Delete -flag but not automatically expunged. If 'immediately, deleted +If `never', deleted articles are marked with the IMAP \\Delete +flag but not automatically expunged. If `immediately', deleted articles are immediately expunged (this requires the server to -support the UID EXPUNGE command). If 'on-exit, deleted articles -are flagged, and all flagged articles are expunged when the -group is closed. +support the UID EXPUNGE command). If `on-exit', deleted articles +are flagged, and all flagged articles are expunged when the group +is closed. For backwards compatibility, this variable may also be set to t or nil. If the server supports UID EXPUNGE, both t and nil are -equivalent to 'immediately. If the server does not support UID -EXPUNGE nil is equivalent to 'never, while t will immediately +equivalent to `immediately'. If the server does not support UID +EXPUNGE nil is equivalent to `never', while t will immediately expunge ALL articles that are currently flagged as deleted (i.e., potentially not only the article that was just deleted).") commit fc3ba91a57bbaf5344e8de3fdbe3a0371f126fcb Author: Eli Zaretskii Date: Sat Sep 28 22:09:11 2019 +0300 Improve indexing of ELisp manual * doc/lispref/frames.texi (Font and Color Parameters): Add index entry for the 'mouse' face. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 8596db7421..f7dfb51dd4 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -2392,6 +2392,7 @@ The color to use for the background of characters. It is equivalent to the @code{:background} attribute of the @code{default} face. @vindex mouse-color@r{, a frame parameter} +@vindex mouse@r{, a face} @item mouse-color The color for the mouse pointer. It is equivalent to the @code{:background} attribute of the @code{mouse} face. commit 6691a5c1ad1c1fe3c55821a4d34d1d2071dcbbdc Author: Stefan Kangas Date: Sat Sep 28 21:05:11 2019 +0200 Fix customizing ibuffer-help-buffer-modes * lisp/ibuffer.el (ibuffer-help-buffer-modes) * lisp/obsolete/info-edit.el (ibuffer-help-buffer-modes): Move Info-edit-mode reference to obsolete file. diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index 3af06eba97..c81b05efec 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el @@ -317,7 +317,7 @@ directory, like `default-directory'." string)) (defcustom ibuffer-help-buffer-modes - '(help-mode apropos-mode Info-mode Info-edit-mode) + '(help-mode apropos-mode Info-mode) "List of \"Help\" major modes." :type '(repeat function)) diff --git a/lisp/obsolete/info-edit.el b/lisp/obsolete/info-edit.el index b64e84003f..55c52b5abd 100644 --- a/lisp/obsolete/info-edit.el +++ b/lisp/obsolete/info-edit.el @@ -78,6 +78,11 @@ This feature will be removed in future.") (buffer-modified-p) (message "Tags may have changed. Use Info-tagify if necessary"))) +;; Moved here from definition of ibuffer-help-buffer-modes to make +;; that variable customizable even though this code is obsolete. See +;; also Bug#30990. +(add-to-list 'ibuffer-help-buffer-modes 'Info-edit-mode) + (provide 'info-edit) ;;; info-edit.el ends here commit cc7f2fb0cc1c077d0648e48d0d9efb713c375abe Author: Stefan Kangas Date: Sat Sep 21 14:58:08 2019 +0200 Document ert test selectors in batch mode (Bug#37476) * doc/misc/ert.texi (Running Tests in Batch Mode): Document test selectors. diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi index 2dbba095d6..889216cbef 100644 --- a/doc/misc/ert.texi +++ b/doc/misc/ert.texi @@ -337,10 +337,14 @@ emacs -batch -l ert -l my-tests.el \ In quiet mode ERT prints only unexpected results and summary. -If ERT is not part of your Emacs distribution, you may need to use -@code{-L /path/to/ert/} so that Emacs can find it. You may need -additional @code{-L} flags to ensure that @code{my-tests.el} and all the -files that it requires are on your @code{load-path}. +You can specify selectors to only run a subset of your tests +(@pxref{Test Selectors}). For example, the following would run all +tests where the name of the test matches the string ``to-match''. + +@example +emacs -batch -l ert -l my-tests.el \ + -eval '(ert-run-tests-batch-and-exit "to-match")' +@end example @node Test Selectors commit a444bb78ad5d1a06f8d5b043e16941fdcc24de16 Author: Stefan Kangas Date: Mon Sep 16 09:29:48 2019 +0200 Improve sorting in package list (Bug#37419) * lisp/emacs-lisp/package.el (package-menu-mode): Allow sorting by version or description. (package-menu--version-predicate): Fix sorting by version. (package-menu--description-predicate): Fix sorting by description. (package-menu--archive-predicate): Fall back to sorting by name if archive is the same. (package-menu--name-predicate, package-menu--status-predicate): Add doc string. * etc/NEWS: Announce the above changes. diff --git a/etc/NEWS b/etc/NEWS index 97b96d1e4e..34b7a5aa29 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -983,6 +983,9 @@ early init file. --- *** Imenu support has been added to 'package-menu-mode'. +--- +*** The package list can now be sorted by version or description. + ** Info +++ diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index a8362cb205..ab1fb8b90f 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2725,11 +2725,11 @@ Letters do not insert themselves; instead, they are commands. package-menu--transaction-status))) (setq tabulated-list-format `[("Package" 18 package-menu--name-predicate) - ("Version" 13 nil) + ("Version" 13 package-menu--version-predicate) ("Status" 10 package-menu--status-predicate) ,@(if (cdr package-archives) '(("Archive" 10 package-menu--archive-predicate))) - ("Description" 0 nil)]) + ("Description" 0 package-menu--description-predicate)]) (setq tabulated-list-padding 2) (setq tabulated-list-sort-key (cons "Status" nil)) (add-hook 'tabulated-list-revert-hook #'package-menu--refresh nil t) @@ -3469,13 +3469,17 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm." (message "Operation %s finished" message-template)))))))) (defun package-menu--version-predicate (A B) - (let ((vA (or (aref (cadr A) 1) '(0))) - (vB (or (aref (cadr B) 1) '(0)))) + "Predicate to sort \"*Packages*\" buffer by the version column. +This is used for `tabulated-list-format' in `package-menu-mode'." + (let ((vA (or (version-to-list (aref (cadr A) 1)) '(0))) + (vB (or (version-to-list (aref (cadr B) 1)) '(0)))) (if (version-list-= vA vB) (package-menu--name-predicate A B) (version-list-< vA vB)))) (defun package-menu--status-predicate (A B) + "Predicate to sort \"*Packages*\" buffer by the status column. +This is used for `tabulated-list-format' in `package-menu-mode'." (let ((sA (aref (cadr A) 2)) (sB (aref (cadr B) 2))) (cond ((string= sA sB) @@ -3506,19 +3510,28 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm." (t (string< sA sB))))) (defun package-menu--description-predicate (A B) - (let ((dA (aref (cadr A) 3)) - (dB (aref (cadr B) 3))) + "Predicate to sort \"*Packages*\" buffer by the description column. +This is used for `tabulated-list-format' in `package-menu-mode'." + (let ((dA (aref (cadr A) (if (cdr package-archives) 4 3))) + (dB (aref (cadr B) (if (cdr package-archives) 4 3)))) (if (string= dA dB) (package-menu--name-predicate A B) (string< dA dB)))) (defun package-menu--name-predicate (A B) + "Predicate to sort \"*Packages*\" buffer by the name column. +This is used for `tabulated-list-format' in `package-menu-mode'." (string< (symbol-name (package-desc-name (car A))) (symbol-name (package-desc-name (car B))))) (defun package-menu--archive-predicate (A B) - (string< (or (package-desc-archive (car A)) "") - (or (package-desc-archive (car B)) ""))) + "Predicate to sort \"*Packages*\" buffer by the archive column. +This is used for `tabulated-list-format' in `package-menu-mode'." + (let ((a (or (package-desc-archive (car A)) "")) + (b (or (package-desc-archive (car B)) ""))) + (if (string= a b) + (package-menu--name-predicate A B) + (string< a b)))) (defun package-menu--populate-new-package-list () "Decide which packages are new in `package-archives-contents'. commit df05c26df3897108619237d359260ed9c91e3d78 Author: Eli Zaretskii Date: Sat Sep 28 17:43:15 2019 +0300 More improvements of doc strings in text-property-search.el * lisp/emacs-lisp/text-property-search.el (text-property-search-forward) (text-property-search-backward): Further improvements of doc strings. (Bug#37488) diff --git a/lisp/emacs-lisp/text-property-search.el b/lisp/emacs-lisp/text-property-search.el index 24d11be21d..a589d0915b 100644 --- a/lisp/emacs-lisp/text-property-search.el +++ b/lisp/emacs-lisp/text-property-search.el @@ -33,24 +33,26 @@ not-current) "Search for the next region of text whose PROPERTY matches VALUE. -If not found, return nil. If found, move point to end of the region and -return a `prop-match' object describing the match. To access the details -of the match, use `prop-match-beginning' and `prop-match-end' for the -buffer positions that limit the region, and `prop-match-value' for the +If not found, return nil and don't move point. +If found, move point to end of the region and return a `prop-match' +object describing the match. To access the details of the match, +use `prop-match-beginning' and `prop-match-end' for the buffer +positions that limit the region, and `prop-match-value' for the value of PROPERTY in the region. PREDICATE is used to decide whether a value of PROPERTY should be considered as matching VALUE. If PREDICATE is t, that means a value must `equal' VALUE to be considered a match. -If PREDICATE is nil, a value will match if it is NOT `equal' to -VALUE, and will also end the match if the value of PROPERTY changes. +If PREDICATE is nil, a value will match if it is non-nil and +is NOT `equal' to VALUE. If PREDICATE is a function, it will be called with two arguments: VALUE and the value of PROPERTY. The function should return -non-nil if these two values should be considered a match. +non-nil if these two values are to be considered a match. If NOT-CURRENT is non-nil, the function will search for the first -region with matching value of PROPERTY that doesn't include point." +region that doesn't include point and has a value of PROPERTY +that matches VALUE." (interactive (list (let ((string (completing-read "Search for property: " obarray))) @@ -70,7 +72,7 @@ region with matching value of PROPERTY that doesn't include point." (let ((origin (point)) (ended nil) pos) - ;; Fix the next candidate. + ;; Find the next candidate. (while (not ended) (setq pos (next-single-property-change (point) property)) (if (not pos) @@ -122,7 +124,8 @@ region with matching value of PROPERTY that doesn't include point." not-current) "Search for the previous region of text whose PROPERTY matches VALUE. -Like `text-property-search-forward', which see, but searches backward." +Like `text-property-search-forward', which see, but searches backward, +and if a matching region is found, moves point to its beginning." (interactive (list (let ((string (completing-read "Search for property: " obarray))) @@ -144,7 +147,7 @@ Like `text-property-search-forward', which see, but searches backward." (ended nil) pos) (forward-char -1) - ;; Fix the next candidate. + ;; Find the previous candidate. (while (not ended) (setq pos (previous-single-property-change (point) property)) (if (not pos) commit 471ce18ae8890ab3444654fd7ac49950044f60d1 Author: Axel Svensson Date: Sat Sep 28 15:44:01 2019 +0200 Update X keysym mapping * lisp/term/x-win.el (x-keysym-table): Update the mappings using current Xorg data. (Bug#37530) Copyright-paperwork-exempt: yes diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 56061371fe..d71bb34525 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -302,7 +302,11 @@ as returned by `x-server-vendor'." (setq i (1+ i)))) ;; Table from Kuhn's proposed additions to the `KEYSYM Encoding' -;; appendix to the X protocol definition. +;; appendix to the X protocol definition. As indicated, some of these +;; have been corrected using information found in keysymdef.h which on +;; a typical system is installed at /usr/include/X11/keysymdef.h. The +;; version used here is from xorgproto version 2019.1 found here: +;; https://gitlab.freedesktop.org/xorg/proto/xorgproto/blob/e0bba743ae7c549c58f92677b239ec7878548228/include/X11/keysymdef.h (dolist (pair '( @@ -579,6 +583,7 @@ as returned by `x-server-vendor'." (#x6aa . ?њ) (#x6ab . ?ћ) (#x6ac . ?ќ) + (#x6ad . ?ґ) ;; Source: keysymdef.h (#x6ae . ?ў) (#x6af . ?џ) (#x6b0 . ?№) @@ -594,6 +599,7 @@ as returned by `x-server-vendor'." (#x6ba . ?Њ) (#x6bb . ?Ћ) (#x6bc . ?Ќ) + (#x6bd . ?Ґ) ;; Source: keysymdef.h (#x6be . ?Ў) (#x6bf . ?Џ) (#x6c0 . ?ю) @@ -810,6 +816,7 @@ as returned by `x-server-vendor'." (#xaa8 . ? ) (#xaa9 . ?—) (#xaaa . ?–) + (#xaac . ?␣) ;; Source: keysymdef.h (#xaae . ?…) (#xaaf . ?‥) (#xab0 . ?⅓) @@ -822,7 +829,17 @@ as returned by `x-server-vendor'." (#xab7 . ?⅚) (#xab8 . ?℅) (#xabb . ?‒) + ;; In keysymdef.h, the keysyms 0xabc and 0xabe are listed as + ;; U+27E8 and U+27E9 respectively. However, the parentheses + ;; indicate that these mappings are deprecated legacy keysyms + ;; that are either not one-to-one or semantically unclear. In + ;; order to not introduce any incompatibility with possible + ;; existing workflows that expect these keysyms to map as they + ;; currently do, to 0x2329 and 0x232a, respectively, they are + ;; left as they are. In particular, PuTTY is known to agree + ;; with this mapping. (#xabc . ?〈) + (#xabd . ?.) ;; Source: keysymdef.h (#xabe . ?〉) (#xac3 . ?⅛) (#xac4 . ?⅜) @@ -839,6 +856,7 @@ as returned by `x-server-vendor'." (#xad2 . ?“) (#xad3 . ?”) (#xad4 . ?℞) + (#xad5 . ?‰) ;; Source: keysymdef.h (#xad6 . ?′) (#xad7 . ?″) (#xad9 . ?✝) @@ -883,20 +901,29 @@ as returned by `x-server-vendor'." (#xba8 . ?∨) (#xba9 . ?∧) (#xbc0 . ?¯) - (#xbc2 . ?⊥) + ;; Source for #xbc2: keysymdef.h. Note that the + ;; `KEYSYM Encoding' appendix to the X protocol definition is + ;; incorrect. + (#xbc2 . ?⊤) (#xbc3 . ?∩) (#xbc4 . ?⌊) (#xbc6 . ?_) (#xbca . ?∘) (#xbcc . ?⎕) - (#xbce . ?⊤) + ;; Source for #xbce: keysymdef.h. Note that the + ;; `KEYSYM Encoding' appendix to the X protocol definition is + ;; incorrect. + (#xbce . ?⊥) (#xbcf . ?○) (#xbd3 . ?⌈) (#xbd6 . ?∪) (#xbd8 . ?⊃) (#xbda . ?⊂) - (#xbdc . ?⊢) - (#xbfc . ?⊣) + ;; Source for #xbdc and #xbfc: keysymdef.h. Note that the + ;; `KEYSYM Encoding' appendix to the X protocol definition is + ;; incorrect. + (#xbdc . ?⊣) + (#xbfc . ?⊢) ;; Hebrew (#xcdf . ?‗) (#xce0 . ?א) @@ -1143,6 +1170,9 @@ as returned by `x-server-vendor'." ;; #x0aff CURSOR Publish ;; #x0dde THAI MAIHANAKAT Thai +;; However, keysymdef.h does have mappings for #x0aac and #x0abd, which +;; are used above. + ;;;; Selections commit 3026af7744c6eed59067bfa12be1df226d8c0d64 Author: Stefan Kangas Date: Fri Sep 13 21:23:24 2019 +0200 Add bug reporting and link the manual on the about screen * lisp/startup.el (fancy-about-text, normal-about-screen): Clarify that "Contribute" also describes how to report bugs. Add new link "Emacs Manual". (Bug#20697) diff --git a/lisp/startup.el b/lisp/startup.el index 863e9aed16..52d4dbb05c 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -1640,7 +1640,7 @@ Each element in the list should be a list of strings or pairs "\tMany people have contributed code included in GNU Emacs\n" :link ("Contributing" ,(lambda (_button) (info "(emacs)Contributing"))) - "\tHow to contribute improvements to Emacs\n" + "\tHow to report bugs and contribute improvements to Emacs\n" "\n" :link ("GNU and Freedom" ,(lambda (_button) (describe-gnu-project))) "\tWhy we developed GNU Emacs, and the GNU operating system\n" @@ -1682,7 +1682,9 @@ Each element in the list should be a list of strings or pairs ,(lambda (_button) (browse-url "https://www.gnu.org/software/emacs/tour/")) "Browse https://www.gnu.org/software/emacs/tour/") - "\tSee an overview of Emacs features at gnu.org")) + "\tSee an overview of Emacs features at gnu.org\n" + :link ("Emacs Manual" ,(lambda (_button) (info-emacs-manual))) + "\tDisplay the Emacs manual in Info mode")) "A list of texts to show in the middle part of the About screen. Each element in the list should be a list of strings or pairs `:face FACE', like `fancy-splash-insert' accepts them.") @@ -2219,7 +2221,7 @@ Type \\[describe-distribution] for information on ")) 'action (lambda (_button) (info "(emacs)Contributing")) 'follow-link t) - (insert "\tHow to contribute improvements to Emacs\n\n") + (insert "\tHow to report bugs and contribute improvements to Emacs\n\n") (insert-button "GNU and Freedom" 'action (lambda (_button) (describe-gnu-project))