diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 4e5168dc7ee..0331c48fa6b 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5288,10 +5288,18 @@ the ``pixel width'' of a character is usually 1, but it could be more for TABs and double-width CJK characters.) @item :align-to @var{hpos} -Specifies that the space should be wide enough to reach @var{hpos}. -If @var{hpos} is a number, it is measured in units of the normal -character width. @var{hpos} can also be a @dfn{pixel width} -specification (@pxref{Pixel Specification}). +Specifies that the space should be wide enough to reach the column +@var{hpos}. If @var{hpos} is a number, it is a column number, and is +measured in units of the canonical character width (@pxref{Frame +Font}). @var{hpos} can also be a @dfn{pixel width} specification +(@pxref{Pixel Specification}). When the current line is wider than +the window, and is either displayed by one or more continuation lines, +or is truncated and possibly scrolled horizontally (@pxref{Horizontal +Scrolling}), @var{hpos} is measured from the beginning of the logical +line, not from the visual beginning of the screen line. This way, +alignment produced by @code{:align-to} is consistent with functions +that count columns, such as @code{current-column} and +@code{move-to-column} (@pxref{Columns}). @end table You should use one and only one of the above properties. You can diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 9b9268ae4ea..7c7f304d55d 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -1715,7 +1715,7 @@ Treating the value as a file name, gets the directory name (the @item t Treating the value as a file name, gets the base name (the ``tail''). -For example, @samp{foo/bar/baz.el(:h)} expands to @samp{baz.el}. +For example, @samp{foo/bar/baz.el(:t)} expands to @samp{baz.el}. @item e Treating the value as a file name, gets the final extension of the diff --git a/doc/misc/org.org b/doc/misc/org.org index 5562a13a005..a4ce53cc6cb 100644 --- a/doc/misc/org.org +++ b/doc/misc/org.org @@ -3284,7 +3284,7 @@ options: | Link Type | Example | |------------+----------------------------------------------------------| -| http | =https://staff.science.uva.nl/c.dominik/= | +| http | =http://staff.science.uva.nl/c.dominik/= | | https | =https://orgmode.org/= | | doi | =doi:10.1000/182= | | file | =file:/home/dominik/images/jupiter.jpg= | diff --git a/etc/HISTORY b/etc/HISTORY index 70f8669cb29..f6df3e6fe60 100644 --- a/etc/HISTORY +++ b/etc/HISTORY @@ -228,7 +228,8 @@ GNU Emacs 28.1 (2022-04-04) emacs-28.1 GNU Emacs 28.2 (2022-09-12) emacs-28.2 -GNU Emacs 28.3 (2023-02-17) emacs-28.3 (was not actually released) +GNU Emacs 28.3 (2023-02-17) emacs-28.3-rc1 +Was not actually released. GNU Emacs 29.1 (2023-07-30) emacs-29.1 diff --git a/etc/NEWS b/etc/NEWS index a8fc7f4e37f..85352fabebc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -715,6 +715,10 @@ provokes an error if used numerically. * Lisp Changes in Emacs 30.1 +** 'defadvice' is marked as obsolete. +See (info "(elisp)Porting Old Advice") for help converting them +to use `advice-add` or `define-advice instead. + +++ ** New variable 'current-key-remap-sequence'. It is bound to the key sequence that caused a call to a function bound diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el index 56f0ae2212c..3265809f592 100644 --- a/lisp/emacs-lisp/advice.el +++ b/lisp/emacs-lisp/advice.el @@ -3131,6 +3131,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...) [DOCSTRING] [INTERACTIVE-FORM] BODY...)" (declare (doc-string 3) (indent 2) + (obsolete "use advice-add or define-advice" "30.1") (debug (&define name ;; thing being advised. (name ;; class is [&or "before" "around" "after" ;; "activation" "deactivation"] diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index c7d8531a870..12c2bc51b92 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -2141,7 +2141,7 @@ See Info node `(elisp) Integer Basics'." '(byte-constant byte-dup byte-stack-ref byte-stack-set byte-discard byte-discardN byte-discardN-preserve-tos byte-symbolp byte-consp byte-stringp byte-listp byte-numberp byte-integerp - byte-eq byte-not + byte-not byte-cons byte-list1 byte-list2 byte-list3 byte-list4 byte-listN byte-interactive-p) ;; How about other side-effect-free-ops? Is it safe to move an @@ -2149,6 +2149,11 @@ See Info node `(elisp) Integer Basics'." ;; No, it is not, because the unwind-protect forms can alter ;; the inside of the object to which nth would apply. ;; For the same reason, byte-equal was deleted from this list. + ;; + ;; In particular, `byte-eq' isn't here despite `eq' being nominally + ;; pure because it is currently affected by `symbols-with-pos-enabled' + ;; and so cannot be sunk past an unwind op that might end a binding of + ;; that variable. Yes, this is unsatisfactory. "Byte-codes that can be moved past an unbind.") (defconst byte-compile-side-effect-and-error-free-ops diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 5b1d958e6c2..f0656628236 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1975,6 +1975,8 @@ also be compiled." (emacs-lisp-compilation-mode)) (let ((directories (list default-directory)) (default-directory default-directory) + (ignore-files-regexp + (mapconcat #'identity byte-compile-ignore-files "\\|")) (skip-count 0) (fail-count 0) (file-count 0) @@ -1995,9 +1997,7 @@ also be compiled." (or (null arg) (eq 0 arg) (y-or-n-p (concat "Check " source "? "))) ;; Directory is requested to be ignored - (not (string-match-p - (regexp-opt byte-compile-ignore-files) - source)) + (not (string-match-p ignore-files-regexp source)) (setq directories (nconc directories (list source)))) ;; It is an ordinary file. Decide whether to compile it. (if (and (string-match emacs-lisp-file-regexp source) @@ -2007,9 +2007,7 @@ also be compiled." (not (auto-save-file-name-p source)) (not (member source (dir-locals--all-files directory))) ;; File is requested to be ignored - (not (string-match-p - (regexp-opt byte-compile-ignore-files) - source))) + (not (string-match-p ignore-files-regexp source))) (progn (cl-incf (pcase (byte-recompile-file source force arg) ('no-byte-compile skip-count) diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 9e906930b92..78dc58e0bcd 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -337,12 +337,15 @@ as the new values of the bound variables in the recursive invocation." ;; Keeping a work buffer around is more efficient than creating a ;; new temporary buffer. (with-current-buffer (get-buffer-create " *string-pixel-width*") - ;; `display-line-numbers-mode' is enabled in internal buffers - ;; that breaks width calculation, so need to disable (bug#59311) + ;; If `display-line-numbers-mode' is enabled in internal + ;; buffers, it breaks width calculation, so disable it (bug#59311) (when (bound-and-true-p display-line-numbers-mode) (display-line-numbers-mode -1)) (delete-region (point-min) (point-max)) - (insert string) + ;; Disable line-prefix and wrap-prefix, for the same reason. + (setq line-prefix nil + wrap-prefix nil) + (insert (propertize string 'line-prefix nil 'wrap-prefix nil)) (car (buffer-text-pixel-size nil nil t))))) ;;;###autoload diff --git a/lisp/find-dired.el b/lisp/find-dired.el index db2f5e7d026..48408d35499 100644 --- a/lisp/find-dired.el +++ b/lisp/find-dired.el @@ -247,8 +247,8 @@ it finishes, type \\[kill-find]." (erase-buffer) (setq default-directory dir) ;; Start the find process. - (shell-command (concat command "&") (current-buffer)) - (let ((proc (get-buffer-process (current-buffer)))) + (let ((proc (start-file-process-shell-command + (buffer-name) (current-buffer) command))) ;; Initialize the process marker; it is used by the filter. (move-marker (process-mark proc) (point) (current-buffer)) (set-process-filter proc #'find-dired-filter) diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 3dd5c790157..2d94182df33 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -229,6 +229,10 @@ interactive command." (lambda (f) (if want-command (commandp f) (or (fboundp f) (get f 'function-documentation)))) + ;; We use 'confirm' here, unlike in other describe-* + ;; commands, for cases like a function that is advised + ;; but not yet defined (e.g., if 'advice-add' is called + ;; before defining the function). 'confirm nil nil (and fn (symbol-name fn))))) (unless (equal val "") diff --git a/lisp/image/image-dired-external.el b/lisp/image/image-dired-external.el index 9f35e17a7e6..77352c25a3b 100644 --- a/lisp/image/image-dired-external.el +++ b/lisp/image/image-dired-external.el @@ -405,7 +405,8 @@ The new file will be named THUMBNAIL-FILE." (not image-dired-rotate-original-ask-before-overwrite)) (progn (copy-file image-dired-temp-rotate-image-file file t) - (image-dired-refresh-thumb)) + (image-dired-refresh-thumb) + (image-dired-update-thumbnail-at-point)) (image-dired-display-image file)))))) diff --git a/lisp/image/image-dired-util.el b/lisp/image/image-dired-util.el index 70911bce45a..53a5e274175 100644 --- a/lisp/image/image-dired-util.el +++ b/lisp/image/image-dired-util.el @@ -190,6 +190,23 @@ Should be used by commands in `image-dired-thumbnail-mode'." "Return non-nil if there is an `image-dired' thumbnail at point." (get-text-property (point) 'image-dired-thumbnail)) +(defun image-dired-update-thumbnail-at-point () + "Update the thumbnail at point if the original image file has been modified. +This function uncaches and removes the thumbnail file under the old name." + (when (image-dired-image-at-point-p) + (let* ((file (image-dired-original-file-name)) + (thumb (expand-file-name (image-dired-thumb-name file))) + (image (get-text-property (point) 'display))) + (when image + (let ((old-thumb (plist-get (cdr image) :file))) + ;; When 'image-dired-thumb-naming' is set to + ;; 'sha1-contents', 'thumb' and 'old-thumb' could be + ;; different file names. Update the thumbnail then. + (unless (string= thumb old-thumb) + (setf (plist-get (cdr image) :file) thumb) + (clear-image-cache old-thumb) + (delete-file old-thumb))))))) + (defun image-dired-window-width-pixels (window) "Calculate WINDOW width in pixels." (declare (obsolete window-body-width "29.1")) diff --git a/lisp/image/image-dired.el b/lisp/image/image-dired.el index 98596510ec1..33beb5b3e49 100644 --- a/lisp/image/image-dired.el +++ b/lisp/image/image-dired.el @@ -590,7 +590,7 @@ used or not. If non-nil, use `display-buffer' instead of `image-dired-previous-line-and-display' where we do not want the thumbnail buffer to be selected." (interactive "P" nil dired-mode) - (setq image-dired--generate-thumbs-start (current-time)) + (setq image-dired--generate-thumbs-start (current-time)) (let ((buf (image-dired-create-thumbnail-buffer)) files dired-buf) (if arg diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 1223bdeb7ea..40efea7bbd0 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -3532,29 +3532,29 @@ BODY is the backend specific code." ;; Set the ownership. (when need-chown - (tramp-set-file-uid-gid filename uid gid))) + (tramp-set-file-uid-gid filename uid gid)) - ;; Set extended attributes. We ignore possible errors, - ;; because ACL strings could be incompatible. - (when attributes - (ignore-errors - (set-file-extended-attributes filename attributes))) + ;; Set extended attributes. We ignore possible errors, + ;; because ACL strings could be incompatible. + (when attributes + (ignore-errors + (set-file-extended-attributes filename attributes))) - ;; Unlock file. - (when file-locked - ;; `unlock-file' exists since Emacs 28.1. - (tramp-compat-funcall 'unlock-file lockname)) + ;; Unlock file. + (when file-locked + ;; `unlock-file' exists since Emacs 28.1. + (tramp-compat-funcall 'unlock-file lockname)) - ;; Sanity check. - (unless (equal curbuf (current-buffer)) - (tramp-error - v 'file-error - "Buffer has changed from `%s' to `%s'" curbuf (current-buffer))) + ;; Sanity check. + (unless (equal curbuf (current-buffer)) + (tramp-error + v 'file-error + "Buffer has changed from `%s' to `%s'" curbuf (current-buffer))) - (when (and (null noninteractive) - (or (eq ,visit t) (string-or-null-p ,visit))) - (tramp-message v 0 "Wrote %s" filename)) - (run-hooks 'tramp-handle-write-region-hook)))))) + (when (and (null noninteractive) + (or (eq ,visit t) (string-or-null-p ,visit))) + (tramp-message v 0 "Wrote %s" filename)) + (run-hooks 'tramp-handle-write-region-hook))))))) ;;; Common file name handler functions for different backends: diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 968ccd7ace9..1dbe91b5633 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -2727,18 +2727,18 @@ This function is called from `c-common-init', once per mode initialization." ;; Emacs < 22 and XEmacs (defmacro c-advise-fl-for-region (function) (declare (debug t)) - `(defadvice ,function (before get-awk-region activate) - ;; Make sure that any string/regexp is completely font-locked. - (when c-buffer-is-cc-mode - (save-excursion - (ad-set-arg 1 c-new-END) ; end - (ad-set-arg 0 c-new-BEG))))) ; beg + (unless (boundp 'font-lock-extend-after-change-region-function) + `(defadvice ,function (before get-awk-region activate) + ;; Make sure that any string/regexp is completely font-locked. + (when c-buffer-is-cc-mode + (save-excursion + (ad-set-arg 1 c-new-END) ; end + (ad-set-arg 0 c-new-BEG)))))) ; beg -(unless (boundp 'font-lock-extend-after-change-region-function) - (c-advise-fl-for-region font-lock-after-change-function) - (c-advise-fl-for-region jit-lock-after-change) - (c-advise-fl-for-region lazy-lock-defer-rest-after-change) - (c-advise-fl-for-region lazy-lock-defer-line-after-change)) +(c-advise-fl-for-region font-lock-after-change-function) +(c-advise-fl-for-region jit-lock-after-change) +(c-advise-fl-for-region lazy-lock-defer-rest-after-change) +(c-advise-fl-for-region lazy-lock-defer-line-after-change) ;; Connect up to `electric-indent-mode' (Emacs 24.4 and later). (defun c-electric-indent-mode-hook () diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 52e5a36f4b0..1930f68617c 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -5214,11 +5214,13 @@ def __FFAP_get_module_path(objstr): (defcustom python-check-command (cond ((executable-find "pyflakes") "pyflakes") + ((executable-find "ruff") "ruff") + ((executable-find "flake8") "flake8") ((executable-find "epylint") "epylint") (t "pyflakes")) "Command used to check a Python file." :type 'string - :version "29.1") + :version "30.1") (defcustom python-check-buffer-name "*Python check: %s*" diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index a4752f7a2ee..3f8e232b71f 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -142,7 +142,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." "export" "extends" "finally" "for" "from" "function" "get" "if" "implements" "import" "in" "instanceof" "interface" "is" "infer" "keyof" "let" "namespace" "new" "of" "private" "protected" - "public" "readonly" "return" "set" "static" "switch" + "public" "readonly" "return" "satisfies" "set" "static" "switch" "target" "throw" "try" "type" "typeof" "var" "void" "while" "with" "yield") "TypeScript keywords for tree-sitter font-locking.") diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el index c3047c786f7..8cb94485369 100644 --- a/lisp/sqlite-mode.el +++ b/lisp/sqlite-mode.el @@ -126,7 +126,7 @@ (forward-line 1) (if (looking-at " ") ;; Delete the info. - (delete-region (point) (if (re-search-forward "^[^ ]" nil t) + (delete-region (point) (if (re-search-forward "^[^ \t]" nil t) (match-beginning 0) (point-max))) ;; Insert the info. diff --git a/lisp/use-package/bind-key.el b/lisp/use-package/bind-key.el index b216c668d83..c45b9e546f7 100644 --- a/lisp/use-package/bind-key.el +++ b/lisp/use-package/bind-key.el @@ -196,6 +196,7 @@ can safely be called at any time." (key-description ,namevar)) (if (symbolp ,keymap) ,keymap (quote ,keymap)))) (,bindingvar (lookup-key ,kmapvar ,keyvar))) + (require 'bind-key) ; ensure `personal-keybindings' is in scope (let ((entry (assoc ,kdescvar personal-keybindings)) (details (list ,command (unless (numberp ,bindingvar) diff --git a/src/keymap.c b/src/keymap.c index da2af98c2d6..1f863885003 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1065,8 +1065,12 @@ possibly_translate_key_sequence (Lisp_Object key, ptrdiff_t *length) xsignal2 (Qerror, build_string ("`key-valid-p' is not defined, so this syntax can't be used: %s"), key); + /* If key-valid-p is unhappy about KEY, we return it as-is. + This happens when menu items define as bindings strings that + should be inserted into the buffer, not commands. See + bug#64927, for example. */ if (NILP (call1 (Qkey_valid_p, AREF (key, 0)))) - xsignal2 (Qerror, build_string ("Invalid `key-parse' syntax: %S"), key); + return key; key = call1 (Qkey_parse, AREF (key, 0)); *length = CHECK_VECTOR_OR_STRING (key); if (*length == 0) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 593fd117685..246ffff532f 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -2001,6 +2001,40 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \ (backtrace-frame-args frame)) call)))))))))) +(ert-deftest bytecomp--eq-symbols-with-pos-enabled () + ;; Verify that we don't optimise away a binding of + ;; `symbols-with-pos-enabled' around an application of `eq' (bug#65017). + (let* ((sym-with-pos1 (read-positioning-symbols "sym")) + (sym-with-pos2 (read-positioning-symbols " sym")) ; <- space! + (without-pos-eq (lambda (a b) + (let ((symbols-with-pos-enabled nil)) + (eq a b)))) + (without-pos-eq-compiled (byte-compile without-pos-eq)) + (with-pos-eq (lambda (a b) + (let ((symbols-with-pos-enabled t)) + (eq a b)))) + (with-pos-eq-compiled (byte-compile with-pos-eq))) + (dolist (mode '(interpreted compiled)) + (ert-info ((symbol-name mode) :prefix "mode: ") + (ert-info ("disabled" :prefix "symbol-pos: ") + (let ((eq-fn (pcase-exhaustive mode + ('interpreted without-pos-eq) + ('compiled without-pos-eq-compiled)))) + (should (equal (funcall eq-fn 'sym 'sym) t)) + (should (equal (funcall eq-fn sym-with-pos1 'sym) nil)) + (should (equal (funcall eq-fn 'sym sym-with-pos1) nil)) + (should (equal (funcall eq-fn sym-with-pos1 sym-with-pos1) t)) + (should (equal (funcall eq-fn sym-with-pos1 sym-with-pos2) nil)))) + (ert-info ("enabled" :prefix "symbol-pos: ") + (let ((eq-fn (pcase-exhaustive mode + ('interpreted with-pos-eq) + ('compiled with-pos-eq-compiled)))) + (should (equal (funcall eq-fn 'sym 'sym) t)) + (should (equal (funcall eq-fn sym-with-pos1 'sym) t)) + (should (equal (funcall eq-fn 'sym sym-with-pos1) t)) + (should (equal (funcall eq-fn sym-with-pos1 sym-with-pos1) t)) + (should (equal (funcall eq-fn sym-with-pos1 sym-with-pos2) t)))))))) + ;; Local Variables: ;; no-byte-compile: t ;; End: