diff options
| author | Eli Zaretskii | 2020-03-25 15:59:19 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2020-03-25 15:59:19 +0200 |
| commit | b85d29f4fd555eda34ffba5b9a6006b5758e2955 (patch) | |
| tree | a41cac4cced340b143401eb36517b9010a59e122 | |
| parent | ed37f038bd6d99fbe0c746d5773c315fed0e3dad (diff) | |
| parent | ce141686d2d890d9d7c3dd881dc5f9bfb5d6d296 (diff) | |
| download | emacs-b85d29f4fd555eda34ffba5b9a6006b5758e2955.tar.gz emacs-b85d29f4fd555eda34ffba5b9a6006b5758e2955.zip | |
Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs
| -rw-r--r-- | etc/NEWS | 16 | ||||
| -rw-r--r-- | lisp/dired.el | 33 | ||||
| -rw-r--r-- | lisp/image/gravatar.el | 43 | ||||
| -rw-r--r-- | test/lisp/image/gravatar-tests.el | 2 |
4 files changed, 73 insertions, 21 deletions
| @@ -104,8 +104,8 @@ shows equivalent key bindings for all commands that have them. | |||
| 104 | *** New option 'dired-mark-region' affects all Dired commands that mark files. | 104 | *** New option 'dired-mark-region' affects all Dired commands that mark files. |
| 105 | When non-nil and the region is active in Transient Mark mode, | 105 | When non-nil and the region is active in Transient Mark mode, |
| 106 | then Dired commands operate only on files in the active region. | 106 | then Dired commands operate only on files in the active region. |
| 107 | The values 'exclusive' and 'inclusive' of this option define | 107 | The values 'file' and 'line' of this option define the details of |
| 108 | the details of marking the last file at the end of the region. | 108 | marking the file at the end of the region. |
| 109 | 109 | ||
| 110 | *** State changing VC operations are supported in dired-mode on files | 110 | *** State changing VC operations are supported in dired-mode on files |
| 111 | (but still not on directories). | 111 | (but still not on directories). |
| @@ -114,7 +114,11 @@ the details of marking the last file at the end of the region. | |||
| 114 | 114 | ||
| 115 | --- | 115 | --- |
| 116 | *** Change to default value of 'message-draft-headers' option. | 116 | *** Change to default value of 'message-draft-headers' option. |
| 117 | No longer includes the Date header. | 117 | The Date header has been removed from the default value, meaning that |
| 118 | draft or delayed messages will get a Date reflecting when the message | ||
| 119 | was sent. To restore the original behavior of dating a message | ||
| 120 | from when it is first saved or delayed, add the symbol 'Date back to | ||
| 121 | this option. | ||
| 118 | 122 | ||
| 119 | ** Help | 123 | ** Help |
| 120 | 124 | ||
| @@ -186,6 +190,12 @@ key binding | |||
| 186 | / v package-menu-filter-by-version | 190 | / v package-menu-filter-by-version |
| 187 | / / package-menu-filter-clear | 191 | / / package-menu-filter-clear |
| 188 | 192 | ||
| 193 | ** Gravatar | ||
| 194 | |||
| 195 | --- | ||
| 196 | *** New user option 'gravatar-service' for host to query for gravatars. | ||
| 197 | Defaults to Libravatar, with Unicornify and Gravatar as options. | ||
| 198 | |||
| 189 | 199 | ||
| 190 | * New Modes and Packages in Emacs 28.1 | 200 | * New Modes and Packages in Emacs 28.1 |
| 191 | 201 | ||
diff --git a/lisp/dired.el b/lisp/dired.el index 438f5e7d8b4..41bbf9f56a2 100644 --- a/lisp/dired.el +++ b/lisp/dired.el | |||
| @@ -296,7 +296,7 @@ new Dired buffers." | |||
| 296 | :version "26.1" | 296 | :version "26.1" |
| 297 | :group 'dired) | 297 | :group 'dired) |
| 298 | 298 | ||
| 299 | (defcustom dired-mark-region 'exclusive | 299 | (defcustom dired-mark-region 'file |
| 300 | "Defines what commands that mark files do with the active region. | 300 | "Defines what commands that mark files do with the active region. |
| 301 | 301 | ||
| 302 | When nil, marking commands don't operate on all files in the | 302 | When nil, marking commands don't operate on all files in the |
| @@ -306,7 +306,8 @@ When the value of this option is non-nil, then all Dired commands | |||
| 306 | that mark or unmark files will operate on all files in the region | 306 | that mark or unmark files will operate on all files in the region |
| 307 | if the region is active in Transient Mark mode. | 307 | if the region is active in Transient Mark mode. |
| 308 | 308 | ||
| 309 | When `exclusive', don't mark the file if the end of the region is | 309 | When `file', the region marking is based on the file name. |
| 310 | This means don't mark the file if the end of the region is | ||
| 310 | before the file name displayed on the Dired line, so the file name | 311 | before the file name displayed on the Dired line, so the file name |
| 311 | is visually outside the region. This behavior is consistent with | 312 | is visually outside the region. This behavior is consistent with |
| 312 | marking files without the region using the key `m' that advances | 313 | marking files without the region using the key `m' that advances |
| @@ -315,12 +316,13 @@ of keys used to mark files is the same as the number of keys | |||
| 315 | used to select the region, e.g. `M-2 m' marks 2 files, and | 316 | used to select the region, e.g. `M-2 m' marks 2 files, and |
| 316 | `C-SPC M-2 n m' marks 2 files, and `M-2 S-down m' marks 2 files. | 317 | `C-SPC M-2 n m' marks 2 files, and `M-2 S-down m' marks 2 files. |
| 317 | 318 | ||
| 318 | When `inclusive', include the file into marking if the end of the region | 319 | When `line', the region marking is based on Dired lines, |
| 320 | so include the file into marking if the end of the region | ||
| 319 | is anywhere on its Dired line, except the beginning of the line." | 321 | is anywhere on its Dired line, except the beginning of the line." |
| 320 | :type '(choice | 322 | :type '(choice |
| 321 | (const :tag "Don't mark files in active region" nil) | 323 | (const :tag "Don't mark files in active region" nil) |
| 322 | (const :tag "Exclude file name outside of region" exclusive) | 324 | (const :tag "Exclude file name outside of region" file) |
| 323 | (const :tag "Include the file at region end line" inclusive)) | 325 | (const :tag "Include the file at region end line" line)) |
| 324 | :group 'dired | 326 | :group 'dired |
| 325 | :version "28.1") | 327 | :version "28.1") |
| 326 | 328 | ||
| @@ -646,16 +648,19 @@ of the region if `dired-mark-region' is non-nil. Otherwise, operate | |||
| 646 | on the whole buffer. | 648 | on the whole buffer. |
| 647 | 649 | ||
| 648 | Return value is the number of files marked, or nil if none were marked." | 650 | Return value is the number of files marked, or nil if none were marked." |
| 649 | `(let ((inhibit-read-only t) count | 651 | `(let* ((inhibit-read-only t) count |
| 650 | (beg (if (and dired-mark-region (use-region-p)) | 652 | (use-region-p (and dired-mark-region |
| 653 | (region-active-p) | ||
| 654 | (> (region-end) (region-beginning)))) | ||
| 655 | (beg (if use-region-p | ||
| 651 | (save-excursion | 656 | (save-excursion |
| 652 | (goto-char (region-beginning)) | 657 | (goto-char (region-beginning)) |
| 653 | (line-beginning-position)) | 658 | (line-beginning-position)) |
| 654 | (point-min))) | 659 | (point-min))) |
| 655 | (end (if (and dired-mark-region (use-region-p)) | 660 | (end (if use-region-p |
| 656 | (save-excursion | 661 | (save-excursion |
| 657 | (goto-char (region-end)) | 662 | (goto-char (region-end)) |
| 658 | (if (if (eq dired-mark-region 'inclusive) | 663 | (if (if (eq dired-mark-region 'line) |
| 659 | (not (bolp)) | 664 | (not (bolp)) |
| 660 | (get-text-property (1- (point)) 'dired-filename)) | 665 | (get-text-property (1- (point)) 'dired-filename)) |
| 661 | (line-end-position) | 666 | (line-end-position) |
| @@ -673,7 +678,7 @@ Return value is the number of files marked, or nil if none were marked." | |||
| 673 | (if (eq dired-del-marker dired-marker-char) | 678 | (if (eq dired-del-marker dired-marker-char) |
| 674 | " for deletion" | 679 | " for deletion" |
| 675 | "") | 680 | "") |
| 676 | (if (and dired-mark-region (use-region-p)) | 681 | (if use-region-p |
| 677 | " in region" | 682 | " in region" |
| 678 | ""))) | 683 | ""))) |
| 679 | (goto-char beg) | 684 | (goto-char beg) |
| @@ -691,7 +696,7 @@ Return value is the number of files marked, or nil if none were marked." | |||
| 691 | (if (eq dired-marker-char ?\s) "un" "") | 696 | (if (eq dired-marker-char ?\s) "un" "") |
| 692 | (if (eq dired-marker-char dired-del-marker) | 697 | (if (eq dired-marker-char dired-del-marker) |
| 693 | "flagged" "marked") | 698 | "flagged" "marked") |
| 694 | (if (and dired-mark-region (use-region-p)) | 699 | (if use-region-p |
| 695 | " in region" | 700 | " in region" |
| 696 | "")))) | 701 | "")))) |
| 697 | (and (> count 0) count))) | 702 | (and (> count 0) count))) |
| @@ -3645,14 +3650,16 @@ this subdir." | |||
| 3645 | (interactive (list current-prefix-arg t)) | 3650 | (interactive (list current-prefix-arg t)) |
| 3646 | (cond | 3651 | (cond |
| 3647 | ;; Mark files in the active region. | 3652 | ;; Mark files in the active region. |
| 3648 | ((and dired-mark-region interactive (use-region-p)) | 3653 | ((and interactive dired-mark-region |
| 3654 | (region-active-p) | ||
| 3655 | (> (region-end) (region-beginning))) | ||
| 3649 | (save-excursion | 3656 | (save-excursion |
| 3650 | (let ((beg (region-beginning)) | 3657 | (let ((beg (region-beginning)) |
| 3651 | (end (region-end))) | 3658 | (end (region-end))) |
| 3652 | (dired-mark-files-in-region | 3659 | (dired-mark-files-in-region |
| 3653 | (progn (goto-char beg) (line-beginning-position)) | 3660 | (progn (goto-char beg) (line-beginning-position)) |
| 3654 | (progn (goto-char end) | 3661 | (progn (goto-char end) |
| 3655 | (if (if (eq dired-mark-region 'inclusive) | 3662 | (if (if (eq dired-mark-region 'line) |
| 3656 | (not (bolp)) | 3663 | (not (bolp)) |
| 3657 | (get-text-property (1- (point)) 'dired-filename)) | 3664 | (get-text-property (1- (point)) 'dired-filename)) |
| 3658 | (line-end-position) | 3665 | (line-end-position) |
diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el index b8542bc3c35..ff59a72ac87 100644 --- a/lisp/image/gravatar.el +++ b/lisp/image/gravatar.el | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | (require 'url) | 27 | (require 'url) |
| 28 | (require 'url-cache) | 28 | (require 'url-cache) |
| 29 | (require 'dns) | ||
| 29 | (eval-when-compile | 30 | (eval-when-compile |
| 30 | (require 'subr-x)) | 31 | (require 'subr-x)) |
| 31 | 32 | ||
| @@ -118,9 +119,42 @@ a gravatar for a given email address." | |||
| 118 | :version "27.1" | 119 | :version "27.1" |
| 119 | :group 'gravatar) | 120 | :group 'gravatar) |
| 120 | 121 | ||
| 121 | (defconst gravatar-base-url | 122 | (defconst gravatar-service-alist |
| 122 | "https://www.gravatar.com/avatar" | 123 | `((gravatar . ,(lambda (_addr) "https://www.gravatar.com/avatar")) |
| 123 | "Base URL for getting gravatars.") | 124 | (unicornify . ,(lambda (_addr) "https://unicornify.pictures/avatar/")) |
| 125 | (libravatar . ,#'gravatar--service-libravatar)) | ||
| 126 | "Alist of supported gravatar services.") | ||
| 127 | |||
| 128 | (defcustom gravatar-service 'libravatar | ||
| 129 | "Symbol denoting gravatar-like service to use. | ||
| 130 | Note that certain services might ignore other options, such as | ||
| 131 | `gravatar-default-image' or certain values as with | ||
| 132 | `gravatar-rating'." | ||
| 133 | :type `(choice ,@(mapcar (lambda (s) `(const ,(car s))) | ||
| 134 | gravatar-service-alist)) | ||
| 135 | :version "28.1" | ||
| 136 | :link '(url-link "https://www.libravatar.org/") | ||
| 137 | :link '(url-link "https://unicornify.pictures/") | ||
| 138 | :link '(url-link "https://gravatar.com/") | ||
| 139 | :group 'gravatar) | ||
| 140 | |||
| 141 | (defun gravatar--service-libravatar (addr) | ||
| 142 | "Find domain that hosts avatars for email address ADDR." | ||
| 143 | ;; implements https://wiki.libravatar.org/api/ | ||
| 144 | (save-match-data | ||
| 145 | (if (not (string-match ".+@\\(.+\\)" addr)) | ||
| 146 | "https://seccdn.libravatar.org/avatar" | ||
| 147 | (let ((domain (match-string 1 addr))) | ||
| 148 | (catch 'found | ||
| 149 | (dolist (record '(("_avatars-sec" . "https") | ||
| 150 | ("_avatars" . "http"))) | ||
| 151 | (let* ((query (concat (car record) "._tcp." domain)) | ||
| 152 | (result (dns-query query 'SRV))) | ||
| 153 | (when result | ||
| 154 | (throw 'found (format "%s://%s/avatar" | ||
| 155 | (cdr record) | ||
| 156 | result))))) | ||
| 157 | "https://seccdn.libravatar.org/avatar"))))) | ||
| 124 | 158 | ||
| 125 | (defun gravatar-hash (mail-address) | 159 | (defun gravatar-hash (mail-address) |
| 126 | "Return the Gravatar hash for MAIL-ADDRESS." | 160 | "Return the Gravatar hash for MAIL-ADDRESS." |
| @@ -142,7 +176,8 @@ a gravatar for a given email address." | |||
| 142 | "Return the URL of a gravatar for MAIL-ADDRESS." | 176 | "Return the URL of a gravatar for MAIL-ADDRESS." |
| 143 | ;; https://gravatar.com/site/implement/images/ | 177 | ;; https://gravatar.com/site/implement/images/ |
| 144 | (format "%s/%s?%s" | 178 | (format "%s/%s?%s" |
| 145 | gravatar-base-url | 179 | (funcall (alist-get gravatar-service gravatar-service-alist) |
| 180 | mail-address) | ||
| 146 | (gravatar-hash mail-address) | 181 | (gravatar-hash mail-address) |
| 147 | (gravatar--query-string))) | 182 | (gravatar--query-string))) |
| 148 | 183 | ||
diff --git a/test/lisp/image/gravatar-tests.el b/test/lisp/image/gravatar-tests.el index e66b5c6803d..66098fa0116 100644 --- a/test/lisp/image/gravatar-tests.el +++ b/test/lisp/image/gravatar-tests.el | |||
| @@ -67,6 +67,6 @@ | |||
| 67 | (gravatar-force-default nil) | 67 | (gravatar-force-default nil) |
| 68 | (gravatar-size nil)) | 68 | (gravatar-size nil)) |
| 69 | (should (equal (gravatar-build-url "foo") "\ | 69 | (should (equal (gravatar-build-url "foo") "\ |
| 70 | https://www.gravatar.com/avatar/acbd18db4cc2f85cedef654fccc4a4d8?r=g")))) | 70 | https://seccdn.libravatar.org/avatar/acbd18db4cc2f85cedef654fccc4a4d8?r=g")))) |
| 71 | 71 | ||
| 72 | ;;; gravatar-tests.el ends here | 72 | ;;; gravatar-tests.el ends here |