commit cdbbc2081ed2da3a641926e76341ed413fb5b9f9 (HEAD, refs/remotes/origin/master) Author: Stefan Kangas Date: Sat Aug 8 01:20:01 2020 +0200 Use lexical-binding in saveplace.el and add tests * lisp/saveplace.el: Use lexical-binding. (save-place-to-alist): Doc fix. * test/lisp/saveplace-tests.el: * test/lisp/saveplace-resources/saveplace: New files. diff --git a/lisp/saveplace.el b/lisp/saveplace.el index 46738ab03d..d420bfb4e9 100644 --- a/lisp/saveplace.el +++ b/lisp/saveplace.el @@ -1,4 +1,4 @@ -;;; saveplace.el --- automatically save place in files +;;; saveplace.el --- automatically save place in files -*- lexical-binding:t -*- ;; Copyright (C) 1993-1994, 2001-2020 Free Software Foundation, Inc. @@ -42,7 +42,6 @@ "Automatically save place in files." :group 'data) - (defvar save-place-alist nil "Alist of saved places to go back to when revisiting files. Each element looks like (FILENAME . POSITION); @@ -175,10 +174,11 @@ file: (declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep)) (defun save-place-to-alist () - ;; put filename and point in a cons box and then cons that onto the - ;; front of the save-place-alist, if save-place-mode is non-nil. - ;; Otherwise, just delete that file from the alist. - ;; first check to make sure alist has been loaded in from the master + "Add current buffer filename and position to `save-place-alist'. +Put filename and point in a cons box and then cons that onto the +front of the `save-place-alist', if `save-place-mode' is non-nil. +Otherwise, just delete that file from the alist." + ;; First check to make sure alist has been loaded in from the master ;; file. If not, do so, then feel free to modify the alist. It ;; will be saved again when Emacs is killed. (or save-place-loaded (load-save-place-alist-from-file)) diff --git a/test/lisp/saveplace-resources/saveplace b/test/lisp/saveplace-resources/saveplace new file mode 100644 index 0000000000..3f3f6d501d --- /dev/null +++ b/test/lisp/saveplace-resources/saveplace @@ -0,0 +1,4 @@ +;;; -*- coding: utf-8 -*- +(("/home/skangas/.emacs.d/cache/recentf" . 1306) + ("/home/skangas/wip/emacs/" + (dired-filename . "/home/skangas/wip/emacs/COPYING"))) diff --git a/test/lisp/saveplace-tests.el b/test/lisp/saveplace-tests.el new file mode 100644 index 0000000000..ae7749fe93 --- /dev/null +++ b/test/lisp/saveplace-tests.el @@ -0,0 +1,103 @@ +;;; saveplace-tests.el --- Tests for saveplace.el -*- lexical-binding:t -*- + +;; Copyright (C) 2019-2020 Free Software Foundation, Inc. + +;; Author: Stefan Kangas + +;; 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: + +(require 'ert) +(require 'saveplace) + +(defvar saveplace-tests-dir + (file-truename + (expand-file-name "saveplace-resources" + (file-name-directory (or load-file-name + buffer-file-name))))) + +(ert-deftest saveplace-test-save-place-to-alist/dir () + (save-place-mode) + (let* ((save-place-alist nil) + (save-place-loaded t) + (loc saveplace-tests-dir)) + (save-window-excursion + (dired loc) + (save-place-to-alist) + (should (equal save-place-alist + `((,(concat loc "/") + (dired-filename . ,(concat loc "/saveplace"))))))))) + +(ert-deftest saveplace-test-save-place-to-alist/file () + (save-place-mode) + (let* ((tmpfile (make-temp-file "emacs-test-saveplace-")) + (save-place-alist nil) + (save-place-loaded t) + (loc tmpfile) + (pos 4)) + (unwind-protect + (save-window-excursion + (find-file loc) + (insert "abc") ; must insert something + (save-place-to-alist) + (should (equal save-place-alist (list (cons tmpfile pos))))) + (delete-file tmpfile)))) + +(ert-deftest saveplace-test-forget-unreadable-files () + (save-place-mode) + (let* ((save-place-loaded t) + (tmpfile (make-temp-file "emacs-test-saveplace-")) + (alist-orig (list (cons "/this/file/does/not/exist" 10) + (cons tmpfile 1917))) + (save-place-alist alist-orig)) + (unwind-protect + (progn + (save-place-forget-unreadable-files) + (should (equal save-place-alist (cdr alist-orig)))) + (delete-file tmpfile)))) + +(ert-deftest saveplace-test-place-alist-to-file () + (save-place-mode) + (let* ((tmpfile (make-temp-file "emacs-test-saveplace-")) + (tmpfile2 (make-temp-file "emacs-test-saveplace-")) + (save-place-file tmpfile) + (save-place-alist (list (cons tmpfile2 99)))) + (unwind-protect + (progn (save-place-alist-to-file) + (setq save-place-alist nil) + (save-window-excursion + (find-file save-place-file) + (unwind-protect + (should (string-match tmpfile2 (buffer-string))) + (kill-buffer)))) + (delete-file tmpfile) + (delete-file tmpfile2)))) + +(ert-deftest saveplace-test-load-alist-from-file () + (save-place-mode) + (let ((save-place-loaded nil) + (save-place-file + (expand-file-name "saveplace" saveplace-tests-dir)) + (save-place-alist nil)) + (load-save-place-alist-from-file) + (should (equal save-place-alist + '(("/home/skangas/.emacs.d/cache/recentf" . 1306) + ("/home/skangas/wip/emacs/" + (dired-filename . "/home/skangas/wip/emacs/COPYING"))))))) + +(provide 'saveplace-tests) +;;; saveplace-tests.el ends here commit 67ffffa66654236ded2cf121cb3139b07d2ac5c8 Author: Stefan Kangas Date: Fri Aug 7 19:40:31 2020 +0200 * lisp/scroll-lock.el: Use lexical-binding. diff --git a/lisp/scroll-lock.el b/lisp/scroll-lock.el index 3a6d9d3642..f20ea1bcc8 100644 --- a/lisp/scroll-lock.el +++ b/lisp/scroll-lock.el @@ -1,4 +1,4 @@ -;;; scroll-lock.el --- Scroll lock scrolling. +;;; scroll-lock.el --- Scroll lock scrolling. -*- lexical-binding:t -*- ;; Copyright (C) 2005-2020 Free Software Foundation, Inc. commit 7196abecb5f5c3cc1282280d2d337b6a86761656 Author: Simen Heggestøyl Date: Tue Jun 16 21:32:58 2020 +0200 Use lexical-binding in browse-url.el and add tests * lisp/net/browse-url.el: Turn on lexical-binding. (browse-url--mailto, browse-url--man, browse-url--browser): Use imperative form in docstrings. (browse-url-delete-temp-file): Turn comment into a proper docstring. * test/lisp/net/browse-url-tests.el: New file with tests for browse-url.el. diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 7c2fde98cc..2b8d4d0ce6 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -1,4 +1,4 @@ -;;; browse-url.el --- pass a URL to a WWW browser +;;; browse-url.el --- pass a URL to a WWW browser -*- lexical-binding: t; -*- ;; Copyright (C) 1995-2020 Free Software Foundation, Inc. @@ -587,7 +587,7 @@ process), or nil (we don't know)." kind))) (defun browse-url--mailto (url &rest args) - "Calls `browse-url-mailto-function' with URL and ARGS." + "Call `browse-url-mailto-function' with URL and ARGS." (funcall browse-url-mailto-function url args)) (defun browse-url--browser-kind-mailto (url) @@ -596,7 +596,7 @@ process), or nil (we don't know)." #'browse-url--browser-kind-mailto) (defun browse-url--man (url &rest args) - "Calls `browse-url-man-function' with URL and ARGS." + "Call `browse-url-man-function' with URL and ARGS." (funcall browse-url-man-function url args)) (defun browse-url--browser-kind-man (url) @@ -605,7 +605,7 @@ process), or nil (we don't know)." #'browse-url--browser-kind-man) (defun browse-url--browser (url &rest args) - "Calls `browse-url-browser-function' with URL and ARGS." + "Call `browse-url-browser-function' with URL and ARGS." (funcall browse-url-browser-function url args)) (defun browse-url--browser-kind-browser (url) @@ -819,8 +819,8 @@ narrowed." (browse-url-of-file file-name)))) (defun browse-url-delete-temp-file (&optional temp-file-name) - ;; Delete browse-url-temp-file-name from the file system - ;; If optional arg TEMP-FILE-NAME is non-nil, delete it instead + "Delete `browse-url-temp-file-name' from the file system. +If optional arg TEMP-FILE-NAME is non-nil, delete it instead." (let ((file-name (or temp-file-name browse-url-temp-file-name))) (if (and file-name (file-exists-p file-name)) (delete-file file-name)))) diff --git a/test/lisp/net/browse-url-tests.el b/test/lisp/net/browse-url-tests.el new file mode 100644 index 0000000000..b2b27d2ae7 --- /dev/null +++ b/test/lisp/net/browse-url-tests.el @@ -0,0 +1,119 @@ +;;; browse-url-tests.el --- Tests for browse-url.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2020 Free Software Foundation, Inc. + +;; Author: Simen Heggestøyl +;; Keywords: + +;; 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: + +;; + +;;; Code: + +(require 'browse-url) +(require 'ert) + +(ert-deftest browse-url-tests-browser-kind () + (should (eq (browse-url--browser-kind #'browse-url-w3 "gnu.org") + 'internal)) + (should + (eq (browse-url--browser-kind #'browse-url-firefox "gnu.org") + 'external))) + +(ert-deftest browse-url-tests-non-html-file-url-p () + (should (browse-url--non-html-file-url-p "file://foo.txt")) + (should-not (browse-url--non-html-file-url-p "file://foo.html"))) + +(ert-deftest browse-url-tests-select-handler-mailto () + (should (eq (browse-url-select-handler "mailto:foo@bar.org") + 'browse-url--mailto)) + (should (eq (browse-url-select-handler "mailto:foo@bar.org" + 'internal) + 'browse-url--mailto)) + (should-not (browse-url-select-handler "mailto:foo@bar.org" + 'external))) + +(ert-deftest browse-url-tests-select-handler-man () + (should (eq (browse-url-select-handler "man:ls") 'browse-url--man)) + (should (eq (browse-url-select-handler "man:ls" 'internal) + 'browse-url--man)) + (should-not (browse-url-select-handler "man:ls" 'external))) + +(ert-deftest browse-url-tests-select-handler-file () + (should (eq (browse-url-select-handler "file://foo.txt") + 'browse-url-emacs)) + (should (eq (browse-url-select-handler "file://foo.txt" 'internal) + 'browse-url-emacs)) + (should-not (browse-url-select-handler "file://foo.txt" 'external))) + +(ert-deftest browse-url-tests-url-encode-chars () + (should (equal (browse-url-url-encode-chars "foobar" "[ob]") + "f%6F%6F%62ar"))) + +(ert-deftest browse-url-tests-encode-url () + (should (equal (browse-url-encode-url "") "")) + (should (equal (browse-url-encode-url "a b c") "a b c")) + (should (equal (browse-url-encode-url "\"a\" \"b\"") + "\"a%22\"b\"")) + (should (equal (browse-url-encode-url "(a) (b)") "(a%29(b)")) + (should (equal (browse-url-encode-url "a$ b$") "a%24b$"))) + +(ert-deftest browse-url-tests-url-at-point () + (with-temp-buffer + (insert "gnu.org") + (should (equal (browse-url-url-at-point) "http://gnu.org")))) + +(ert-deftest browse-url-tests-file-url () + (should (equal (browse-url-file-url "/foo") "file:///foo")) + (should (equal (browse-url-file-url "/foo:") "ftp://foo/")) + (should (equal (browse-url-file-url "/ftp@foo:") "ftp://foo/")) + (should (equal (browse-url-file-url "/anonymous@foo:") + "ftp://foo/"))) + +(ert-deftest browse-url-tests-delete-temp-file () + (let ((browse-url-temp-file-name + (make-temp-file "browse-url-tests-"))) + (browse-url-delete-temp-file) + (should-not (file-exists-p browse-url-temp-file-name))) + (let ((file (make-temp-file "browse-url-tests-"))) + (browse-url-delete-temp-file file) + (should-not (file-exists-p file)))) + +(ert-deftest browse-url-tests-add-buttons () + (with-temp-buffer + (insert "Visit https://gnu.org") + (goto-char (point-min)) + (browse-url-add-buttons) + (goto-char (- (point-max) 1)) + (should (eq (get-text-property (point) 'face) + 'browse-url-button)) + (should (get-text-property (point) 'browse-url-data)))) + +(ert-deftest browse-url-tests-button-copy () + (with-temp-buffer + (insert "Visit https://gnu.org") + (goto-char (point-min)) + (browse-url-add-buttons) + (should-error (browse-url-button-copy)) + (goto-char (- (point-max) 1)) + (browse-url-button-copy) + (should (equal (car kill-ring) "https://gnu.org")))) + +(provide 'browse-url-tests) +;;; browse-url-tests.el ends here commit 3e39aa6cfa6822b535d597b3e59abfea38610a48 Author: Stefan Kangas Date: Fri Aug 7 14:42:41 2020 +0200 Remove support for Mosaic from browse-url * lisp/net/browse-url.el (browse-url-mosaic-program) (browse-url-mosaic-arguments, browse-url-mosaic-pidfile) (browse-url-CCI-port, browse-url-CCI-host) (browse-url-default-browser, browse-url-mosaic, browse-url-cci): Remove support for the Mosaic browser, which saw its last release in 1997, or 23 years ago. * etc/NEWS: Announce its removal. diff --git a/etc/NEWS b/etc/NEWS index dcd8ea6a9b..850b166069 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -547,6 +547,9 @@ either an internal or external browser. *** Support for the conkeror browser is now obsolete. +*** Support for the Mosaic browser has been removed. +This support has been obsolete since 25.1. + ** SHR --- diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 8892e800cd..7c2fde98cc 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -425,25 +425,6 @@ Passing an interactive argument to \\[browse-url], or specific browser commands reverses the effect of this variable." :type 'boolean) -(defcustom browse-url-mosaic-program "xmosaic" - "The name by which to invoke Mosaic (or mMosaic)." - :type 'string - :version "20.3") - -(make-obsolete-variable 'browse-url-mosaic-program nil "25.1") - -(defcustom browse-url-mosaic-arguments nil - "A list of strings to pass to Mosaic as arguments." - :type '(repeat (string :tag "Argument"))) - -(make-obsolete-variable 'browse-url-mosaic-arguments nil "25.1") - -(defcustom browse-url-mosaic-pidfile "~/.mosaicpid" - "The name of the pidfile created by Mosaic." - :type 'string) - -(make-obsolete-variable 'browse-url-mosaic-pidfile nil "25.1") - (defcustom browse-url-conkeror-program "conkeror" "The name by which to invoke Conkeror." :type 'string @@ -498,22 +479,6 @@ Used by the `browse-url-of-file' command." "Hook run after `browse-url-of-file' has asked a browser to load a file." :type 'hook) -(defcustom browse-url-CCI-port 3003 - "Port to access XMosaic via CCI. -This can be any number between 1024 and 65535 but must correspond to -the value set in the browser." - :type 'integer) - -(make-obsolete-variable 'browse-url-CCI-port nil "25.1") - -(defcustom browse-url-CCI-host "localhost" - "Host to access XMosaic via CCI. -This should be the host name of the machine running XMosaic with CCI -enabled. The port number should be set in `browse-url-CCI-port'." - :type 'string) - -(make-obsolete-variable 'browse-url-CCI-host nil "25.1") - (defvar browse-url-temp-file-name nil) (make-variable-buffer-local 'browse-url-temp-file-name) @@ -1075,8 +1040,6 @@ instead of `browse-url-new-window-flag'." ;;; ((executable-find browse-url-galeon-program) 'browse-url-galeon) ((executable-find browse-url-kde-program) 'browse-url-kde) ;;; ((executable-find browse-url-netscape-program) 'browse-url-netscape) -;;; ((executable-find browse-url-mosaic-program) 'browse-url-mosaic) -;;; ((executable-find browse-url-conkeror-program) 'browse-url-conkeror) ((executable-find browse-url-chrome-program) 'browse-url-chrome) ((executable-find browse-url-xterm-program) 'browse-url-text-xterm) ((locate-library "w3") 'browse-url-w3) @@ -1444,93 +1407,6 @@ used instead of `browse-url-new-window-flag'." (function-put 'browse-url-gnome-moz 'browse-url-browser-kind 'external) -;; --- Mosaic --- - -;;;###autoload -(defun browse-url-mosaic (url &optional new-window) - "Ask the XMosaic WWW browser to load URL. - -Default to the URL around or before point. The strings in variable -`browse-url-mosaic-arguments' are also passed to Mosaic and the -program is invoked according to the variable -`browse-url-mosaic-program'. - -When called interactively, if variable `browse-url-new-window-flag' is -non-nil, load the document in a new Mosaic window, otherwise use a -random existing one. A non-nil interactive prefix argument reverses -the effect of `browse-url-new-window-flag'. - -When called non-interactively, optional second argument NEW-WINDOW is -used instead of `browse-url-new-window-flag'." - (declare (obsolete nil "25.1")) - (interactive (browse-url-interactive-arg "Mosaic URL: ")) - (let ((pidfile (expand-file-name browse-url-mosaic-pidfile)) - pid) - (if (file-readable-p pidfile) - (with-temp-buffer - (insert-file-contents pidfile) - (setq pid (read (current-buffer))))) - (if (and (integerp pid) (zerop (signal-process pid 0))) ; Mosaic running - (progn - (with-temp-buffer - (insert (if (browse-url-maybe-new-window new-window) - "newwin\n" - "goto\n") - url "\n") - (with-file-modes ?\700 - (if (file-exists-p - (setq pidfile (format "/tmp/Mosaic.%d" pid))) - (delete-file pidfile)) - ;; https://debbugs.gnu.org/17428. Use O_EXCL. - (write-region nil nil pidfile nil 'silent nil 'excl))) - ;; Send signal SIGUSR to Mosaic - (message "Signaling Mosaic...") - (signal-process pid 'SIGUSR1) - ;; Or you could try: - ;; (call-process "kill" nil 0 nil "-USR1" (int-to-string pid)) - (message "Signaling Mosaic...done")) - ;; Mosaic not running - start it - (message "Starting %s..." browse-url-mosaic-program) - (apply 'start-process "xmosaic" nil browse-url-mosaic-program - (append browse-url-mosaic-arguments (list url))) - (message "Starting %s...done" browse-url-mosaic-program)))) - -(function-put 'browse-url-mosaic 'browse-url-browser-kind 'external) - -;; --- Mosaic using CCI --- - -;;;###autoload -(defun browse-url-cci (url &optional new-window) - "Ask the XMosaic WWW browser to load URL. -Default to the URL around or before point. - -This function only works for XMosaic version 2.5 or later. You must -select `CCI' from XMosaic's File menu, set the CCI Port Address to the -value of variable `browse-url-CCI-port', and enable `Accept requests'. - -When called interactively, if variable `browse-url-new-window-flag' is -non-nil, load the document in a new browser window, otherwise use a -random existing one. A non-nil interactive prefix argument reverses -the effect of `browse-url-new-window-flag'. - -When called non-interactively, optional second argument NEW-WINDOW is -used instead of `browse-url-new-window-flag'." - (declare (obsolete nil "25.1")) - (interactive (browse-url-interactive-arg "Mosaic URL: ")) - (open-network-stream "browse-url" " *browse-url*" - browse-url-CCI-host browse-url-CCI-port) - ;; Todo: start browser if fails - (process-send-string "browse-url" - (concat "get url (" url ") output " - (if (browse-url-maybe-new-window new-window) - "new" - "current") - "\r\n")) - (process-send-string "browse-url" "disconnect\r\n") - (delete-process "browse-url")) - -(function-put 'browse-url-cci 'browse-url-browser-kind 'external) - ;; --- Conkeror --- ;;;###autoload (defun browse-url-conkeror (url &optional new-window) commit d0ad6306727067936c9c8717dfc4e3aae5774902 Author: Lars Ingebrigtsen Date: Fri Aug 7 14:07:14 2020 +0200 Fix fontification of %d in strings in cperl-mode * lisp/progmodes/cperl-mode.el (cperl-init-faces): Don't fontify directives like %d in strings as hashes (bug#22867). diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index 5ecd5668b3..6122caf518 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -5753,7 +5753,7 @@ indentation and initial hashes. Behaves usually outside of comment." (if (eq (char-after (match-beginning 2)) ?%) 'cperl-hash-face 'cperl-array-face) - t) ; arrays and hashes + nil) ; arrays and hashes ("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)" 1 (if (= (- (match-end 2) (match-beginning 2)) 1) commit 7ed61d6193629fa88d348221db3f1df7130a8bd3 Author: Stefan Kangas Date: Fri Aug 7 13:54:50 2020 +0200 Make more erc function aliases obsolete * lisp/erc/erc-compat.el (erc-propertize, erc-view-mode-enter) (erc-function-arglist, erc-delete-dups) (erc-replace-regexp-in-string): Make these aliases obsolete. * lisp/erc/erc-capab.el (erc-capab-identify-add-prefix) (erc-capab-identify-remove/set-identified-flag): * lisp/erc/erc-dcc.el (erc-dcc-chat-parse-output) (erc-dcc-unquote-filename, pcomplete/erc-mode/DCC): * lisp/erc/erc-list.el (erc-list-menu-mode, erc-list-button) (erc-list-make-string): * lisp/erc/erc-log.el (erc-log-standardize-name): * lisp/erc/erc-match.el (erc-log-matches-make-buffer): * lisp/erc/erc-networks.el (erc-server-select): * lisp/erc/erc.el (erc-message-english-PART) (erc-update-mode-line-buffer, erc-format-my-nick) (erc-format-@nick, erc-get-user-mode-prefix, erc-display-prompt) (erc-part-reason-zippy, erc-quit-reason-zippy, erc-get-arglist) (erc-toggle-debug-irc-protocol, erc-log-irc-protocol) (erc-migrate-modules): Adjust callers. diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el index fc45725f78..4afe6a7614 100644 --- a/lisp/erc/erc-capab.el +++ b/lisp/erc/erc-capab.el @@ -170,11 +170,11 @@ PARSED is an `erc-parsed' response struct." (string-match "^\\([-\\+]\\)\\(.+\\)$" msg)) (setf (erc-response.contents parsed) (if erc-capab-identify-mode - (erc-propertize (match-string 2 msg) - 'erc-identified - (if (string= (match-string 1 msg) "+") - 1 - 0)) + (propertize (match-string 2 msg) + 'erc-identified + (if (string= (match-string 1 msg) "+") + 1 + 0)) (match-string 2 msg))) nil))) @@ -190,9 +190,9 @@ PARSED is an `erc-parsed' response struct." ;; assuming the first use of `nickname' is the sender's nick (re-search-forward (regexp-quote nickname) nil t)) (goto-char (match-beginning 0)) - (insert (erc-propertize erc-capab-identify-prefix - 'font-lock-face - 'erc-capab-identify-unidentified)))))) + (insert (propertize erc-capab-identify-prefix + 'font-lock-face + 'erc-capab-identify-unidentified)))))) (defun erc-capab-identify-get-unidentified-nickname (parsed) "Return the nickname of the user if unidentified. diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el index 388728b04a..d71221b267 100644 --- a/lisp/erc/erc-compat.el +++ b/lisp/erc/erc-compat.el @@ -43,12 +43,12 @@ Return the same string, if the encoding operation is trivial. See `erc-encoding-coding-alist'." (encode-coding-string s coding-system t)) -(defalias 'erc-propertize 'propertize) -(defalias 'erc-view-mode-enter 'view-mode-enter) +(define-obsolete-function-alias 'erc-propertize #'propertize "28.1") +(define-obsolete-function-alias 'erc-view-mode-enter #'view-mode-enter "28.1") (autoload 'help-function-arglist "help-fns") -(defalias 'erc-function-arglist 'help-function-arglist) -(defalias 'erc-delete-dups 'delete-dups) -(defalias 'erc-replace-regexp-in-string 'replace-regexp-in-string) +(define-obsolete-function-alias 'erc-function-arglist #'help-function-arglist "28.1") +(define-obsolete-function-alias 'erc-delete-dups #'delete-dups "28.1") +(define-obsolete-function-alias 'erc-replace-regexp-in-string #'replace-regexp-in-string "28.1") (defun erc-set-write-file-functions (new-val) (set (make-local-variable 'write-file-functions) new-val)) diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el index 8ccceec459..bf98eb818f 100644 --- a/lisp/erc/erc-dcc.el +++ b/lisp/erc/erc-dcc.el @@ -423,7 +423,7 @@ where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc." #'(lambda (elt) (eq (plist-get elt :type) 'CHAT)) erc-dcc-list))) - ('close (erc-delete-dups + ('close (delete-dups (mapcar (lambda (elt) (symbol-name (plist-get elt :type))) erc-dcc-list))) ('get (mapcar #'erc-dcc-nick @@ -636,8 +636,8 @@ that subcommand." (define-inline erc-dcc-unquote-filename (filename) (inline-quote - (erc-replace-regexp-in-string "\\\\\\\\" "\\" - (erc-replace-regexp-in-string "\\\\\"" "\"" ,filename t t) t t))) + (replace-regexp-in-string "\\\\\\\\" "\\" + (replace-regexp-in-string "\\\\\"" "\"" ,filename t t) t t))) (defun erc-dcc-handle-ctcp-send (proc query nick login host to) "This is called if a CTCP DCC SEND subcommand is sent to the client. @@ -1193,8 +1193,8 @@ other client." (setq posn (match-end 0)) (erc-display-message nil nil proc - 'dcc-chat-privmsg ?n (erc-propertize erc-dcc-from 'font-lock-face - 'erc-nick-default-face) ?m line)) + 'dcc-chat-privmsg ?n (propertize erc-dcc-from 'font-lock-face + 'erc-nick-default-face) ?m line)) (setq erc-dcc-unprocessed-output (substring str posn))))) (defun erc-dcc-chat-buffer-killed () diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el index 5faeabb721..036d7733ed 100644 --- a/lisp/erc/erc-list.el +++ b/lisp/erc/erc-list.el @@ -71,13 +71,13 @@ (defun erc-list-make-string (channel users topic) (concat channel - (erc-propertize " " - 'display (list 'space :align-to erc-list-nusers-column) - 'face 'fixed-pitch) + (propertize " " + 'display (list 'space :align-to erc-list-nusers-column) + 'face 'fixed-pitch) users - (erc-propertize " " - 'display (list 'space :align-to erc-list-topic-column) - 'face 'fixed-pitch) + (propertize " " + 'display (list 'space :align-to erc-list-topic-column) + 'face 'fixed-pitch) topic)) ;; Insert a record into the list buffer. @@ -143,19 +143,19 @@ ;; Helper function that makes a buttonized column header. (defun erc-list-button (title column) - (erc-propertize title - 'column-number column - 'help-echo "mouse-1: sort by column" - 'mouse-face 'header-line-highlight - 'keymap erc-list-menu-sort-button-map)) + (propertize title + 'column-number column + 'help-echo "mouse-1: sort by column" + 'mouse-face 'header-line-highlight + 'keymap erc-list-menu-sort-button-map)) (define-derived-mode erc-list-menu-mode special-mode "ERC-List" "Major mode for editing a list of irc channels." (setq header-line-format (concat - (erc-propertize " " - 'display '(space :align-to 0) - 'face 'fixed-pitch) + (propertize " " + 'display '(space :align-to 0) + 'face 'fixed-pitch) (erc-list-make-string (erc-list-button "Channel" 1) (erc-list-button "# Users" 2) "Topic"))) diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el index 1bad6d16c8..e2c066da9b 100644 --- a/lisp/erc/erc-log.el +++ b/lisp/erc/erc-log.el @@ -334,7 +334,7 @@ This will not work with full paths, only names. Any unsafe characters in the name are replaced with \"!\". The filename is downcased." - (downcase (erc-replace-regexp-in-string + (downcase (replace-regexp-in-string "[/\\]" "!" (convert-standard-filename filename)))) (defun erc-current-logfile (&optional buffer) diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el index 0e98f2bc61..6e87a183fc 100644 --- a/lisp/erc/erc-match.el +++ b/lisp/erc/erc-match.el @@ -577,9 +577,9 @@ See `erc-log-match-format'." (with-current-buffer buffer (unless buffer-already (insert " == Type \"q\" to dismiss messages ==\n") - (erc-view-mode-enter nil (lambda (buffer) - (when (y-or-n-p "Discard messages? ") - (kill-buffer buffer))))) + (view-mode-enter nil (lambda (buffer) + (when (y-or-n-p "Discard messages? ") + (kill-buffer buffer))))) buffer))) (defun erc-log-matches-come-back (proc parsed) diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el index 415fb53fee..8551cdd1de 100644 --- a/lisp/erc/erc-networks.el +++ b/lisp/erc/erc-networks.el @@ -812,7 +812,7 @@ As an example: (let* ((completion-ignore-case t) (net (intern (completing-read "Network: " - (erc-delete-dups + (delete-dups (mapcar (lambda (x) (list (symbol-name (nth 1 x)))) erc-server-alist))))) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 62aa76d25c..404a4c0997 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1863,7 +1863,7 @@ buffer rather than a server buffer.") ;; modify `transforms' to specify what needs to be changed ;; each item is in the format '(old . new) (let ((transforms '((pcomplete . completion)))) - (erc-delete-dups + (delete-dups (mapcar (lambda (m) (or (cdr (assoc m transforms)) m)) mods)))) @@ -2316,7 +2316,7 @@ and appears in face `erc-input-face' in the buffer." (setq result (concat result network-name " << " line "\n"))) result) - (erc-propertize + (propertize (concat network-name " >> " string (if (/= ?\n (aref string @@ -2339,7 +2339,7 @@ If ARG is non-nil, show the *erc-protocol* buffer." (interactive "P") (let* ((buf (get-buffer-create "*erc-protocol*"))) (with-current-buffer buf - (erc-view-mode-enter) + (view-mode-enter) (when (null (current-local-map)) (let ((inhibit-read-only t)) (insert (erc-make-notice "This buffer displays all IRC protocol traffic exchanged with each server.\n")) @@ -2773,7 +2773,7 @@ See also `erc-server-send'." (defun erc-get-arglist (fun) "Return the argument list of a function without the parens." - (let ((arglist (format "%S" (erc-function-arglist fun)))) + (let ((arglist (format "%S" (help-function-arglist fun)))) (if (string-match "\\`(\\(.*\\))\\'" arglist) (match-string 1 arglist) arglist))) @@ -3558,7 +3558,7 @@ If S is non-nil, it will be used as the quit reason." If S is non-nil, it will be used as the quit reason." (or s (if (fboundp 'yow) - (erc-replace-regexp-in-string "\n" "" (yow)) + (replace-regexp-in-string "\n" "" (yow)) (erc-quit/part-reason-default)))) (make-obsolete 'erc-quit-reason-zippy "it will be removed." "24.4") @@ -3585,7 +3585,7 @@ If S is non-nil, it will be used as the part reason." If S is non-nil, it will be used as the quit reason." (or s (if (fboundp 'yow) - (erc-replace-regexp-in-string "\n" "" (yow)) + (replace-regexp-in-string "\n" "" (yow)) (erc-quit/part-reason-default)))) (make-obsolete 'erc-part-reason-zippy "it will be removed." "24.4") @@ -4001,13 +4001,13 @@ If FACE is non-nil, it will be used to propertize the prompt. If it is nil, ;; Do not extend the text properties when typing at the end ;; of the prompt, but stuff typed in front of the prompt ;; shall remain part of the prompt. - (setq prompt (erc-propertize prompt - 'start-open t ; XEmacs - 'rear-nonsticky t ; Emacs - 'erc-prompt t - 'field t - 'front-sticky t - 'read-only t)) + (setq prompt (propertize prompt + 'start-open t ; XEmacs + 'rear-nonsticky t ; Emacs + 'erc-prompt t + 'field t + 'front-sticky t + 'read-only t)) (erc-put-text-property 0 (1- (length prompt)) 'font-lock-face (or face 'erc-prompt-face) prompt) @@ -4390,15 +4390,15 @@ See also `erc-format-nick-function'." (defun erc-get-user-mode-prefix (user) (when user (cond ((erc-channel-user-owner-p user) - (erc-propertize "~" 'help-echo "owner")) + (propertize "~" 'help-echo "owner")) ((erc-channel-user-admin-p user) - (erc-propertize "&" 'help-echo "admin")) + (propertize "&" 'help-echo "admin")) ((erc-channel-user-op-p user) - (erc-propertize "@" 'help-echo "operator")) + (propertize "@" 'help-echo "operator")) ((erc-channel-user-halfop-p user) - (erc-propertize "%" 'help-echo "half-op")) + (propertize "%" 'help-echo "half-op")) ((erc-channel-user-voice-p user) - (erc-propertize "+" 'help-echo "voice")) + (propertize "+" 'help-echo "voice")) (t "")))) (defun erc-format-@nick (&optional user _channel-data) @@ -4409,7 +4409,7 @@ prefix. Use CHANNEL-DATA to determine op and voice status. See also `erc-format-nick-function'." (when user (let ((nick (erc-server-user-nickname user))) - (concat (erc-propertize + (concat (propertize (erc-get-user-mode-prefix nick) 'font-lock-face 'erc-nick-prefix-face) nick)))) @@ -4422,12 +4422,12 @@ also `erc-format-nick-function'." (nick (erc-current-nick)) (mode (erc-get-user-mode-prefix nick))) (concat - (erc-propertize open 'font-lock-face 'erc-default-face) - (erc-propertize mode 'font-lock-face 'erc-my-nick-prefix-face) - (erc-propertize nick 'font-lock-face 'erc-my-nick-face) - (erc-propertize close 'font-lock-face 'erc-default-face))) + (propertize open 'font-lock-face 'erc-default-face) + (propertize mode 'font-lock-face 'erc-my-nick-prefix-face) + (propertize nick 'font-lock-face 'erc-my-nick-face) + (propertize close 'font-lock-face 'erc-default-face))) (let ((prefix "> ")) - (erc-propertize prefix 'font-lock-face 'erc-default-face)))) + (propertize prefix 'font-lock-face 'erc-default-face)))) (defun erc-echo-notice-in-default-buffer (s parsed buffer _sender) "Echos a private notice in the default buffer, namely the @@ -6489,16 +6489,16 @@ if `erc-away' is non-nil." (fill-region (point-min) (point-max)) (buffer-string)))) (setq header-line-format - (erc-replace-regexp-in-string + (replace-regexp-in-string "%" "%%" (if face - (erc-propertize header 'help-echo help-echo - 'face face) - (erc-propertize header 'help-echo help-echo)))))) + (propertize header 'help-echo help-echo + 'face face) + (propertize header 'help-echo help-echo)))))) (t (setq header-line-format (if face - (erc-propertize header 'face face) + (propertize header 'face face) header))))))) (force-mode-line-update))) @@ -6765,7 +6765,7 @@ functions." nick user host channel (if (not (string= reason "")) (format ": %s" - (erc-replace-regexp-in-string "%" "%%" reason)) + (replace-regexp-in-string "%" "%%" reason)) ""))))) commit b44a5d849e2d29bf91abe9015105cc71da458b1f Author: Stephen Leake Date: Fri Aug 7 04:43:18 2020 -0700 * lisp/files.el (auto-mode-alist): delete ada-mode; now in GNU ELPA only diff --git a/lisp/files.el b/lisp/files.el index 742fd78df1..1909669346 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2683,8 +2683,6 @@ since only a single case-insensitive search through the alist is made." ("\\.p\\'" . pascal-mode) ("\\.pas\\'" . pascal-mode) ("\\.\\(dpr\\|DPR\\)\\'" . delphi-mode) - ("\\.ad[abs]\\'" . ada-mode) - ("\\.ad[bs]\\.dg\\'" . ada-mode) ("\\.\\([pP]\\([Llm]\\|erl\\|od\\)\\|al\\)\\'" . perl-mode) ("Imakefile\\'" . makefile-imake-mode) ("Makeppfile\\(?:\\.mk\\)?\\'" . makefile-makepp-mode) ; Put this before .mk commit 1545f28a98e143f027bd9cf69a2f0d323ad49ed3 Author: Lars Ingebrigtsen Date: Fri Aug 7 13:36:50 2020 +0200 Add some documentation for widget-describe and button-describe * doc/emacs/help.texi (Key Help): Document button-describe and widget-describe. * lisp/button.el (push-button): Mention button-describe. * lisp/cus-edit.el (Custom-newline): Mention widget-describe (bug#139). diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 167c32c4d2..06ad5a583d 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -220,6 +220,16 @@ documentation string of the command it runs. command is not on any key, that means you must use @kbd{M-x} to run it. @kbd{C-h w} runs the command @code{where-is}. +@findex button-describe +@findex widget-describe + Some modes in Emacs use various buttons (@pxref{Buttons,,,elisp, The +Emacs Lisp Reference Manual}) and widgets +(@pxref{Introduction,,,widget, Emacs Widgets}) that can be clicked to +perform some action. To find out what function is ultimately invoked +by these buttons, Emacs provides the @code{button-describe} and +@code{widget-describe} commands, that should be run with point over +the button. + @node Name Help @section Help by Command or Variable Name diff --git a/etc/NEWS b/etc/NEWS index 201c0b58cd..dcd8ea6a9b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -123,8 +123,8 @@ horizontal movements now stop at the edge of the board. setting the variable 'auto-save-visited-mode' buffer-locally to nil. ** New commands to describe buttons and widgets have been added. -'describe-widget' (on a widget) will pop up a help buffer and give a -description of the properties. Likewise 'describe-button' does the +'widget-describe' (on a widget) will pop up a help buffer and give a +description of the properties. Likewise 'button-describe' does the same for a button. diff --git a/lisp/button.el b/lisp/button.el index 941b9fe720..03ab59b109 100644 --- a/lisp/button.el +++ b/lisp/button.el @@ -464,8 +464,12 @@ see). POS defaults to point, except when `push-button' is invoked interactively as the result of a mouse-event, in which case, the mouse event is used. + If there's no button at POS, do nothing and return nil, otherwise -return t." +return t. + +To get a description of what function will called when pushing a +butting, use the `button-describe' command." (interactive (list (if (integerp last-command-event) (point) last-command-event))) (if (and (not (integerp pos)) (eventp pos)) diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 1942f25e89..16695967df 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -4841,7 +4841,10 @@ The format is suitable for use with `easy-menu-define'." (error "You can't edit this part of the Custom buffer")) (defun Custom-newline (pos &optional event) - "Invoke button at POS, or refuse to allow editing of Custom buffer." + "Invoke button at POS, or refuse to allow editing of Custom buffer. + +To see what function the widget will call, use the +`widget-describe' command." (interactive "@d") (let ((button (get-char-property pos 'button))) ;; If there is no button at point, then use the one at the start commit 95b60c84b3bbed262d0af75bc69d4df9cb2cd9eb Author: Mauro Aranda Date: Fri Aug 7 13:14:41 2020 +0200 Add new commands to describe buttons and widgets * lisp/help-fns.el (describe-widget-functions): New variable, used by describe-widget. (describe-widget): New command, to display information about a widget. * lisp/button.el (button-describe): New command, for describing a button. (button--describe): Helper function for button-describe. * lisp/wid-edit.el (widget-describe): New command, for describing a widget. (widget--resolve-parent-action): Helper function, to allow widget-describe to display more useful information (bug#139). diff --git a/etc/NEWS b/etc/NEWS index 7429d392e4..201c0b58cd 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -122,6 +122,11 @@ horizontal movements now stop at the edge of the board. ** Autosaving via 'auto-save-visited-mode' can now be inhibited by setting the variable 'auto-save-visited-mode' buffer-locally to nil. +** New commands to describe buttons and widgets have been added. +'describe-widget' (on a widget) will pop up a help buffer and give a +description of the properties. Likewise 'describe-button' does the +same for a button. + * Changes in Specialized Modes and Packages in Emacs 28.1 diff --git a/lisp/button.el b/lisp/button.el index d9c36a0375..941b9fe720 100644 --- a/lisp/button.el +++ b/lisp/button.el @@ -555,6 +555,51 @@ Returns the button found." (interactive "p\nd\nd") (forward-button (- n) wrap display-message no-error)) +(defun button--describe (properties) + "Describe a button's PROPERTIES (an alist) in a *Help* buffer. +This is a helper function for `button-describe', in order to be possible to +use `help-setup-xref'. + +Each element of PROPERTIES should be of the form (PROPERTY . VALUE)." + (help-setup-xref (list #'button--describe properties) + (called-interactively-p 'interactive)) + (with-help-window (help-buffer) + (with-current-buffer (help-buffer) + (insert (format-message "This button's type is `%s'." + (alist-get 'type properties))) + (dolist (prop '(action mouse-action)) + (let ((name (symbol-name prop)) + (val (alist-get prop properties))) + (when (functionp val) + (insert "\n\n" + (propertize (capitalize name) 'face 'bold) + "\nThe " name " of this button is") + (if (symbolp val) + (progn + (insert (format-message " `%s',\nwhich is " val)) + (describe-function-1 val)) + (insert "\n") + (princ val)))))))) + +(defun button-describe (&optional button-or-pos) + "Display a buffer with information about the button at point. + +When called from Lisp, pass BUTTON-OR-POS as the button to describe, or a +buffer position where a button is present. If BUTTON-OR-POS is nil, the +button at point is the button to describe." + (interactive "d") + (let* ((button (cond ((integer-or-marker-p button-or-pos) + (button-at button-or-pos)) + ((null button-or-pos) (button-at (point))) + ((overlayp button-or-pos) button-or-pos))) + (props (and button + (mapcar (lambda (prop) + (cons prop (button-get button prop))) + '(type action mouse-action))))) + (when props + (button--describe props) + t))) + (provide 'button) ;;; button.el ends here diff --git a/lisp/help-fns.el b/lisp/help-fns.el index b953647063..5a99103f6a 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1769,6 +1769,50 @@ documentation for the major and minor modes of that buffer." ;; For the sake of IELM and maybe others nil) +;; Widgets. + +(defvar describe-widget-functions + '(button-describe widget-describe) + "A list of functions for `describe-widget' to call. +Each function should take one argument, a buffer position, and return +non-nil if it described a widget at that position.") + +;;;###autoload +(defun describe-widget (&optional pos) + "Display a buffer with information about a widget. +You can use this command to describe buttons (e.g., the links in a *Help* +buffer), editable fields of the customization buffers, etc. + +Interactively, click on a widget to describe it, or hit RET to describe the +widget at point. + +When called from Lisp, POS may be a buffer position or a mouse position list. + +Calls each function of the list `describe-widget-functions' in turn, until +one of them returns non-nil." + (interactive + (list + (let ((key + (read-key + "Click on a widget, or hit RET to describe the widget at point"))) + (cond ((eq key ?\C-m) (point)) + ((and (mouse-event-p key) + (eq (event-basic-type key) 'mouse-1) + (equal (event-modifiers key) '(click))) + (event-end key)) + ((eq key ?\C-g) (signal 'quit nil)) + (t (user-error "You didn't specify a widget")))))) + (let (buf) + ;; Allow describing a widget in a different window. + (when (posnp pos) + (setq buf (window-buffer (posn-window pos)) + pos (posn-point pos))) + (with-current-buffer (or buf (current-buffer)) + (unless (cl-some (lambda (fun) (when (fboundp fun) (funcall fun pos))) + describe-widget-functions) + (message "No widget found at that position"))))) + + ;;; Replacements for old lib-src/ programs. Don't seem especially useful. ;; Replaces lib-src/digest-doc.c. diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 284fd1d6cb..ea7e266e0d 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -577,6 +577,63 @@ respectively." (if (and widget (funcall function widget maparg)) (setq overlays nil))))) +(defun widget-describe (&optional widget-or-pos) + "Describe the widget at point. +Displays a buffer with information about the widget (e.g., its actions) as well +as a link to browse all the properties of the widget. + +This command resolves the indirection of widgets running the action of its +parents, so the real action executed can be known. + +When called from Lisp, pass WIDGET-OR-POS as the widget to describe, +or a buffer position where a widget is present. If WIDGET-OR-POS is nil, +the widget at point is the widget to describe." + (interactive "d") + (require 'wid-browse) ; The widget-browse widget. + (let ((widget (if (widgetp widget-or-pos) + widget-or-pos + (widget-at widget-or-pos))) + props) + (when widget + (help-setup-xref (list #'widget-describe widget) + (called-interactively-p 'interactive)) + (setq props (list (cons 'action (widget--resolve-parent-action widget)) + (cons 'mouse-down-action + (widget-get widget :mouse-down-action)))) + (with-help-window (help-buffer) + (with-current-buffer (help-buffer) + (widget-insert "This widget's type is ") + (widget-create 'widget-browse :format "%[%v%]\n%d" + :doc (get (car widget) 'widget-documentation) + :help-echo "Browse this widget's properties" + widget) + (dolist (action '(action mouse-down-action)) + (let ((name (symbol-name action)) + (val (alist-get action props))) + (when (functionp val) + (widget-insert "\n\n" (propertize (capitalize name) 'face 'bold) + "'\nThe " name " of this widget is") + (if (symbolp val) + (progn (widget-insert " ") + (widget-create 'function-link :value val + :button-prefix "" :button-suffix "" + :help-echo "Describe this function")) + (widget-insert "\n") + (princ val))))))) + (widget-setup) + t))) + +(defun widget--resolve-parent-action (widget) + "Resolve the real action of WIDGET up its inheritance chain. +Follow the WIDGET's parents, until its :action is no longer +`widget-parent-action', and return its value." + (let ((action (widget-get widget :action)) + (parent (widget-get widget :parent))) + (while (eq action 'widget-parent-action) + (setq parent (widget-get parent :parent) + action (widget-get parent :action))) + action)) + ;;; Images. (defcustom widget-image-directory (file-name-as-directory commit c32d6b21b81bed54d9738816c9164157ab6165c3 Author: Eli Zaretskii Date: Fri Aug 7 14:03:24 2020 +0300 Fix documentation of 'missing-newline-at-eof' * doc/emacs/display.texi (Useless Whitespace): * etc/NEWS (missing-newline-at-eof): Improve wording and punctuation. diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 5778d95b4d..75ef520d62 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1335,7 +1335,7 @@ customize the variable @code{whitespace-line-column}. Highlight newlines. @item missing-newline-at-eof -Highlight the final character in a buffer unless it's a newline +Highlight the final character if the buffer doesn't end with a newline character. @item empty diff --git a/etc/NEWS b/etc/NEWS index 002a078f84..7429d392e4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -459,10 +459,10 @@ The new default value is 2000000 (2 megabytes). ** Whitespace mode +++ -*** A new style has been added: 'missing-newline-at-eof' -If present in 'whitespace-style' (and it is now by default), the final -character in the buffer will be highlighted unless it's a newline -character. +*** New style 'missing-newline-at-eof'. +If present in 'whitespace-style' (as it is by default), the final +character in the buffer will be highlighted if the buffer doesn't end +with a newline. ** Texinfo commit 2e4c63664d75de46b21d8853f187fc1116cb8240 Author: Lars Ingebrigtsen Date: Fri Aug 7 12:56:13 2020 +0200 Buffer-menu-select doc string clarification * lisp/buff-menu.el (Buffer-menu-select): Document that it removed the marks (bug#6491). diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el index 655a76a713..9fe0dbae38 100644 --- a/lisp/buff-menu.el +++ b/lisp/buff-menu.el @@ -488,8 +488,9 @@ Buffers marked with \\`\\[Buffer-menu-delete]' are deleted (defun Buffer-menu-select () "Select this line's buffer; also, display buffers marked with `>'. You can mark buffers with the \\`\\[Buffer-menu-mark]' command. + This command deletes and replaces all the previously existing windows -in the selected frame." +in the selected frame, and will remove any marks." (interactive) (let* ((this-buffer (Buffer-menu-buffer t)) (menu-buffer (current-buffer)) commit 92a0667f6b4c71c12c61206b49c575b24ca991f8 Author: Eli Zaretskii Date: Fri Aug 7 13:54:39 2020 +0300 ; * lisp/arc-mode.el (archive-copy-file): Doc fix. diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 97213ab9e1..ae85fc55ad 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -1041,7 +1041,9 @@ return nil. Otherwise point is returned." next)) (defun archive-copy-file (file new-name) - "Copy file under point to a different location." + "Copy FILE to a location specified by NEW-NAME. +Interactively, FILE is the file at point, and the function prompts +for NEW-NAME." (interactive (let ((name (archive--file-desc-ext-file-name (archive-get-descr)))) (list name commit 8c4fe522860e733778531167c7ed6532840f40d4 Author: Peder O. Klingenberg Date: Thu Aug 6 14:32:52 2020 +0200 * lisp/play/snake.el (snake-null-map): Quit on `q'. (Bug#42731) diff --git a/lisp/play/snake.el b/lisp/play/snake.el index d7c0683a05..70d80c464f 100644 --- a/lisp/play/snake.el +++ b/lisp/play/snake.el @@ -192,6 +192,7 @@ and then start moving it leftwards.") (defvar snake-null-map (let ((map (make-sparse-keymap 'snake-null-map))) (define-key map "n" 'snake-start-game) + (define-key map "q" 'quit-window) map) "Keymap for finished Snake games.") commit 9c34b50fa17565311d1868de6a6557d128ed9206 Author: Lars Ingebrigtsen Date: Fri Aug 7 11:59:25 2020 +0200 Add a new command to copy a file from zip files * lisp/arc-mode.el (archive-copy-file): New command, keystroke and menu bar entry (bug#26192). (archive-extract): Refactored out code from here... (archive--extract-file): ... to here for use in archive-copy-file. diff --git a/etc/NEWS b/etc/NEWS index 64b77feb11..002a078f84 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -175,6 +175,11 @@ and variables. 'archive-hideshow-column'. These let you control which columns are displayed and which are kept hidden. +--- +*** New command bound to 'C': 'archive-copy-file' +This command extracts the file under point and writes the data to a +file. + ** Emacs Lisp mode *** The mode-line now indicates whether we're using lexical or dynamic scoping. diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 901f09302e..97213ab9e1 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -391,6 +391,7 @@ file. Archive and member name will be added." (define-key map "e" 'archive-extract) (define-key map "f" 'archive-extract) (define-key map "\C-m" 'archive-extract) + (define-key map "C" 'archive-copy-file) (define-key map "m" 'archive-mark) (define-key map "n" 'archive-next-line) (define-key map "\C-n" 'archive-next-line) @@ -430,6 +431,9 @@ file. Archive and member name will be added." (define-key map [menu-bar immediate view] '(menu-item "View This File" archive-view :help "Display file at cursor in View Mode")) + (define-key map [menu-bar immediate view] + '(menu-item "Copy This File" archive-copy-file + :help "Copy file at cursor to another location")) (define-key map [menu-bar immediate display] '(menu-item "Display in Other Window" archive-display-other-window :help "Display file at cursor in another window")) @@ -1036,6 +1040,26 @@ return nil. Otherwise point is returned." (archive-goto-file short)) next)) +(defun archive-copy-file (file new-name) + "Copy file under point to a different location." + (interactive + (let ((name (archive--file-desc-ext-file-name (archive-get-descr)))) + (list name + (read-file-name (format "Copy %s to: " name))))) + (when (file-directory-p new-name) + (setq new-name (expand-file-name file new-name))) + (when (and (file-exists-p new-name) + (not (yes-or-no-p (format "%s already exists; overwrite? " + new-name)))) + (user-error "Not overwriting %s" new-name)) + (let* ((descr (archive-get-descr)) + (archive (buffer-file-name)) + (extractor (archive-name "extract")) + (ename (archive--file-desc-ext-file-name descr))) + (with-temp-buffer + (archive--extract-file extractor archive ename) + (write-region (point-min) (point-max) new-name)))) + (defun archive-extract (&optional other-window-p event) "In archive mode, extract this entry of the archive into its own buffer." (interactive (list nil last-input-event)) @@ -1077,26 +1101,7 @@ return nil. Otherwise point is returned." (setq archive-subfile-mode descr) (setq archive-file-name-coding-system file-name-coding) (if (and - (null - (let (;; We may have to encode the file name argument for - ;; external programs. - (coding-system-for-write - (and enable-multibyte-characters - archive-file-name-coding-system)) - ;; We read an archive member by no-conversion at - ;; first, then decode appropriately by calling - ;; archive-set-buffer-as-visiting-file later. - (coding-system-for-read 'no-conversion) - ;; Avoid changing dir mtime by lock_file - (create-lockfiles nil)) - (condition-case err - (if (fboundp extractor) - (funcall extractor archive ename) - (archive-*-extract archive ename - (symbol-value extractor))) - (error - (ding (message "%s" (error-message-string err))) - nil)))) + (null (archive--extract-file extractor archive ename)) just-created) (progn (set-buffer-modified-p nil) @@ -1129,6 +1134,27 @@ return nil. Otherwise point is returned." (other-window-p (switch-to-buffer-other-window buffer)) (t (switch-to-buffer buffer)))))) +(defun archive--extract-file (extractor archive ename) + (let (;; We may have to encode the file name argument for + ;; external programs. + (coding-system-for-write + (and enable-multibyte-characters + archive-file-name-coding-system)) + ;; We read an archive member by no-conversion at + ;; first, then decode appropriately by calling + ;; archive-set-buffer-as-visiting-file later. + (coding-system-for-read 'no-conversion) + ;; Avoid changing dir mtime by lock_file + (create-lockfiles nil)) + (condition-case err + (if (fboundp extractor) + (funcall extractor archive ename) + (archive-*-extract archive ename + (symbol-value extractor))) + (error + (ding (message "%s" (error-message-string err))) + nil)))) + (defun archive-*-extract (archive name command) (let* ((default-directory (file-name-as-directory archive-tmpdir)) (tmpfile (expand-file-name (file-name-nondirectory name) commit 8a9b13be10fcb95481b177cf8c873fc41e0eb8dc Author: Lars Ingebrigtsen Date: Fri Aug 7 11:30:55 2020 +0200 Allow ffap to do the right thing with 'https://gnu.org' * lisp/thingatpt.el (thing-at-point-bounds-of-url-at-point): Don't include trailing ' in the URL, because it's more likely to be a punctuation character (bug#29410). diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el index 1a15df33e5..483a2c9bd8 100644 --- a/lisp/thingatpt.el +++ b/lisp/thingatpt.el @@ -334,7 +334,7 @@ the bounds of a possible ill-formed URI (one lacking a scheme)." ;; may contain parentheses but may not contain spaces (RFC3986). (let* ((allowed-chars "--:=&?$+@-Z_[:alpha:]~#,%;*()!'") (skip-before "^[0-9a-zA-Z]") - (skip-after ":;.,!?") + (skip-after ":;.,!?'") (pt (point)) (beg (save-excursion (skip-chars-backward allowed-chars) commit 0facaeec1a37481536b6cef13c88d9728c2ec29b Author: Mattias Engdegård Date: Mon Aug 3 16:29:06 2020 +0200 Clean up and improve compilation of arithmetic (bug#42597) * lisp/emacs-lisp/byte-opt.el (byte-optimize-associative-math) (byte-optimize-min-max): Transform 3-arg min/max call into two 2-arg calls, which is faster. * lisp/emacs-lisp/bytecomp.el (byte-compile-associative): Rename to... (byte-compile-variadic-numeric): ...this function and simplify, fixing incorrect comments. The 3-arg strength reduction is now always done in the optimisers and is no longer needed here. (byte-compile-min-max): New function. (byte-compile-minus): Simplify, remove incorrect comment, and use byte-compile-variadic-numeric. (byte-compile-quo): Simplify and fix comment. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 0d9c449b3b..4987596bf9 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -648,14 +648,23 @@ (setq args (cons (car rest) args))) (setq rest (cdr rest))) (if (cdr constants) - (if args - (list (car form) - (apply (car form) constants) - (if (cdr args) - (cons (car form) (nreverse args)) - (car args))) - (apply (car form) constants)) - form))) + (let ((const (apply (car form) (nreverse constants)))) + (if args + (append (list (car form) const) + (nreverse args)) + const)) + form))) + +(defun byte-optimize-min-max (form) + "Optimize `min' and `max'." + (let ((opt (byte-optimize-associative-math form))) + (if (and (consp opt) (memq (car opt) '(min max)) + (= (length opt) 4)) + ;; (OP x y z) -> (OP (OP x y) z), in order to use binary byte ops. + (list (car opt) + (list (car opt) (nth 1 opt) (nth 2 opt)) + (nth 3 opt)) + opt))) ;; Use OP to reduce any leading prefix of constant numbers in the list ;; (cons ACCUM ARGS) down to a single number, and return the @@ -878,8 +887,8 @@ (put '* 'byte-optimizer #'byte-optimize-multiply) (put '- 'byte-optimizer #'byte-optimize-minus) (put '/ 'byte-optimizer #'byte-optimize-divide) -(put 'max 'byte-optimizer #'byte-optimize-associative-math) -(put 'min 'byte-optimizer #'byte-optimize-associative-math) +(put 'max 'byte-optimizer #'byte-optimize-min-max) +(put 'min 'byte-optimizer #'byte-optimize-min-max) (put '= 'byte-optimizer #'byte-optimize-binary-predicate) (put 'eq 'byte-optimizer #'byte-optimize-binary-predicate) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 8f76a3abb9..7ae8749ab4 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3580,10 +3580,10 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\"" (byte-defop-compiler (% byte-rem) 2) (byte-defop-compiler aset 3) -(byte-defop-compiler max byte-compile-associative) -(byte-defop-compiler min byte-compile-associative) -(byte-defop-compiler (+ byte-plus) byte-compile-associative) -(byte-defop-compiler (* byte-mult) byte-compile-associative) +(byte-defop-compiler max byte-compile-min-max) +(byte-defop-compiler min byte-compile-min-max) +(byte-defop-compiler (+ byte-plus) byte-compile-variadic-numeric) +(byte-defop-compiler (* byte-mult) byte-compile-variadic-numeric) ;;####(byte-defop-compiler move-to-column 1) (byte-defop-compiler-1 interactive byte-compile-noop) @@ -3730,30 +3730,36 @@ discarding." (if byte-compile--for-effect (setq byte-compile--for-effect nil) (byte-compile-out 'byte-constant (nth 1 form)))) -;; Compile a function that accepts one or more args and is right-associative. -;; We do it by left-associativity so that the operations -;; are done in the same order as in interpreted code. -;; We treat the one-arg case, as in (+ x), like (* x 1). -;; in order to convert markers to numbers, and trigger expected errors. -(defun byte-compile-associative (form) +;; Compile a pure function that accepts zero or more numeric arguments +;; and has an opcode for the binary case. +;; Single-argument calls are assumed to be numeric identity and are +;; compiled as (* x 1) in order to convert markers to numbers and +;; trigger type errors. +(defun byte-compile-variadic-numeric (form) + (pcase (length form) + (1 + ;; No args: use the identity value for the operation. + (byte-compile-constant (eval form))) + (2 + ;; One arg: compile (OP x) as (* x 1). This is identity for + ;; all numerical values including -0.0, infinities and NaNs. + (byte-compile-form (nth 1 form)) + (byte-compile-constant 1) + (byte-compile-out (get '* 'byte-opcode) 0)) + (3 + (byte-compile-form (nth 1 form)) + (byte-compile-form (nth 2 form)) + (byte-compile-out (get (car form) 'byte-opcode) 0)) + (_ + ;; >2 args: compile as a single function call. + (byte-compile-normal-call form)))) + +(defun byte-compile-min-max (form) + "Byte-compile calls to `min' or `max'." (if (cdr form) - (let ((opcode (get (car form) 'byte-opcode)) - args) - (if (and (< 3 (length form)) - (memq opcode (list (get '+ 'byte-opcode) - (get '* 'byte-opcode)))) - ;; Don't use binary operations for > 2 operands, as that - ;; may cause overflow/truncation in float operations. - (byte-compile-normal-call form) - (setq args (copy-sequence (cdr form))) - (byte-compile-form (car args)) - (setq args (cdr args)) - (or args (setq args '(1) - opcode (get '* 'byte-opcode))) - (dolist (arg args) - (byte-compile-form arg) - (byte-compile-out opcode 0)))) - (byte-compile-constant (eval form)))) + (byte-compile-variadic-numeric form) + ;; No args: warn and emit code that raises an error when executed. + (byte-compile-normal-call form))) ;; more complicated compiler macros @@ -3768,7 +3774,7 @@ discarding." (byte-defop-compiler indent-to) (byte-defop-compiler insert) (byte-defop-compiler-1 function byte-compile-function-form) -(byte-defop-compiler-1 - byte-compile-minus) +(byte-defop-compiler (- byte-diff) byte-compile-minus) (byte-defop-compiler (/ byte-quo) byte-compile-quo) (byte-defop-compiler nconc) @@ -3835,30 +3841,17 @@ discarding." ((byte-compile-normal-call form))))) (defun byte-compile-minus (form) - (let ((len (length form))) - (cond - ((= 1 len) (byte-compile-constant 0)) - ((= 2 len) - (byte-compile-form (cadr form)) - (byte-compile-out 'byte-negate 0)) - ((= 3 len) - (byte-compile-form (nth 1 form)) - (byte-compile-form (nth 2 form)) - (byte-compile-out 'byte-diff 0)) - ;; Don't use binary operations for > 2 operands, as that may - ;; cause overflow/truncation in float operations. - (t (byte-compile-normal-call form))))) + (if (/= (length form) 2) + (byte-compile-variadic-numeric form) + (byte-compile-form (cadr form)) + (byte-compile-out 'byte-negate 0))) (defun byte-compile-quo (form) - (let ((len (length form))) - (cond ((< len 2) - (byte-compile-subr-wrong-args form "1 or more")) - ((= len 3) - (byte-compile-two-args form)) - (t - ;; Don't use binary operations for > 2 operands, as that - ;; may cause overflow/truncation in float operations. - (byte-compile-normal-call form))))) + (if (= (length form) 3) + (byte-compile-two-args form) + ;; N-ary `/' is not the left-reduction of binary `/' because if any + ;; argument is a float, then everything is done in floating-point. + (byte-compile-normal-call form))) (defun byte-compile-nconc (form) (let ((len (length form))) commit 204273c3b9f0a77459661790aa929f86067a9ab1 Author: Mattias Engdegård Date: Mon Aug 3 15:29:41 2020 +0200 Fix byte-compilation of (+ -0.0) (bug#42597) * lisp/emacs-lisp/bytecomp.el (byte-compile-associative): Translate numerical identity expressions, such as (+ x) and (* x), into (* x 1) since the previous translation (+ x 0) gets it wrong for x = -0.0. * test/lisp/emacs-lisp/bytecomp-tests.el (byte-opt-testsuite-arith-data): Add test cases. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 22e648e44b..8f76a3abb9 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3733,7 +3733,7 @@ discarding." ;; Compile a function that accepts one or more args and is right-associative. ;; We do it by left-associativity so that the operations ;; are done in the same order as in interpreted code. -;; We treat the one-arg case, as in (+ x), like (+ x 0). +;; We treat the one-arg case, as in (+ x), like (* x 1). ;; in order to convert markers to numbers, and trigger expected errors. (defun byte-compile-associative (form) (if (cdr form) @@ -3748,8 +3748,8 @@ discarding." (setq args (copy-sequence (cdr form))) (byte-compile-form (car args)) (setq args (cdr args)) - (or args (setq args '(0) - opcode (get '+ 'byte-opcode))) + (or args (setq args '(1) + opcode (get '* 'byte-opcode))) (dolist (arg args) (byte-compile-form arg) (byte-compile-out opcode 0)))) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index c235dd43fc..894914300a 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -47,6 +47,11 @@ (let ((a 1.0)) (/ 3 a 2)) (let ((a most-positive-fixnum) (b 2.0)) (* a 2 b)) (let ((a 3) (b 2)) (/ a b 1.0)) + (let ((a -0.0)) (+ a)) + (let ((a -0.0)) (- a)) + (let ((a -0.0)) (* a)) + (let ((a -0.0)) (min a)) + (let ((a -0.0)) (max a)) (/ 3 -1) (+ 4 3 2 1) (+ 4 3 2.0 1)