From 32ef7550edc887f1f8e052cb57a61c4e82b6eecd Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Oct 2022 14:13:50 +0300 Subject: [PATCH 01/99] ; Improve documentation of 'file-in-directory-p' * lisp/files.el (file-in-directory-p): Clarify doc string. * doc/lispref/files.texi (Truenames): Move the documentation of 'file-in-directory-p' from here... (Contents of Directories): ...to here. Add index entries. (Bug#58364) --- doc/lispref/files.texi | 19 +++++++++++-------- lisp/files.el | 7 ++++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 08677f789a5..32a862b5825 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1250,14 +1250,6 @@ the @samp{smb} method. For all other connection methods, runtime tests are performed. @end defun -@defun file-in-directory-p file dir -This function returns @code{t} if @var{file} is a file in directory -@var{dir}, or in a subdirectory of @var{dir}. It also returns -@code{t} if @var{file} and @var{dir} are the same directory. It -compares the truenames of the two directories. If @var{dir} does not -name an existing directory, the return value is @code{nil}. -@end defun - @defun vc-responsible-backend file This function determines the responsible VC backend of the given @var{file}. For example, if @file{emacs.c} is a file tracked by Git, @@ -3052,6 +3044,17 @@ is called with one argument (the file or directory) and should return non-@code{nil} if that directory is the one it is looking for. @end defun +@cindex parent directory of file +@cindex ancestor directory of file +@cindex file, ancestor directory of +@defun file-in-directory-p file dir +This function returns @code{t} if @var{file} is a file in directory +@var{dir}, or in a subdirectory of @var{dir}. It also returns +@code{t} if @var{file} and @var{dir} are the same directory. It +compares the truenames of the two directories. If @var{dir} does not +name an existing directory, the return value is @code{nil}. +@end defun + @defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format count This is similar to @code{directory-files} in deciding which files to report on and how to report their names. However, instead diff --git a/lisp/files.el b/lisp/files.el index 860b9ca7249..e07f4796258 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6166,9 +6166,10 @@ If FILE1 or FILE2 does not exist, the return value is unspecified." (equal f1-attr f2-attr)))))) (defun file-in-directory-p (file dir) - "Return non-nil if FILE is in DIR or a subdirectory of DIR. -A directory is considered to be \"in\" itself. -Return nil if DIR is not an existing directory." + "Return non-nil if DIR is a parent directory of FILE. +Value is non-nil if FILE is inside DIR or inside a subdirectory of DIR. +A directory is considered to be a \"parent\" of itself. +DIR must be an existing directory, otherwise the function returns nil." (let ((handler (or (find-file-name-handler file 'file-in-directory-p) (find-file-name-handler dir 'file-in-directory-p)))) (if handler From 6b560992681a1588ed4ed0c6b103021f8b13e056 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 8 Oct 2022 13:20:17 +0200 Subject: [PATCH 02/99] Mention seq-keep in shortdoc * lisp/emacs-lisp/shortdoc.el (sequence): Mention seq-keep. --- lisp/emacs-lisp/shortdoc.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 4cfd658e10d..dbac03432c1 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -897,6 +897,8 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :eval (seq-drop-while #'numberp '(1 2 c d 5))) (seq-filter :eval (seq-filter #'numberp '(a b 3 4 f 6))) + (seq-keep + :eval (seq-keep #'cl-digit-char-p '(?6 ?a ?7))) (seq-remove :eval (seq-remove #'numberp '(1 2 c d 5))) (seq-remove-at-position From 594b3b2cfa56cfd9b03a3e473a7f3bcbd3e72802 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 8 Oct 2022 14:54:38 +0200 Subject: [PATCH 03/99] * etc/TODO (Wishlist items): Add libarchive(3) integration. --- etc/TODO | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/etc/TODO b/etc/TODO index d884539037d..9314a397b5c 100644 --- a/etc/TODO +++ b/etc/TODO @@ -886,7 +886,6 @@ window associated with that modeline. https://lists.gnu.org/r/emacs-devel/2007-09/msg02416.html ** Random things that were planned for Emacs-24 - Stefan Monnier writes: "Random things that cross my mind right now that I'd like to see. Some of them from my local hacks, but it's not obvious at all whether they'll make it." @@ -1737,11 +1736,18 @@ https://lists.gnu.org/r/emacs-devel/2012-06/msg00354.html ** Maybe replace lib-src/rcs2log with a Lisp implementation It wouldn't have to be a complete replacement, just enough for vc-rcs-update-changelog. + ** Allow Emacs to use the bottom-right corner of a TTY Emacs doesn't use the bottom-right corner of a TTY when terminfo capability "am" (auto_right_margin) is defined. It could use the bottom-right corner nonetheless when certain other capabilities are defined. See bug#57607. + +** Replace tramp-archive.el by a native libarchive(3) implementation. +The former is based on the GVFS archive backend, which makes it +available on GNU/Linix only. That implementation has further +drawbacks like it doesn't support to write into archives. + * Other known bugs ** 'make-frame' forgets unhandled parameters, at least for X11 frames From dc9f07d39f83b86db4e207b670ec15f85bce0add Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 8 Oct 2022 14:57:47 +0200 Subject: [PATCH 04/99] Fix typo in etc/TODO --- etc/TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/TODO b/etc/TODO index 9314a397b5c..6253a0a93aa 100644 --- a/etc/TODO +++ b/etc/TODO @@ -1745,7 +1745,7 @@ defined. See bug#57607. ** Replace tramp-archive.el by a native libarchive(3) implementation. The former is based on the GVFS archive backend, which makes it -available on GNU/Linix only. That implementation has further +available on GNU/Linux only. That implementation has further drawbacks like it doesn't support to write into archives. * Other known bugs From e3fac2be0423d8ea7b8418286b791586be8b58fa Mon Sep 17 00:00:00 2001 From: Visuwesh Date: Sat, 8 Oct 2022 15:13:48 +0200 Subject: [PATCH 05/99] Fix misleading prompt in vc-git-create-tag * lisp/vc/vc-git.el (vc-git-create-tag): Actually pass the DEFAULT argument to vc-read-revision (bug#58378). --- lisp/vc/vc-git.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index f9dae8b9ea3..ea06ccaf870 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -1635,7 +1635,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"." (start-point (when branchp (vc-read-revision (format-prompt "Start point" (car (vc-git-branches))) - (list dir) 'Git)))) + (list dir) 'Git (car (vc-git-branches)))))) (and (or (zerop (vc-git-command nil t nil "update-index" "--refresh")) (y-or-n-p "Modified files exist. Proceed? ") (user-error (format "Can't create %s with modified files" From 5017f2573f7f878a05f82f69d96e50a6f4d78ec0 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 8 Oct 2022 15:26:01 +0200 Subject: [PATCH 06/99] Fix vtable-insert-object line insertion * lisp/emacs-lisp/vtable.el (vtable-insert-object): Pass in the correct ellipsis values (bug#58370). (vtable--insert-line): Don't bug out on missing optional arguments. --- lisp/emacs-lisp/vtable.el | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el index 9bdf90bf1d6..de8503a1cb1 100644 --- a/lisp/emacs-lisp/vtable.el +++ b/lisp/emacs-lisp/vtable.el @@ -353,6 +353,11 @@ This also updates the displayed table." (let* ((cache (vtable--cache table)) (inhibit-read-only t) (keymap (get-text-property (point) 'keymap)) + (ellipsis (if (vtable-ellipsis table) + (propertize (truncate-string-ellipsis) + 'face (vtable-face table)) + "")) + (ellipsis-width (string-pixel-width ellipsis)) (elem (and after-object (assq after-object (car cache)))) (line (cons object (vtable--compute-cached-line table object)))) @@ -370,7 +375,8 @@ This also updates the displayed table." ;; FIXME: We have to adjust colors in lines below this if we ;; have :row-colors. (vtable--insert-line table line 0 - (nth 1 cache) (vtable--spacer table)) + (nth 1 cache) (vtable--spacer table) + ellipsis ellipsis-width) (add-text-properties start (point) (list 'keymap keymap 'vtable table))) ;; We may have inserted a non-numerical value into a previously @@ -516,7 +522,8 @@ This also updates the displayed table." (if (> (nth 1 elem) (elt widths index)) (concat (vtable--limit-string - pre-computed (- (elt widths index) ellipsis-width)) + pre-computed (- (elt widths index) + (or ellipsis-width 0))) ellipsis) pre-computed)) ;; Recompute widths. @@ -524,7 +531,8 @@ This also updates the displayed table." (if (> (string-pixel-width value) (elt widths index)) (concat (vtable--limit-string - value (- (elt widths index) ellipsis-width)) + value (- (elt widths index) + (or ellipsis-width 0))) ellipsis) value)))) (start (point)) From 49160969ced3482398b9ae616fa482bc92ce9e34 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 8 Oct 2022 15:41:14 +0200 Subject: [PATCH 07/99] Make sqlite-select signal errors when there's an error * src/sqlite.c (load_dll_functions): Update. (Fsqlite_select): Signal an error when there's an error preparing the statement. --- src/sqlite.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sqlite.c b/src/sqlite.c index 54bfb7b6c61..9375b44da25 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -51,6 +51,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_bind_double, (sqlite3_stmt*, int, double)); DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int)); DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); +DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); @@ -88,6 +89,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, # undef sqlite3_bind_null # undef sqlite3_bind_int # undef sqlite3_errmsg +# undef sqlite3_errstr # undef sqlite3_step # undef sqlite3_changes # undef sqlite3_column_count @@ -112,6 +114,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, # define sqlite3_bind_null fn_sqlite3_bind_null # define sqlite3_bind_int fn_sqlite3_bind_int # define sqlite3_errmsg fn_sqlite3_errmsg +# define sqlite3_errstr fn_sqlite3_errstr # define sqlite3_step fn_sqlite3_step # define sqlite3_changes fn_sqlite3_changes # define sqlite3_column_count fn_sqlite3_column_count @@ -139,6 +142,7 @@ load_dll_functions (HMODULE library) LOAD_DLL_FN (library, sqlite3_bind_null); LOAD_DLL_FN (library, sqlite3_bind_int); LOAD_DLL_FN (library, sqlite3_errmsg); + LOAD_DLL_FN (library, sqlite3_errstr); LOAD_DLL_FN (library, sqlite3_step); LOAD_DLL_FN (library, sqlite3_changes); LOAD_DLL_FN (library, sqlite3_column_count); @@ -528,7 +532,7 @@ which means that we return a set object that can be queried with { if (stmt) sqlite3_finalize (stmt); - + errmsg = sqlite3_errstr (ret); goto exit; } From aa350ba27599c7496f6edc37ef2470051bd9431b Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Sat, 8 Oct 2022 14:41:53 +0200 Subject: [PATCH 08/99] ; Add missing documentation strings * lisp/vc/vc.el (vc-read-revision): Add a docstring. (vc-read-multiple-revisions): Add a docstring. --- lisp/vc/vc.el | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 72189cfcb87..1c64551d068 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1921,6 +1921,13 @@ Return t if the buffer had changes, nil otherwise." "History for `vc-read-revision'.") (defun vc-read-revision (prompt &optional files backend default initial-input multiple) + "Query the user for a revision using PROMPT. +All subsequent arguments are optional. FILES may specify a file +set to restrict the revisions to. BACKEND is a VC backend as +listed in `vc-handled-backends'. DEFAULT and INITIAL-INPUT are +handled as defined by `completing-read'. If MULTIPLE is non-nil, +the user may be prompted for multiple revisions. If possible +this means that `completing-read-multiple' will be used." (cond ((null files) (let ((vc-fileset (vc-deduce-fileset t))) ;FIXME: why t? --Stef @@ -1942,6 +1949,10 @@ Return t if the buffer had changes, nil otherwise." answer))))) (defun vc-read-multiple-revisions (prompt &optional files backend default initial-input) + "Query the user for multiple revisions. +This is equivalent to invoking `vc-read-revision' with t for +MULTIPLE. The arguments PROMPT, FILES, BACKEND, DEFAULT and +INITIAL-INPUT are passed on to `vc-read-revision' directly." (vc-read-revision prompt files backend default initial-input t)) (defun vc-diff-build-argument-list-internal (&optional fileset) From 84945e86be6b8dc8237983de901eb677bee3ae8b Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Sat, 8 Oct 2022 15:06:26 +0200 Subject: [PATCH 09/99] ; * lisp/vc/vc.el (vc-prepare-patches-separately): Fix docstring Noticed by German Pacenza. --- lisp/vc/vc.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 1c64551d068..13cc4fbaa69 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3293,10 +3293,11 @@ immediately after this one." (apply #'vc-user-edit-command (apply old args)))))) (defcustom vc-prepare-patches-separately t - "Non-nil means that `vc-prepare-patch' creates a single message. -A single message is created by attaching all patches to the body -of a single message. If nil, each patch will be sent out in a -separate message, which will be prepared sequentially." + "Configure the default behaviour of `vc-prepare-patch'. +If nil, a single message is created by attaching all patches to +the body of a single message. If non-nil, each patch will be +sent out in a separate message, which will be prepared +sequentially." :type 'boolean :safe #'booleanp :version "29.1") From b8ab4f018bd541caf8d7b71e0b1bd6f81f2d3bbb Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Oct 2022 17:40:25 +0300 Subject: [PATCH 10/99] ; * lisp/vc/vc.el (vc-prepare-patches-separately): Doc fix. --- lisp/vc/vc.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 13cc4fbaa69..ba3a4c58cf1 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3293,11 +3293,11 @@ immediately after this one." (apply #'vc-user-edit-command (apply old args)))))) (defcustom vc-prepare-patches-separately t - "Configure the default behaviour of `vc-prepare-patch'. -If nil, a single message is created by attaching all patches to -the body of a single message. If non-nil, each patch will be -sent out in a separate message, which will be prepared -sequentially." + "Whether `vc-prepare-patch' should generate a separate message for each patch. +If nil, `vc-prepare-patch' creates a single email message by attaching +all the patches to the body of that message. If non-nil, each patch +will be sent out in a separate message, and the messages will be +prepared sequentially." :type 'boolean :safe #'booleanp :version "29.1") From 8de7995ae6388e5ae5418cb6af579281121f14a4 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 8 Oct 2022 12:19:40 -0400 Subject: [PATCH 11/99] package.el: Understand a few more variations in tarball formats * lisp/emacs-lisp/package.el (package-untar-buffer): Fix thinko. (package-tar-file-info): Handle the case where the first file is in a subdirectory. * test/lisp/emacs-lisp/package-tests.el (package-test-bug58367): New test. * test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar: * test/lisp/emacs-lisp/package-resources/v7-withsub-0.1.tar: New files. --- lisp/emacs-lisp/package.el | 10 +++++--- .../package-resources/ustar-withsub-0.1.tar | Bin 0 -> 10240 bytes .../package-resources/v7-withsub-0.1.tar | Bin 0 -> 10240 bytes test/lisp/emacs-lisp/package-tests.el | 24 ++++++++++++++++-- 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar create mode 100644 test/lisp/emacs-lisp/package-resources/v7-withsub-0.1.tar diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 4268f7d27a7..d619142d64c 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -930,7 +930,7 @@ untar into a directory named DIR; otherwise, signal an error." (or (string-match regexp name) ;; Tarballs created by some utilities don't list ;; directories with a trailing slash (Bug#13136). - (and (string-equal dir name) + (and (string-equal (expand-file-name dir) name) (eq (tar-header-link-type tar-data) 5)) (error "Package does not untar cleanly into directory %s/" dir))))) (tar-untar-buffer)) @@ -1192,8 +1192,12 @@ Return the pkg-desc, with desc-kind set to KIND." "Find package information for a tar file. The return result is a `package-desc'." (cl-assert (derived-mode-p 'tar-mode)) - (let* ((dir-name (file-name-directory - (tar-header-name (car tar-parse-info)))) + (let* ((dir-name (named-let loop + ((filename (tar-header-name (car tar-parse-info)))) + (let ((dirname (file-name-directory filename))) + ;; The first file can be in a subdir: look for the top. + (if dirname (loop (directory-file-name dirname)) + (file-name-as-directory filename))))) (desc-file (package--description-file dir-name)) (tar-desc (tar-get-file-descriptor (concat dir-name desc-file)))) (unless tar-desc diff --git a/test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar b/test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar new file mode 100644 index 0000000000000000000000000000000000000000..009c4fc420c7c69f971d16a8a67d1f73b2cd1c19 GIT binary patch literal 10240 zcmXRdE=erXEzc~;C@xLXHPAC;pgu4#FflMUHDxd`FfcSXH9)2fpn$>9#MsEdz|6$J z#Eikfz|hFd(3ruL`cA<#5gY&v1_ni$$r+fk2oXZ^2$e&M1@=C2{OdzRic6EI<_{9$ z-@x3^7!>~|rpBhD@lUlFz-*pR3>*NX`5#>Vb5RtMqnd|c2!NA6mhvB3BIu>&Q0^&0 z`QOCI0G|I1q50py$Y3=8Qy%mLO|Z7MRzOJudZ{@Iy1Kdw!~k6_U4@*~ip=E19NnbM zyp+tmbSs4tYXw~`T`n$bYlVQs8T1z9;rDw`3h-8 z`MIc?l{7WExHJli^2;()QWexue5c8U)x)WIDa8sIsYR(Ht^`C09Z>rpTK_}yzivTx zI>luGq5N-TU<}XyMh51f_Me%lx%p`RCzyLFR{+Wm?x}gHMTsS;DGCLU46BfmTAW;z zSx}OhpNA!bfrXstFa_s-6XVhRPp$CBXO6YCwE`jy=%wZ;=<4b!5Ce3zbQN+^D>9Q4 zb99q3^HMVN(ybIqtQB;%bh)^!trY?ild}`kQ+2~qi;6Sz^Q;sM^bA1~*2>DtiKQj^ zIr)hxTpB5O_Wd8Fp# zw;lRMOPs;?gK6$}h`INmWoscuJEC)03%rDa8sIsYR(Hz0^Yl6I%Y)Eyzx% zQW-!f{~MZ{!t=km5xD+0GBPs7muyGns1yRAtl^%Tms*rqlA5AW0LiloDXGQDMVSR9 znfZC>*$h-ffbzIPUcPQpWl5@Ta(-?>W=^V=LJ3G1oTD@IQgvZQDIrprl7f Date: Fri, 7 Oct 2022 18:17:40 +0200 Subject: [PATCH 12/99] Improved format string error message (bug#58168) * src/editfns.c (styled_format): Better message when the conversion char is non-ASCII from a unibyte format string. --- src/editfns.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/editfns.c b/src/editfns.c index c1414071c79..3f9618edb08 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3551,10 +3551,15 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) || float_conversion || conversion == 'i' || conversion == 'o' || conversion == 'x' || conversion == 'X')) - error ("Invalid format operation %%%c", - multibyte_format - ? STRING_CHAR ((unsigned char *) format - 1) - : *((unsigned char *) format - 1)); + { + unsigned char *p = (unsigned char *) format - 1; + if (multibyte_format) + error ("Invalid format operation %%%c", STRING_CHAR (p)); + else + error (*p <= 127 ? "Invalid format operation %%%c" + : "Invalid format operation char #o%03o", + *p); + } else if (! (FIXNUMP (arg) || ((BIGNUMP (arg) || FLOATP (arg)) && conversion != 'c'))) error ("Format specifier doesn't match argument type"); From 9af63d2e8be06dec7a2f90bfe112cbc1397f7942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 8 Oct 2022 16:24:40 +0200 Subject: [PATCH 13/99] Better Lisp_String comments * src/lisp.h (struct Lisp_String): Comments improved. * src/pdumper.c (dump_string): Update hash (comment change only). --- src/lisp.h | 13 +++++++++---- src/pdumper.c | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lisp.h b/src/lisp.h index 9710dbef8d2..56f24d82810 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1575,10 +1575,15 @@ struct Lisp_String { struct { - ptrdiff_t size; /* MSB is used as the markbit. */ - ptrdiff_t size_byte; /* Set to -1 for unibyte strings, - -2 for data in rodata, - -3 for immovable unibyte strings. */ + /* Number of characters in string; MSB is used as the mark bit. */ + ptrdiff_t size; + /* If nonnegative, number of bytes in the string (which is multibyte). + If negative, the string is unibyte: + -1 for data normally allocated + -2 for data in rodata (C string constants) + -3 for data that must be immovable (used for bytecode) */ + ptrdiff_t size_byte; + INTERVAL intervals; /* Text properties in this string. */ unsigned char *data; } s; diff --git a/src/pdumper.c b/src/pdumper.c index 903298f17d2..5e6ccd9bd88 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2067,7 +2067,7 @@ dump_interval_tree (struct dump_context *ctx, static dump_off dump_string (struct dump_context *ctx, const struct Lisp_String *string) { -#if CHECK_STRUCTS && !defined (HASH_Lisp_String_C2CAF90352) +#if CHECK_STRUCTS && !defined (HASH_Lisp_String_03B2DF1C8E) # error "Lisp_String changed. See CHECK_STRUCTS comment in config.h." #endif /* If we have text properties, write them _after_ the string so that From e4769b20f166aeb78d66d1ac1db4628f72683372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 8 Oct 2022 15:25:50 +0200 Subject: [PATCH 14/99] Restrict string-lessp vectorisation to safe architectures * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): New. (Fstring_lessp): Only use word operations where safe, because string data from purespace may be unaligned. --- src/fns.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/fns.c b/src/fns.c index bc4915eb25b..5eab35a5646 100644 --- a/src/fns.c +++ b/src/fns.c @@ -433,6 +433,21 @@ If string STR1 is greater, the value is a positive number N; return Qt; } +/* Check whether the platform allows access to unaligned addresses for + size_t integers without trapping or undue penalty (a few cycles is OK). + + This whitelist is incomplete but since it is only used to improve + performance, omitting cases is safe. */ +#if defined __x86_64__|| defined __amd64__ \ + || defined __i386__ || defined __i386 \ + || defined __arm64__ || defined __aarch64__ \ + || defined __powerpc__ || defined __powerpc \ + || defined __ppc__ || defined __ppc +#define HAVE_FAST_UNALIGNED_ACCESS 1 +#else +#define HAVE_FAST_UNALIGNED_ACCESS 0 +#endif + DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, doc: /* Return non-nil if STRING1 is less than STRING2 in lexicographic order. Case is significant. @@ -468,18 +483,23 @@ Symbols are also allowed; their print names are used instead. */) ptrdiff_t nb1 = SBYTES (string1); ptrdiff_t nb2 = SBYTES (string2); ptrdiff_t nb = min (nb1, nb2); - - /* First compare entire machine words. (String data is allocated - with word alignment.) */ - typedef size_t word_t; - int ws = sizeof (word_t); - const word_t *w1 = (const word_t *) SDATA (string1); - const word_t *w2 = (const word_t *) SDATA (string2); ptrdiff_t b = 0; - while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) - b += ws; - /* Scan forward to the differing byte (at most ws-1 bytes). */ + /* String data is normally allocated with word alignment, but + there are exceptions (notably pure strings) so we restrict the + wordwise skipping to safe architectures. */ + if (HAVE_FAST_UNALIGNED_ACCESS) + { + /* First compare entire machine words. */ + typedef size_t word_t; + int ws = sizeof (word_t); + const word_t *w1 = (const word_t *) SDATA (string1); + const word_t *w2 = (const word_t *) SDATA (string2); + while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) + b += ws; + } + + /* Scan forward to the differing byte. */ while (b < nb && SREF (string1, b) == SREF (string2, b)) b++; From 81eb7c1809423966975b67a62c8945267d05b1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 8 Oct 2022 18:39:48 +0200 Subject: [PATCH 15/99] ; * test/src/fns-tests.el (fns-tests--string-lessp-cases): Extend. --- test/src/fns-tests.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 9a2bd5cef34..5d5d497c997 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -152,6 +152,8 @@ (,(string-to-multibyte "abc") < "abd") (,(string-to-multibyte "abc") < ,(string-to-multibyte "abd")) (,(string-to-multibyte "\x80") = ,(string-to-multibyte "\x80")) + ("Liberté, Égalité, Fraternité" = "Liberté, Égalité, Fraternité") + ("Liberté, Égalité, Fraternité" < "Liberté, Égalité, Sororité") ;; Cases concerning the ordering of raw bytes: these are ;; troublesome because the current `string<' order is not very useful as From 9d47364634f96b2f2651a7f3942f8f87b920f02d Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 8 Oct 2022 23:06:03 -0400 Subject: [PATCH 16/99] * lisp/url/url-file.el (url-file): Don't bind `coding-system-for-read` Binding it causes errors when some of the enclosed code ends up loading a `.el` file, and it is unnecessary since the rest of the code (in `url-file-asynch-callback`) is already careful to use `insert-file-contents-literally`. --- lisp/url/url-file.el | 1 - 1 file changed, 1 deletion(-) diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el index a72b2e67a6a..6258e999c1d 100644 --- a/lisp/url/url-file.el +++ b/lisp/url/url-file.el @@ -150,7 +150,6 @@ it up to them." (uncompressed-filename nil) (content-type nil) (content-encoding nil) - (coding-system-for-read 'binary) (filename (url-file-build-filename url))) (or filename (error "File does not exist: %s" (url-recreate-url url))) ;; Need to figure out the content-type from the real extension, From 22374f21229da6052a4d8f13916c79515dddf4f1 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 9 Oct 2022 19:58:07 +0800 Subject: [PATCH 17/99] Fix user time handling bug on GNOME Shell and Metacity * src/xfns.c (x_window): Avoid extraneous XChangeWindowAttributes. * src/xterm.c (x_display_set_last_user_time): New argument SET_PROPERTY. Do not change the user time property if it is not true. All callers changed. (handle_one_xevent): Avoid setting the user time property on LeaveNotify and XI_Leave events. --- src/xfns.c | 14 +++++++---- src/xterm.c | 72 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index 8cea93c6698..91124488994 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4179,11 +4179,15 @@ x_window (struct frame *f) { /* XIM server might require some X events. */ unsigned long fevent = NoEventMask; - XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); - attributes.event_mask |= fevent; - attribute_mask = CWEventMask; - XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - attribute_mask, &attributes); + + if (fevent) + { + XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); + attributes.event_mask |= fevent; + attribute_mask = CWEventMask; + XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + attribute_mask, &attributes); + } } } #endif /* HAVE_X_I18N */ diff --git a/src/xterm.c b/src/xterm.c index aaf2e7988be..a374b13780b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -7601,11 +7601,25 @@ static void x_check_font (struct frame *, struct font *); user time. We don't sanitize timestamps from events sent by the X server itself because some Lisp might have set the user time to a ridiculously large value, and this way a more reasonable timestamp - can be obtained upon the next event. */ + can be obtained upon the next event. + + SET_PROPERTY specifies whether or not to change the user time + property for the active frame. The important thing is to not set + the last user time upon leave events; on Metacity and GNOME Shell, + mapping a new frame on top of the old frame potentially causes + LeaveNotify or XI_Leave to be sent to the old frame if it contains + the pointer, as the new frame will initially stack above the old + frame. If _NET_WM_USER_TIME is changed at that point, then GNOME + may get notified about the user time change on the old frame before + it tries to focus the new frame, which will make it consider the + new frame (whose user time property will not have been updated at + that point, due to not being focused) as having been mapped + out-of-order, and lower the new frame, which is typically not what + users want. */ static void x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, - bool send_event) + bool send_event, bool set_property) { #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME uint_fast64_t monotonic_time; @@ -7678,7 +7692,8 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, #ifndef USE_GTK /* Don't waste bandwidth if the time hasn't actually changed. */ - if (focus_frame && old_time != dpyinfo->last_user_time) + if (focus_frame && old_time != dpyinfo->last_user_time + && set_property) { time = dpyinfo->last_user_time; @@ -7719,6 +7734,7 @@ x_set_gtk_user_time (struct frame *f, Time time) itself. */ #ifndef USE_GTK + static void x_update_frame_user_time_window (struct frame *f) { @@ -7782,13 +7798,14 @@ x_update_frame_user_time_window (struct frame *f) } } } + #endif void x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo, Time time) { - x_display_set_last_user_time (dpyinfo, time, true); + x_display_set_last_user_time (dpyinfo, time, true, true); } @@ -12761,7 +12778,7 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, /* The last-focus-change time of the device changed, so update the frame's user time. */ x_display_set_last_user_time (dpyinfo, event->time, - event->send_event); + event->send_event, true); device->focus_frame = mentioned_frame; device->focus_frame_time = event->time; @@ -12771,7 +12788,7 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, /* The last-focus-change time of the device changed, so update the frame's user time. */ x_display_set_last_user_time (dpyinfo, event->time, - event->send_event); + event->send_event, false); device->focus_frame = NULL; @@ -14153,7 +14170,8 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, < dpyinfo->last_mouse_movement_time)) x_display_set_last_user_time (dpyinfo, dpyinfo->last_mouse_movement_time, - dpyinfo->last_mouse_movement_time_send_event); + dpyinfo->last_mouse_movement_time_send_event, + true); if ((!f1 || FRAME_TOOLTIP_P (f1)) && (EQ (track_mouse, Qdropping) @@ -14769,7 +14787,8 @@ xg_scroll_callback (GtkRange *range, GtkScrollType scroll, dpyinfo = FRAME_DISPLAY_INFO (f); if (time != GDK_CURRENT_TIME) - x_display_set_last_user_time (dpyinfo, time, true); + x_display_set_last_user_time (dpyinfo, time, true, + true); switch (scroll) { @@ -18091,7 +18110,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, required for SetInputFocus to work correctly after taking the input focus. */ x_display_set_last_user_time (dpyinfo, event->xclient.data.l[1], - true); + true, true); goto done; } @@ -19079,7 +19098,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, case KeyPress: x_display_set_last_user_time (dpyinfo, event->xkey.time, - event->xkey.send_event); + event->xkey.send_event, + true); ignore_next_mouse_click_timeout = 0; coding = Qlatin_1; @@ -19558,7 +19578,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case EnterNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event); + event->xcrossing.send_event, true); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -19681,7 +19701,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case LeaveNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event); + event->xcrossing.send_event, false); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -20496,7 +20516,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { if (event->xbutton.type == ButtonPress) x_display_set_last_user_time (dpyinfo, event->xbutton.time, - event->xbutton.send_event); + event->xbutton.send_event, true); #ifdef HAVE_XWIDGETS struct xwidget_view *xvw = xwidget_view_from_window (event->xbutton.window); @@ -20548,7 +20568,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == ButtonPress) { x_display_set_last_user_time (dpyinfo, event->xbutton.time, - event->xbutton.send_event); + event->xbutton.send_event, true); dpyinfo->grabbed |= (1 << event->xbutton.button); dpyinfo->last_mouse_frame = f; @@ -21105,7 +21125,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.send_event = enter->send_event; x_display_set_last_user_time (dpyinfo, enter->time, - enter->send_event); + enter->send_event, true); #ifdef USE_MOTIF use_copy = true; @@ -21291,7 +21311,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_display_set_last_user_time (dpyinfo, leave->time, - leave->send_event); + leave->send_event, false); #ifdef HAVE_XWIDGETS { @@ -21566,7 +21586,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, state = xi_convert_event_state (xev); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (found_valuator) xwidget_scroll (xv, xev->event_x, xev->event_y, @@ -21586,7 +21606,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (found_valuator) { x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); #if defined USE_GTK && !defined HAVE_GTK3 @@ -22077,7 +22097,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->evtype == XI_ButtonPress) { x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); dpyinfo->grabbed |= (1 << xev->detail); dpyinfo->last_mouse_frame = f; @@ -22120,7 +22140,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->flags & XIPointerEmulated) x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); #endif x_dnd_note_self_wheel (dpyinfo, x_dnd_last_seen_window, @@ -22356,7 +22376,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->evtype == XI_ButtonPress) x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); source = xi_device_from_id (dpyinfo, xev->sourceid); device = xi_device_from_id (dpyinfo, xev->deviceid); @@ -22735,7 +22755,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); ignore_next_mouse_click_timeout = 0; f = x_any_window_to_frame (dpyinfo, xev->event); @@ -23374,7 +23394,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23472,7 +23492,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23519,7 +23539,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23560,7 +23580,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, pev->deviceid); source = xi_device_from_id (dpyinfo, pev->sourceid); x_display_set_last_user_time (dpyinfo, pev->time, - pev->send_event); + pev->send_event, true); if (!device) goto XI_OTHER; From 0ce91ed8b478364a69502751d86bf5c5568a429c Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 9 Oct 2022 02:19:14 +0200 Subject: [PATCH 18/99] Clean up Fsqlite_select slightly * src/sqlite.c (Fsqlite_select): Clean up code slightly. --- src/sqlite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sqlite.c b/src/sqlite.c index 9375b44da25..a46acf8523a 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -557,7 +557,7 @@ which means that we return a set object that can be queried with /* Return the data directly. */ Lisp_Object data = Qnil; - while ((ret = sqlite3_step (stmt)) == SQLITE_ROW) + while (sqlite3_step (stmt) == SQLITE_ROW) data = Fcons (row_to_value (stmt), data); if (EQ (return_type, Qfull)) From b5dc0513d53cf0e520c8e9c4ca197cb7ccdf2b23 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 9 Oct 2022 16:17:22 +0200 Subject: [PATCH 19/99] Make Fsqlite_select error data better * src/sqlite.c (Fsqlite_select): Add more the more specific error text to the error data (bug#58363). --- src/sqlite.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/sqlite.c b/src/sqlite.c index a46acf8523a..ababa73b99f 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -521,9 +521,8 @@ which means that we return a set object that can be queried with xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); sqlite3 *sdb = XSQLITE (db)->db; - Lisp_Object retval = Qnil; - const char *errmsg = NULL; - Lisp_Object encoded = encode_string (query); + Lisp_Object retval = Qnil, errmsg = Qnil, + encoded = encode_string (query); sqlite3_stmt *stmt = NULL; int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), SBYTES (encoded), @@ -532,7 +531,12 @@ which means that we return a set object that can be queried with { if (stmt) sqlite3_finalize (stmt); - errmsg = sqlite3_errstr (ret); + errmsg = build_string (sqlite3_errstr (ret)); + /* More details about what went wrong. */ + const char *sql_error = sqlite3_errmsg (sdb); + if (sql_error) + errmsg = CALLN (Fformat, build_string ("%s (%s)"), + errmsg, build_string (sql_error)); goto exit; } @@ -543,7 +547,7 @@ which means that we return a set object that can be queried with if (err != NULL) { sqlite3_finalize (stmt); - errmsg = err; + errmsg = build_string (err); goto exit; } } @@ -567,8 +571,8 @@ which means that we return a set object that can be queried with sqlite3_finalize (stmt); exit: - if (errmsg != NULL) - xsignal1 (Qerror, build_string (errmsg)); + if (! NILP (errmsg)) + xsignal1 (Qerror, errmsg); return retval; } From 90c3a25eb112f9c2b3d5fe2b5697160f7df10324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Sat, 8 Oct 2022 15:37:00 +0530 Subject: [PATCH 20/99] Set the PARENTS argument for language environments * lisp/language/indonesian.el * lisp/language/philippine.el * lisp/language/misc-lang.el (set-language-info-alist): Add PARENTS argument. (Bug#58376) --- lisp/language/indonesian.el | 21 ++++++++++++++------- lisp/language/misc-lang.el | 18 ++++++++++++------ lisp/language/philippine.el | 12 ++++++++---- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/lisp/language/indonesian.el b/lisp/language/indonesian.el index 699f8192543..5afcd27759d 100644 --- a/lisp/language/indonesian.el +++ b/lisp/language/indonesian.el @@ -34,7 +34,8 @@ (input-method . "balinese") (sample-text . "Balinese (ᬅᬓ᭄ᬱᬭᬩᬮᬶ) ᬒᬁᬲ᭄ᬯᬲ᭄ᬢ᭄ᬬᬲ᭄ᬢᬸ") (documentation . "\ -Balinese language and its script are supported in this language environment."))) +Balinese language and its script are supported in this language environment.")) + '("Indonesian")) (set-language-info-alist "Javanese" '((charset unicode) @@ -43,7 +44,8 @@ Balinese language and its script are supported in this language environment."))) (input-method . "javanese") (sample-text . "Javanese (ꦲꦏ꧀ꦱꦫꦗꦮ) ꦲꦭꦺꦴ") (documentation . "\ -Javanese language and its script are supported in this language environment."))) +Javanese language and its script are supported in this language environment.")) + '("Indonesian")) (set-language-info-alist "Sundanese" '((charset unicode) @@ -52,7 +54,8 @@ Javanese language and its script are supported in this language environment."))) (input-method . "sundanese") (sample-text . "Sundanese (ᮃᮊ᮪ᮞᮛᮞᮥᮔ᮪ᮓ) ᮞᮙ᮪ᮕᮥᮛᮞᮥᮔ᮪") (documentation . "\ -Sundanese language and its script are supported in this language environment."))) +Sundanese language and its script are supported in this language environment.")) + '("Indonesian")) (set-language-info-alist "Batak" '((charset unicode) @@ -62,7 +65,8 @@ Sundanese language and its script are supported in this language environment.")) (sample-text . "Batak (ᯘᯮᯒᯗ᯲ᯅᯗᯂ᯲) ᯂᯬᯒᯘ᯲ / ᯔᯧᯐᯬᯀᯱᯐᯬᯀᯱ") (documentation . "\ Languages that use the Batak script, such as Karo, Toba, Pakpak, Mandailing -and Simalungun, are supported in this language environment."))) +and Simalungun, are supported in this language environment.")) + '("Indonesian")) (set-language-info-alist "Rejang" '((charset unicode) @@ -71,7 +75,8 @@ and Simalungun, are supported in this language environment."))) (input-method . "rejang") (sample-text . "Rejang (ꥆꤰ꥓ꤼꤽ ꤽꥍꤺꥏ) ꤸꥉꥐꤺꥉꥂꥎ") (documentation . "\ -Rejang language and its script are supported in this language environment."))) +Rejang language and its script are supported in this language environment.")) + '("Indonesian")) (set-language-info-alist "Makasar" '((charset unicode) @@ -80,7 +85,8 @@ Rejang language and its script are supported in this language environment."))) (input-method . "makasar") (sample-text . "Makasar (𑻪𑻢𑻪𑻢) 𑻦𑻤𑻵𑻱") (documentation . "\ -Makassarese language and its script Makasar are supported in this language environment."))) +Makassarese language and its script Makasar are supported in this language environment.")) + '("Indonesian")) (set-language-info-alist "Buginese" '((charset unicode) @@ -89,7 +95,8 @@ Makassarese language and its script Makasar are supported in this language envir (input-method . "lontara") (sample-text . "Buginese (ᨒᨚᨈᨑ) ᨖᨒᨚ") (documentation . "\ -Buginese language and its script Lontara are supported in this language environment."))) +Buginese language and its script Lontara are supported in this language environment.")) + '("Indonesian")) ;; Balinese composition rules (let ((consonant "[\x1B13-\x1B33\x1B45-\x1B4B]") diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el index 370be4b4a39..c34017d9b3a 100644 --- a/lisp/language/misc-lang.el +++ b/lisp/language/misc-lang.el @@ -228,7 +228,8 @@ thin (i.e. 1-dot width) space." (sample-text . "Hanifi Rohingya (𐴌𐴟𐴇𐴥𐴝𐴚𐴒𐴙𐴝 𐴇𐴝𐴕𐴞𐴉𐴞 𐴓𐴠𐴑𐴤𐴝) 𐴀𐴝𐴏𐴓𐴝𐴀𐴡𐴤𐴛𐴝𐴓𐴝𐴙𐴑𐴟𐴔") (documentation . "\ Rohingya language and its script Hanifi Rohingya are supported -in this language environment."))) +in this language environment.")) + '("Misc")) ;; Hanifi Rohingya composition rules (set-char-table-range @@ -251,7 +252,8 @@ in this language environment."))) (sample-text . "Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁") (documentation . "\ Language environment for Gāndhārī, Sanskrit, and other languages -using the Kharoṣṭhī script."))) +using the Kharoṣṭhī script.")) + '("Misc")) (let ((consonant "[\U00010A00\U00010A10-\U00010A35]") (vowel "[\U00010A01-\U00010A06]") @@ -281,7 +283,8 @@ using the Kharoṣṭhī script."))) (sample-text . "Adlam (𞤀𞤣𞤤𞤢𞤥) 𞤅𞤢𞤤𞤢𞥄𞤥") (documentation . "\ Fulani language and its script Adlam are supported -in this language environment."))) +in this language environment.")) + '("Misc")) ;; Adlam composition rules (set-char-table-range @@ -303,7 +306,8 @@ in this language environment."))) (sample-text . "Mende Kikakui (𞠀𞠁𞠂) 𞠛𞠉") (documentation . "\ Mende language and its script Kikakui are supported -in this language environment."))) +in this language environment.")) + '("Misc")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Gothic @@ -317,7 +321,8 @@ in this language environment."))) (sample-text . "Gothic (𐌲𐌿𐍄𐌹𐍃𐌺𐌰) 𐌷𐌰𐌹𐌻𐍃 / 𐌷𐌰𐌹𐌻𐌰") (documentation . "\ Ancient Gothic language using the Gothic script is supported in this -language environment."))) +language environment.")) + '("Misc")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Coptic @@ -331,7 +336,8 @@ language environment."))) (sample-text . "Coptic (ⲘⲉⲧⲢⲉⲙ̀ⲛⲭⲏⲙⲓ) Ⲛⲟⲩϥⲣⲓ") (documentation . "\ Coptic language using the Coptic script is supported in this -language environment."))) +language environment.")) + '("Misc")) (provide 'misc-lang) diff --git a/lisp/language/philippine.el b/lisp/language/philippine.el index e52ad6912cd..ce619bdaa1d 100644 --- a/lisp/language/philippine.el +++ b/lisp/language/philippine.el @@ -35,7 +35,8 @@ (sample-text . "Tagalog (ᜊᜌ᜔ᜊᜌᜒᜈ᜔) ᜃᜓᜋᜓᜐ᜔ᜆ") (documentation . "\ Tagalog language using the Baybayin script is supported in -this language environment."))) +this language environment.")) + '("Philippine")) (set-language-info-alist "Hanunoo" '((charset unicode) @@ -44,7 +45,8 @@ this language environment."))) (input-method . "hanunoo") (sample-text . "Hanunoo (ᜱᜨᜳᜨᜳᜢ) ᜫᜬᜧ᜴ ᜣᜭᜯᜥ᜴ ᜰᜲᜭᜥ᜴") (documentation . "\ -Philippine Language Hanunoo is supported in this language environment."))) +Philippine Language Hanunoo is supported in this language environment.")) + '("Philippine")) (set-language-info-alist "Buhid" '((charset unicode) @@ -52,7 +54,8 @@ Philippine Language Hanunoo is supported in this language environment."))) (coding-priority utf-8) (input-method . "buhid") (documentation . "\ -Philippine Language Buhid is supported in this language environment."))) +Philippine Language Buhid is supported in this language environment.")) + '("Philippine")) (set-language-info-alist "Tagbanwa" '((charset unicode) @@ -61,7 +64,8 @@ Philippine Language Buhid is supported in this language environment."))) (input-method . "tagbanwa") (sample-text . "Tagbanwa (ᝦᝪᝯ) ᝫᝩᝬᝥ ᝣᝮᝧᝯ") (documentation . "\ -Philippine Languages Tagbanwa are supported in this language environment."))) +Philippine Languages Tagbanwa are supported in this language environment.")) + '("Philippine")) ;; Tagalog composition rules (let ((akshara "[\x1700-\x1711\x171F]") From 93136169cba9c7c8f827dbc2f579b95a75d15fad Mon Sep 17 00:00:00 2001 From: Michael Heerdegen Date: Sun, 18 Sep 2022 12:26:53 +0200 Subject: [PATCH 21/99] Try to speed up extended command shorthand computation Discussed in Bug#51143. * lisp/simple.el (execute-extended-command--shorter): Compute a complete list of `commandp' symbols once. This significantly speeds up complicated cases while the slowdown of simple cases is still accetable. --- lisp/simple.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lisp/simple.el b/lisp/simple.el index d2dcbe27a07..e804f717b01 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2465,9 +2465,13 @@ Also see `suggest-key-bindings'." (defun execute-extended-command--shorter (name typed) (let ((candidates '()) + commands (max (length typed)) (len 1) binding) + ;; Precompute a list of commands once to avoid repeated `commandp' testing + ;; of symbols in the `completion-try-completion' call inside the loop below + (mapatoms (lambda (s) (when (commandp s) (push s commands)))) (while (and (not binding) (progn (unless candidates @@ -2480,8 +2484,8 @@ Also see `suggest-key-bindings'." (input-pending-p) ;Dummy call to trigger input-processing, bug#23002. (let ((candidate (pop candidates))) (when (equal name - (car-safe (completion-try-completion - candidate obarray 'commandp len))) + (car-safe (completion-try-completion + candidate commands nil len))) (setq binding candidate)))) binding)) From f91ae9479000eb3c91eaed2a1300678466b823d4 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 10 Oct 2022 09:42:19 +0300 Subject: [PATCH 22/99] ; * lisp/progmodes/gdb-mi.el (gdb): Fix a typo. (Bug#58400) --- lisp/progmodes/gdb-mi.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 6e8032b7eae..0de3d213a4d 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -966,7 +966,7 @@ detailed description of this mode. (if gdb-active-process (gdb-gud-context-command "-exec-continue") "-exec-run"))) - "C-v" "Start or continue execution. Use a prefix to specify arguments.") + "\C-v" "Start or continue execution. Use a prefix to specify arguments.") ;; For debugging Emacs only. (gud-def gud-pp From e016e60a0452bc26f562780f43c2bcd4aab21bdc Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 10 Oct 2022 11:05:18 +0300 Subject: [PATCH 23/99] ; Clarify correct use of 'xref-query-replace-in-results' * lisp/progmodes/xref.el (xref--query-replace-1): Improve the user-error message. (xref-query-replace-in-results): Clarify restrictions in the doc string. * doc/emacs/maintaining.texi (Xref Commands, Identifier Search): Clarify the correct usage of 'xref-query-replace-in-results'. --- doc/emacs/maintaining.texi | 19 ++++++++++++------- lisp/progmodes/xref.el | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 6857e67def9..671d4dd4225 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2302,7 +2302,9 @@ Display the reference on the current line in the other window @item r @var{pattern} @key{RET} @var{replacement} @key{RET} Perform interactive query-replace on references that match @var{pattern} (@code{xref-query-replace-in-results}), replacing -the match with @var{replacement}. @xref{Identifier Search}. +the match with @var{replacement}. This command can only be used in +@file{*xref*} buffers that show all the matches for an identifier in +all the relevant files. @xref{Identifier Search}. @item g @findex xref-revert-buffer @@ -2336,7 +2338,8 @@ them. @item M-? Find all the references for the identifier at point. -@item M-x xref-query-replace-in-results @key{RET} @var{replacement} @key{RET} +@item r@r{, Xref command} +@itemx M-x xref-query-replace-in-results @key{RET} @var{replacement} @key{RET} @itemx C-u M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} @var{replacement} @key{RET} Interactively replace @var{regexp} with @var{replacement} in the names of all the identifiers shown in the @file{*xref*} buffer. @@ -2382,16 +2385,18 @@ shown. The default value is @code{nil}, which just shows the results in the @file{*xref*} buffer, but doesn't select any of them. @findex xref-query-replace-in-results - @kbd{M-x xref-query-replace-in-results} reads a @var{replacement} + @kbd{r} (@code{xref-query-replace-in-results}) reads a @var{replacement} string, just like ordinary @kbd{M-x query-replace-regexp}. It then renames the identifiers shown in the @file{*xref*} buffer in all the places in all the files where these identifiers are referenced, such that their new name is @var{replacement}. This is useful when you rename your identifiers as part of refactoring. This command should -be invoked in the @file{*xref*} buffer generated by @kbd{M-?}. With a -prefix argument, the command also prompts for a regexp to match -identifier names, and renames that regexp in the names of the matching -identifiers with @var{replacement}. +be invoked in the @file{*xref*} buffer generated by @kbd{M-?}. By +default, the command replaces the entire name of each identifier with +@var{replacement}, but if invoked with a prefix argument, the command +prompts for a regexp to match identifier names, and replaces only the +matches of that regexp in the names of the identifiers with +@var{replacement}. @findex xref-find-references-and-replace @kbd{M-x xref-find-references-and-replace} works similarly to diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index ac04b64ce59..47b4b3d15c8 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -751,17 +751,22 @@ quit the *xref* buffer." (defun xref-query-replace-in-results (from to) "Perform interactive replacement of FROM with TO in all displayed xrefs. -This command interactively replaces FROM with TO in the names of the +This function interactively replaces FROM with TO in the names of the references displayed in the current *xref* buffer. -When called interactively, it uses '.*' as FROM, which means -replace the whole name. Unless called with prefix argument, in -which case the user is prompted for both FROM and TO. +When called interactively, it uses '.*' as FROM, which means replace +the whole name, and prompts the user for TO. +If invoked with prefix argument, it prompts the user for both FROM and TO. As each match is found, the user must type a character saying what to do with it. Type SPC or `y' to replace the match, DEL or `n' to skip and go to the next match. For more directions, -type \\[help-command] at that time." +type \\[help-command] at that time. + +Note that this function cannot be used in *xref* buffers that show +a partial list of all references, such as the *xref* buffer created +by \\[xref-find-definitions] and its variants, since those list only +some of the references to the identifiers." (interactive (let* ((fr (if current-prefix-arg @@ -891,7 +896,8 @@ ITEMS is an xref item which " ; FIXME: Expand documentation. (setq pairs (cdr buf-pairs)) (setq continue (perform-replace from to t t nil nil multi-query-replace-map))) - (unless did-it-once (user-error "No suitable matches here")) + (unless did-it-once + (user-error "Cannot use subset of matches for global renaming")) (when (and continue (not buf-pairs)) (message "All results processed")))) From 28904d78a59b0057c4a4fbaaaf63577be6a19f77 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 10 Oct 2022 11:09:43 +0300 Subject: [PATCH 24/99] ; Fix last change. --- doc/emacs/maintaining.texi | 2 +- lisp/progmodes/xref.el | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 671d4dd4225..ad4a3ea3506 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2338,7 +2338,7 @@ them. @item M-? Find all the references for the identifier at point. -@item r@r{, Xref command} +@item r @itemx M-x xref-query-replace-in-results @key{RET} @var{replacement} @key{RET} @itemx C-u M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} @var{replacement} @key{RET} Interactively replace @var{regexp} with @var{replacement} in the names diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 47b4b3d15c8..afb45099139 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -897,7 +897,8 @@ ITEMS is an xref item which " ; FIXME: Expand documentation. (setq continue (perform-replace from to t t nil nil multi-query-replace-map))) (unless did-it-once - (user-error "Cannot use subset of matches for global renaming")) + (user-error + "Cannot use subset of matches of identifier for global renaming")) (when (and continue (not buf-pairs)) (message "All results processed")))) From 7ab6ec364d56c292de2d6294e9424824866691b3 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 9 Oct 2022 17:06:46 +0200 Subject: [PATCH 25/99] Fix some indentation in Fsqlite_execute * src/sqlite.c (Fsqlite_execute): Fix indentation. --- src/sqlite.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sqlite.c b/src/sqlite.c index ababa73b99f..7af3760eb4c 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -415,14 +415,15 @@ Value is the number of affected rows. */) } /* Bind ? values. */ - if (!NILP (values)) { - const char *err = bind_values (sdb, stmt, values); - if (err != NULL) - { - errmsg = err; - goto exit; - } - } + if (!NILP (values)) + { + const char *err = bind_values (sdb, stmt, values); + if (err != NULL) + { + errmsg = err; + goto exit; + } + } ret = sqlite3_step (stmt); sqlite3_finalize (stmt); From 7e7dc74ffbab5eac863657ef719e9f47165708b3 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 10 Oct 2022 10:58:33 +0200 Subject: [PATCH 26/99] Support "insert into ... returning ..." in sqlite-execute * doc/lispref/text.texi (Database): Mention it. * src/sqlite.c (Fsqlite_execute): Support syntax like "insert into ... returning ..." (bug#58390). --- doc/lispref/text.texi | 9 ++- src/sqlite.c | 142 ++++++++++++++++++++++-------------------- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 8b859042ad0..e0768721d94 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -5321,9 +5321,12 @@ This has exactly the same effect as the previous example, but is more efficient and safer (because it doesn't involve any string parsing or interpolation). -@code{sqlite-execute} returns the number of affected rows. For -instance, an @samp{insert} statement will return @samp{1}, whereas an -@samp{update} statement may return zero or a higher number. +@code{sqlite-execute} usually returns the number of affected rows. +For instance, an @samp{insert} statement will typically return +@samp{1}, whereas an @samp{update} statement may return zero or a +higher number. However, when using @acronym{SQL} statements like +@samp{insert into ... returning ...} and the like, the values +specified by @samp{returning ...} will be returned instead. Strings in SQLite are, by default, stored as @code{utf-8}, and selecting a text column will decode the string using that charset. diff --git a/src/sqlite.c b/src/sqlite.c index 7af3760eb4c..65b1dc492f6 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -377,73 +377,6 @@ bind_values (sqlite3 *db, sqlite3_stmt *stmt, Lisp_Object values) return NULL; } -DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, - doc: /* Execute a non-select SQL statement. -If VALUES is non-nil, it should be a vector or a list of values -to bind when executing a statement like - - insert into foo values (?, ?, ...) - -Value is the number of affected rows. */) - (Lisp_Object db, Lisp_Object query, Lisp_Object values) -{ - check_sqlite (db, false); - CHECK_STRING (query); - if (!(NILP (values) || CONSP (values) || VECTORP (values))) - xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); - - sqlite3 *sdb = XSQLITE (db)->db; - Lisp_Object retval = Qnil; - const char *errmsg = NULL; - Lisp_Object encoded = encode_string (query); - sqlite3_stmt *stmt = NULL; - - /* We only execute the first statement -- if there's several - (separated by a semicolon), the subsequent statements won't be - done. */ - int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - if (stmt != NULL) - { - sqlite3_finalize (stmt); - sqlite3_reset (stmt); - } - - errmsg = sqlite3_errmsg (sdb); - goto exit; - } - - /* Bind ? values. */ - if (!NILP (values)) - { - const char *err = bind_values (sdb, stmt, values); - if (err != NULL) - { - errmsg = err; - goto exit; - } - } - - ret = sqlite3_step (stmt); - sqlite3_finalize (stmt); - if (ret != SQLITE_OK && ret != SQLITE_DONE) - { - errmsg = sqlite3_errmsg (sdb); - goto exit; - } - - retval = make_fixnum (sqlite3_changes (sdb)); - - exit: - if (errmsg != NULL) - xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? - Qsqlite_locked_error: Qerror, - build_string (errmsg)); - - return retval; -} - static Lisp_Object row_to_value (sqlite3_stmt *stmt) { @@ -488,6 +421,81 @@ row_to_value (sqlite3_stmt *stmt) return Fnreverse (values); } +DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, + doc: /* Execute a non-select SQL statement. +If VALUES is non-nil, it should be a vector or a list of values +to bind when executing a statement like + + insert into foo values (?, ?, ...) + +Value is the number of affected rows. */) + (Lisp_Object db, Lisp_Object query, Lisp_Object values) +{ + check_sqlite (db, false); + CHECK_STRING (query); + if (!(NILP (values) || CONSP (values) || VECTORP (values))) + xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); + + sqlite3 *sdb = XSQLITE (db)->db; + const char *errmsg = NULL; + Lisp_Object encoded = encode_string (query); + sqlite3_stmt *stmt = NULL; + + /* We only execute the first statement -- if there's several + (separated by a semicolon), the subsequent statements won't be + done. */ + int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + if (stmt != NULL) + { + sqlite3_finalize (stmt); + sqlite3_reset (stmt); + } + + errmsg = sqlite3_errmsg (sdb); + goto exit; + } + + /* Bind ? values. */ + if (!NILP (values)) + { + const char *err = bind_values (sdb, stmt, values); + if (err != NULL) + { + errmsg = err; + goto exit; + } + } + + ret = sqlite3_step (stmt); + + if (ret == SQLITE_ROW) + { + Lisp_Object data = Qnil; + do + data = Fcons (row_to_value (stmt), data); + while (sqlite3_step (stmt) == SQLITE_ROW); + + sqlite3_finalize (stmt); + return Fnreverse (data); + } + else if (ret == SQLITE_OK || ret == SQLITE_DONE) + { + Lisp_Object rows = make_fixnum (sqlite3_changes (sdb)); + sqlite3_finalize (stmt); + return rows; + } + else + errmsg = sqlite3_errmsg (sdb); + + exit: + sqlite3_finalize (stmt); + xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? + Qsqlite_locked_error: Qerror, + build_string (errmsg)); +} + static Lisp_Object column_names (sqlite3_stmt *stmt) { From ed436db1320339862fad5ac754a6ec42de06c766 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 10 Oct 2022 12:14:33 +0300 Subject: [PATCH 27/99] ; * doc/lispref/text.texi (Database): Fix markup in last change. --- doc/lispref/text.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index e0768721d94..509ce56725d 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -5325,8 +5325,8 @@ interpolation). For instance, an @samp{insert} statement will typically return @samp{1}, whereas an @samp{update} statement may return zero or a higher number. However, when using @acronym{SQL} statements like -@samp{insert into ... returning ...} and the like, the values -specified by @samp{returning ...} will be returned instead. +@w{@samp{insert into @dots{} returning @dots{}}} and the like, the values +specified by @w{@samp{returning @dots{}}} will be returned instead. Strings in SQLite are, by default, stored as @code{utf-8}, and selecting a text column will decode the string using that charset. From b7802190fe3735704bba72b5c3030f67d9c1d3da Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 10 Oct 2022 12:37:04 +0300 Subject: [PATCH 28/99] ; Update the doc string of 'compilation-auto-jump-to-first-error' * lisp/progmodes/compile.el (compilation-auto-jump-to-first-error): Doc fix. (Bug#58407) --- lisp/progmodes/compile.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index ded5d2130e5..6473b507785 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -980,12 +980,17 @@ Faces `compilation-error-face', `compilation-warning-face', "Face name to use for leaving directory messages.") (defcustom compilation-auto-jump-to-first-error nil - "If non-nil, automatically jump to the first error during compilation." + "If non-nil, automatically jump to the first error during compilation. + +The value `if-location-known' means automatically jump to the first error +if the error's file can be found. The value `first-known' means jump to +the first error whose file can be found. Any other non-nil value means +jump to the first error unconditionally." :type '(choice (const :tag "Never" nil) (const :tag "Always" t) (const :tag "If location known" if-location-known) (const :tag "First known location" first-known)) - :version "23.1") + :version "29.1") (defvar-local compilation-auto-jump-to-next nil "If non-nil, automatically jump to the next error encountered.") From e25bdd794629909020247ad6da13f9f0dab9a6e8 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Mon, 10 Oct 2022 12:45:45 +0200 Subject: [PATCH 29/99] Fix `vc-prepare-patch' docstring * lisp/vc/vc.el (vc-prepare-patch): Correct description of `vc-prepare-patches-separately'. --- lisp/vc/vc.el | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index ba3a4c58cf1..60481318e3b 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3332,12 +3332,14 @@ If nil, no default will be used. This option may be set locally." ;;;###autoload (defun vc-prepare-patch (addressee subject revisions) "Compose an Email sending patches for REVISIONS to ADDRESSEE. -If `vc-prepare-patches-separately' is non-nil, SUBJECT will be used -as the default subject for the message. Otherwise a separate -message will be composed for each revision. +If `vc-prepare-patches-separately' is nil, SUBJECT will be used +as the default subject for the message (and it will be prompted +for when called interactively). Otherwise a separate message +will be composed for each revision, with SUBJECT derived from the +invidividual commits. When invoked interactively in a Log View buffer with marked -revisions, these revisions will be used." +revisions, those revisions will be used." (interactive (let ((revs (or (log-view-get-marked) (vc-read-multiple-revisions "Revisions: "))) From 8851a75ca7642ce071a23c24a81e22e443be0b05 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 10 Oct 2022 14:09:54 +0200 Subject: [PATCH 30/99] Add a test for sqlite "insert ... returning" * test/src/sqlite-tests.el (sqlite-returning): Add a test for "insert ... returning". --- test/src/sqlite-tests.el | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el index 5af43923012..be4f60ab57f 100644 --- a/test/src/sqlite-tests.el +++ b/test/src/sqlite-tests.el @@ -241,4 +241,17 @@ (should (multibyte-string-p c1)) (should-not (multibyte-string-p c2))))))) +(ert-deftest sqlite-returning () + (skip-unless (sqlite-available-p)) + (let (db) + (progn + (setq db (sqlite-open)) + (sqlite-execute db "CREATE TABLE people1 (people_id INTEGER PRIMARY KEY, first TEXT, last TEXT)") + (should (null (sqlite-select db "select * from people1"))) + (should + (equal + (sqlite-execute db "INSERT INTO people1 (first, last) values (?, ?) RETURNING people_id, first" + '("Joe" "Doe")) + '((1 "Joe"))))))) + ;;; sqlite-tests.el ends here From 345de32a5db8ef165feeda77c99ce56e4d6e911c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 10 Oct 2022 12:35:56 -0700 Subject: [PATCH 31/99] Port bwrap/allows-stdout test to Ubuntu 22.04.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this patch, Ubuntu 22.04.1 x86-64 "make check" reports a failure in test/src/emacs-tests.el’s emacs-tests/bwrap/allows-stdout. One can reproduce the bug without using the Emacs executable, by running this script: #!/bin/bash export LC_ALL=C exec strace -f -o /tmp/tr bwrap --ro-bind / / --seccomp 20 -- \ cat /dev/null 20< lib-src/seccomp-filter-exec.bpf This script exits with status 159, because "cat" didn’t get started (it got a SIGSYS signal early on). The command "journalctl -g SECCOMP" indicated that rseq (syscall 334) was the problem. This syscall is issued by /lib64/ld-linux-x86-64.so.2 before ‘main’ is called. There’s another problem with the clone3 syscall, which is used by pthread_create starting in glibc 2.34. pthread_create is called by g_child_watch_source_new, which is called by init_process_emacs. * lib-src/seccomp-filter.c (main): Allow rseq, clone3. This causes the test to pass. Perhaps a fancier, more accurate patch could be written by someone who has the time. --- lib-src/seccomp-filter.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c index 041bf5c749b..e45aa0c17f6 100644 --- a/lib-src/seccomp-filter.c +++ b/lib-src/seccomp-filter.c @@ -206,6 +206,9 @@ main (int argc, char **argv) SCMP_A2_32 (SCMP_CMP_MASKED_EQ, ~(PROT_NONE | PROT_READ | PROT_WRITE), 0)); + /* Allow restartable sequences. The dynamic linker uses them. */ + RULE (SCMP_ACT_ALLOW, SCMP_SYS (rseq)); + /* Futexes are used everywhere. */ RULE (SCMP_ACT_ALLOW, SCMP_SYS (futex), SCMP_A1_32 (SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE)); @@ -324,6 +327,8 @@ main (int argc, char **argv) | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID), 0)); + /* glibc 2.34+ pthread_create uses clone3. */ + RULE (SCMP_ACT_ALLOW, SCMP_SYS (clone3)); RULE (SCMP_ACT_ALLOW, SCMP_SYS (sigaltstack)); RULE (SCMP_ACT_ALLOW, SCMP_SYS (set_robust_list)); From 5df95ba039d93b26b11adcf61646467cd7174740 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Mon, 10 Oct 2022 21:46:24 +0200 Subject: [PATCH 32/99] Fix Tramp completion on MS Windows * lisp/net/tramp.el (tramp-build-remote-file-name-spec-regexp): Revert previous change, it's too complicate. (tramp-build-completion-file-name-regexp): Use `tramp-prefix-format' instead of `tramp-prefix-regexp'. (Bug#558133) --- lisp/net/tramp.el | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 03dc47a053f..4ff57e5d560 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1088,34 +1088,18 @@ Derived from `tramp-postfix-host-format'.") (defun tramp-build-remote-file-name-spec-regexp () "Construct a regexp matching a Tramp file name for a Tramp syntax. It is expected, that `tramp-syntax' has the proper value." - ;; Starting with Emacs 27, we can use `rx-let'. - (let* ((user-regexp - (tramp-compat-rx - (group-n 6 (regexp tramp-user-regexp)) - (regexp tramp-postfix-user-regexp))) - (host-regexp - (tramp-compat-rx - (group-n 7 (| (regexp tramp-host-regexp) - (: (regexp tramp-prefix-ipv6-regexp) - (? (regexp tramp-ipv6-regexp)) - (regexp tramp-postfix-ipv6-regexp))) - ;; Optional port. - (? (regexp tramp-prefix-port-regexp) - (regexp tramp-port-regexp))))) - (user-host-regexp - (if (eq tramp-syntax 'simplified) - ;; There must be either user or host. - (tramp-compat-rx - (| (: (regexp user-regexp) (? (regexp host-regexp))) - (: (? (regexp user-regexp)) (regexp host-regexp)))) - (tramp-compat-rx - (? (regexp user-regexp)) (? (regexp host-regexp)))))) - (tramp-compat-rx - ;; Method. - (group-n 5 (regexp tramp-method-regexp)) - (regexp tramp-postfix-method-regexp) - ;; User and host. - (regexp user-host-regexp)))) + (tramp-compat-rx + ;; Method. + (group (regexp tramp-method-regexp)) (regexp tramp-postfix-method-regexp) + ;; Optional user. This includes domain. + (? (group (regexp tramp-user-regexp)) (regexp tramp-postfix-user-regexp)) + ;; Optional host. + (? (group (| (regexp tramp-host-regexp) + (: (regexp tramp-prefix-ipv6-regexp) + (? (regexp tramp-ipv6-regexp)) + (regexp tramp-postfix-ipv6-regexp))) + ;; Optional port. + (? (regexp tramp-prefix-port-regexp) (regexp tramp-port-regexp)))))) (defvar tramp-remote-file-name-spec-regexp nil ; Initialized when defining `tramp-syntax'! @@ -1214,7 +1198,8 @@ The `ftp' syntax does not support methods.") ;; "/ssh:host:~/path" becomes "c:/ssh:host:~/path". See also ;; `tramp-drop-volume-letter'. (? (regexp tramp-volume-letter-regexp)) - (regexp tramp-prefix-regexp) + ;; We cannot use `tramp-prefix-regexp', because it starts with `bol'. + (literal tramp-prefix-format) ;; Optional multi hops. (* (regexp tramp-remote-file-name-spec-regexp) @@ -1862,7 +1847,8 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME &optional HOP)." tramp-prefix-regexp "" (replace-regexp-in-string (tramp-compat-rx - (regexp tramp-postfix-host-regexp) eos) tramp-postfix-hop-format + (regexp tramp-postfix-host-regexp) eos) + tramp-postfix-hop-format (tramp-make-tramp-file-name vec 'noloc))))) (defun tramp-completion-make-tramp-file-name (method user host localname) From ebc19f56aaeb98b834eea1ce8768ca13bed8578c Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sun, 9 Oct 2022 15:53:27 -0700 Subject: [PATCH 33/99] Don't prompt when killing an Emacs client if it's the last client * lisp/server.el (server-kill-emacs-query-function): Ignore the current client (if any) when checking for live clients (bug#58404). --- lisp/server.el | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lisp/server.el b/lisp/server.el index 3caa335c4eb..90d97c1538e 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1589,14 +1589,19 @@ specifically for the clients and did not exist before their request for it." (server-buffer-done (current-buffer)))) (defun server-kill-emacs-query-function () - "Ask before exiting Emacs if it has live clients. + "Ask before exiting Emacs if it has other live clients. A \"live client\" is a client with at least one live buffer -associated with it." - (or (not (seq-some (lambda (proc) - (seq-some #'buffer-live-p - (process-get proc 'buffers))) - server-clients)) - (yes-or-no-p "This Emacs session has clients; exit anyway? "))) +associated with it. These clients were (probably) started by +external processes that are waiting for some buffers to be +edited. If there are any other clients, we don't want to fail +their waiting processes, so ask the user to be sure." + (let ((this-client (frame-parameter nil 'client))) + (or (not (seq-some (lambda (proc) + (unless (eq proc this-client) + (seq-some #'buffer-live-p + (process-get proc 'buffers)))) + server-clients)) + (yes-or-no-p "This Emacs session has other clients; exit anyway? ")))) (defun server-kill-buffer () "Remove the current buffer from its clients' buffer list. From 36ab1644964ae5a933bd9808536f60d4ae64c99f Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Tue, 11 Oct 2022 02:18:19 +0200 Subject: [PATCH 34/99] Improve error message from sqlite-execute * src/sqlite.c (sqlite_prepare_errmsg): New function. (Fsqlite_execute): Use it to get the same error format for both execute and select. (Fsqlite_select): Factored out from here. --- src/sqlite.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/sqlite.c b/src/sqlite.c index 65b1dc492f6..1526e344e53 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -421,6 +421,19 @@ row_to_value (sqlite3_stmt *stmt) return Fnreverse (values); } +static Lisp_Object +sqlite_prepare_errmsg (int code, sqlite3 *sdb) +{ + Lisp_Object errmsg = build_string (sqlite3_errstr (code)); + /* More details about what went wrong. */ + const char *sql_error = sqlite3_errmsg (sdb); + if (sql_error) + return CALLN (Fformat, build_string ("%s (%s)"), + errmsg, build_string (sql_error)); + else + return errmsg; +} + DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, doc: /* Execute a non-select SQL statement. If VALUES is non-nil, it should be a vector or a list of values @@ -437,8 +450,8 @@ Value is the number of affected rows. */) xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); sqlite3 *sdb = XSQLITE (db)->db; - const char *errmsg = NULL; - Lisp_Object encoded = encode_string (query); + Lisp_Object errmsg = Qnil, + encoded = encode_string (query); sqlite3_stmt *stmt = NULL; /* We only execute the first statement -- if there's several @@ -453,7 +466,7 @@ Value is the number of affected rows. */) sqlite3_reset (stmt); } - errmsg = sqlite3_errmsg (sdb); + errmsg = sqlite_prepare_errmsg (ret, sdb); goto exit; } @@ -463,7 +476,7 @@ Value is the number of affected rows. */) const char *err = bind_values (sdb, stmt, values); if (err != NULL) { - errmsg = err; + errmsg = build_string (err); goto exit; } } @@ -487,13 +500,13 @@ Value is the number of affected rows. */) return rows; } else - errmsg = sqlite3_errmsg (sdb); + errmsg = build_string (sqlite3_errmsg (sdb)); exit: sqlite3_finalize (stmt); xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? Qsqlite_locked_error: Qerror, - build_string (errmsg)); + errmsg); } static Lisp_Object @@ -540,12 +553,7 @@ which means that we return a set object that can be queried with { if (stmt) sqlite3_finalize (stmt); - errmsg = build_string (sqlite3_errstr (ret)); - /* More details about what went wrong. */ - const char *sql_error = sqlite3_errmsg (sdb); - if (sql_error) - errmsg = CALLN (Fformat, build_string ("%s (%s)"), - errmsg, build_string (sql_error)); + errmsg = sqlite_prepare_errmsg (ret, sdb); goto exit; } From b0585441a321a144f2bbdc269b3cfc6c14bab7cf Mon Sep 17 00:00:00 2001 From: kobarity Date: Mon, 10 Oct 2022 22:24:17 +0900 Subject: [PATCH 35/99] Fix Python completion failure under certain conditions * lisp/progmodes/python.el (python-shell-send-string-no-output): Save and restore `comint-last-prompt-overlay' or `comint-last-prompt'. * test/lisp/progmodes/python-tests.el (python-tests-shell-wait-for-prompt): New helper function. (python-tests-with-temp-buffer-with-shell): New helper macro. (python-shell-completion-1, python-shell-completion-native-1) (python-shell-completion-native-with-ffap-1) (python-shell-completion-native-with-eldoc-1): New tests (bug#58389). --- lisp/progmodes/python.el | 26 +++++--- test/lisp/progmodes/python-tests.el | 93 +++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 8 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 80c5b31b6ea..680b57fc3ef 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -3413,15 +3413,25 @@ detecting a prompt at the end of the buffer." "Send STRING to PROCESS and inhibit output. Return the output." (or process (setq process (python-shell-get-process-or-error))) - (cl-letf (((process-filter process) - (lambda (_proc str) - (with-current-buffer (process-buffer process) - (python-shell-output-filter str)))) - (python-shell-output-filter-in-progress t) - (inhibit-quit t)) + (cl-letf* (((process-filter process) + (lambda (_proc str) + (with-current-buffer (process-buffer process) + (python-shell-output-filter str)))) + (python-shell-output-filter-in-progress t) + (inhibit-quit t) + (buffer (process-buffer process)) + (last-prompt (cond ((boundp 'comint-last-prompt-overlay) + 'comint-last-prompt-overlay) + ((boundp 'comint-last-prompt) + 'comint-last-prompt))) + (last-prompt-value (buffer-local-value last-prompt buffer))) (or (with-local-quit - (python-shell-send-string string process) + (unwind-protect + (python-shell-send-string string process) + (when (not (null last-prompt)) + (with-current-buffer buffer + (set last-prompt last-prompt-value)))) (while python-shell-output-filter-in-progress ;; `python-shell-output-filter' takes care of setting ;; `python-shell-output-filter-in-progress' to NIL after it @@ -3430,7 +3440,7 @@ Return the output." (prog1 python-shell-output-filter-buffer (setq python-shell-output-filter-buffer nil))) - (with-current-buffer (process-buffer process) + (with-current-buffer buffer (comint-interrupt-subjob))))) (defun python-shell-internal-send-string (string) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index fdaedb5fd7a..60ff9bb613a 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -43,6 +43,37 @@ always located at the beginning of buffer." (goto-char (point-min)) ,@body))) +(defun python-tests-shell-wait-for-prompt () + "Wait for the prompt in the shell buffer." + (python-shell-with-shell-buffer + (while (not (if-let ((prompt (python-util-comint-last-prompt))) + (python-shell-comint-end-of-output-p + (buffer-substring-no-properties + (car prompt) (cdr prompt))))) + (sit-for 0.1)))) + +(defmacro python-tests-with-temp-buffer-with-shell (contents &rest body) + "Create a `python-mode' enabled temp buffer with CONTENTS and `run-python'. +BODY is code to be executed within the temp buffer. Point is +always located at the beginning of buffer. Native completion is +turned off. Shell buffer will be killed on exit." + (declare (indent 1) (debug t)) + `(with-temp-buffer + (let ((python-indent-guess-indent-offset nil) + (python-shell-completion-native-enable nil)) + (python-mode) + (unwind-protect + (progn + (run-python nil t) + (insert ,contents) + (goto-char (point-min)) + (python-tests-shell-wait-for-prompt) + ,@body) + (when (python-shell-get-buffer) + (python-shell-with-shell-buffer + (let (kill-buffer-hook kill-buffer-query-functions) + (kill-buffer)))))))) + (defmacro python-tests-with-temp-file (contents &rest body) "Create a `python-mode' enabled file with CONTENTS. BODY is code to be executed within the temp buffer. Point is @@ -4365,6 +4396,68 @@ def foo(): (python-shell-interpreter "/some/path/to/bin/pypy")) (should (python-shell-completion-native-interpreter-disabled-p)))) +(ert-deftest python-shell-completion-1 () + (skip-unless (executable-find python-tests-shell-interpreter)) + (python-tests-with-temp-buffer-with-shell + " +import abc +" + (let ((inhibit-message t)) + (python-shell-send-buffer) + (python-tests-shell-wait-for-prompt) + (goto-char (point-max)) + (insert "abc.") + (should (completion-at-point)) + (insert "A") + (should (completion-at-point))))) + +(ert-deftest python-shell-completion-native-1 () + (skip-unless (executable-find python-tests-shell-interpreter)) + (python-tests-with-temp-buffer-with-shell + " +import abc +" + (let ((inhibit-message t)) + (python-shell-completion-native-turn-on) + (python-shell-send-buffer) + (python-tests-shell-wait-for-prompt) + (goto-char (point-max)) + (insert "abc.") + (should (completion-at-point)) + (insert "A") + (should (completion-at-point))))) + +(ert-deftest python-shell-completion-native-with-ffap-1 () + (skip-unless (executable-find python-tests-shell-interpreter)) + (python-tests-with-temp-buffer-with-shell + " +import abc +" + (let ((inhibit-message t)) + (python-shell-completion-native-turn-on) + (python-shell-send-buffer) + (python-tests-shell-wait-for-prompt) + (goto-char (point-max)) + (insert "abc.") + ;; This is called when FFAP is enabled and a find-file function is called. + (python-ffap-module-path "abc.") + (should (completion-at-point))))) + +(ert-deftest python-shell-completion-native-with-eldoc-1 () + (skip-unless (executable-find python-tests-shell-interpreter)) + (python-tests-with-temp-buffer-with-shell + " +import abc +" + (let ((inhibit-message t)) + (python-shell-completion-native-turn-on) + (python-shell-send-buffer) + (python-tests-shell-wait-for-prompt) + (goto-char (point-max)) + (insert "abc.") + ;; This is called by idle-timer when ElDoc is enabled. + (python-eldoc-function) + (should (completion-at-point))))) From cf9ac857857e52a337864b3ea0dc39c186d56158 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Tue, 11 Oct 2022 02:39:05 +0200 Subject: [PATCH 36/99] Remove the view-remove-frame-by-deleting variable * lisp/view.el (view-remove-frame-by-deleting): Remove variable that hasn't been used since 2011 -- 357f93d245344 reworked the code and stopped using it (bug#58413). --- lisp/view.el | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lisp/view.el b/lisp/view.el index 1207f01db21..d9b1a2d0e7d 100644 --- a/lisp/view.el +++ b/lisp/view.el @@ -68,13 +68,6 @@ the F command in `view-mode', but you can set it to t if you want the action for all scroll commands in view mode." :type 'boolean) -;;;###autoload -(defcustom view-remove-frame-by-deleting t - "Determine how View mode removes a frame no longer needed. -If nil, make an icon of the frame. If non-nil, delete the frame." - :type 'boolean - :version "23.1") - (defcustom view-exits-all-viewing-windows nil "Non-nil means restore all windows used to view buffer. Commands that restore windows when finished viewing a buffer, From 92703e00dc44af604355858bf227b07e99fb2c4c Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Tue, 11 Oct 2022 02:52:51 +0200 Subject: [PATCH 37/99] Add gettid to seccomp-filter * lib-src/seccomp-filter.c (main): gettid is necessary on RHEL 9.0 (bug#56359). --- lib-src/seccomp-filter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c index e45aa0c17f6..7e54b878a22 100644 --- a/lib-src/seccomp-filter.c +++ b/lib-src/seccomp-filter.c @@ -221,6 +221,7 @@ main (int argc, char **argv) RULE (SCMP_ACT_ALLOW, SCMP_SYS (getuid)); RULE (SCMP_ACT_ALLOW, SCMP_SYS (geteuid)); RULE (SCMP_ACT_ALLOW, SCMP_SYS (getpid)); + RULE (SCMP_ACT_ALLOW, SCMP_SYS (gettid)); RULE (SCMP_ACT_ALLOW, SCMP_SYS (getpgrp)); /* Allow operations on open file descriptors. File descriptors are From 4a1a4bf0e2dfe3987b18cfd2122d43db1e8a58c1 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 7 Oct 2022 21:55:30 -0700 Subject: [PATCH 38/99] Accommodate missing spec values in erc-format-message * lisp/erc/erc.el (erc-format-message): Although not mentioned in its log message, commit 5281946fbf6b3cdbec5ce82e0057c71849faf4d2 "Make format-spec accept function substitutions" also fixed a bug involving the `ignore-missing' parameter of `format-spec'. Until now, ERC has been relying on the old behavior to gracefully handle malformed server messages. This commit tries to regain that functionality. --- lisp/erc/erc.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index f128387bcf6..db39e341b2f 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -6961,6 +6961,8 @@ shortened server name instead." (defvar tabbar--local-hlf) +;; FIXME when 29.1 is cut and `format-spec' is added to ELPA Compat, +;; remove the function invocations from the spec form below. (defun erc-update-mode-line-buffer (buffer) "Update the mode line in a single ERC buffer BUFFER." (with-current-buffer buffer @@ -7325,7 +7327,7 @@ See also `format-spec'." (error "No format spec for message %s" msg)) (when (functionp entry) (setq entry (apply entry args))) - (format-spec entry (apply #'format-spec-make args)))) + (format-spec entry (apply #'format-spec-make args) 'ignore))) ;;; Various hook functions From 163000fb5980a0a098d1c4620b88a4717702d779 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 11 Oct 2022 15:45:08 +0800 Subject: [PATCH 39/99] Remove some more unnecessary calls to block_input * src/xterm.c (x_update_opaque_region, show_back_buffer) (XTbuffer_flipping_unblocked_hook, x_clear_under_internal_border) (x_after_update_window_line): Remove and add calls to block_input as required. --- src/xterm.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index a374b13780b..21207a31461 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5139,24 +5139,20 @@ x_update_opaque_region (struct frame *f, XEvent *configure) if (!FRAME_DISPLAY_INFO (f)->alpha_bits) return; - block_input (); if (f->alpha_background < 1.0) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, NULL, 0); #ifndef HAVE_GTK3 else - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opaque_region, 4); #else else if (FRAME_TOOLTIP_P (f)) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opaque_region, 4); @@ -5174,7 +5170,6 @@ x_update_opaque_region (struct frame *f, XEvent *configure) } } #endif - unblock_input (); } @@ -7144,8 +7139,6 @@ show_back_buffer (struct frame *f) cairo_t *cr; #endif - block_input (); - if (FRAME_X_DOUBLE_BUFFERED_P (f)) { #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME @@ -7174,8 +7167,6 @@ show_back_buffer (struct frame *f) } FRAME_X_NEED_BUFFER_FLIP (f) = false; - - unblock_input (); } #endif @@ -7283,8 +7274,12 @@ XTframe_up_to_date (struct frame *f) static void XTbuffer_flipping_unblocked_hook (struct frame *f) { + block_input (); + if (FRAME_X_NEED_BUFFER_FLIP (f)) show_back_buffer (f); + + unblock_input (); } #endif @@ -7313,8 +7308,6 @@ x_clear_under_internal_border (struct frame *f) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); - block_input (); - if (face) { unsigned long color = face->background; @@ -7335,8 +7328,6 @@ x_clear_under_internal_border (struct frame *f) x_clear_area (f, width - border, 0, border, height); x_clear_area (f, 0, height - border, width, border); } - - unblock_input (); } } @@ -7384,7 +7375,6 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); - block_input (); if (face) { unsigned long color = face->background; @@ -7402,7 +7392,6 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) x_clear_area (f, 0, y, width, height); x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height); } - unblock_input (); } } #endif From 4f114c0d95caa0e26de3d188cebe9e3cbcb2dee8 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 11 Oct 2022 13:26:01 +0300 Subject: [PATCH 40/99] Speed up scrolling when lines are very long and truncated * src/window.c (window_scroll_for_long_lines): New function. (window_scroll): Call 'window_scroll_for_long_lines' when lines are very long and truncated on display. Also, disable 'fontification-functions' during scrolling in that case. * src/xdisp.c (redisplay_window): When recentering the window's display, go back to the centering position using a simplified method, if lines in the buffer are very long and truncated on display. --- src/window.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/xdisp.c | 15 +++++++- 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/src/window.c b/src/window.c index da80fabe33f..4e8b352e164 100644 --- a/src/window.c +++ b/src/window.c @@ -52,6 +52,7 @@ static ptrdiff_t get_leaf_windows (struct window *, struct window **, ptrdiff_t); static void window_scroll_pixel_based (Lisp_Object, int, bool, bool); static void window_scroll_line_based (Lisp_Object, int, bool, bool); +static void window_scroll_for_long_lines (struct window *, int, bool); static void foreach_window (struct frame *, bool (* fn) (struct window *, void *), void *); @@ -5536,19 +5537,40 @@ window_internal_height (struct window *w) static void window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror) { + struct window *w = XWINDOW (window); + struct buffer *b = XBUFFER (w->contents); + bool long_lines_truncated = + b->long_line_optimizations_p && !NILP (BVAR (b, truncate_lines)); specpdl_ref count = SPECPDL_INDEX (); n = clip_to_bounds (INT_MIN, n, INT_MAX); - wset_redisplay (XWINDOW (window)); + wset_redisplay (w); - if (whole && fast_but_imprecise_scrolling) + /* Does this window's buffer have very long and truncated lines? */ + if (b->long_line_optimizations_p + && !long_lines_truncated + && !NILP (Vtruncate_partial_width_windows) + && w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w)))) + { + if (FIXNUMP (Vtruncate_partial_width_windows)) + long_lines_truncated = + w->total_cols < XFIXNAT (Vtruncate_partial_width_windows); + else + long_lines_truncated = true; + } + + if (whole && (fast_but_imprecise_scrolling || long_lines_truncated)) specbind (Qfontification_functions, Qnil); - /* On GUI frames, use the pixel-based version which is much slower - than the line-based one but can handle varying line heights. */ - if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame))) + if (whole && long_lines_truncated) + window_scroll_for_long_lines (w, n, noerror); + else if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame))) { + + /* On GUI frames, use the pixel-based version which is much + slower than the line-based one, but can handle varying + line heights. */ record_unwind_protect_void (unwind_display_working_on_window); display_working_on_window_p = true; window_scroll_pixel_based (window, n, whole, noerror); @@ -5598,6 +5620,71 @@ sanitize_next_screen_context_lines (void) return clip_to_bounds (0, next_screen_context_lines, 1000000); } +/* Implementation of window_scroll for very long and truncated lines. + This is a simplified version, it only handles WHOLE window scrolls, + and doesn't honor scroll-preserve-screen-position nor scroll-margin. */ +static void +window_scroll_for_long_lines (struct window *w, int n, bool noerror) +{ + ptrdiff_t startpos = marker_position (w->start); + ptrdiff_t startbyte = marker_byte_position (w->start); + int nscls = sanitize_next_screen_context_lines (); + register int ht = window_internal_height (w); + + n *= max (1, ht - nscls); + + /* If point is not visible in window, bring it inside window. */ + struct position pos; + int rtop, rbot, dummy_rowh, dummy_vpos, dummy_x, dummy_y; + if (!(PT >= startpos + && PT <= ZV + && startpos <= ZV + && pos_visible_p (w, PT, &dummy_x, &dummy_y, &rtop, &rbot, &dummy_rowh, + &dummy_vpos) + && !rtop && !rbot)) + { + pos = *vmotion (PT, PT_BYTE, - (ht / 2), w); + startpos = pos.bufpos; + startbyte = pos.bytepos; + } + SET_PT_BOTH (startpos, startbyte); + + bool lose = n < 0 && PT == BEGV; + pos = *vmotion (PT, PT_BYTE, n, w); + if (lose) + { + if (noerror) + return; + else + xsignal0 (Qbeginning_of_buffer); + } + + bool bolp = pos.bufpos == BEGV || FETCH_BYTE (pos.bytepos - 1) == '\n'; + if (pos.bufpos < ZV) + { + set_marker_restricted_both (w->start, w->contents, + pos.bufpos, pos.bytepos); + w->start_at_line_beg = bolp; + wset_update_mode_line (w); + /* Set force_start so that redisplay_window will run + the window-scroll-functions. */ + w->force_start = true; + SET_PT_BOTH (pos.bufpos, pos.bytepos); + if (n > 0) + pos = *vmotion (PT, PT_BYTE, ht / 2, w); + else if (n < 0) + pos = *vmotion (PT, PT_BYTE, - (ht / 2), w); + SET_PT_BOTH (pos.bufpos, pos.bytepos); + } + else + { + if (noerror) + return; + else + xsignal0 (Qend_of_buffer); + } +} + /* Implementation of window_scroll that works based on pixel line heights. See the comment of window_scroll for parameter descriptions. */ diff --git a/src/xdisp.c b/src/xdisp.c index 9534e27843e..e390de6a336 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -20165,7 +20165,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) from point. */ centering_position = window_box_height (w) / 2; } - move_it_vertically_backward (&it, centering_position); + if (current_buffer->long_line_optimizations_p + && it.line_wrap == TRUNCATE) + { + /* For very long and truncated lines, go back using a simplified + method, which ignored any inaccuracies due to line-height + differences, display properties/overlays, etc. */ + int nlines = centering_position / frame_line_height; + + while (nlines-- && IT_CHARPOS (it) > BEGV) + back_to_previous_visible_line_start (&it); + reseat_1 (&it, it.current.pos, true); + } + else + move_it_vertically_backward (&it, centering_position); eassert (IT_CHARPOS (it) >= BEGV); From 5724ee61313c52a17f94ebad52f2e8e7a44fe7cd Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Tue, 11 Oct 2022 13:02:20 +0200 Subject: [PATCH 41/99] Make read-string-from-buffer and string-edit mention each other * lisp/textmodes/string-edit.el (read-string-from-buffer) (string-edit): Mention each other in the doc strings. --- lisp/textmodes/string-edit.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el index 53850674ac0..562ab60d137 100644 --- a/lisp/textmodes/string-edit.el +++ b/lisp/textmodes/string-edit.el @@ -46,7 +46,9 @@ called with no parameters. PROMPT will be inserted at the start of the buffer, but won't be included in the resulting string. If PROMPT is nil, no help text -will be inserted." +will be inserted. + +Also see `read-string-from-buffer'." (with-current-buffer (generate-new-buffer "*edit string*") (when prompt (let ((inhibit-read-only t)) @@ -88,7 +90,9 @@ The user finishes editing with \\\\[string-edit-done], or PROMPT will be inserted at the start of the buffer, but won't be included in the resulting string. If nil, no prompt will be -inserted in the buffer." +inserted in the buffer. + +Also see `string-edit'." (string-edit prompt string From 48df8bbb1fd55e363c85e968de3719c9ec5150a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Tue, 11 Oct 2022 11:10:46 +0200 Subject: [PATCH 42/99] ; * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): run faster on mainframes --- src/fns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fns.c b/src/fns.c index 5eab35a5646..40557923827 100644 --- a/src/fns.c +++ b/src/fns.c @@ -442,7 +442,8 @@ If string STR1 is greater, the value is a positive number N; || defined __i386__ || defined __i386 \ || defined __arm64__ || defined __aarch64__ \ || defined __powerpc__ || defined __powerpc \ - || defined __ppc__ || defined __ppc + || defined __ppc__ || defined __ppc \ + || defined __s390__ || defined __s390x__ #define HAVE_FAST_UNALIGNED_ACCESS 1 #else #define HAVE_FAST_UNALIGNED_ACCESS 0 From 61b6da5acef2d550022c664e628346539ba1852f Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 11 Oct 2022 19:55:14 +0800 Subject: [PATCH 43/99] Also avoid setting _NET_WM_USER_TIME on crossing * src/xterm.c (handle_one_xevent): Stop setting user time prop on crossing events. --- src/xterm.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 21207a31461..9c34fce7c5b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -7592,17 +7592,19 @@ static void x_check_font (struct frame *, struct font *); ridiculously large value, and this way a more reasonable timestamp can be obtained upon the next event. + Alternatively, the server time could've overflowed. + SET_PROPERTY specifies whether or not to change the user time property for the active frame. The important thing is to not set the last user time upon leave events; on Metacity and GNOME Shell, mapping a new frame on top of the old frame potentially causes - LeaveNotify or XI_Leave to be sent to the old frame if it contains - the pointer, as the new frame will initially stack above the old - frame. If _NET_WM_USER_TIME is changed at that point, then GNOME - may get notified about the user time change on the old frame before - it tries to focus the new frame, which will make it consider the - new frame (whose user time property will not have been updated at - that point, due to not being focused) as having been mapped + crossing events to be sent to the old frame if it contains the + pointer, as the new frame will initially stack above the old frame. + If _NET_WM_USER_TIME is changed at that point, then GNOME may get + notified about the user time change on the old frame before it + tries to focus the new frame, which will make it consider the new + frame (whose user time property will not have been updated at that + point, due to not being focused) as having been mapped out-of-order, and lower the new frame, which is typically not what users want. */ @@ -19567,7 +19569,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case EnterNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event, true); + event->xcrossing.send_event, false); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -21114,7 +21116,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.send_event = enter->send_event; x_display_set_last_user_time (dpyinfo, enter->time, - enter->send_event, true); + enter->send_event, false); #ifdef USE_MOTIF use_copy = true; From 3787d0b11a40484bf15e860ac300f35a91734ffb Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 11 Oct 2022 20:20:44 +0300 Subject: [PATCH 44/99] ; * doc/lispref/windows.texi (Window Hooks): Fix markup (bug#58445). --- doc/lispref/windows.texi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 5d31f70e01f..1334e3bcf82 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -6591,32 +6591,32 @@ time window change functions were run for @var{window}'s frame. If it returns @code{nil}, @var{window} has been created after that. If it returns @code{t}, @var{window} was not shown at that time but has been restored from a previously saved window configuration afterwards. -Otherwise, the return value is the buffer shown by @code{window} at +Otherwise, the return value is the buffer shown by @var{window} at that time. @end defun @defun window-old-pixel-width &optional window This function returns the total pixel width of @var{window} the -last time window change functions found @code{window} live on its -frame. It is zero if @code{window} was created after that. +last time window change functions found @var{window} live on its +frame. It is zero if @var{window} was created after that. @end defun @defun window-old-pixel-height &optional window This function returns the total pixel height of @var{window} the last -time window change functions found @code{window} live on its frame. -It is zero if @code{window} was created after that. +time window change functions found @var{window} live on its frame. +It is zero if @var{window} was created after that. @end defun @defun window-old-body-pixel-width &optional window This function returns the pixel width of @var{window}'s text area the -last time window change functions found @code{window} live on its -frame. It is zero if @code{window} was created after that. +last time window change functions found @var{window} live on its +frame. It is zero if @var{window} was created after that. @end defun @defun window-old-body-pixel-height &optional window This function returns the pixel height of @var{window}'s text area the -last time window change functions found @code{window} live on its -frame. It is zero if @code{window} was created after that. +last time window change functions found @var{window} live on its +frame. It is zero if @var{window} was created after that. @end defun In order to find out which window or frame was selected the last time From 37447209042e174f4e95c8d0166418d2aef018ed Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Tue, 11 Oct 2022 21:17:55 +0200 Subject: [PATCH 45/99] Add trampoline AOT compilation target (bug#58318) * Makefile.in (trampolines): New target. * lisp/Makefile.in (trampolines): Likewise. * lisp/emacs-lisp/comp.el (comp-compile-all-trampolines): New function. --- Makefile.in | 5 +++++ lisp/Makefile.in | 6 ++++++ lisp/emacs-lisp/comp.el | 11 +++++++++++ 3 files changed, 22 insertions(+) diff --git a/Makefile.in b/Makefile.in index 741a4c5538a..2d617e2294d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -530,6 +530,11 @@ lisp: src lib lib-src lisp nt: Makefile $(MAKE) -C $@ all +trampolines: src lisp +ifeq ($(HAVE_NATIVE_COMP),yes) + $(MAKE) -C lisp trampolines +endif + # Pass an unexpanded $srcdir to src's Makefile, which then # expands it using its own value of srcdir (which points to the # source directory of src/). diff --git a/lisp/Makefile.in b/lisp/Makefile.in index 256017f6c5b..338814fdda2 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in @@ -430,6 +430,12 @@ compile-always: find $(lisp) -name '*.elc' $(FIND_DELETE) $(MAKE) compile +.PHONY: trampolines +trampolines: compile +ifeq ($(HAVE_NATIVE_COMP),yes) + $(emacs) -l comp -f comp-compile-all-trampolines +endif + .PHONY: backup-compiled-files compile-after-backup # Backup compiled Lisp files in elc.tar.gz. If that file already diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 6656b7e57c1..889bffa3f5c 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -4204,6 +4204,17 @@ bytecode definition was not changed in the meantime)." ;;; Compiler entry points. +(defun comp-compile-all-trampolines () + "Pre-compile AOT all trampolines." + (let ((comp-running-batch-compilation t) + ;; We want to target only the 'native-lisp' directory. + (native-compile-target-directory + (car (last native-comp-eln-load-path)))) + (mapatoms (lambda (f) + (when (subr-primitive-p (symbol-function f)) + (message "Compiling trampoline for: %s" f) + (comp-trampoline-compile f)))))) + ;;;###autoload (defun comp-lookup-eln (filename) "Given a Lisp source FILENAME return the corresponding .eln file if found. From ef6e518035fddf13547d7f1f945b5069a0fe6ea7 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Wed, 12 Oct 2022 00:04:54 +0300 Subject: [PATCH 46/99] ; lisp/progmodes/project.el: Bump version --- lisp/progmodes/project.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index ee94d0d85d8..ac278edd409 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1,7 +1,7 @@ ;;; project.el --- Operations on the current project -*- lexical-binding: t; -*- ;; Copyright (C) 2015-2022 Free Software Foundation, Inc. -;; Version: 0.8.1 +;; Version: 0.8.2 ;; Package-Requires: ((emacs "26.1") (xref "1.4.0")) ;; This is a GNU ELPA :core package. Avoid using functionality that From 2953d89d74ebfe6a6bcbe0d25a60a845acad0e13 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 12 Oct 2022 15:07:49 +0800 Subject: [PATCH 47/99] Stop relying on Xt hack to set window manager hints * src/widget.c (get_wm_shell): Return WMShellWidget. (update_wm_hints, widget_update_wm_size_hints): Return whether or not size hints changed. * src/widget.h: Delete `size_switch'. * src/widgetprv.h (EmacsFramePart): Likewise. * src/xterm.c (x_wm_set_size_hint): Set size hints the usual way if Xt did not set them. (bug#58412) --- src/widget.c | 42 ++++++++++++++++++++++++------------------ src/widget.h | 2 +- src/widgetprv.h | 3 --- src/xterm.c | 19 +++++++++++++++---- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/widget.c b/src/widget.c index 5a75cdaca8e..aaab33b6d8e 100644 --- a/src/widget.c +++ b/src/widget.c @@ -195,7 +195,7 @@ round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, out_width, out_height); } -static Widget +static WMShellWidget get_wm_shell (Widget w) { Widget wmshell; @@ -204,7 +204,7 @@ get_wm_shell (Widget w) wmshell && !XtIsWMShell (wmshell); wmshell = XtParent (wmshell)); - return wmshell; + return (WMShellWidget) wmshell; } #if 0 /* Currently not used. */ @@ -269,8 +269,8 @@ set_frame_size (EmacsFrame ew) (f, build_string ("set_frame_size")); } -static void -update_wm_hints (Widget wmshell, EmacsFrame ew) +static bool +update_wm_hints (WMShellWidget wmshell, EmacsFrame ew) { int cw; int ch; @@ -280,6 +280,12 @@ update_wm_hints (Widget wmshell, EmacsFrame ew) int char_height; int base_width; int base_height; + char buffer[sizeof wmshell->wm.size_hints]; + char *hints_ptr; + + /* Copy the old size hints to the buffer. */ + memcpy (buffer, &wmshell->wm.size_hints, + sizeof wmshell->wm.size_hints); pixel_to_char_size (ew, ew->core.width, ew->core.height, &char_width, &char_height); @@ -292,27 +298,29 @@ update_wm_hints (Widget wmshell, EmacsFrame ew) base_height = (wmshell->core.height - ew->core.height + (rounded_height - (char_height * ch))); - /* Ensure that Xt actually sets window manager hint flags specified - by the caller by making sure XtNminWidth (a relatively harmless - resource) always changes each time this function is invoked. */ - ew->emacs_frame.size_switch = !ew->emacs_frame.size_switch; - - XtVaSetValues (wmshell, + XtVaSetValues ((Widget) wmshell, XtNbaseWidth, (XtArgVal) base_width, XtNbaseHeight, (XtArgVal) base_height, XtNwidthInc, (XtArgVal) (frame_resize_pixelwise ? 1 : cw), XtNheightInc, (XtArgVal) (frame_resize_pixelwise ? 1 : ch), - XtNminWidth, (XtArgVal) (base_width - + ew->emacs_frame.size_switch), - XtNminHeight, (XtArgVal) (base_height - + ew->emacs_frame.size_switch), + XtNminWidth, (XtArgVal) base_width, + XtNminHeight, (XtArgVal) base_height, NULL); + + /* Return if size hints really changed. If they did not, then Xt + probably didn't set them either (or take the flags into + account.) */ + hints_ptr = (char *) &wmshell->wm.size_hints; + + /* Skip flags, which is unsigned long. */ + return memcmp (hints_ptr + sizeof (long), buffer + sizeof (long), + sizeof wmshell->wm.wm_hints - sizeof (long)); } -void +bool widget_update_wm_size_hints (Widget widget, Widget frame) { - update_wm_hints (widget, (EmacsFrame) frame); + return update_wm_hints ((WMShellWidget) widget, (EmacsFrame) frame); } static void @@ -357,8 +365,6 @@ EmacsFrameInitialize (Widget request, Widget new, exit (1); } - ew->emacs_frame.size_switch = 1; - update_from_various_frame_slots (ew); set_frame_size (ew); } diff --git a/src/widget.h b/src/widget.h index 2906d5ff9ec..cf83cb10781 100644 --- a/src/widget.h +++ b/src/widget.h @@ -97,6 +97,6 @@ extern struct _DisplayContext *display_context; /* Special entry points */ void EmacsFrameSetCharSize (Widget, int, int); void widget_store_internal_border (Widget widget); -void widget_update_wm_size_hints (Widget widget, Widget frame); +bool widget_update_wm_size_hints (Widget widget, Widget frame); #endif /* _EmacsFrame_h */ diff --git a/src/widgetprv.h b/src/widgetprv.h index fe960326b03..3a4d9206ffe 100644 --- a/src/widgetprv.h +++ b/src/widgetprv.h @@ -49,9 +49,6 @@ typedef struct { Boolean visual_bell; /* flash instead of beep */ int bell_volume; /* how loud is beep */ - int size_switch; /* hack to make setting size - hints work correctly */ - /* private state */ } EmacsFramePart; diff --git a/src/xterm.c b/src/xterm.c index 9c34fce7c5b..9059ad7136e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -28006,6 +28006,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) Window window = FRAME_OUTER_WINDOW (f); #ifdef USE_X_TOOLKIT WMShellWidget shell; + bool hints_changed; #endif if (!window) @@ -28032,8 +28033,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) shell->wm.size_hints.flags |= USPosition; } - widget_update_wm_size_hints (f->output_data.x->widget, - f->output_data.x->edit_widget); + hints_changed + = widget_update_wm_size_hints (f->output_data.x->widget, + f->output_data.x->edit_widget); #ifdef USE_MOTIF /* Do this all over again for the benefit of Motif, which always @@ -28046,6 +28048,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) shell->wm.size_hints.flags &= ~PPosition; shell->wm.size_hints.flags |= USPosition; } +#endif /* Drill hints into Motif, since it keeps setting its own. */ size_hints.flags = shell->wm.size_hints.flags; @@ -28063,15 +28066,23 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y; size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x; size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y; -#ifdef HAVE_X11XTR6 size_hints.base_width = shell->wm.base_width; size_hints.base_height = shell->wm.base_height; size_hints.win_gravity = shell->wm.win_gravity; -#endif +#ifdef USE_MOTIF XSetWMNormalHints (XtDisplay (f->output_data.x->widget), XtWindow (f->output_data.x->widget), &size_hints); +#else + /* In many cases, widget_update_wm_size_hints will not have + updated the size hints if only flags changed. When that + happens, set the WM hints manually. */ + + if (!hints_changed) + XSetWMNormalHints (XtDisplay (f->output_data.x->widget), + XtWindow (f->output_data.x->widget), + &size_hints); #endif return; From aa559c15537a59147bb01617b4a1f9eee20af3a1 Mon Sep 17 00:00:00 2001 From: kobarity Date: Wed, 12 Oct 2022 13:14:33 +0200 Subject: [PATCH 48/99] Fix Python completion when point in shell buffer is before prompt * lisp/progmodes/python.el (python-shell-completion-at-point): Limit prompt boundaries check to shell buffer. * test/lisp/progmodes/python-tests.el (python-shell-completion-2): (python-shell-completion-native-2): New tests (bug#58441). --- lisp/progmodes/python.el | 6 ++++-- test/lisp/progmodes/python-tests.el | 33 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 680b57fc3ef..0de76b0bde3 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -4069,7 +4069,8 @@ With argument MSG show activation/deactivation message." Optional argument PROCESS forces completions to be retrieved using that one instead of current buffer's process." (setq process (or process (get-buffer-process (current-buffer)))) - (let* ((line-start (if (derived-mode-p 'inferior-python-mode) + (let* ((is-shell-buffer (derived-mode-p 'inferior-python-mode)) + (line-start (if is-shell-buffer ;; Working on a shell buffer: use prompt end. (cdr (python-util-comint-last-prompt)) (line-beginning-position))) @@ -4100,7 +4101,8 @@ using that one instead of current buffer's process." (completion-fn (with-current-buffer (process-buffer process) (cond ((or (null prompt) - (< (point) (cdr prompt-boundaries))) + (and is-shell-buffer + (< (point) (cdr prompt-boundaries)))) #'ignore) ((or (not python-shell-completion-native-enable) ;; Even if native completion is enabled, for diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 60ff9bb613a..9ad2d169308 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -4411,6 +4411,22 @@ import abc (insert "A") (should (completion-at-point))))) +(ert-deftest python-shell-completion-2 () + "Should work regardless of the point in the Shell buffer." + (skip-unless (executable-find python-tests-shell-interpreter)) + (python-tests-with-temp-buffer-with-shell + " +import abc +" + (let ((inhibit-message t)) + (python-shell-send-buffer) + (python-tests-shell-wait-for-prompt) + (python-shell-with-shell-buffer + (goto-char (point-min))) + (goto-char (point-max)) + (insert "abc.") + (should (completion-at-point))))) + (ert-deftest python-shell-completion-native-1 () (skip-unless (executable-find python-tests-shell-interpreter)) (python-tests-with-temp-buffer-with-shell @@ -4427,6 +4443,23 @@ import abc (insert "A") (should (completion-at-point))))) +(ert-deftest python-shell-completion-native-2 () + "Should work regardless of the point in the Shell buffer." + (skip-unless (executable-find python-tests-shell-interpreter)) + (python-tests-with-temp-buffer-with-shell + " +import abc +" + (let ((inhibit-message t)) + (python-shell-completion-native-turn-on) + (python-shell-send-buffer) + (python-tests-shell-wait-for-prompt) + (python-shell-with-shell-buffer + (goto-char (point-min))) + (goto-char (point-max)) + (insert "abc.") + (should (completion-at-point))))) + (ert-deftest python-shell-completion-native-with-ffap-1 () (skip-unless (executable-find python-tests-shell-interpreter)) (python-tests-with-temp-buffer-with-shell From 820e6f399d0af56ebfdc581f68424f4cb9cbe53b Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Wed, 12 Oct 2022 13:40:51 +0200 Subject: [PATCH 49/99] Fix thinko in read-string-from-buffer * lisp/textmodes/string-edit.el (string-edit-done): Return an empty string when the user has entered no text. --- lisp/textmodes/string-edit.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el index 562ab60d137..3270050ca4a 100644 --- a/lisp/textmodes/string-edit.el +++ b/lisp/textmodes/string-edit.el @@ -119,9 +119,7 @@ This will kill the current buffer." (interactive) (goto-char (point-min)) ;; Skip past the help text. - (when-let ((match (text-property-search-forward - 'string-edit--prompt nil t))) - (goto-char (prop-match-beginning match))) + (text-property-search-forward 'string-edit--prompt) (let ((string (buffer-substring (point) (point-max))) (callback string-edit--success-callback)) (quit-window 'kill) From 1e961eda7275802f88d855fccf097b4081d21b18 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 12 Oct 2022 20:40:03 +0800 Subject: [PATCH 50/99] Improve makefile-imake-mode * lisp/progmodes/make-mode.el (makefile-imake-font-lock-keywords): Give Imake priority over CPP keywords, and don't require comments to start at BOL. (makefile-imake-mode): Set comment-start to some sensible value. --- lisp/progmodes/make-mode.el | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el index cbbcf1c2b7c..5f265212992 100644 --- a/lisp/progmodes/make-mode.el +++ b/lisp/progmodes/make-mode.el @@ -488,17 +488,12 @@ not be enclosed in { } or ( )." (defconst makefile-imake-font-lock-keywords - (append - (makefile-make-font-lock-keywords - makefile-var-use-regex - makefile-statements - t - nil - '("^XCOMM.*$" . font-lock-comment-face) - '("XVAR\\(?:use\\|def\\)[0-9]" 0 font-lock-keyword-face prepend) - '("@@" . font-lock-preprocessor-face) - ) - cpp-font-lock-keywords)) + (append (list '("XCOMM.*$" . font-lock-comment-face) + '("XVAR\\(?:use\\|def\\)[0-9]" 0 + font-lock-keyword-face prepend) + '("@@" . font-lock-preprocessor-face)) + cpp-font-lock-keywords + makefile-font-lock-keywords)) (defconst makefile-syntax-propertize-function @@ -932,7 +927,9 @@ Makefile mode can be configured by modifying the following variables: :syntax-table makefile-imake-mode-syntax-table (setq-local syntax-propertize-function nil) (setq font-lock-defaults - `(makefile-imake-font-lock-keywords ,@(cdr font-lock-defaults)))) + `(makefile-imake-font-lock-keywords ,@(cdr font-lock-defaults))) + (setq-local comment-start "XCOMM") + (setq-local comment-start-skip "XCOMM[ \t]*")) From 5a94a2e5b054f6866762f6eb7f7bbafd24bf02de Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Wed, 12 Oct 2022 14:59:25 +0200 Subject: [PATCH 51/99] Clarify Native-Compilation Variables slightly * doc/lispref/compile.texi (Native-Compilation Variables): Clarify trampoline bit (bug#58429). --- doc/lispref/compile.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi index 7ccee08e53a..70e0f98f443 100644 --- a/doc/lispref/compile.texi +++ b/doc/lispref/compile.texi @@ -985,7 +985,7 @@ too late. While setting this variable disables automatic compilation of Lisp files, the compiler may still be invoked to install @dfn{trampolines} if any built-in functions are redefined. However, these trampolines -will not get written to disk. +will not get written to your cache directory. You can also use the @samp{EMACS_INHIBIT_AUTOMATIC_NATIVE_COMPILATION} environment variable to disable native compilation. From da752c04664c0e22a2f6b4a41dfa1fed4d5276ff Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 12 Oct 2022 17:06:33 -0400 Subject: [PATCH 52/99] src/frame.c (do_switch_frame): Fix bug#58343 * src/frame.c (do_switch_frame): Move call to `get-mru-window` outside of the "critical region" where (selected-window) != (frame-selected-window). * src/minibuf.c (move_minibuffers_onto_frame): Add arg `frame`. Use it instead of `selected_frame`. Adjust all callers. * src/lisp.h (move_minibuffers_onto_frame): Adjust declaration. --- src/frame.c | 28 ++++++++++++++++------------ src/lisp.h | 2 +- src/minibuf.c | 12 +++++++----- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/frame.c b/src/frame.c index 91b9bec82c3..f076a5ba54e 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1503,17 +1503,7 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); - selected_frame = frame; - - move_minibuffers_onto_frame (sf, for_deletion); - - if (f->select_mini_window_flag - && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) - f->selected_window = f->minibuffer_window; - f->select_mini_window_flag = false; - - if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) - last_nonminibuf_frame = XFRAME (selected_frame); + move_minibuffers_onto_frame (sf, frame, for_deletion); /* If the selected window in the target frame is its mini-window, we move to a different window, the most recently used one, unless there is a @@ -1528,6 +1518,20 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) Fset_frame_selected_window (frame, w, Qnil); } + /* After setting `selected_frame`, we're temporarily in an inconsistent + state where (selected-window) != (frame-selected-window). Until this + invariant is restored we should be very careful not to run ELisp code. + (bug#58343) */ + selected_frame = frame; + + if (f->select_mini_window_flag + && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) + f->selected_window = f->minibuffer_window; + f->select_mini_window_flag = false; + + if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) + last_nonminibuf_frame = XFRAME (selected_frame); + Fselect_window (f->selected_window, norecord); /* We want to make sure that the next event generates a frame-switch @@ -2110,7 +2114,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) else /* Ensure any minibuffers on FRAME are moved onto the selected frame. */ - move_minibuffers_onto_frame (f, true); + move_minibuffers_onto_frame (f, selected_frame, true); /* Don't let echo_area_window to remain on a deleted frame. */ if (EQ (f->minibuffer_window, echo_area_window)) diff --git a/src/lisp.h b/src/lisp.h index 56f24d82810..5f6721595c0 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4792,7 +4792,7 @@ extern void clear_regexp_cache (void); extern Lisp_Object Vminibuffer_list; extern Lisp_Object last_minibuf_string; -extern void move_minibuffers_onto_frame (struct frame *, bool); +extern void move_minibuffers_onto_frame (struct frame *, Lisp_Object, bool); extern bool is_minibuffer (EMACS_INT, Lisp_Object); extern EMACS_INT this_minibuffer_depth (Lisp_Object); extern EMACS_INT minibuf_level; diff --git a/src/minibuf.c b/src/minibuf.c index bedc5644807..3f34b1b0834 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -187,13 +187,15 @@ zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window) /* If `minibuffer_follows_selected_frame' is t, or we're about to delete a frame which potentially "contains" minibuffers, move them - from the old frame to the selected frame. This function is + from the old frame to the to-be-selected frame. This function is intended to be called from `do_switch_frame' in frame.c. OF is the - old frame, FOR_DELETION is true if OF is about to be deleted. */ + old frame, FRAME is the to-be-selected frame, and FOR_DELETION is true + if OF is about to be deleted. */ void -move_minibuffers_onto_frame (struct frame *of, bool for_deletion) +move_minibuffers_onto_frame (struct frame *of, Lisp_Object frame, + bool for_deletion) { - struct frame *f = XFRAME (selected_frame); + struct frame *f = XFRAME (frame); minibuf_window = f->minibuffer_window; if (!(minibuf_level @@ -206,7 +208,7 @@ move_minibuffers_onto_frame (struct frame *of, bool for_deletion) { zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); if (for_deletion && XFRAME (MB_frame) != of) - MB_frame = selected_frame; + MB_frame = frame; } } From 4b4b093ab387fb0f0f0c588831d0c4fc2bd097f3 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 13 Oct 2022 04:46:32 +0200 Subject: [PATCH 53/99] ; * admin/make-tarball.txt: Fix typo. --- admin/make-tarball.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt index ad2aacb57a9..3aee05c3d06 100644 --- a/admin/make-tarball.txt +++ b/admin/make-tarball.txt @@ -389,7 +389,7 @@ Next, regenerate the various manuals in HTML, PDF, and PS formats: Now change to the 'manual' directory and invoke upload-manuals: - ../admin/updload-manuals /path/to/webpages/cvs/checkout + ../admin/upload-manuals /path/to/webpages/cvs/checkout where /path/to/webpages/cvs/checkout is the place where you have the CVS checkout of the Emacs Web pages, with subdirectories 'manual' From c522021a3019fa8f8598319a867326ec59b2bfaf Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 13 Oct 2022 09:00:17 +0200 Subject: [PATCH 54/99] Fix misleading "File exists, but cannot be read" in browse-url-emacs * src/fileio.c (Finsert_file_contents): Don't signal an error about not being able to open the file when we're fetching things via handlers -- in that case, modtime isn't necessarily set, and if there's a handler, it should take care of this (bug#42431). --- src/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fileio.c b/src/fileio.c index dd7f85ec97f..a2388898034 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5000,7 +5000,7 @@ by calling `format-decode', which see. */) unbind_to (count1, Qnil); } - if (!NILP (visit) && current_buffer->modtime.tv_nsec < 0) + if (NILP (handler) && !NILP (visit) && current_buffer->modtime.tv_nsec < 0) { /* Signal an error if visiting a file that could not be opened. */ report_file_errno ("Opening input file", orig_filename, save_errno); From 3d41cc03d96b0383ad87c985ff48077e39cac985 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Thu, 13 Oct 2022 10:13:07 +0300 Subject: [PATCH 55/99] * lisp/outline.el (outline--fix-buttons-after-change): New function. (outline-minor-mode): Use it. (outline--make-margin-overlay): Remove inhibit-read-only. --- lisp/outline.el | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lisp/outline.el b/lisp/outline.el index 93a9247f613..b2b36a764ce 100644 --- a/lisp/outline.el +++ b/lisp/outline.el @@ -516,13 +516,7 @@ See the command `outline-mode' for more information on this mode." (set-window-buffer nil (window-buffer))) (when (or outline--use-buttons outline--use-margins) (add-hook 'after-change-functions - (lambda (beg end _len) - (when outline--use-buttons - (remove-overlays beg end 'outline-button t)) - (when outline--use-margins - (remove-overlays beg end 'outline-margin t)) - (outline--fix-up-all-buttons beg end)) - nil t)) + #'outline--fix-buttons-after-change nil t)) (when outline-minor-mode-highlight (if (and global-font-lock-mode (font-lock-specified-p major-mode)) (progn @@ -1105,8 +1099,7 @@ If non-nil, EVENT should be a mouse event." (if outline--use-rtl 'outline-close-rtl-in-margins 'outline-close-in-margins) - 'outline-open-in-margins))) - (inhibit-read-only t)) + 'outline-open-in-margins)))) (overlay-put o 'before-string (propertize " " 'display @@ -1451,6 +1444,9 @@ convenient way to make a table of contents of the buffer." (insert "\n\n")))))) (kill-new (buffer-string))))))) + +;;; Initial visibility + (defcustom outline-default-state nil "If non-nil, some headings are initially outlined. @@ -1629,6 +1625,9 @@ LEVEL, decides of subtree visibility according to beg end))) (run-hooks 'outline-view-change-hook))) + +;;; Visibility cycling + (defun outline--cycle-state () "Return the cycle state of current heading. Return either `hide-all', `headings-only', or `show-all'." @@ -1741,6 +1740,19 @@ With a prefix argument, show headings up to that LEVEL." (setq outline--cycle-buffer-state 'show-all) (message "Show all"))))) + +;;; Button/margin indicators + +(defun outline--fix-buttons-after-change (beg end _len) + ;; Handle whole lines + (save-excursion (goto-char beg) (setq beg (pos-bol))) + (save-excursion (goto-char end) (setq end (pos-eol))) + (when outline--use-buttons + (remove-overlays beg end 'outline-button t)) + (when outline--use-margins + (remove-overlays beg end 'outline-margin t)) + (outline--fix-up-all-buttons beg end)) + (defvar-keymap outline-navigation-repeat-map "C-b" #'outline-backward-same-level From 7054481ed5ab588c308cb06a137bab24d777a1ab Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Thu, 13 Oct 2022 10:23:44 +0300 Subject: [PATCH 56/99] * lisp/outline.el: Rearrange button/margin functions. (outline--make-button-overlay, outline--make-margin-overlay) (outline--insert-open-button, outline--insert-close-button) (outline--fix-up-all-buttons): Move to the section "Button/margin indicators". --- lisp/outline.el | 200 ++++++++++++++++++++++++------------------------ 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/lisp/outline.el b/lisp/outline.el index b2b36a764ce..b87d3ac5e7f 100644 --- a/lisp/outline.el +++ b/lisp/outline.el @@ -1059,106 +1059,6 @@ If non-nil, EVENT should be a mouse event." (mouse-set-point event)) (outline-flag-subtree t))) -(defun outline--make-button-overlay (type) - (let ((o (seq-find (lambda (o) - (overlay-get o 'outline-button)) - (overlays-at (point))))) - (unless o - (setq o (make-overlay (point) (1+ (point)))) - (overlay-put o 'evaporate t) - (overlay-put o 'follow-link 'mouse-face) - (overlay-put o 'mouse-face 'highlight) - (overlay-put o 'outline-button t)) - (let ((icon (icon-elements (if (eq type 'close) - (if outline--use-rtl - 'outline-close-rtl - 'outline-close) - 'outline-open))) - (inhibit-read-only t)) - ;; In editing buffers we use overlays only, but in other buffers - ;; we use a mix of text properties, text and overlays to make - ;; movement commands work more logically. - (when (derived-mode-p 'special-mode) - (put-text-property (point) (1+ (point)) 'face (plist-get icon 'face))) - (if-let ((image (plist-get icon 'image))) - (overlay-put o 'display image) - (overlay-put o 'display (concat (plist-get icon 'string) - (string (char-after (point))))) - (overlay-put o 'face (plist-get icon 'face)))) - o)) - -(defun outline--make-margin-overlay (type) - (let ((o (seq-find (lambda (o) - (overlay-get o 'outline-margin)) - (overlays-at (point))))) - (unless o - (setq o (make-overlay (point) (1+ (point)))) - (overlay-put o 'evaporate t) - (overlay-put o 'outline-margin t)) - (let ((icon (icon-elements (if (eq type 'close) - (if outline--use-rtl - 'outline-close-rtl-in-margins - 'outline-close-in-margins) - 'outline-open-in-margins)))) - (overlay-put - o 'before-string - (propertize " " 'display - `((margin ,(if outline--use-rtl - 'right-margin 'left-margin)) - ,(or (plist-get icon 'image) - (plist-get icon 'string)))))) - o)) - -(defun outline--insert-open-button (&optional use-margins) - (with-silent-modifications - (save-excursion - (beginning-of-line) - (if use-margins - (outline--make-margin-overlay 'open) - (when (derived-mode-p 'special-mode) - (let ((inhibit-read-only t)) - (insert " ") - (beginning-of-line))) - (let ((o (outline--make-button-overlay 'open))) - (overlay-put o 'help-echo "Click to hide") - (overlay-put o 'keymap - (define-keymap - "RET" #'outline-hide-subtree - "" #'outline-hide-subtree))))))) - -(defun outline--insert-close-button (&optional use-margins) - (with-silent-modifications - (save-excursion - (beginning-of-line) - (if use-margins - (outline--make-margin-overlay 'close) - (when (derived-mode-p 'special-mode) - (let ((inhibit-read-only t)) - (insert " ") - (beginning-of-line))) - (let ((o (outline--make-button-overlay 'close))) - (overlay-put o 'help-echo "Click to show") - (overlay-put o 'keymap - (define-keymap - "RET" #'outline-show-subtree - "" #'outline-show-subtree))))))) - -(defun outline--fix-up-all-buttons (&optional from to) - (when (or outline--use-buttons outline--use-margins) - (when from - (save-excursion - (goto-char from) - (setq from (line-beginning-position)))) - (outline-map-region - (lambda () - (if (save-excursion - (outline-end-of-heading) - (seq-some (lambda (o) (eq (overlay-get o 'invisible) 'outline)) - (overlays-at (point)))) - (outline--insert-close-button outline--use-margins) - (outline--insert-open-button outline--use-margins))) - (or from (point-min)) (or to (point-max))))) - (define-obsolete-function-alias 'hide-subtree #'outline-hide-subtree "25.1") (defun outline-hide-leaves () @@ -1743,6 +1643,106 @@ With a prefix argument, show headings up to that LEVEL." ;;; Button/margin indicators +(defun outline--make-button-overlay (type) + (let ((o (seq-find (lambda (o) + (overlay-get o 'outline-button)) + (overlays-at (point))))) + (unless o + (setq o (make-overlay (point) (1+ (point)))) + (overlay-put o 'evaporate t) + (overlay-put o 'follow-link 'mouse-face) + (overlay-put o 'mouse-face 'highlight) + (overlay-put o 'outline-button t)) + (let ((icon (icon-elements (if (eq type 'close) + (if outline--use-rtl + 'outline-close-rtl + 'outline-close) + 'outline-open))) + (inhibit-read-only t)) + ;; In editing buffers we use overlays only, but in other buffers + ;; we use a mix of text properties, text and overlays to make + ;; movement commands work more logically. + (when (derived-mode-p 'special-mode) + (put-text-property (point) (1+ (point)) 'face (plist-get icon 'face))) + (if-let ((image (plist-get icon 'image))) + (overlay-put o 'display image) + (overlay-put o 'display (concat (plist-get icon 'string) + (string (char-after (point))))) + (overlay-put o 'face (plist-get icon 'face)))) + o)) + +(defun outline--make-margin-overlay (type) + (let ((o (seq-find (lambda (o) + (overlay-get o 'outline-margin)) + (overlays-at (point))))) + (unless o + (setq o (make-overlay (point) (1+ (point)))) + (overlay-put o 'evaporate t) + (overlay-put o 'outline-margin t)) + (let ((icon (icon-elements (if (eq type 'close) + (if outline--use-rtl + 'outline-close-rtl-in-margins + 'outline-close-in-margins) + 'outline-open-in-margins)))) + (overlay-put + o 'before-string + (propertize " " 'display + `((margin ,(if outline--use-rtl + 'right-margin 'left-margin)) + ,(or (plist-get icon 'image) + (plist-get icon 'string)))))) + o)) + +(defun outline--insert-open-button (&optional use-margins) + (with-silent-modifications + (save-excursion + (beginning-of-line) + (if use-margins + (outline--make-margin-overlay 'open) + (when (derived-mode-p 'special-mode) + (let ((inhibit-read-only t)) + (insert " ") + (beginning-of-line))) + (let ((o (outline--make-button-overlay 'open))) + (overlay-put o 'help-echo "Click to hide") + (overlay-put o 'keymap + (define-keymap + "RET" #'outline-hide-subtree + "" #'outline-hide-subtree))))))) + +(defun outline--insert-close-button (&optional use-margins) + (with-silent-modifications + (save-excursion + (beginning-of-line) + (if use-margins + (outline--make-margin-overlay 'close) + (when (derived-mode-p 'special-mode) + (let ((inhibit-read-only t)) + (insert " ") + (beginning-of-line))) + (let ((o (outline--make-button-overlay 'close))) + (overlay-put o 'help-echo "Click to show") + (overlay-put o 'keymap + (define-keymap + "RET" #'outline-show-subtree + "" #'outline-show-subtree))))))) + +(defun outline--fix-up-all-buttons (&optional from to) + (when (or outline--use-buttons outline--use-margins) + (when from + (save-excursion + (goto-char from) + (setq from (line-beginning-position)))) + (outline-map-region + (lambda () + (if (save-excursion + (outline-end-of-heading) + (seq-some (lambda (o) (eq (overlay-get o 'invisible) 'outline)) + (overlays-at (point)))) + (outline--insert-close-button outline--use-margins) + (outline--insert-open-button outline--use-margins))) + (or from (point-min)) (or to (point-max))))) + (defun outline--fix-buttons-after-change (beg end _len) ;; Handle whole lines (save-excursion (goto-char beg) (setq beg (pos-bol))) From 4af4df18c54748eaac87be51660f3c80a415a82f Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 13 Oct 2022 09:52:44 +0200 Subject: [PATCH 57/99] Fix browse-url-emacs for file: URLs on Windows * lisp/net/browse-url.el (browse-url-emacs): Fix up file:///c:/foo/bar URLs on windows (bug#58464). --- lisp/net/browse-url.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 2d528c4862c..1597f3651a5 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -1294,6 +1294,11 @@ currently selected window instead." (let ((file (url-unhex-string (url-filename parsed)))) (when-let ((coding (browse-url--file-name-coding-system))) (setq file (decode-coding-string file 'utf-8))) + ;; The local-part of file: URLs on Windows is supposed to + ;; start with an extra slash. + (when (eq system-type 'windows-nt) + (setq file (replace-regexp-in-string + "\\`/\\([a-z]:\\)" "\\1" file))) (funcall func file)) (let ((file-name-handler-alist (cons (cons url-handler-regexp 'url-file-handler) From 12f261c4708d58362c9e080a686b0e41821c6db8 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 13 Oct 2022 10:08:55 +0200 Subject: [PATCH 58/99] Fix hl-line-mode/global-hl-line-mode logic again * lisp/hl-line.el (hl-line-mode): Make explicit calls to (hl-line-mode 1) work again when global-hl-line-mode is on (bug#58478). --- lisp/hl-line.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/hl-line.el b/lisp/hl-line.el index 693c94eea8c..87bea1017f1 100644 --- a/lisp/hl-line.el +++ b/lisp/hl-line.el @@ -156,7 +156,8 @@ line about point in the selected window only." :group 'hl-line ;; If the global mode is switched on, then `M-x hl-line-mode' should ;; switch the mode off in this buffer. - (when global-hl-line-mode + (when (and global-hl-line-mode + (eq arg 'toggle)) (setq hl-line-mode nil) (setq-local global-hl-line-mode nil) (global-hl-line-unhighlight)) From 97de273dca8d97039131f9d3f29b2820b5497805 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 13 Oct 2022 01:48:10 -0700 Subject: [PATCH 59/99] Simplify recent "File exists" fix * src/fileio.c (Finsert_file_contents): Simplify previous change that fixed bug#42431. --- src/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fileio.c b/src/fileio.c index a2388898034..49553f3c91f 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5000,7 +5000,7 @@ by calling `format-decode', which see. */) unbind_to (count1, Qnil); } - if (NILP (handler) && !NILP (visit) && current_buffer->modtime.tv_nsec < 0) + if (save_errno != 0) { /* Signal an error if visiting a file that could not be opened. */ report_file_errno ("Opening input file", orig_filename, save_errno); From e6c701c8c332e8564ffbb8cd9398c341377323ee Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 13 Oct 2022 18:47:49 +0800 Subject: [PATCH 60/99] Shrink client list window structure * src/xterm.c (struct x_client_list_window): Rearrange members for better alignment. --- src/xterm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 9059ad7136e..27a66873484 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1425,9 +1425,6 @@ struct x_client_list_window /* The width and height of the window. */ int width, height; - /* Whether or not the window is mapped. */ - bool mapped_p; - /* A bitmask describing events Emacs was listening for from the window before some extra events were added in `x_dnd_compute_toplevels'. */ @@ -1439,9 +1436,6 @@ struct x_client_list_window /* The next window in this list. */ struct x_client_list_window *next; - /* The Motif protocol style of this window, if any. */ - uint8_t xm_protocol_style; - /* The extents of the frame window in each direction. */ int frame_extents_left; int frame_extents_right; @@ -1452,18 +1446,24 @@ struct x_client_list_window /* The border width of this window. */ int border_width; - /* The rectangles making up the input shape. */ - XRectangle *input_rects; - /* The number of rectangles composing the input shape. */ int n_input_rects; + /* The rectangles making up the input shape. */ + XRectangle *input_rects; + /* The rectangles making up the bounding shape. */ XRectangle *bounding_rects; /* The number of rectangles composing the bounding shape. */ int n_bounding_rects; #endif + + /* The Motif protocol style of this window, if any. */ + uint8_t xm_protocol_style; + + /* Whether or not the window is mapped. */ + bool mapped_p; }; /* List of all toplevels in stacking order, from top to bottom. */ From 6efc64395282a960000d6fd9ac2e33ab7c764478 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 13 Oct 2022 15:46:56 +0200 Subject: [PATCH 61/99] Make `info' treat "\n" in node names as "\s" * lisp/info.el (info): Treat "\n" in node name as "\s". (Bug#57936) --- lisp/info.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lisp/info.el b/lisp/info.el index 292bf93a6f4..fabba2734a3 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -763,6 +763,11 @@ See a list of available Info commands in `Info-mode'." (read-file-name "Info file name: " nil nil t)) (if (numberp current-prefix-arg) (format "*info*<%s>" current-prefix-arg)))) + (when file-or-node + ;; Info node names don't contain newlines, so allow for easier use + ;; of names that might have been wrapped (in emails, etc.). + (setq file-or-node + (string-replace "\n" " " file-or-node))) (info-setup file-or-node (pop-to-buffer-same-window (or buffer "*info*")))) From 10f55975d34dd7299f72fdf8d93fd8cbe2e41e25 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 13 Oct 2022 09:33:46 -0700 Subject: [PATCH 62/99] Improve checks for recent "File exists" fixup * src/fileio.c (Finsert_file_contents): Add an assertion (bug#42431). --- src/fileio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fileio.c b/src/fileio.c index 49553f3c91f..b9a57dd5800 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5003,6 +5003,7 @@ by calling `format-decode', which see. */) if (save_errno != 0) { /* Signal an error if visiting a file that could not be opened. */ + eassert (!NILP (visit) && NILP (handler)); report_file_errno ("Opening input file", orig_filename, save_errno); } From 85e47d9a9e809b7278fa6dc282ecb4a7a8f54690 Mon Sep 17 00:00:00 2001 From: Bill Wohler Date: Thu, 13 Oct 2022 09:49:55 -0700 Subject: [PATCH 63/99] ; Continued cleanup of "-hooks" * doc/misc/mh-e.texi: Replace mh-kill-folder-suppress-prompt-hook with mh-kill-folder-suppress-prompt-functions. --- doc/misc/mh-e.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi index ed5c64bb478..3901974ede8 100644 --- a/doc/misc/mh-e.texi +++ b/doc/misc/mh-e.texi @@ -3120,7 +3120,7 @@ retracted---without question@footnote{In previous versions of MH-E, this option suppressed the confirmation in @code{mh-kill-folder}. Since this kept most users from setting this option, @code{mh-kill-folder} was modified in version 6.0 to always ask for -confirmation subject to @code{mh-kill-folder-suppress-prompt-hook}. +confirmation subject to @code{mh-kill-folder-suppress-prompt-functions}. @xref{Folders}.}. @cindex MH-Folder mode @@ -3402,7 +3402,7 @@ Hook run by q before quitting MH-E (default: @code{nil}). Hook run by @code{mh-folder-mode} when visiting a new folder (default: @code{nil}). @c ------------------------- -@item mh-kill-folder-suppress-prompt-hook +@item mh-kill-folder-suppress-prompt-functions Abnormal hook run at the beginning of @code{mh-kill-folder} (default: @code{'mh-search-p}). @c ------------------------- From cbd04ad3d572850775f18bde868c71abcde733ed Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Thu, 13 Oct 2022 21:13:45 +0200 Subject: [PATCH 64/99] Clarify structure of file-attribute's device number * doc/lispref/buffers.texi (Buffer File Name): Fix description of buffer-file-number. * doc/lispref/files.texi (File Attributes): Clarify type of device number. Describe file-attribute-file-number. (Bug#58446) * etc/NEWS: Mention file-attribute-file-number. * lisp/files.el (buffer-file-number, file-attribute-device-number) (file-attribute-collect): Fix docstring. (file-attribute-file-number): New defsubst. (find-buffer-visiting, find-file-noselect) (set-visited-file-name, basic-save-buffer): * lisp/startup.el (normal-top-level-add-subdirs-to-load-path): * lisp/eshell/em-unix.el (eshell-shuffle-files): Use it. * src/dired.c (Ffile_attributes): Fix docstring. --- doc/lispref/buffers.texi | 4 ++-- doc/lispref/files.texi | 13 ++++++++----- etc/NEWS | 9 +++++++-- lisp/eshell/em-unix.el | 6 ++---- lisp/files.el | 24 +++++++++++++++--------- lisp/startup.el | 2 +- src/dired.c | 5 +++-- 7 files changed, 38 insertions(+), 25 deletions(-) diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi index 6a1d125701c..b46b6c52d86 100644 --- a/doc/lispref/buffers.texi +++ b/doc/lispref/buffers.texi @@ -427,12 +427,12 @@ It is a permanent local, unaffected by @end defvar @defvar buffer-file-number -This buffer-local variable holds the file number and directory device +This buffer-local variable holds the inode number and directory device number of the file visited in the current buffer, or @code{nil} if no file or a nonexistent file is visited. It is a permanent local, unaffected by @code{kill-all-local-variables}. -The value is normally a list of the form @code{(@var{filenum} +The value is normally a list of the form @code{(@var{inodenum} @var{devnum})}. This pair of numbers uniquely identifies the file among all files accessible on the system. See the function @code{file-attributes}, in @ref{File Attributes}, for more information diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 0e8efa3297c..b9d4e87dc73 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1405,13 +1405,16 @@ a nonnegative integer. @item The filesystem number of the device that the file is on -@code{file-attribute-device-number}), an integer. -This element and the file's inode number -together give enough information to distinguish any two files on the -system---no two files can have the same values for both of these -numbers. +(@code{file-attribute-device-number}), an integer or a cons cell of +integers. The latter is sometimes used by remote files, in order to +distinguish the remote filesystems from the local ones. @end enumerate +The file's inode and device numbers together give enough information +to distinguish any two files on the system---no two files can have the +same values for both of these numbers. This tupel is returned by +@code{file-attribute-file-number}. + For example, here are the file attributes for @file{files.texi}: @example diff --git a/etc/NEWS b/etc/NEWS index ca857056fd8..7808c3beb20 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1872,7 +1872,7 @@ If non-nil, multiple revisions can be queried. This is done using 'completing-read-multiple'. --- -*** New function 'vc-read-multiple-revisions' +*** New function 'vc-read-multiple-revisions'. This function invokes 'vc-read-revision' with a non-nil value for MULTIPLE. @@ -1880,7 +1880,7 @@ MULTIPLE. *** New command 'vc-prepare-patch'. Patches for any version control system can be prepared using VC. The command will query what commits to send and will compose messages for -your mail user agent. The behaviour of 'vc-prepare-patch' can be +your mail user agent. The behavior of 'vc-prepare-patch' can be modified by the user options 'vc-prepare-patches-separately' and 'vc-default-patch-addressee'. @@ -3147,6 +3147,11 @@ The following generalized variables have been made obsolete: * Lisp Changes in Emacs 29.1 ++++ +** New accessor function 'file-attribute-file-number'. +It returns the list of the inode and device numbers retrieved by +'file-attributes'. This value can be used to identify a file uniquely. + +++ ** New macro 'while-let'. This is like 'when-let', but repeats until a binding form is nil. diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el index 40b83010f94..378b0ceeeae 100644 --- a/lisp/eshell/em-unix.el +++ b/lisp/eshell/em-unix.el @@ -372,12 +372,10 @@ Remove the DIRECTORY(ies), if they are empty.") (setq attr (eshell-file-attributes (car files))) (file-attribute-inode-number attr-target) (file-attribute-inode-number attr) - (equal (file-attribute-inode-number attr-target) - (file-attribute-inode-number attr)) (file-attribute-device-number attr-target) (file-attribute-device-number attr) - (equal (file-attribute-device-number attr-target) - (file-attribute-device-number attr))) + (equal (file-attribute-file-number attr-target) + (file-attribute-file-number attr))) (eshell-error (format-message "%s: `%s' and `%s' are the same file\n" command (car files) target))) (t diff --git a/lisp/files.el b/lisp/files.el index 94d110f0b7d..1a301485517 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -208,8 +208,8 @@ if the file has changed on disk and you have not edited the buffer." :group 'find-file) (defvar-local buffer-file-number nil - "The device number and file number of the file visited in the current buffer. -The value is a list of the form (FILENUM DEVNUM). + "The inode and device numbers of the file visited in the current buffer. +The value is a list of the form (INODENUM DEVNUM). This pair of numbers uniquely identifies the file. If the buffer is visiting a new file, the value is nil.") (put 'buffer-file-number 'permanent-local t) @@ -2163,7 +2163,7 @@ If there is no such live buffer, return nil." (setq list (cdr list))) found) (let* ((attributes (file-attributes truename)) - (number (nthcdr 10 attributes)) + (number (file-attribute-file-number attributes)) (list (buffer-list)) found) (and buffer-file-numbers-unique (car-safe number) ;Make sure the inode is not just nil. @@ -2366,7 +2366,7 @@ the various files." (let* ((buf (get-file-buffer filename)) (truename (abbreviate-file-name (file-truename filename))) (attributes (file-attributes truename)) - (number (nthcdr 10 attributes)) + (number (file-attribute-file-number attributes)) ;; Find any buffer for a file that has same truename. (other (and (not buf) (find-buffer-visiting @@ -4744,7 +4744,7 @@ the old visited file has been renamed to the new name FILENAME." (setq buffer-file-name truename)))) (setq buffer-file-number (if filename - (nthcdr 10 (file-attributes buffer-file-name)) + (file-attribute-file-number (file-attributes buffer-file-name)) nil)) ;; write-file-functions is normally used for things like ftp-find-file ;; that visit things that are not local files as if they were files. @@ -5733,7 +5733,7 @@ Before and after saving the buffer, this function runs (setq save-buffer-coding-system last-coding-system-used) (setq buffer-file-coding-system last-coding-system-used)) (setq buffer-file-number - (nthcdr 10 (file-attributes buffer-file-name))) + (file-attribute-file-number (file-attributes buffer-file-name))) (if setmodes (condition-case () (progn @@ -8658,19 +8658,25 @@ It is a nonnegative integer." (defsubst file-attribute-device-number (attributes) "The file system device number in ATTRIBUTES returned by `file-attributes'. -It is an integer." +It is an integer or a cons cell of integers." (nth 11 attributes)) +(defsubst file-attribute-file-number (attributes) + "The inode and device numbers in ATTRIBUTES returned by `file-attributes'. +The value is a list of the form (INODENUM DEVNUM). +This pair of numbers uniquely identifies the file." + (nthcdr 10 attributes)) + (defun file-attribute-collect (attributes &rest attr-names) "Return a sublist of ATTRIBUTES returned by `file-attributes'. ATTR-NAMES are symbols with the selected attribute names. Valid attribute names are: type, link-number, user-id, group-id, access-time, modification-time, status-change-time, size, modes, -inode-number and device-number." +inode-number, device-number and file-number." (let ((all '(type link-number user-id group-id access-time modification-time status-change-time - size modes inode-number device-number)) + size modes inode-number device-number file-number)) result) (while attr-names (let ((attr (pop attr-names))) diff --git a/lisp/startup.el b/lisp/startup.el index 04de7e42fea..c7faf4abc6f 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -458,7 +458,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'." ;; The Windows version doesn't report meaningful inode numbers, so ;; use the canonicalized absolute file name of the directory instead. (setq attrs (or canonicalized - (nthcdr 10 (file-attributes this-dir)))) + (file-attribute-file-number (file-attributes this-dir)))) (unless (member attrs normal-top-level-add-subdirs-inode-list) (push attrs normal-top-level-add-subdirs-inode-list) (dolist (file contents) diff --git a/src/dired.c b/src/dired.c index c2c099f0a5f..32c083ad7b0 100644 --- a/src/dired.c +++ b/src/dired.c @@ -923,11 +923,12 @@ Elements of the attribute list are: 8. File modes, as a string of ten letters or dashes as in ls -l. 9. An unspecified value, present only for backward compatibility. 10. inode number, as a nonnegative integer. -11. Filesystem device number, as an integer. +11. Filesystem device number, as an integer or a cons cell of integers. Large integers are bignums, so `eq' might not work on them. On most filesystems, the combination of the inode and the device -number uniquely identifies the file. +number uniquely identifies the file. This is provided by the access +function `file-attribute-file-number'. On MS-Windows, performance depends on `w32-get-true-file-attributes', which see. From 9074103fbff70a30664b291f5ea3af443f88e4d8 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 14 Oct 2022 10:12:03 +0300 Subject: [PATCH 65/99] ; Fix recent change in documentation of "device number" * src/dired.c (Ffile_attributes): * lisp/files.el (buffer-file-number, file-attribute-file-number): Fix wording of the doc strings. * etc/NEWS: * doc/lispref/buffers.texi (Buffer File Name): * doc/lispref/files.texi (File Attributes): Fix a typo and wording. (Bug#58446) --- doc/lispref/buffers.texi | 8 ++++---- doc/lispref/files.texi | 12 ++++++------ etc/NEWS | 6 ++++-- lisp/files.el | 12 +++++++----- src/dired.c | 6 +++--- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi index b46b6c52d86..c40e088293e 100644 --- a/doc/lispref/buffers.texi +++ b/doc/lispref/buffers.texi @@ -427,19 +427,19 @@ It is a permanent local, unaffected by @end defvar @defvar buffer-file-number -This buffer-local variable holds the inode number and directory device -number of the file visited in the current buffer, or @code{nil} if no +This buffer-local variable holds the inode number and device +identifier of the file visited in the current buffer, or @code{nil} if no file or a nonexistent file is visited. It is a permanent local, unaffected by @code{kill-all-local-variables}. The value is normally a list of the form @code{(@var{inodenum} -@var{devnum})}. This pair of numbers uniquely identifies the file among +@var{device})}. This tuple uniquely identifies the file among all files accessible on the system. See the function @code{file-attributes}, in @ref{File Attributes}, for more information about them. If @code{buffer-file-name} is the name of a symbolic link, then both -numbers refer to the recursive target. +@var{inodenum} and @var{device} refer to the recursive target of the link. @end defvar @defun get-file-buffer filename diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index b9d4e87dc73..2467364dc6e 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1404,16 +1404,16 @@ The file's inode number (@code{file-attribute-inode-number}), a nonnegative integer. @item -The filesystem number of the device that the file is on +The filesystem's identifier of the device that the file is on (@code{file-attribute-device-number}), an integer or a cons cell of -integers. The latter is sometimes used by remote files, in order to -distinguish the remote filesystems from the local ones. +two integers. The latter is sometimes used by remote files, in order +to distinguish remote filesystems from local ones. @end enumerate -The file's inode and device numbers together give enough information +The file's inode and device together give enough information to distinguish any two files on the system---no two files can have the -same values for both of these numbers. This tupel is returned by -@code{file-attribute-file-number}. +same values for both of these attributes. This tuple that uniquely +identifies the file is returned by @code{file-attribute-file-number}. For example, here are the file attributes for @file{files.texi}: diff --git a/etc/NEWS b/etc/NEWS index 7808c3beb20..464cb2719f5 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3149,8 +3149,10 @@ The following generalized variables have been made obsolete: +++ ** New accessor function 'file-attribute-file-number'. -It returns the list of the inode and device numbers retrieved by -'file-attributes'. This value can be used to identify a file uniquely. +It returns the list of the inode number and device identifier +retrieved by 'file-attributes'. This value can be used to identify a +file uniquely. The device identifier can be a single number or (for +remote files) a cons of 2 numbers. +++ ** New macro 'while-let'. diff --git a/lisp/files.el b/lisp/files.el index 1a301485517..dd10f7399cc 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -208,9 +208,10 @@ if the file has changed on disk and you have not edited the buffer." :group 'find-file) (defvar-local buffer-file-number nil - "The inode and device numbers of the file visited in the current buffer. -The value is a list of the form (INODENUM DEVNUM). -This pair of numbers uniquely identifies the file. + "The inode number and the device of the file visited in the current buffer. +The value is a list of the form (INODENUM DEVICE), where DEVICE can be +either a single number or a cons cell of two numbers. +This tuple of numbers uniquely identifies the file. If the buffer is visiting a new file, the value is nil.") (put 'buffer-file-number 'permanent-local t) @@ -8663,8 +8664,9 @@ It is an integer or a cons cell of integers." (defsubst file-attribute-file-number (attributes) "The inode and device numbers in ATTRIBUTES returned by `file-attributes'. -The value is a list of the form (INODENUM DEVNUM). -This pair of numbers uniquely identifies the file." +The value is a list of the form (INODENUM DEVICE), where DEVICE could be +either a single number or a cons cell of two numbers. +This tuple of numbers uniquely identifies the file." (nthcdr 10 attributes)) (defun file-attribute-collect (attributes &rest attr-names) diff --git a/src/dired.c b/src/dired.c index 32c083ad7b0..1b4edf20483 100644 --- a/src/dired.c +++ b/src/dired.c @@ -923,12 +923,12 @@ Elements of the attribute list are: 8. File modes, as a string of ten letters or dashes as in ls -l. 9. An unspecified value, present only for backward compatibility. 10. inode number, as a nonnegative integer. -11. Filesystem device number, as an integer or a cons cell of integers. +11. Filesystem device identifier, as an integer or a cons cell of integers. Large integers are bignums, so `eq' might not work on them. On most filesystems, the combination of the inode and the device -number uniquely identifies the file. This is provided by the access -function `file-attribute-file-number'. +identifier uniquely identifies the file. This unique file identification +is provided by the access function `file-attribute-file-number'. On MS-Windows, performance depends on `w32-get-true-file-attributes', which see. From 6ea69fc7340e48cf73df351a544c1d8946395b3d Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 14 Oct 2022 15:52:16 +0800 Subject: [PATCH 66/99] Avoid redundant creation of XRender pictures * src/xterm.c (x_composite_image): Take arg DESTINATION. Do not create a picture if it is set. (x_draw_image_foreground, x_draw_image_foreground_1): Pass destination where appropriate. --- src/xterm.c | 64 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 27a66873484..0fca9788ce5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -9603,31 +9603,49 @@ x_draw_glyph_string_box (struct glyph_string *s) #ifndef USE_CAIRO + static void x_composite_image (struct glyph_string *s, Pixmap dest, +#ifdef HAVE_XRENDER + Picture destination, +#endif int srcX, int srcY, int dstX, int dstY, int width, int height) { - Display *display = FRAME_X_DISPLAY (s->f); + Display *display; +#ifdef HAVE_XRENDER + XRenderPictFormat *default_format; + XRenderPictureAttributes attr UNINIT; +#endif + + display = FRAME_X_DISPLAY (s->f); + #ifdef HAVE_XRENDER if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f)) { - Picture destination; - XRenderPictFormat *default_format; - XRenderPictureAttributes attr UNINIT; + if (destination == None) + { + /* The destination picture was not specified. This means we + have to create a picture representing the */ + default_format = FRAME_X_PICTURE_FORMAT (s->f); + destination = XRenderCreatePicture (display, dest, + default_format, 0, &attr); - default_format = FRAME_X_PICTURE_FORMAT (s->f); - destination = XRenderCreatePicture (display, dest, - default_format, 0, &attr); + XRenderComposite (display, (s->img->mask_picture + ? PictOpOver : PictOpSrc), + s->img->picture, s->img->mask_picture, + destination, srcX, srcY, srcX, srcY, + dstX, dstY, width, height); - XRenderComposite (display, s->img->mask_picture ? PictOpOver : PictOpSrc, - s->img->picture, s->img->mask_picture, destination, - srcX, srcY, - srcX, srcY, - dstX, dstY, - width, height); + XRenderFreePicture (display, destination); + } + else + XRenderComposite (display, (s->img->mask_picture + ? PictOpOver : PictOpSrc), + s->img->picture, s->img->mask_picture, + destination, srcX, srcY, srcX, srcY, + dstX, dstY, width, height); - XRenderFreePicture (display, destination); return; } #endif @@ -9637,6 +9655,7 @@ x_composite_image (struct glyph_string *s, Pixmap dest, srcX, srcY, width, height, dstX, dstY); } + #endif /* !USE_CAIRO */ @@ -9715,6 +9734,9 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.height = s->slice.height; if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) x_composite_image (s, FRAME_X_DRAWABLE (s->f), +#ifdef HAVE_XRENDER + FRAME_X_PICTURE (s->f), +#endif s->slice.x + r.x - x, s->slice.y + r.y - y, r.x, r.y, r.width, r.height); } @@ -9728,7 +9750,12 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) - x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + x_composite_image (s, FRAME_X_DRAWABLE (s->f), +#ifdef HAVE_XRENDER + FRAME_X_PICTURE (s->f), +#endif + s->slice.x + r.x - x, + s->slice.y + r.y - y, r.x, r.y, r.width, r.height); /* When the image has a mask, we can expect that at @@ -9894,8 +9921,11 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap) XChangeGC (display, s->gc, mask, &xgcv); x_composite_image (s, pixmap, - s->slice.x, s->slice.y, - x, y, s->slice.width, s->slice.height); +#ifdef HAVE_XRENDER + None, +#endif + s->slice.x, s->slice.y, x, y, + s->slice.width, s->slice.height); XSetClipMask (display, s->gc, None); } else From 271791b55b29945c30ddeb3eb7988f36246a2dfa Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 14 Oct 2022 19:04:44 +0800 Subject: [PATCH 67/99] Fix bug#56153 * src/nsterm.m (get_keysym_name) (ns_draw_glyphless_glyph_string_foreground): Fix new Mac OS deprecations. ([EmacsApp terminate:]): Use kbd_buffer_store_event instead of emacs_event. (bug#56153) ([EmacsView windowDidChangeBackingProperties:]): Fix new Mac OS deprecation. --- src/nsterm.m | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index 82fe58e90ec..1fc72d83f66 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2479,7 +2479,7 @@ get_keysym_name (int keysym) { static char value[16]; NSTRACE ("get_keysym_name"); - sprintf (value, "%d", keysym); + snprintf (value, 16, "%d", keysym); return value; } @@ -4263,7 +4263,7 @@ ns_draw_glyphless_glyph_string_foreground (struct glyph_string *s) { unsigned int ch = glyph->u.glyphless.ch; eassume (ch <= MAX_CHAR); - sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch); + snprintf (buf, 7, "%0*X", ch < 0x10000 ? 4 : 6, ch); str = buf; } @@ -6116,17 +6116,20 @@ ns_term_shutdown (int sig) - (void) terminate: (id)sender { + struct input_event ie; + struct frame *f; + NSTRACE ("[EmacsApp terminate:]"); - struct frame *emacsframe = SELECTED_FRAME (); + f = SELECTED_FRAME (); + EVENT_INIT (ie); - if (!emacs_event) - return; + ie.kind = NS_NONKEY_EVENT; + ie.code = KEY_NS_POWER_OFF; + ie.arg = Qt; /* mark as non-key event */ + XSETFRAME (ie.frame_or_window, f); - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_POWER_OFF; - emacs_event->arg = Qt; /* mark as non-key event */ - EV_TRAILER ((id)nil); + kbd_buffer_store_event (&ie); } static bool @@ -8593,7 +8596,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) EmacsLayer *layer = (EmacsLayer *)[self layer]; [layer setContentsScale:[[notification object] backingScaleFactor]]; - [layer setColorSpace:[[[notification object] colorSpace] CGColorSpace]]; + [layer setColorSpace:[(id) [[notification object] colorSpace] CGColorSpace]]; ns_clear_frame (emacsframe); expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame)); From b175a9fb7eea49cdf8171821498f2c5efaaecd98 Mon Sep 17 00:00:00 2001 From: Reuben Thomas Date: Fri, 14 Oct 2022 13:30:43 +0200 Subject: [PATCH 68/99] Do perl documentation lookups case-insensitively, like man * lisp/progmodes/cperl-mode.el (cperl-perldoc): add -i to the perldoc command. --- lisp/progmodes/cperl-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index 20a73e238e9..539b2771490 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -8323,7 +8323,7 @@ the appropriate statement modifier." 'cperl-short-docs 'variable-documentation)))) (Man-switches "") - (manual-program (if is-func "perldoc -f" "perldoc"))) + (manual-program (concat "perldoc -i" (if is-func " -f")))) (Man-getpage-in-background word))) ;;;###autoload From be1afa047f74f3197e530b28971249593b12d177 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 11 Oct 2022 12:28:45 +0200 Subject: [PATCH 69/99] * lisp/play/zone.el (zone): Allow selecting a program --- lisp/play/zone.el | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lisp/play/zone.el b/lisp/play/zone.el index b0ce0194cf0..5ea5bbc9267 100644 --- a/lisp/play/zone.el +++ b/lisp/play/zone.el @@ -103,9 +103,24 @@ If the element is a function or a list of a function and a number, program)))) ;;;###autoload -(defun zone () - "Zone out, completely." - (interactive) +(defun zone (&optional pgm) + "Zone out, completely. +With a prefix argument the user is prompted for a program to run. +When called from Lisp the optional argument PGM can be used to +run a specific program. The program must be a member of +`zone-programs'." + (interactive + (and current-prefix-arg + (let ((choice (completing-read + "Program: " + (mapcar + (lambda (prog) + (substring (symbol-name prog) 9)) + zone-programs) + nil t))) + (list (intern (concat "zone-pgm-" choice)))))) + (unless pgm + (setq pgm (aref zone-programs (random (length zone-programs))))) (save-window-excursion (let ((f (selected-frame)) (outbuf (get-buffer-create "*zone*")) @@ -125,8 +140,7 @@ If the element is a function or a list of a function and a number, (set-window-start (selected-window) (point-min)) (set-window-point (selected-window) wp) (sit-for 0 500) - (let ((pgm (elt zone-programs (random (length zone-programs)))) - (ct (and f (frame-parameter f 'cursor-type))) + (let ((ct (and f (frame-parameter f 'cursor-type))) (show-trailing-whitespace nil) restore) (when ct From ff0fe620024b79a1cae4e31c2f4ed6f857b9db9e Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 11 Oct 2022 18:09:58 +0200 Subject: [PATCH 70/99] Mention that vc-prepare-patch can interact with a log-view ; * doc/emacs/vc1-xtra.texi (Preparing Patches): Extend documentation. --- doc/emacs/vc1-xtra.texi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi index 66d3f51c306..23d5f504322 100644 --- a/doc/emacs/vc1-xtra.texi +++ b/doc/emacs/vc1-xtra.texi @@ -291,8 +291,13 @@ When collaborating on projects it is common to send patches via email, to share changes. If you wish to do this using VC, you can use the @code{vc-prepare-patch} command. This will prompt you for the revisions you wish to share, and which destination email address(es) -to use. The command will then prepare those revisions using your -@abbr{MUA, Mail User Agent} for you to review and send. +to use. The revisions are separated using commas (or whatever was +configured by @var{crm-separator}). The command will then prepare +those revisions using your @abbr{MUA, Mail User Agent} for you to +review and send. + +When invoked interactively in a Log View buffer with marked revisions, +these revisions will be used. @vindex vc-prepare-patches-separately Depending on the value of the user option From 5426b4d7bffd368a0116d70cb95904ff3bfda0c5 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 11 Oct 2022 20:43:40 +0200 Subject: [PATCH 71/99] Allow reordering commits in 'vc-prepare-patch' prompt * lisp/vc/vc.el (vc-prepare-patch): Use marked log-view commits as initial input. --- lisp/vc/vc.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 60481318e3b..9e8dbfbe013 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3341,8 +3341,12 @@ invidividual commits. When invoked interactively in a Log View buffer with marked revisions, those revisions will be used." (interactive - (let ((revs (or (log-view-get-marked) - (vc-read-multiple-revisions "Revisions: "))) + (let ((revs (vc-read-multiple-revisions + "Revisions: " nil nil nil + (or (and-let* ((revs (log-view-get-marked))) + (mapconcat #'identity revs ",")) + (and-let* ((file (buffer-file-name))) + (vc-working-revision file))))) to) (require 'message) (while (null (setq to (completing-read-multiple From 60f46b45d9654e1cabffecec176844ab0c752fe3 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 11 Oct 2022 20:46:15 +0200 Subject: [PATCH 72/99] Prepare all inline patches at once * lisp/vc/vc.el (vc-prepare-patch): Remove the usage of 'recursive-edit' when 'vc-prepare-patches-separately' is non-nil. --- lisp/vc/vc.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 9e8dbfbe013..0ef867beed8 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3370,7 +3370,8 @@ revisions, those revisions will be used." 'prepare-patch rev)) revisions))) (if vc-prepare-patches-separately - (dolist (patch patches) + (dolist (patch (reverse patches) + (message "Prepared %d patches..." (length patches))) (compose-mail addressee (plist-get patch :subject) nil nil nil nil @@ -3381,8 +3382,7 @@ revisions, those revisions will be used." (insert-buffer-substring (plist-get patch :buffer) (plist-get patch :body-start) - (plist-get patch :body-end))) - (recursive-edit)) + (plist-get patch :body-end)))) (compose-mail addressee subject nil nil nil nil (mapcar (lambda (p) From 000cd5f9f6a1e34520e8cdd6fd278ef0e208a85f Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 11 Oct 2022 21:23:26 +0200 Subject: [PATCH 73/99] ; * lisp/vc/vc.el (vc-default-prepare-patch): Add missing argument --- lisp/vc/vc.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 0ef867beed8..781e7785e41 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3315,7 +3315,7 @@ If nil, no default will be used. This option may be set locally." (buffer &optional type description disposition)) (declare-function log-view-get-marked "log-view" ()) -(defun vc-default-prepare-patch (rev) +(defun vc-default-prepare-patch (_backend rev) (let ((backend (vc-backend buffer-file-name))) (with-current-buffer (generate-new-buffer " *vc-default-prepare-patch*") (vc-diff-internal From db69681759991d5403552682706accd6218b731f Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 6 Oct 2022 14:03:04 +0200 Subject: [PATCH 74/99] * lisp/net/rcirc.el (rcirc-generate-log-filename): Append ".log" (Bug#54718) --- lisp/net/rcirc.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index fa481ce5283..1da4fce8315 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -2176,9 +2176,11 @@ connection." (defun rcirc-generate-log-filename (process target) "Return filename for log file based on PROCESS and TARGET." - (if target - (rcirc-generate-new-buffer-name process target) - (process-name process))) + (concat + (if target + (rcirc-generate-new-buffer-name process target) + (process-name process)) + ".log")) (defcustom rcirc-log-filename-function 'rcirc-generate-log-filename "A function to generate the filename used by rcirc's logging facility. From 6539eb05889c783d782f114d9c072208d3080561 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Wed, 5 Oct 2022 19:45:27 +0200 Subject: [PATCH 75/99] Prevent .dir-locals.el from being byte-compiled * lisp/files-x.el (modify-dir-local-variable): Add a 'no-byte-compile' file local variable when generating a .dir-locals.el file. * .dir-locals.el: Add 'no-byte-compile'. (Bug#58486) --- .dir-locals.el | 2 +- lisp/files-x.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.dir-locals.el b/.dir-locals.el index 84617a79807..f7c73031cc8 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -1,4 +1,4 @@ -;;; Directory Local Variables +;;; Directory Local Variables -*- no-byte-compile: t; -*- ;;; For more information see (info "(emacs) Directory Variables") ((nil . ((tab-width . 8) diff --git a/lisp/files-x.el b/lisp/files-x.el index da1e44e2504..f6d5d6cc272 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -489,7 +489,7 @@ from the MODE alist ignoring the input argument VALUE." dir-locals-directory-cache)) ;; Insert modified alist of directory-local variables. - (insert ";;; Directory Local Variables\n") + (insert ";;; Directory Local Variables -*- no-byte-compile: t -*-\n") (insert ";;; For more information see (info \"(emacs) Directory Variables\")\n\n") (princ (dir-locals-to-string (sort variables From cae00567690033308ff06b5d09629e55813c52dd Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 13 Oct 2022 12:02:02 +0200 Subject: [PATCH 76/99] Allow filtering what items are added to Ecomplete * etc/NEWS: Mention new option. * lisp/ecomplete.el (ecomplete-filter-regexp): Add new option. (ecomplete-add-item): Respect new option. (bug#58487) --- etc/NEWS | 5 +++++ lisp/ecomplete.el | 35 +++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 464cb2719f5..dcbf3a6aa32 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1376,6 +1376,11 @@ the ecomplete database. *** New user option 'ecomplete-auto-select'. If non-nil and there's only one matching option, auto-select that. +--- +*** New user option 'ecomplete-filter-regexp'. +If non-nil this user option describes what email addresses to ignore +and not add to the database. + ** Dired +++ diff --git a/lisp/ecomplete.el b/lisp/ecomplete.el index 6ff67d46d20..21f5f456ea0 100644 --- a/lisp/ecomplete.el +++ b/lisp/ecomplete.el @@ -86,6 +86,11 @@ string that was matched." :type 'boolean :version "29.1") +(defcustom ecomplete-filter-regexp nil + "Regular expression of addresses to not store." + :type 'regexp + :version "29.1") + ;;; Internal variables. (defvar ecomplete-database nil) @@ -104,20 +109,22 @@ string that was matched." By default, the longest version of TEXT will be preserved, but if FORCE is non-nil, use TEXT exactly as is." (unless ecomplete-database (ecomplete-setup)) - (let ((elems (assq type ecomplete-database)) - (now (time-convert nil 'integer)) - entry) - (unless elems - (push (setq elems (list type)) ecomplete-database)) - (if (setq entry (assoc key (cdr elems))) - (pcase-let ((`(,_key ,count ,_time ,oldtext) entry)) - (setcdr entry (list (1+ count) now - ;; Preserve the "more complete" text. - (if (or force - (>= (length text) (length oldtext))) - text - oldtext)))) - (nconc elems (list (list key 1 now text)))))) + (unless (and ecomplete-filter-regexp + (string-match-p ecomplete-filter-regexp key)) + (let ((elems (assq type ecomplete-database)) + (now (time-convert nil 'integer)) + entry) + (unless elems + (push (setq elems (list type)) ecomplete-database)) + (if (setq entry (assoc key (cdr elems))) + (pcase-let ((`(,_key ,count ,_time ,oldtext) entry)) + (setcdr entry (list (1+ count) now + ;; Preserve the "more complete" text. + (if (or force + (>= (length text) (length oldtext))) + text + oldtext)))) + (nconc elems (list (list key 1 now text))))))) (defun ecomplete--remove-item (type key) "Remove the element of TYPE and KEY from the ecomplete database." From 8fc5148429545b795dcd8be2740088582a2d4e23 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Fri, 14 Oct 2022 09:39:45 +0200 Subject: [PATCH 77/99] * lisp/net/rcirc.el (rcirc-bridged-nick): Inherit from highlight --- lisp/net/rcirc.el | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index 1da4fce8315..eadaf00c4b8 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -3020,11 +3020,7 @@ for nick completion." :version "29.1") (defface rcirc-bridged-nick - '((((class color) (min-colors 88) (background light)) :background "SlateGray1") - (((class color) (min-colors 88) (background dark)) :background "DarkSlateGray4") - (((class color) (min-colors 16) (background light)) :background "LightBlue") - (((class color) (min-colors 16) (background dark)) :background "DarkSlateGray") - (t :background "blue")) + '((t :inherit highlight)) "Face used for pseudo-nick ." :version "29.1") From 51fc195d39de6d7b1dad782d5d89476462eb6db8 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Sat, 17 Sep 2022 16:52:01 +0200 Subject: [PATCH 78/99] Add a quick-help menu * lisp/help.el (help-map): Bind 'help-quit-or-quick' instead of 'help-quit'. (help-quick-sections): Add variable. (help-quick): Add main command. (cheat-sheet): Add alias for 'help-quick'. (help-quit-or-quick): Add auxiliary command. lisp/help.el (help-for-help): Mention 'help-quit-or-quick'. * etc/NEWS (https): Mention 'help-quit'. --- etc/NEWS | 6 +++ lisp/help.el | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index dcbf3a6aa32..b73c2c47d5d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1024,6 +1024,12 @@ The apropos commands will now select the apropos window if If the symbol at point is a keymap, 'describe-keymap' suggests it as the default candidate. +--- +*** New command 'help-quick' displays an overview of common commands. +The command pops up a buffer at the bottom of the screen with a few +helpful commands for various tasks. You can toggle the display using +'C-h q'. + ** Outline Mode +++ diff --git a/lisp/help.el b/lisp/help.el index b4b9120da3e..3f5e57d7d5f 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -112,7 +112,7 @@ buffer.") (define-key map "v" 'describe-variable) (define-key map "w" 'where-is) (define-key map "x" 'describe-command) - (define-key map "q" 'help-quit) + (define-key map "q" 'help-quit-or-quick) map) "Keymap for characters following the Help key.") @@ -125,11 +125,143 @@ buffer.") (defvar help-button-cache nil) + +(defvar help-quick-sections + '(("File" + (save-buffers-kill-terminal . "exit") + (find-file . "find") + (write-file . "write") + (save-buffer . "save") + (save-some-buffers . "all")) + ("Buffer" + (kill-buffer . "kill") + (list-buffers . "list") + (switch-to-buffer . "switch") + (goto-line . "goto line") + (read-only-mode . "read only")) + ("Window" + (delete-window . "only other") + (delete-other-windows . "only this") + (split-window-below . "split vert.") + (split-window-right . "split horiz.") + (other-window . "other window")) + ("Mark & Kill" + (set-mark-command . "mark") + (kill-line . "kill line") + (kill-ring-save . "kill region") + (yank . "yank") + (exchange-point-and-mark . "swap")) + ("Projects" + (project-switch-project . "switch") + (project-find-file . "find file") + (project-find-regexp . "search") + (project-query-replace-regexp . "search & replace") + (project-compile . "compile")) + ("Misc." + (undo . "undo") + (isearch-forward . "search") + (isearch-backward . "reverse search") + (query-replace . "search & replace") + (fill-paragraph . "reformat")))) + +(declare-function prop-match-value "text-property-search" (match)) + +;; Inspired by a mg fork (https://github.com/troglobit/mg) +(defun help-quick () + "Display a quick-help buffer." + (interactive) + (with-current-buffer (get-buffer-create "*Quick Help*") + (let ((inhibit-read-only t) (padding 2) blocks) + + ;; Go through every section and prepare a text-rectangle to be + ;; inserted later. + (dolist (section help-quick-sections) + (let ((max-key-len 0) (max-cmd-len 0) keys) + (dolist (ent (reverse (cdr section))) + (catch 'skip + (let* ((bind (where-is-internal (car ent) nil t)) + (key (if bind + (propertize + (key-description bind) + 'face 'help-key-binding) + (throw 'skip nil)))) + (setq max-cmd-len (max (length (cdr ent)) max-cmd-len) + max-key-len (max (length key) max-key-len)) + (push (list key (cdr ent) (car ent)) keys)))) + (when keys + (let ((fmt (format "%%-%ds %%-%ds%s" max-key-len max-cmd-len + (make-string padding ?\s))) + (width (+ max-key-len 1 max-cmd-len padding))) + (push `(,width + ,(propertize + (concat + (car section) + (make-string (- width (length (car section))) ?\s)) + 'face 'bold) + ,@(mapcar (lambda (ent) + (format fmt + (propertize + (car ent) + 'quick-help-cmd + (caddr ent)) + (cadr ent))) + keys)) + blocks))))) + + ;; Insert each rectangle in order until they don't fit into the + ;; frame any more, in which case the next sections are inserted + ;; in a new "line". + (erase-buffer) + (dolist (block (nreverse blocks)) + (when (> (+ (car block) (current-column)) (frame-width)) + (goto-char (point-max)) + (newline 2)) + (save-excursion + (insert-rectangle (cdr block))) + (end-of-line)) + (delete-trailing-whitespace) + + (save-excursion + (goto-char (point-min)) + (while-let ((match (text-property-search-forward 'quick-help-cmd))) + (make-text-button (prop-match-beginning match) + (prop-match-end match) + 'mouse-face 'highlight + 'button t + 'keymap button-map + 'action #'describe-symbol + 'button-data (prop-match-value match))))) + + (help-mode) + + ;; Display the buffer at the bottom of the frame... + (with-selected-window (display-buffer-at-bottom (current-buffer) '()) + ;; ... mark it as dedicated to prevent focus from being stolen + (set-window-dedicated-p (selected-window) t) + ;; ... and shrink it immediately. + (fit-window-to-buffer)) + (message + (substitute-command-keys "Toggle the quick help buffer using \\[help-quit-or-quick].")))) + +(defalias 'cheat-sheet #'help-quick) + (defun help-quit () "Just exit from the Help command's command loop." (interactive) nil) +(defun help-quit-or-quick () + "Call `help-quit' or `help-quick' depending on the context." + (interactive) + (cond + (help-buffer-under-preparation + ;; FIXME: There should be a better way to detect if we are in the + ;; help command loop. + (help-quit)) + ((and-let* ((window (get-buffer-window "*Quick Help*"))) + (quit-window t window))) + ((help-quick)))) + (defvar help-return-method nil "What to do to \"exit\" the help buffer. This is a list @@ -279,6 +411,7 @@ Do not call this in the scope of `with-help-window'." ("describe-package" "Describe a specific Emacs package") "" ("help-with-tutorial" "Start the Emacs tutorial") + ("help-quick-or-quit" "Display the quick help buffer.") ("view-echo-area-messages" "Show recent messages (from echo area)") ("view-lossage" ,(format "Show last %d input keystrokes (lossage)" From 3da935d5339dfb43cb1be2df5f83b74b4e34ccc1 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Fri, 14 Oct 2022 17:40:26 +0000 Subject: [PATCH 79/99] Correctly fontify C++'s operator"" _tag (...) Give both the "" and _tag font-lock-function-name-face. Also correct the fontification of an inherited class name when there is an attribute between the class name being declared and the colon introducing the inheritance. * lisp/progmodes/cc-engine.el (c-forward-over-colon-type-list): New function. (c-forward-keyword-clause): Use the above new function instead of a looking-at. (c-forward-name, c-forward-declarator): Accept both the "" and the tag as part of the name. * lisp/progmodes/cc-fonts.el (c-font-lock-declarators): Fontify the "" (which already has font-lock-string-face) and the tag with font-lock-function-name-face. * lisp/progmodes/cc-langs.el (c-overloadable-operators): Add "" to this list. (c-sub-colon-type-list-re): New lang-const and lang-var. --- lisp/progmodes/cc-engine.el | 45 ++++++++++++++++++++++++++++++++----- lisp/progmodes/cc-fonts.el | 20 +++++++++++++++-- lisp/progmodes/cc-langs.el | 12 ++++++++-- 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 0ac96219a19..223b1e917fe 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -8356,6 +8356,23 @@ multi-line strings (but not C++, for example)." (goto-char here)))) t) +(defun c-forward-over-colon-type-list () + ;; If we're at a sequence of characters which can extend from, e.g., + ;; a class name up to a colon introducing an inheritance list, + ;; move forward over them, including the colon, and return non-nil. + ;; Otherwise return nil, leaving point unmoved. + (let ((here (point)) pos) + (while (and (re-search-forward c-sub-colon-type-list-re nil t) + (not (eq (char-after) ?:)) + (c-major-mode-is 'c++-mode) + (setq pos (c-looking-at-c++-attribute))) + (goto-char pos)) + (if (eq (char-after) ?:) + (progn (forward-char) + t) + (goto-char here) + nil))) + (defun c-forward-keyword-clause (match) ;; Submatch MATCH in the current match data is assumed to surround a ;; token. If it's a keyword, move over it and any immediately @@ -8463,12 +8480,11 @@ multi-line strings (but not C++, for example)." (and c-record-type-identifiers (progn ;; If a keyword matched both one of the types above and - ;; this one, we match `c-colon-type-list-re' after the + ;; this one, we move forward to the colon following the ;; clause matched above. (goto-char safe-pos) - (looking-at c-colon-type-list-re)) + (c-forward-over-colon-type-list)) (progn - (goto-char (match-end 0)) (c-forward-syntactic-ws) (c-forward-keyword-prefixed-id type)) ;; There's a type after the `c-colon-type-list-re' match @@ -8921,8 +8937,16 @@ multi-line strings (but not C++, for example)." ;; Got some other operator. (setq c-last-identifier-range (cons (point) (match-end 0))) + (if (and (eq (char-after) ?\") + (eq (char-after (1+ (point))) ?\")) + ;; operator"" has an (?)optional tag after it. + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws lim+) + (when (c-on-identifier) + (c-forward-token-2 1 nil lim+))) (goto-char (match-end 0)) - (c-forward-syntactic-ws lim+) + (c-forward-syntactic-ws lim+)) (setq pos (point) res 'operator))) @@ -9676,7 +9700,7 @@ point unchanged and return nil." ;; (e.g. "," or ";" or "}"). (let ((here (point)) id-start id-end brackets-after-id paren-depth decorated - got-init arglist) + got-init arglist double-double-quote) (or limit (setq limit (point-max))) (if (and (< (point) limit) @@ -9705,6 +9729,10 @@ point unchanged and return nil." (setq id-start (point)) (if (looking-at c-overloadable-operators-regexp) (progn + (when (and (c-major-mode-is 'c++-mode) + (eq (char-after) ?\") + (eq (char-after (1+ (point))) ?\")) + (setq double-double-quote t)) (goto-char (match-end 0)) (c-forward-syntactic-ws limit) (setq got-identifier t) @@ -9756,6 +9784,13 @@ point unchanged and return nil." t) (t nil))) + (progn + (c-forward-syntactic-ws limit) + (when (and double-double-quote ; C++'s operator"" _tag + (c-on-identifier)) + (c-forward-token-2 1 nil limit)) + t) + ;; Skip out of the parens surrounding the identifier. If closing ;; parens are missing, this form returns nil. (or (= paren-depth 0) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 2e71285cb36..b4ff32b9070 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1141,12 +1141,28 @@ casts and declarations are fontified. Used on level 2 and higher." (while (and (< (point) id-end) (re-search-forward c-opt-identifier-prefix-key id-end t)) (c-forward-syntactic-ws limit)))) - (when (not (get-text-property (point) 'face)) + ;; Only apply the face when the text doesn't have one yet. + ;; Exception: The "" in C++'s operator"" will already wrongly have + ;; string face. + (when (memq (get-text-property (point) 'face) + '(nil font-lock-string-face)) (c-put-font-lock-face (point) id-end (cond ((not (memq types '(nil t))) types) (is-function 'font-lock-function-name-face) - (t 'font-lock-variable-name-face)))))) + (t 'font-lock-variable-name-face)))) + ;; Fontify any _tag in C++'s operator"" _tag. + (when (and + (c-major-mode-is 'c++-mode) + (equal (buffer-substring-no-properties id-start id-end) + "\"\"")) + (goto-char id-end) + (c-forward-syntactic-ws limit) + (when (c-on-identifier) + (c-put-font-lock-face + (point) + (progn (c-forward-over-token) (point)) + font-lock-function-name-face))))) (and template-class (eq init-char ?=) ; C++ ""? (progn diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index cd23483a58f..650c8720ee4 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1449,8 +1449,7 @@ form\". See also `c-op-identifier-prefix'." "??'=" "xor_eq" "&=" "and_eq" "|=" "??!=" "or_eq" "<<" ">>" ">>=" "<<=" "==" "!=" "not_eq" "<=>" "<=" ">=" "&&" "and" "||" "??!??!" "or" "++" "--" "," "->*" "->" - "()" "[]" "<::>" "??(??)") - ;; These work like identifiers in Pike. + "()" "[]" "\"\"" "<::>" "??(??)") pike '("`+" "`-" "`&" "`|" "`^" "`<<" "`>>" "`*" "`/" "`%" "`~" "`==" "`<" "`>" "`!" "`[]" "`[]=" "`->" "`->=" "`()" "``+" "``-" "``&" "``|" "``^" "``<<" "``>>" "``*" "``/" "``%" @@ -2936,6 +2935,15 @@ regexp if `c-colon-type-list-kwds' isn't nil." "[^][{}();,/#=:]*:"))) (c-lang-defvar c-colon-type-list-re (c-lang-const c-colon-type-list-re)) +(c-lang-defconst c-sub-colon-type-list-re + "Regexp matching buffer content that may come between a keyword in +`c-colon-type-list-kwds' and a putative colon, or nil if there are no +such keywords. Exception: it does not match any C++ attributes." + t (if (c-lang-const c-colon-type-list-re) + (substring (c-lang-const c-colon-type-list-re) 0 -1))) +(c-lang-defvar c-sub-colon-type-list-re + (c-lang-const c-sub-colon-type-list-re)) + (c-lang-defconst c-paren-nontype-kwds "Keywords that may be followed by a parenthesis expression that doesn't contain type identifiers." From eeffc1f5ae36284e8d08c0f529e115032d7e0d04 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Fri, 14 Oct 2022 21:32:15 +0200 Subject: [PATCH 80/99] Rename `file-attribute-file-number' to `file-attribute-file-identifier' * doc/lispref/files.texi (File Attributes): * etc/NEWS: * lisp/files.el (find-buffer-visiting, find-file-noselect) (set-visited-file-name, basic-save-buffer) (file-attribute-file-identifier): * lisp/startup.el (normal-top-level-add-subdirs-to-load-path): * lisp/eshell/em-unix.el (eshell-shuffle-files): * src/dired.c (Ffile_attributes): Rename `file-attribute-file-number' to `file-attribute-file-identifier'. --- doc/lispref/files.texi | 2 +- etc/NEWS | 2 +- lisp/eshell/em-unix.el | 4 ++-- lisp/files.el | 11 ++++++----- lisp/startup.el | 3 ++- src/dired.c | 2 +- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 2467364dc6e..b26d4f10585 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1413,7 +1413,7 @@ to distinguish remote filesystems from local ones. The file's inode and device together give enough information to distinguish any two files on the system---no two files can have the same values for both of these attributes. This tuple that uniquely -identifies the file is returned by @code{file-attribute-file-number}. +identifies the file is returned by @code{file-attribute-file-identifier}. For example, here are the file attributes for @file{files.texi}: diff --git a/etc/NEWS b/etc/NEWS index b73c2c47d5d..96415870523 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3159,7 +3159,7 @@ The following generalized variables have been made obsolete: * Lisp Changes in Emacs 29.1 +++ -** New accessor function 'file-attribute-file-number'. +** New accessor function 'file-attribute-file-identifier'. It returns the list of the inode number and device identifier retrieved by 'file-attributes'. This value can be used to identify a file uniquely. The device identifier can be a single number or (for diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el index 378b0ceeeae..4b5e4dd53ed 100644 --- a/lisp/eshell/em-unix.el +++ b/lisp/eshell/em-unix.el @@ -374,8 +374,8 @@ Remove the DIRECTORY(ies), if they are empty.") (file-attribute-inode-number attr) (file-attribute-device-number attr-target) (file-attribute-device-number attr) - (equal (file-attribute-file-number attr-target) - (file-attribute-file-number attr))) + (equal (file-attribute-file-identifier attr-target) + (file-attribute-file-identifier attr))) (eshell-error (format-message "%s: `%s' and `%s' are the same file\n" command (car files) target))) (t diff --git a/lisp/files.el b/lisp/files.el index dd10f7399cc..3fa0f2f3b81 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2164,7 +2164,7 @@ If there is no such live buffer, return nil." (setq list (cdr list))) found) (let* ((attributes (file-attributes truename)) - (number (file-attribute-file-number attributes)) + (number (file-attribute-file-identifier attributes)) (list (buffer-list)) found) (and buffer-file-numbers-unique (car-safe number) ;Make sure the inode is not just nil. @@ -2367,7 +2367,7 @@ the various files." (let* ((buf (get-file-buffer filename)) (truename (abbreviate-file-name (file-truename filename))) (attributes (file-attributes truename)) - (number (file-attribute-file-number attributes)) + (number (file-attribute-file-identifier attributes)) ;; Find any buffer for a file that has same truename. (other (and (not buf) (find-buffer-visiting @@ -4745,7 +4745,7 @@ the old visited file has been renamed to the new name FILENAME." (setq buffer-file-name truename)))) (setq buffer-file-number (if filename - (file-attribute-file-number (file-attributes buffer-file-name)) + (file-attribute-file-identifier (file-attributes buffer-file-name)) nil)) ;; write-file-functions is normally used for things like ftp-find-file ;; that visit things that are not local files as if they were files. @@ -5734,7 +5734,8 @@ Before and after saving the buffer, this function runs (setq save-buffer-coding-system last-coding-system-used) (setq buffer-file-coding-system last-coding-system-used)) (setq buffer-file-number - (file-attribute-file-number (file-attributes buffer-file-name))) + (file-attribute-file-identifier + (file-attributes buffer-file-name))) (if setmodes (condition-case () (progn @@ -8662,7 +8663,7 @@ It is a nonnegative integer." It is an integer or a cons cell of integers." (nth 11 attributes)) -(defsubst file-attribute-file-number (attributes) +(defsubst file-attribute-file-identifier (attributes) "The inode and device numbers in ATTRIBUTES returned by `file-attributes'. The value is a list of the form (INODENUM DEVICE), where DEVICE could be either a single number or a cons cell of two numbers. diff --git a/lisp/startup.el b/lisp/startup.el index c7faf4abc6f..725984b815b 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -458,7 +458,8 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'." ;; The Windows version doesn't report meaningful inode numbers, so ;; use the canonicalized absolute file name of the directory instead. (setq attrs (or canonicalized - (file-attribute-file-number (file-attributes this-dir)))) + (file-attribute-file-identifier + (file-attributes this-dir)))) (unless (member attrs normal-top-level-add-subdirs-inode-list) (push attrs normal-top-level-add-subdirs-inode-list) (dolist (file contents) diff --git a/src/dired.c b/src/dired.c index 1b4edf20483..ef729df5d2b 100644 --- a/src/dired.c +++ b/src/dired.c @@ -928,7 +928,7 @@ Elements of the attribute list are: Large integers are bignums, so `eq' might not work on them. On most filesystems, the combination of the inode and the device identifier uniquely identifies the file. This unique file identification -is provided by the access function `file-attribute-file-number'. +is provided by the access function `file-attribute-file-identifier'. On MS-Windows, performance depends on `w32-get-true-file-attributes', which see. From f5c6e628ed311761cfe9c0d2dd68baa2806abab4 Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Mon, 3 Oct 2022 23:34:07 +0300 Subject: [PATCH 81/99] Update image-circular-tests.el * test/manual/image-circular-tests.el (image-test-duplicate-keywords): Skip unless images are supported. (image-test-circular-plist, image-test-:type-property-value): Ditto. Wrap only failing forms in should[-error] rather than entire test bodies. Use simpler printed notation in place of function calls. (image-test-circular-specs): Ditto. Wrap overly wide docstring. Mark as failing since shortly after its introduction (bug#36403#63). --- test/manual/image-circular-tests.el | 41 +++++++++++++++++------------ 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/test/manual/image-circular-tests.el b/test/manual/image-circular-tests.el index 1299970f827..d2187cbbadc 100644 --- a/test/manual/image-circular-tests.el +++ b/test/manual/image-circular-tests.el @@ -27,8 +27,11 @@ (require 'ert) +(declare-function image-size "image.c" (spec &optional pixels frame)) + (ert-deftest image-test-duplicate-keywords () "Test that duplicate keywords in an image spec lead to rejection." + (skip-unless (display-images-p)) (should-error (image-size `(image :type xbm :type xbm :data-width 1 :data-height 1 :data ,(bool-vector t)) @@ -36,33 +39,37 @@ (ert-deftest image-test-circular-plist () "Test that a circular image spec is rejected." - (should-error - (let ((l `(image :type xbm :data-width 1 :data-height 1 - :data ,(bool-vector t)))) - (setcdr (last l) '#1=(:invalid . #1#)) - (image-size l t)))) + (skip-unless (display-images-p)) + (let ((spec `(image :type xbm :data-width 1 :data-height 1 + :data ,(bool-vector t) + . ,'#1=(:invalid . #1#)))) + (should-error (image-size spec t)))) (ert-deftest image-test-:type-property-value () "Test that :type is allowed as a property value in an image spec." + (skip-unless (display-images-p)) (should (equal (image-size `(image :dummy :type :type xbm :data-width 1 :data-height 1 :data ,(bool-vector t)) t) - (cons 1 1)))) + '(1 . 1)))) (ert-deftest image-test-circular-specs () - "Test that circular image spec property values do not cause infinite recursion." - (should - (let* ((circ1 (cons :dummy nil)) - (circ2 (cons :dummy nil)) - (spec1 `(image :type xbm :data-width 1 :data-height 1 - :data ,(bool-vector 1) :ignored ,circ1)) - (spec2 `(image :type xbm :data-width 1 :data-height 1 + "Test with circular image spec property values. +In particular, test that they do not cause infinite recursion." + :expected-result :failed ;; FIXME: bug#36403#63. + (skip-unless (display-images-p)) + ;; Two copies needed to warm up image cache. + (let* ((circ1 (list :dummy)) + (circ2 (list :dummy)) + (spec1 `(image :type xbm :data-width 1 :data-height 1 + :data ,(bool-vector 1) :ignored ,circ1)) + (spec2 `(image :type xbm :data-width 1 :data-height 1 :data ,(bool-vector 1) :ignored ,circ2))) - (setcdr circ1 circ1) - (setcdr circ2 circ2) - (and (equal (image-size spec1 t) (cons 1 1)) - (equal (image-size spec2 t) (cons 1 1)))))) + (setcdr circ1 circ1) + (setcdr circ2 circ2) + (should (equal (image-size spec1 t) '(1 . 1))) + (should (equal (image-size spec2 t) '(1 . 1))))) (provide 'image-circular-tests) ;;; image-circular-tests.el ends here. From 8300899953cf903f2e3dcf2e985b16044959df7c Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 15 Oct 2022 03:02:17 +0200 Subject: [PATCH 82/99] Use file-size-human-readable in memory-report--format * lisp/emacs-lisp/memory-report.el (memory-report--format): Use file-size-human-readable. --- lisp/emacs-lisp/memory-report.el | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el index 56b1ea6ed48..968a80b59e7 100644 --- a/lisp/emacs-lisp/memory-report.el +++ b/lisp/emacs-lisp/memory-report.el @@ -262,12 +262,7 @@ by counted more than once." (cl-struct-slot-info struct-type))))) (defun memory-report--format (bytes) - (setq bytes (/ bytes 1024.0)) - (let ((units '("KiB" "MiB" "GiB" "TiB"))) - (while (>= bytes 1024) - (setq bytes (/ bytes 1024.0)) - (setq units (cdr units))) - (format "%6.1f %s" bytes (car units)))) + (format "%10s" (file-size-human-readable bytes 'iec " "))) (defun memory-report--gc-elem (elems type) (* (nth 1 (assq type elems)) From e1090b091415bdb2c728de6597562262bd155897 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 15 Oct 2022 05:07:35 +0200 Subject: [PATCH 83/99] ; Auto-commit of loaddefs files. --- lisp/ldefs-boot.el | 53 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index c9502fbb212..517b23b1ea9 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -15397,7 +15397,7 @@ it is disabled. ;;; Generated autoloads from progmodes/hideshow.el -(defvar hs-special-modes-alist (mapcar 'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|]*[^/]>" "