commit 45a631134fbbf6b5226c8233bfb72197695d5c84 (HEAD, refs/remotes/origin/master) Merge: 74ceb6922c6 21b2954c90e Author: Eli Zaretskii Date: Sun May 26 03:01:29 2024 -0400 ; Merge from origin/emacs-29 The following commit was skipped: 21b2954c90e ; Fix markup in manuals commit 21b2954c90eb5b6fa1bbfeda4c5074a0bdc53ba8 (refs/remotes/origin/emacs-29) Author: Eli Zaretskii Date: Sun May 26 09:49:52 2024 +0300 ; Fix markup in manuals * doc/emacs/files.texi (Visiting): * doc/lispref/processes.texi (Filter Functions, Sentinels): Fix markup and punctuation. Reported by Andrés Ramírez . diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 01d22564f2e..a3fa138e36d 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -372,12 +372,12 @@ you could say: '(("src/emacs/[^/]+/\\(.*\\)\\'" "src/emacs/.*/\\1"))) @end lisp -As you can see, this is a list of @var{(MATCH EXPANSION...)} elements. -The @var{match} is a regular expression that matches the visited file -name, and each @var{expansion} may refer to match groups by using -@samp{\\1} and so on. The resulting expansion string is then applied -to the file system to see if any files match this expansion -(interpreted as a regexp). +As you can see, this is a list of elements of the form +@w{@code{(@var{MATCH} @var{expansion}@dots{})}}. The @var{match} is a +regular expression that matches the visited file name, and each +@var{expansion} may refer to match groups by using @samp{\\1} and so +on. The resulting expansion string is then applied to the file system +to see if any files match this expansion (interpreted as a regexp). @vindex find-file-hook @vindex find-file-not-found-functions diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index e3eee3d0719..9ad44a55dd1 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -1762,7 +1762,7 @@ program was running when the filter function was started. However, if This makes it possible to use the Lisp debugger to debug filter functions. @xref{Debugger}. If an error is caught, Emacs pauses for @code{process-error-pause-time} seconds so that the user sees the -error. @xref{Asynchronous Processes} +error. @xref{Asynchronous Processes}. Many filter functions sometimes (or always) insert the output in the process's buffer, mimicking the actions of the default filter. @@ -2168,7 +2168,7 @@ programs was running when the sentinel was started. However, if This makes it possible to use the Lisp debugger to debug the sentinel. @xref{Debugger}. If an error is caught, Emacs pauses for @code{process-error-pause-time} seconds so that the user sees the -error. @xref{Asynchronous Processes} +error. @xref{Asynchronous Processes}. While a sentinel is running, the process sentinel is temporarily set to @code{nil} so that the sentinel won't run recursively. commit 74ceb6922c621cf48a2c9f6e6622133b522252ab Author: Po Lu Date: Sun May 26 11:50:13 2024 +0800 Address compilation errors and warnings on x86 Solaris 10 systems * doc/misc/ede.texi (Extending EDE): * doc/misc/flymake.texi (Top, Using Flymake): Insert punctuation after xrefs. * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate): Print number of files being scraped. * src/dired.c (directory_files_internal): * src/eval.c (Fmake_interpreted_closure, Fdefvaralias): * src/fns.c (Fassoc): Work around optimizer failures. diff --git a/doc/misc/ede.texi b/doc/misc/ede.texi index 15f7a329803..ae179832753 100644 --- a/doc/misc/ede.texi +++ b/doc/misc/ede.texi @@ -1027,13 +1027,13 @@ superclasses, specifically the PROJECT and TARGET@. All commands in target. All specific projects in @ede{} derive subclasses of the @ede{} -superclasses. In this way, specific behaviors such as how a project -is saved, or how a target is compiled can be customized by a project -author in detail. @ede{} communicates to these project objects via an -API using methods. The commands you use in @ede{} mode are high-level +superclasses. In this way, specific behaviors such as how a project is +saved, or how a target is compiled can be customized by a project author +in detail. @ede{} communicates to these project objects via an API +using methods. The commands you use in @ede{} mode are high-level functional wrappers over these methods. @xref{Top,,, eieio, EIEIO -manual} for details on using @eieio{} to extending classes, and -writing methods. +manual}, for details on using @eieio{} to extending classes, and writing +methods. If you intend to extend @ede{}, it is most likely that a new target type is needed in one of the existing project types. The rest of this chapter diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi index 7019f4b2ca0..6b605a6c095 100644 --- a/doc/misc/flymake.texi +++ b/doc/misc/flymake.texi @@ -59,11 +59,10 @@ types of diagnostics. To learn about using Flymake, @pxref{Using Flymake}. -When the Emacs LSP support mode Eglot is enabled, Flymake will use -that as an additional back-end. @xref{Eglot Features,,, eglot, Eglot: -The Emacs LSP Client} Flymake is also designed to be easily extended -to support new backends via an Elisp interface. @xref{Extending -Flymake}. +When the Emacs LSP support mode Eglot is enabled, Flymake will use that +as an additional back-end. @xref{Eglot Features,,, eglot, Eglot: The +Emacs LSP Client}. Flymake is also designed to be easily extended to +support new backends via an Elisp interface. @xref{Extending Flymake}. @ifnottex @insertcopying @@ -94,7 +93,7 @@ write your own Flymake backend functions. @xref{Backend functions}. When the Emacs LSP support mode Eglot is enabled, Flymake will use that as an additional back-end automatically. @xref{Eglot Features,,, -eglot, Eglot: The Emacs LSP Client} +eglot, Eglot: The Emacs LSP Client}. @menu * Starting Flymake:: diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 581053f6304..50e90cdf94c 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -601,7 +601,6 @@ instead of just updating them with the new/changed autoloads." (if (consp dir) dir (list dir))))) (updating (and (file-exists-p output-file) (not generate-full))) (defs nil)) - ;; Allow the excluded files to be relative. (setq excluded-files (mapcar (lambda (file) (expand-file-name file dir)) @@ -610,7 +609,8 @@ instead of just updating them with the new/changed autoloads." ;; Collect all the autoload data. (let ((progress (make-progress-reporter (byte-compile-info - (concat "Scraping files for loaddefs")) + (format "Scraping %s files for loaddefs" + (length files))) 0 (length files) nil 10)) (output-time (file-attribute-modification-time (file-attributes output-file))) diff --git a/src/dired.c b/src/dired.c index bfbacf70917..37a9cad992f 100644 --- a/src/dired.c +++ b/src/dired.c @@ -351,8 +351,11 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, specpdl_ptr = specpdl_ref_to_ptr (count); if (NILP (nosort)) - list = CALLN (Fsort, Fnreverse (list), - attrs ? Qfile_attributes_lessp : Qstring_lessp); + { + Lisp_Object ordered = Fnreverse (list); + list = CALLN (Fsort, ordered, + attrs ? Qfile_attributes_lessp : Qstring_lessp); + } (void) directory_volatile; return list; diff --git a/src/eval.c b/src/eval.c index 8cabe2d2cc7..20b9ca9a0ec 100644 --- a/src/eval.c +++ b/src/eval.c @@ -527,14 +527,22 @@ IFORM if non-nil should be of the form (interactive ...). */) (Lisp_Object args, Lisp_Object body, Lisp_Object env, Lisp_Object docstring, Lisp_Object iform) { + Lisp_Object ifcdr, value, slots[6]; + CHECK_CONS (body); /* Make sure it's not confused with byte-code! */ CHECK_LIST (args); CHECK_LIST (iform); - Lisp_Object ifcdr = Fcdr (iform); - Lisp_Object slots[] = { args, body, env, Qnil, docstring, - NILP (Fcdr (ifcdr)) - ? Fcar (ifcdr) - : CALLN (Fvector, XCAR (ifcdr), XCDR (ifcdr)) }; + ifcdr = CDR (iform); + if (NILP (CDR (ifcdr))) + value = CAR (ifcdr); + else + value = CALLN (Fvector, XCAR (ifcdr), XCDR (ifcdr)); + slots[0] = args; + slots[1] = body; + slots[2] = env; + slots[3] = Qnil; + slots[4] = docstring; + slots[5] = value; /* Adjusting the size is indispensable since, as for byte-code objects, we distinguish interactive functions by the presence or absence of the iform slot. */ @@ -675,12 +683,17 @@ signal a `cyclic-variable-indirection' error. */) else if (!NILP (Fboundp (new_alias)) && !EQ (find_symbol_value (new_alias), find_symbol_value (base_variable))) - call2 (Qdisplay_warning, - list3 (Qdefvaralias, Qlosing_value, new_alias), - CALLN (Fformat_message, - build_string - ("Overwriting value of `%s' by aliasing to `%s'"), - new_alias, base_variable)); + { + Lisp_Object message, formatted; + + message = build_string ("Overwriting value of `%s' by aliasing" + " to `%s'"); + formatted = CALLN (Fformat_message, message, + new_alias, base_variable); + call2 (Qdisplay_warning, + list3 (Qdefvaralias, Qlosing_value, new_alias), + formatted); + } { union specbinding *p; diff --git a/src/fns.c b/src/fns.c index e7dc8dc1bb7..48607b2c5d0 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2006,11 +2006,12 @@ TESTFN is called with 2 arguments: a car of an alist element and KEY. */) FOR_EACH_TAIL (tail) { Lisp_Object car = XCAR (tail); - if (CONSP (car) - && (NILP (testfn) - ? (EQ (XCAR (car), key) || !NILP (Fequal - (XCAR (car), key))) - : !NILP (call2 (testfn, XCAR (car), key)))) + if (!CONSP (car)) + continue; + if ((NILP (testfn) + ? (EQ (XCAR (car), key) || !NILP (Fequal + (XCAR (car), key))) + : !NILP (call2 (testfn, XCAR (car), key)))) return car; } CHECK_LIST_END (tail, alist); commit 2a12f39ffe87b0b2885d9b7e92962eeed3c8029e Author: Dmitry Gutov Date: Sun May 26 05:56:14 2024 +0300 Improve navigation to cl-defgeneric uses * lisp/emacs-lisp/cl-generic.el (cl--generic-find-defgeneric-regexp): Use "symbol end" boundary (bug#71068). diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 8bda857afdd..11685d09d12 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -1087,7 +1087,7 @@ MET-NAME is as returned by `cl--generic-load-hist-format'." (re-search-forward base-re nil t)))) ;; WORKAROUND: This can't be a defconst due to bug#21237. -(defvar cl--generic-find-defgeneric-regexp "(\\(?:cl-\\)?defgeneric[ \t]+%s\\>") +(defvar cl--generic-find-defgeneric-regexp "(\\(?:cl-\\)?defgeneric[ \t]+%s\\_>") (with-eval-after-load 'find-func (defvar find-function-regexp-alist) commit 7ca238c4413284253c06ed2b060a7a0f79653b40 Author: Dmitry Gutov Date: Sun May 26 00:58:57 2024 +0300 xref-revert-buffer: Make inhibit-modification-hooks binding a bit safer * lisp/progmodes/xref.el (xref-revert-buffer): Make sure that the inhibit-modification-hooks binding does not cover xref--fetcher funcall. Only the printing step (issue mentioned in bug#53749). diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 534bd930e13..af77e860020 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -1277,11 +1277,11 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)." "Refresh the search results in the current buffer." (interactive) (let ((inhibit-read-only t) - (buffer-undo-list t) - (inhibit-modification-hooks t)) + (buffer-undo-list t)) (save-excursion (condition-case err - (let ((alist (xref--analyze (funcall xref--fetcher)))) + (let ((alist (xref--analyze (funcall xref--fetcher))) + (inhibit-modification-hooks t)) (erase-buffer) (xref--insert-xrefs alist)) (user-error commit 57dc1ed665d72bc58befa4853fa479b770fe4fcc Author: Jim Porter Date: Sat May 25 13:46:24 2024 -0700 Fix a race condition when evaluating Eshell commands * lisp/eshell/esh-cmd.el (eshell-do-eval): Don't defer when all the processes are done. * test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/pipeline-wait/nested-pipes): New test. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index dae1a77552f..57aeff59266 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -1287,13 +1287,15 @@ have been replaced by constants." (setcdr form (cdr new-form))) (eshell-do-eval form synchronous-p)) (if-let (((memq (car form) eshell-deferrable-commands)) - (procs (eshell-make-process-list result))) + (procs (eshell-make-process-list result)) + (active (seq-some #'eshell-process-active-p procs))) (if synchronous-p (apply #'eshell/wait procs) (eshell-manipulate form "inserting ignore form" (setcar form 'ignore) (setcdr form nil)) - (throw 'eshell-defer procs)) + (when active + (throw 'eshell-defer procs))) (list 'quote result)))))))))))) ;; command invocation diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el index ef965a896c1..d84f8802bdc 100644 --- a/test/lisp/eshell/esh-cmd-tests.el +++ b/test/lisp/eshell/esh-cmd-tests.el @@ -213,6 +213,18 @@ This should also wait for the subcommand." (eshell-match-command-output "echo ${*echo hi | *cat} | *cat" "hi"))) +(ert-deftest esh-cmd-test/pipeline-wait/nested-pipes () + "Check that piping a subcommand with its own pipe works. +This should also wait for the subcommand." + (skip-unless (and (executable-find "echo") + (executable-find "cat") + (executable-find "sh") + (executable-find "sleep"))) + (with-temp-eshell + (eshell-match-command-output + "{ sh -c 'sleep 1; echo goodbye 1>&2' | *echo hello } | *cat" + "hello\ngoodbye\n"))) + (ert-deftest esh-cmd-test/reset-in-pipeline/subcommand () "Check that subcommands reset `eshell-in-pipeline-p'." (skip-unless (executable-find "cat")) commit 91509d5d2a2dc818830cff63f13d6efcb229dc0c Author: Michael Albinus Date: Sat May 25 17:23:30 2024 +0200 Make Tramp's async processes more robust * lisp/simple.el (shell-command-sentinel): Check process property `remote-command' first. * lisp/net/tramp.el (tramp-handle-make-process): * lisp/net/tramp-androidsu.el (tramp-androidsu-handle-make-process): Set sentinel `ignore'. (Bug#71049) * test/lisp/net/tramp-tests.el (tramp--test-deftest-direct-async-process): Don't suppress internal sentinel. (tramp-test32-shell-commanddirect-async): Don't tag it :unstable. diff --git a/lisp/net/tramp-androidsu.el b/lisp/net/tramp-androidsu.el index 95b852d2068..b2f0bab650d 100644 --- a/lisp/net/tramp-androidsu.el +++ b/lisp/net/tramp-androidsu.el @@ -385,6 +385,8 @@ FUNCTION." ;; Generate a command to start the process using `su' with ;; suitable options for specifying the mount namespace and ;; suchlike. + ;; Suppress `internal-default-process-sentinel', which is + ;; set when :sentinel is nil. (Bug#71049) (setq p (let ((android-use-exec-loader nil)) (make-process @@ -407,7 +409,7 @@ FUNCTION." :coding coding :noquery noquery :connection-type connection-type - :sentinel sentinel + :sentinel (or sentinel #'ignore) :stderr stderr))) ;; Set filter. Prior Emacs 29.1, it doesn't work reliably ;; to provide it as `make-process' argument when filter is diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 18116229337..9385b023392 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -5011,9 +5011,9 @@ should be set conmnection-local.") (string-join command) (tramp-get-remote-pipe-buf v))) (signal 'error (cons "Command too long:" command))) - ;; Replace `login-args' place holders. Split ControlMaster - ;; options. (setq + ;; Replace `login-args' place holders. Split ControlMaster + ;; options. login-args (append (flatten-tree (tramp-get-method-parameter v 'tramp-async-args)) @@ -5025,11 +5025,13 @@ should be set conmnection-local.") ?h (or host "") ?u (or user "") ?p (or port "") ?c (format-spec (or options "") (format-spec-make ?t tmpfile)) ?d (or device "") ?a (or pta "") ?l "")))) + ;; Suppress `internal-default-process-sentinel', which is + ;; set when :sentinel is nil. (Bug#71049) p (make-process :name name :buffer buffer :command (append `(,login-program) login-args command) :coding coding :noquery noquery :connection-type connection-type - :sentinel sentinel :stderr stderr)) + :sentinel (or sentinel #'ignore) :stderr stderr)) ;; Set filter. Prior Emacs 29.1, it doesn't work reliably ;; to provide it as `make-process' argument when filter is ;; t. See Bug#51177. diff --git a/lisp/simple.el b/lisp/simple.el index 5177905ee1b..ae8a824cb54 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -4863,11 +4863,14 @@ and are used only if a pop-up buffer is displayed." ;; We have a sentinel to prevent insertion of a termination message ;; in the buffer itself, and to set the point in the buffer when ;; `shell-command-dont-erase-buffer' is non-nil. +;; For remote shells, `process-command' does not serve the proper shell +;; command. We use process property `remote-command' instead. (Bug#71049) (defun shell-command-sentinel (process signal) (when (memq (process-status process) '(exit signal)) (shell-command-set-point-after-cmd (process-buffer process)) (message "%s: %s." - (car (cdr (cdr (process-command process)))) + (car (cdr (cdr (or (process-get process 'remote-command) + (process-command process))))) (substring signal 0 -1)))) (defun shell-command-on-region (start end command diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 130f4a76ff5..2c61efb04d8 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -5390,10 +5390,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." ;; We do expect an established connection already, ;; `file-truename' does it by side-effect. Suppress ;; `tramp--test-enabled', in order to keep the connection. - ;; Suppress "Process ... finished" messages. - (cl-letf (((symbol-function #'tramp--test-enabled) #'tramp-compat-always) - ((symbol-function #'internal-default-process-sentinel) - #'ignore)) + (cl-letf (((symbol-function #'tramp--test-enabled) #'tramp-compat-always)) (file-truename ert-remote-temporary-file-directory) (funcall (ert-test-body ert-test)))))) @@ -5936,7 +5933,7 @@ INPUT, if non-nil, is a string sent to the process." (when (natnump cols) (should (= cols async-shell-command-width)))))) -(tramp--test-deftest-direct-async-process tramp-test32-shell-command 'unstable) +(tramp--test-deftest-direct-async-process tramp-test32-shell-command) ;; This test is inspired by Bug#39067. (ert-deftest tramp-test32-shell-command-dont-erase-buffer () commit 129c6778e640f8ae9ba0eba9ad9ce81b4bf2328e Author: Andrea Corallo Date: Sat May 25 17:12:22 2024 +0200 * src/Makefile.in (ELN_DESTDIR, BIN_DESTDIR): Give a default (bug#70842). diff --git a/src/Makefile.in b/src/Makefile.in index e839a74dabf..a14ae5eacb8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -34,6 +34,11 @@ top_builddir = @top_builddir@ abs_top_srcdir=@abs_top_srcdir@ VPATH = $(srcdir) +# Set these to 'not-set' when they are not set from top-level to please +# 'load--fixup-all-elns' (bug#70842). +ELN_DESTDIR=not-set +BIN_DESTDIR=not-set + # This is not empty if this is a Makefile that will be copied to # cross/src. XCONFIGURE = @XCONFIGURE@ commit ed7e57697572f641b50d24071867675bf89bed0f Merge: cb67c34bcfe 4f0121f8dbe Author: Eli Zaretskii Date: Sat May 25 08:00:48 2024 -0400 Merge from origin/emacs-29 4f0121f8dbe Avoid assertion violations in displaying under 'outline-m... 1bf65836622 Improve documentation of 'no-special-glyphs' frame parameter 3647645e948 Fix Python font lock of chained assignment statement 3291dea441f Fix example in Calc manual 350ae75f5c1 Avoid crashes on MS-Windows due to invalid UNC file names ccf8dba44a3 ; * lisp/face-remap.el (text-scale-adjust): Doc fix. 5ab144c77cd ; Improve documentation of backing up files commit 4f0121f8dbe2ca0ec8fe2831353f01782e5e6b9d Author: Eli Zaretskii Date: Sat May 25 14:23:43 2024 +0300 Avoid assertion violations in displaying under 'outline-minor-mode' * src/xdisp.c (init_from_display_pos): Initialize BYTEPOS correctly, since 'init_iterator' no longer computes it from CHARPOS as needed. This fixes a change made on Mar 13, 2013. (Bug#71194) diff --git a/src/xdisp.c b/src/xdisp.c index 6e945ed114b..1b198df4076 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3876,7 +3876,7 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos) if (in_ellipses_for_invisible_text_p (pos, w)) { --charpos; - bytepos = 0; + bytepos = BYTE_TO_CHAR (charpos); } /* Keep in mind: the call to reseat in init_iterator skips invisible commit cb67c34bcfe525cbab75d7af8c6e6244d61eb228 Author: Mattias Engdegård Date: Sat May 25 12:20:30 2024 +0200 Omit `store-substring` from lisp manual (bug#70784) * doc/lispref/strings.texi (Modifying Strings): Remove `store-substring` which is not really useful enough to merit a mention here. diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 7f640255a7a..6e5c3521135 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -473,28 +473,12 @@ needed, but we recommend to always make sure @var{string} is multibyte Representations}), if @var{char} is a non-@acronym{ASCII} character, not a raw byte. - A more powerful function is @code{store-substring}: - -@defun store-substring string idx obj -This function alters part of the contents of the specified @var{string}, -by storing @var{obj} starting at character index @var{idx}. The -argument @var{obj} may be either a character (in which case the function -behaves exactly as @code{aset}) or a (smaller) string. If @var{obj} -is a multibyte string, we recommend to make sure @var{string} is also -multibyte, even if it's pure-@acronym{ASCII}. - -Since it is impossible to change the number of characters in an -existing string, it is an error if @var{obj} consists of more -characters than would fit in @var{string} starting at character index -@var{idx}. -@end defun - To clear out a string that contained a password, use @code{clear-string}: @defun clear-string string This makes @var{string} a unibyte string and clears its contents to -zeros. It may also change @var{string}'s length. +null characters. It may also change @var{string}'s length. @end defun @need 2000 commit 1bf658366220ce1019721f24d96ef8f82bd18cff Author: Eli Zaretskii Date: Sat May 25 13:22:45 2024 +0300 Improve documentation of 'no-special-glyphs' frame parameter * doc/lispref/frames.texi (Layout Parameters): Document limitations of support for 'no-special-glyphs' frame parameter. (Bug#71163) * doc/lispref/display.texi (Truncation): Update for when 'fringe-mode' is off. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 869bf15a40a..ef44c8d80f5 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -148,7 +148,8 @@ boundary. @xref{Filling}. On a graphical display, tiny arrow images in the window fringes indicate truncated and continued lines (@pxref{Fringes}). On a text -terminal, a @samp{$} in the rightmost column of the window indicates +terminal, and on a graphical display when @code{fringe-mode} was +turned off, a @samp{$} in the rightmost column of the window indicates truncation; a @samp{\} on the rightmost column indicates a line that wraps. (The display table can specify alternate characters to use for this; @pxref{Display Tables}). diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index edc080153d6..fe5745a85ab 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -1928,10 +1928,16 @@ integer). @xref{Line Height}, for more information. @vindex no-special-glyphs@r{, a frame parameter} @item no-special-glyphs If this is non-@code{nil}, it suppresses the display of any truncation -and continuation glyphs (@pxref{Truncation}) for all buffers displayed -by this frame. This is useful to eliminate such glyphs when fitting a -frame to its buffer via @code{fit-frame-to-buffer} (@pxref{Resizing -Windows}). +(@pxref{Truncation}) and continuation glyphs for all the buffers +displayed by this frame. This is useful to eliminate such glyphs when +fitting a frame to its buffer via @code{fit-frame-to-buffer} +(@pxref{Resizing Windows}). This frame parameter has effect only for +GUI frames shown on graphical displays, and only if the fringes are +disabled. This parameter is intended as a purely-presentation +feature, and in particular should not be used for frames where the +user can interactively insert text, or more generally where the cursor +is shown. A notable example of frames where this is used is tooltip +frames (@pxref{Tooltips}). @end table commit d54178f535b1eafe4919a282cf85a9b553469de2 Author: Eli Zaretskii Date: Sat May 25 13:02:20 2024 +0300 Improve documentation of sending commands to shells * doc/lispref/processes.texi (Synchronous Processes): * lisp/subr.el (call-shell-region): * lisp/simple.el (shell-command-on-region) (shell-command-to-string): Document system-dependent aspects of sending commands to shells. (Bug#71081) diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index c356c905dee..c5fbb0fb818 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -616,11 +616,24 @@ is similar than @code{call-process-region}, with process being a shell. The arguments @code{delete}, @code{destination} and the return value are like in @code{call-process-region}. Note that this function doesn't accept additional arguments. + +If @var{command} names a shell (e.g., via @code{shell-file-name}), keep +in mind that behavior of various shells when commands are piped to their +standard input is shell- and system-dependent, and thus non-portable. +The differences are especially prominent when the region includes more +than one line, i.e.@: when piping to a shell commands with embedded +newlines. Lisp programs using this technique will therefore need to +format the text in the region differently, according to the expectations +of the shell. @end defun @defun shell-command-to-string command This function executes @var{command} (a string) as a shell command, -then returns the command's output as a string. +then returns the command's output as a string. If @var{command} +actually includes more than one command, the behavior depends on the +shell to be invoked (determined by @code{shell-file-name} for local +commands). In particular, the separator between the commands cannot be +a newline on MS-Windows; use @samp{&&} instead. @end defun @c There is also shell-command-on-region, but that is more of a user @@ -944,6 +957,7 @@ example the function @code{ange-ftp-hook-function}). In such cases, this function does nothing and returns @code{nil}. @end defun +@vindex shell-file-name @defun start-process-shell-command name buffer-or-name command This function is like @code{start-process}, except that it uses a shell to execute the specified @var{command}. The argument diff --git a/lisp/simple.el b/lisp/simple.el index bcd26da13ed..5177905ee1b 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -4928,7 +4928,14 @@ interactively, this is t. Non-nil REGION-NONCONTIGUOUS-P means that the region is composed of noncontiguous pieces. The most common example of this is a rectangular region, where the pieces are separated by newline -characters." +characters. + +If COMMAND names a shell (e.g., via `shell-file-name'), keep in mind +that behavior of various shells when commands are piped to their +standard input is shell- and system-dependent, and thus non-portable. +The differences are especially prominent when the region includes +more than one line, i.e. when piping to a shell commands with embedded +newlines." (interactive (let (string) (unless (mark) (user-error "The mark is not set now, so there is no region")) @@ -5110,7 +5117,13 @@ other cases, consider alternatives such as `call-process' or `process-lines', which do not invoke the shell. Consider using built-in functions like `rename-file' instead of the external command \"mv\". For more information, see Info node -`(elisp)Security Considerations'." +`(elisp)Security Considerations'. + +If COMMAND includes several separate commands to run one after +the other, the separator between the individual commands needs +to be shell- and system-dependent. In particular, the MS-Windows +shell cmd.exe doesn't support commands with embedded newlines; +use the \"&&\" separator instead." (with-output-to-string (with-current-buffer standard-output (shell-command command t)))) diff --git a/lisp/subr.el b/lisp/subr.el index d6481fdf73e..eda5b7ae31b 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4782,7 +4782,14 @@ t (mix it with ordinary output), or a file name string. If BUFFER is 0, `call-shell-region' returns immediately with value nil. Otherwise it waits for COMMAND to terminate and returns a numeric exit status or a signal description string. -If you quit, the process is killed with SIGINT, or SIGKILL if you quit again." +If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. + +If COMMAND names a shell (e.g., via `shell-file-name'), keep in mind +that behavior of various shells when commands are piped to their +standard input is shell- and system-dependent, and thus non-portable. +The differences are especially prominent when the region includes +more than one line, i.e. when piping to a shell commands with embedded +newlines." (call-process-region start end shell-file-name delete buffer nil shell-command-switch command)) commit 1a48b53040d1ec24798c07c7dacafe134aa15a5e Author: Michael Albinus Date: Sat May 25 11:34:04 2024 +0200 Adapt Tramp's progress-reporter messages * lisp/net/tramp-androidsu.el (tramp-androidsu-maybe-open-connection): * lisp/net/tramp-gvfs.el (tramp-gvfs-maybe-open-connection): Adapt progress-reporter message. * lisp/net/tramp-sh.el (tramp-maybe-open-connection): Divide progress-reporter into two parts. (Bug#70901) diff --git a/lisp/net/tramp-androidsu.el b/lisp/net/tramp-androidsu.el index ee0241812ee..95b852d2068 100644 --- a/lisp/net/tramp-androidsu.el +++ b/lisp/net/tramp-androidsu.el @@ -118,16 +118,14 @@ multibyte mode and waits for the shell prompt to appear." (unless (process-live-p p) (with-tramp-progress-reporter vec 3 - (if (tramp-string-empty-or-nil-p (tramp-file-name-user vec)) - (format "Opening connection %s for %s using %s" - process-name - (tramp-file-name-host vec) - (tramp-file-name-method vec)) - (format "Opening connection %s for %s@%s using %s" - process-name - (tramp-file-name-user vec) - (tramp-file-name-host vec) - (tramp-file-name-method vec))) + (format "Opening connection%s for %s%s using %s" + (if (tramp-string-empty-or-nil-p process-name) + "" (concat " " process-name)) + (if (tramp-string-empty-or-nil-p + (tramp-file-name-user vec)) + "" (concat (tramp-file-name-user vec) "@")) + (tramp-file-name-host vec) + (tramp-file-name-method vec)) (let* ((coding-system-for-read 'utf-8-unix) (process-connection-type tramp-process-connection-type) ;; The executable loader cannot execute setuid diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 93071ed7350..b1820b3e2fe 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -2245,10 +2245,10 @@ connection if a previous connection has died for some reason." (tramp-make-tramp-file-name vec 'noloc)))) (with-tramp-progress-reporter - vec 3 - (if (tramp-string-empty-or-nil-p user) - (format "Opening connection for %s using %s" host method) - (format "Opening connection for %s@%s using %s" user host method)) + vec 3 (format "Opening connection for %s%s using %s" + (if (tramp-string-empty-or-nil-p user) + "" (concat user "@")) + host method) ;; Enable `auth-source'. (tramp-set-connection-property diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 569922a9852..c079455a444 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -5263,193 +5263,194 @@ connection if a previous connection has died for some reason." ;; New connection must be opened. (condition-case err (unless (process-live-p p) - (with-tramp-progress-reporter - vec 3 - (if (tramp-string-empty-or-nil-p (tramp-file-name-user vec)) - (format "Opening connection %s for %s using %s" - process-name - (tramp-file-name-host vec) - (tramp-file-name-method vec)) - (format "Opening connection %s for %s@%s using %s" - process-name - (tramp-file-name-user vec) - (tramp-file-name-host vec) - (tramp-file-name-method vec))) - - (catch 'uname-changed - ;; Start new process. - (when (and p (processp p)) - (delete-process p)) - (setenv "TERM" tramp-terminal-type) - (setenv "LC_ALL" (tramp-get-local-locale vec)) - (if (stringp tramp-histfile-override) - (setenv "HISTFILE" tramp-histfile-override) - (if tramp-histfile-override - (progn - (setenv "HISTFILE") - (setenv "HISTFILESIZE" "0") - (setenv "HISTSIZE" "0")))) - (setenv "PROMPT_COMMAND") - (setenv "PS1" tramp-initial-end-of-output) - (unless (stringp tramp-encoding-shell) - (tramp-error vec 'file-error "`tramp-encoding-shell' not set")) - (let* ((current-host tramp-system-name) - (target-alist (tramp-compute-multi-hops vec)) - (previous-hop tramp-null-hop) - ;; We will apply `tramp-ssh-controlmaster-options' - ;; only for the first hop. - (options (tramp-ssh-controlmaster-options vec)) - (process-connection-type tramp-process-connection-type) - (process-adaptive-read-buffering nil) - ;; There are unfortunate settings for - ;; "cmdproxy" on W32 systems. - (process-coding-system-alist nil) - (coding-system-for-read nil) - (extra-args - (tramp-get-sh-extra-args tramp-encoding-shell)) - ;; This must be done in order to avoid our file - ;; name handler. - (p (let ((default-directory - tramp-compat-temporary-file-directory)) - (apply - #'start-process - (tramp-get-connection-name vec) - (tramp-get-connection-buffer vec) - (append - `(,tramp-encoding-shell) - (and extra-args (split-string extra-args)) - (and tramp-encoding-command-interactive - `(,tramp-encoding-command-interactive))))))) - - ;; This is needed for ssh or PuTTY based processes, - ;; and only if the respective options are set. - ;; Perhaps, the setting could be more fine-grained. - ;; (process-put p 'tramp-shared-socket t) - ;; Set sentinel. Initialize variables. - (set-process-sentinel p #'tramp-process-sentinel) - (tramp-post-process-creation p vec) - (setq tramp-current-connection (cons vec (current-time))) - - ;; Set connection-local variables. - (tramp-set-connection-local-variables vec) - - ;; Check whether process is alive. - (tramp-barf-if-no-shell-prompt - p 10 - "Couldn't find local shell prompt for %s" - tramp-encoding-shell) - - ;; Now do all the connections as specified. - (while target-alist - (let* ((hop (car target-alist)) - (l-method (tramp-file-name-method hop)) - (l-user (tramp-file-name-user hop)) - (l-domain (tramp-file-name-domain hop)) - (l-host (tramp-file-name-host hop)) - (l-port (tramp-file-name-port hop)) - (remote-shell - (tramp-get-method-parameter hop 'tramp-remote-shell)) - (extra-args (tramp-get-sh-extra-args remote-shell)) - (async-args - (flatten-tree - (tramp-get-method-parameter hop 'tramp-async-args))) - (connection-timeout - (tramp-get-method-parameter - hop 'tramp-connection-timeout - tramp-connection-timeout)) - (command - (tramp-get-method-parameter - hop 'tramp-login-program)) - ;; We don't create the temporary file. In - ;; fact, it is just a prefix for the - ;; ControlPath option of ssh; the real - ;; temporary file has another name, and it - ;; is created and protected by ssh. It is - ;; also removed by ssh when the connection - ;; is closed. The temporary file name is - ;; cached in the main connection process, - ;; therefore we cannot use - ;; `tramp-get-connection-process'. - (tmpfile - (with-tramp-connection-property - (tramp-get-process vec) "temp-file" - (tramp-compat-make-temp-name))) - r-shell) - - ;; Check, whether there is a restricted shell. - (dolist (elt tramp-restricted-shell-hosts-alist) - (when (string-match-p elt current-host) - (setq r-shell t))) - (setq current-host l-host) - - ;; Set password prompt vector. + (catch 'uname-changed + ;; Start new process. + (when (and p (processp p)) + (delete-process p)) + (setenv "TERM" tramp-terminal-type) + (setenv "LC_ALL" (tramp-get-local-locale vec)) + (if (stringp tramp-histfile-override) + (setenv "HISTFILE" tramp-histfile-override) + (if tramp-histfile-override + (progn + (setenv "HISTFILE") + (setenv "HISTFILESIZE" "0") + (setenv "HISTSIZE" "0")))) + (setenv "PROMPT_COMMAND") + (setenv "PS1" tramp-initial-end-of-output) + (unless (stringp tramp-encoding-shell) + (tramp-error vec 'file-error "`tramp-encoding-shell' not set")) + (let* ((current-host tramp-system-name) + (target-alist (tramp-compute-multi-hops vec)) + (previous-hop tramp-null-hop) + ;; We will apply `tramp-ssh-controlmaster-options' + ;; only for the first hop. + (options (tramp-ssh-controlmaster-options vec)) + (process-connection-type tramp-process-connection-type) + (process-adaptive-read-buffering nil) + ;; There are unfortunate settings for "cmdproxy" + ;; on W32 systems. + (process-coding-system-alist nil) + (coding-system-for-read nil) + (extra-args (tramp-get-sh-extra-args tramp-encoding-shell)) + ;; This must be done in order to avoid our file + ;; name handler. + (p (let ((default-directory + tramp-compat-temporary-file-directory)) + (apply + #'start-process + (tramp-get-connection-name vec) + (tramp-get-connection-buffer vec) + (append + `(,tramp-encoding-shell) + (and extra-args (split-string extra-args)) + (and tramp-encoding-command-interactive + `(,tramp-encoding-command-interactive))))))) + + ;; This is needed for ssh or PuTTY based processes, + ;; and only if the respective options are set. + ;; Perhaps, the setting could be more fine-grained. + ;; (process-put p 'tramp-shared-socket t) + ;; Set sentinel. Initialize variables. + (set-process-sentinel p #'tramp-process-sentinel) + (tramp-post-process-creation p vec) + (setq tramp-current-connection (cons vec (current-time))) + + ;; Set connection-local variables. + (tramp-set-connection-local-variables vec) + + ;; Check whether process is alive. + (tramp-barf-if-no-shell-prompt + p 10 + "Couldn't find local shell prompt for %s" + tramp-encoding-shell) + + ;; Now do all the connections as specified. + (while target-alist + (let* ((hop (car target-alist)) + (l-method (tramp-file-name-method hop)) + (l-user (tramp-file-name-user hop)) + (l-domain (tramp-file-name-domain hop)) + (l-host (tramp-file-name-host hop)) + (l-port (tramp-file-name-port hop)) + (remote-shell + (tramp-get-method-parameter hop 'tramp-remote-shell)) + (extra-args (tramp-get-sh-extra-args remote-shell)) + (async-args + (flatten-tree + (tramp-get-method-parameter hop 'tramp-async-args))) + (connection-timeout + (tramp-get-method-parameter + hop 'tramp-connection-timeout + tramp-connection-timeout)) + (command + (tramp-get-method-parameter + hop 'tramp-login-program)) + ;; We don't create the temporary file. In + ;; fact, it is just a prefix for the + ;; ControlPath option of ssh; the real + ;; temporary file has another name, and it is + ;; created and protected by ssh. It is also + ;; removed by ssh when the connection is + ;; closed. The temporary file name is cached + ;; in the main connection process, therefore + ;; we cannot use + ;; `tramp-get-connection-process'. + (tmpfile + (with-tramp-connection-property + (tramp-get-process vec) "temp-file" + (tramp-compat-make-temp-name))) + r-shell) + + ;; Check, whether there is a restricted shell. + (dolist (elt tramp-restricted-shell-hosts-alist) + (when (string-match-p elt current-host) + (setq r-shell t))) + (setq current-host l-host) + + ;; Set password prompt vector. + (tramp-set-connection-property + p "password-vector" + (if (tramp-get-method-parameter + hop 'tramp-password-previous-hop) + (let ((pv (copy-tramp-file-name previous-hop))) + (setf (tramp-file-name-method pv) l-method) + pv) + (make-tramp-file-name + :method l-method :user l-user :domain l-domain + :host l-host :port l-port))) + + ;; Set session timeout. + (when-let ((timeout + (tramp-get-method-parameter + hop 'tramp-session-timeout))) (tramp-set-connection-property - p "password-vector" - (if (tramp-get-method-parameter - hop 'tramp-password-previous-hop) - (let ((pv (copy-tramp-file-name previous-hop))) - (setf (tramp-file-name-method pv) l-method) - pv) - (make-tramp-file-name - :method l-method :user l-user :domain l-domain - :host l-host :port l-port))) - - ;; Set session timeout. - (when-let ((timeout - (tramp-get-method-parameter - hop 'tramp-session-timeout))) - (tramp-set-connection-property - p "session-timeout" timeout)) - - ;; Replace `login-args' place holders. - (setq - command - (string-join - (append - ;; We do not want to see the trailing local - ;; prompt in `start-file-process'. - (unless r-shell '("exec")) - `(,command) - ;; Add arguments for asynchronous processes. - (when process-name async-args) - (tramp-expand-args - hop 'tramp-login-args nil - ?h (or l-host "") ?u (or l-user "") ?p (or l-port "") - ?c (format-spec options (format-spec-make ?t tmpfile)) - ?n (concat - "2>" (tramp-get-remote-null-device previous-hop)) - ?l (concat remote-shell " " extra-args " -i")) - ;; A restricted shell does not allow "exec". - (when r-shell '("&&" "exit")) '("||" "exit")) - " ")) - - ;; Send the command. - (tramp-message vec 3 "Sending command `%s'" command) + p "session-timeout" timeout)) + + ;; Replace `login-args' place holders. + (setq + command + (string-join + (append + ;; We do not want to see the trailing local + ;; prompt in `start-file-process'. + (unless r-shell '("exec")) + `(,command) + ;; Add arguments for asynchronous processes. + (when process-name async-args) + (tramp-expand-args + hop 'tramp-login-args nil + ?h (or l-host "") ?u (or l-user "") ?p (or l-port "") + ?c (format-spec options (format-spec-make ?t tmpfile)) + ?n (concat + "2>" (tramp-get-remote-null-device previous-hop)) + ?l (concat remote-shell " " extra-args " -i")) + ;; A restricted shell does not allow "exec". + (when r-shell '("&&" "exit")) '("||" "exit")) + " ")) + + ;; Send the command. + (with-tramp-progress-reporter + vec 3 + (format "Opening connection%s for %s%s using %s" + (if (tramp-string-empty-or-nil-p process-name) + "" (concat " " process-name)) + (if (tramp-string-empty-or-nil-p l-user) + "" (concat l-user "@")) + l-host l-method) (tramp-send-command vec command t t) (tramp-process-actions p vec (min pos (with-current-buffer (process-buffer p) (point-max))) - tramp-actions-before-shell connection-timeout) - (tramp-message - vec 3 "Found remote shell prompt on `%s'" l-host) - - ;; Next hop. - (setq options "" - target-alist (cdr target-alist) - previous-hop hop))) - - ;; Activate session timeout. - (when (tramp-get-connection-property p "session-timeout") - (run-at-time - (tramp-get-connection-property p "session-timeout") nil - #'tramp-timeout-session vec)) - - ;; Make initial shell settings. - (tramp-open-connection-setup-interactive-shell p vec) - - ;; Mark it as connected. - (tramp-set-connection-property p "connected" t))))) + tramp-actions-before-shell connection-timeout)) + + ;; Next hop. + (setq options "" + target-alist (cdr target-alist) + previous-hop hop))) + + ;; Activate session timeout. + (when (tramp-get-connection-property p "session-timeout") + (run-at-time + (tramp-get-connection-property p "session-timeout") nil + #'tramp-timeout-session vec)) + + ;; Make initial shell settings. + (with-tramp-progress-reporter + vec 3 + (format "Setup connection%s for %s%s using %s" + (if (tramp-string-empty-or-nil-p process-name) + "" (concat " " process-name)) + (if (tramp-string-empty-or-nil-p + (tramp-file-name-user vec)) + "" (concat (tramp-file-name-user vec) "@")) + (tramp-file-name-host vec) + (tramp-file-name-method vec)) + (tramp-open-connection-setup-interactive-shell p vec)) + + ;; Mark it as connected. + (tramp-set-connection-property p "connected" t)))) ;; Cleanup, and propagate the signal. ((error quit) commit 9fbe9dc4c3e580c014d444986f2910cde6216b35 Author: Eli Zaretskii Date: Sat May 25 11:59:21 2024 +0300 ; Improve doc strings in textsec.el * lisp/international/textsec.el (textsec-email-address-suspicious-p) (textsec-email-address-header-suspicious-p, textsec-scripts) (textsec-single-script-p, textsec-covering-scripts) (textsec-restriction-level, textsec-mixed-numbers-p) (textsec-resolved-script-set) (textsec-single-script-confusable-p) (textsec-mixed-script-confusable-p) (textsec-whole-script-confusable-p) (textsec-local-address-suspicious-p) (textsec-bidi-controls-suspicious-p, textsec-name-suspicious-p) (textsec-suspicious-nonspacing-p): Doc fixes. diff --git a/lisp/international/textsec.el b/lisp/international/textsec.el index ce1f6c1d592..4740dd81345 100644 --- a/lisp/international/textsec.el +++ b/lisp/international/textsec.el @@ -44,15 +44,20 @@ (require 'uni-scripts)) (defun textsec-scripts (string) - "Return a list of Unicode scripts used in STRING. -The scripts returned by this function use the Unicode Script property -as defined by the Unicode Standard Annex 24 (UAX#24)." + "Return a list of Unicode scripts used by characters in STRING. +The return value is a list where for each character in STRING, +there is a list of script symbols for that character. Thus, each +script's symbol can appear more than once; use `textsec-covering-scripts' +to obtain a list in which each script appears at most once. +The script symbols returned by this function follow the Unicode Script +property of characters as defined by the Unicode Standard Annex 24 (UAX#24). +See the Unicode UCD file Scripts.txt for the scripts defined by Unicode." (seq-map (lambda (char) (elt textsec--char-scripts char)) string)) (defun textsec-single-script-p (string) - "Return non-nil if STRING is all in a single Unicode script. + "Return non-nil if STRING's characters belong to a single Unicode script. Note that the concept of \"single script\" used by this function isn't obvious -- some mixtures of scripts count as a \"single @@ -60,8 +65,8 @@ script\". See https://www.unicode.org/reports/tr39/#Mixed_Script_Detection -for details. The Unicode scripts are as defined by the -Unicode Standard Annex 24 (UAX#24)." +for details. The Unicode script property of a characters is defined by +the Unicode Standard Annex 24 (UAX#24)." (let ((scripts (mapcar (lambda (s) (append s @@ -98,9 +103,11 @@ Unicode Standard Annex 24 (UAX#24)." '(korea)))) (defun textsec-covering-scripts (string) - "Return a minimal list of scripts used in STRING. + "Return a minimal list of scripts used by characters in STRING. Note that a string may have several different minimal cover sets. -The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." +The return value is a list of script symbols. +The script property of characters is defined by the Unicode Standard +Annex 24 (UAX#24)." (let* ((scripts (textsec-scripts string)) (set (car scripts))) (dolist (s scripts) @@ -108,7 +115,8 @@ The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." (sort (delq 'common (delq 'inherited set)) #'string<))) (defun textsec-restriction-level (string) - "Say what restriction level STRING qualifies for. + "Return the restriction level for which STRING qualifies. +The return value is a symbol. Levels are (in decreasing order of restrictiveness) `ascii-only', `single-script', `highly-restrictive', `moderately-restrictive', `minimally-restrictive' and `unrestricted'." @@ -163,7 +171,14 @@ Levels are (in decreasing order of restrictiveness) `ascii-only', 'unrestricted)))) (defun textsec-mixed-numbers-p (string) - "Return non-nil if STRING includes numbers from different decimal systems." + "Return non-nil if STRING includes numbers from different decimal systems. + +This function examines only characters in STRING whose Unicode general +category, as reported by `get-char-code-property' with its second +argument \\='general-category, is Decimal_Numbers (Nd). It returns +non-nil if it finds numerical characters from different numerical +systems. For example, ASCII digit characters and ARABIC-INDIC DIGIT +characters belong to different decimal systems." (> (length (seq-uniq @@ -199,15 +214,20 @@ This algorithm is described in: (defun textsec-resolved-script-set (string) "Return the resolved script set for STRING. -This is the minimal covering script set for STRING, but is nil is -STRING isn't a single script string. -The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." +The value is a list whose members are symbols of the minimal covering +script set for STRING; the value is nil if STRING isn't a single-script +string. +The script property of characters is defined by the Unicode Standard +Annex 24 (UAX#24)." (and (textsec-single-script-p string) (textsec-covering-scripts string))) (defun textsec-single-script-confusable-p (string1 string2) "Say whether STRING1 and STRING2 are single-script confusables. -The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." +Two strings are said to be confusables if they might look very +similarly on display. +The script property of characters is defined by the Unicode Standard +Annex 24 (UAX#24)." (and (equal (textsec-unconfuse-string string1) (textsec-unconfuse-string string2)) ;; And they have to have at least one resolved script in @@ -217,7 +237,10 @@ The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." (defun textsec-mixed-script-confusable-p (string1 string2) "Say whether STRING1 and STRING2 are mixed-script confusables. -The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." +Two strings are said to be confusables if they might look very +similarly on display. +The script property of characters is defined by the Unicode Standard +Annex 24 (UAX#24)." (and (equal (textsec-unconfuse-string string1) (textsec-unconfuse-string string2)) ;; And they have no resolved scripts in common. @@ -225,8 +248,11 @@ The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." (textsec-resolved-script-set string2))))) (defun textsec-whole-script-confusable-p (string1 string2) - "Say whether STRING1 and STRING2 are whole-script confusables. -The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)." + "Say whether two single-script strings STRING1 and STRING2 are confusables. +Two strings are said to be confusables if they might look very +similarly on display. +The script property of characters is defined by the Unicode Standard +Annex 24 (UAX#24)." (and (textsec-mixed-script-confusable-p string1 string2) (textsec-single-script-p string1) (textsec-single-script-p string2))) @@ -287,7 +313,7 @@ or use certain other unusual mixtures of characters." (defun textsec-local-address-suspicious-p (local) "Say whether LOCAL part of an email address looks suspicious. -LOCAL is the bit before \"@\" in an email address. +LOCAL is the part before \"@\" in an email address, a string. If it isn't suspicious, return nil. If it is, return a string explaining the potential problem. @@ -307,7 +333,7 @@ certain other unusual mixtures of characters." (format "`%s' contains invalid dots" local)))) (defun textsec-bidi-controls-suspicious-p (string) - "Return non-nil of STRING uses bidi controls in suspicious ways. + "Return non-nil of STRING uses bidirectional controls in suspicious ways. If STRING doesn't include any suspicious uses of bidirectional formatting control characters, return nil. Otherwise, return the index of the first character in STRING affected by such suspicious @@ -315,8 +341,8 @@ use of bidi controls. If the returned value is beyond the length of STRING, it means any text following STRING on display might be affected by bidi controls in STRING." (with-temp-buffer - ;; We add a string that's representative of some text that could - ;; follow STRING, with the purpose of detecting residual bidi + ;; We follow STRING with text that's representative of some text + ;; that could follow it, with the purpose of detecting residual bidi ;; state at end of STRING which could then affect the following ;; text. (insert string "a1א:!") @@ -327,8 +353,8 @@ affected by bidi controls in STRING." (defun textsec-name-suspicious-p (name) "Say whether NAME looks suspicious. -NAME is (for instance) the free-text display name part of an -email address. +NAME is a string, for instance, the free-text display name part +of an email address. If it isn't suspicious, return nil. If it is, return a string explaining the potential problem. @@ -360,6 +386,10 @@ other unusual mixtures of characters." If it doesn't, return nil. If it does, return a string explaining the potential problem. +Nonspacing characters are those whose general Unicode category is +Mn (nonspacing mark) or Me (enclosing mark). Examples include +diacritics and accents. + Use of nonspacing characters is considered suspicious if there are two or more consecutive identical nonspacing characters, or too many consecutive nonspacing characters." @@ -385,10 +415,11 @@ consecutive nonspacing characters." nil))) (defun textsec-email-address-suspicious-p (address) - "Say whether EMAIL address looks suspicious. + "Say whether email ADDRESS looks suspicious. If it isn't, return nil. If it is, return a string explaining the potential problem. +ADDRESS should be a string that specifies an email address. An email address is considered suspicious if either of its two parts -- the local address name or the domain -- are found to be suspicious by, respectively, `textsec-local-address-suspicious-p' @@ -399,7 +430,7 @@ and `textsec-domain-suspicious-p'." (textsec-local-address-suspicious-p local)))) (defun textsec-email-address-header-suspicious-p (email) - "Say whether EMAIL looks suspicious. + "Say whether EMAIL address specification looks suspicious. If it isn't, return nil. If it is, return a string explaining the potential problem. commit 5f3f461cd0c76b1b171bb9eda3db1f561bc22b80 Author: Eli Zaretskii Date: Sat May 25 10:33:07 2024 +0300 Avoid rare errors in dabbrev.el * lisp/dabbrev.el (dabbrev-expand, dabbrev--find-expansion): Make sure 'dabbrev--last-buffer' is a live buffer before using its value. (Bug#70824) diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 853c0f4b290..7b6cbb78cef 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el @@ -495,7 +495,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (save-excursion (save-restriction (widen) - (if dabbrev--last-buffer + (if (buffer-live-p dabbrev--last-buffer) (set-buffer dabbrev--last-buffer)) ;; Find the end of the last "expansion" word. (if (or (eq dabbrev--last-direction 1) @@ -557,7 +557,8 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (setq dabbrev--last-buffer-found dabbrev--last-buffer)) (message nil)) (if (and (or (eq (current-buffer) dabbrev--last-buffer) - (null dabbrev--last-buffer)) + (null dabbrev--last-buffer) + (buffer-live-p dabbrev--last-buffer)) (numberp dabbrev--last-expansion-location) (and (> dabbrev--last-expansion-location (point)))) (setq dabbrev--last-expansion-location @@ -731,7 +732,7 @@ of the start of the occurrence." (save-excursion ;; If we were scanning something other than the current buffer, ;; continue scanning there. - (when dabbrev--last-buffer + (when (buffer-live-p dabbrev--last-buffer) (set-buffer dabbrev--last-buffer)) (or ;; ------------------------------------------ @@ -748,7 +749,7 @@ of the start of the occurrence." ;; or whatever buffer we were last scanning. ;; ------------------------------------------ (and (or (not dabbrev-search-these-buffers-only) - dabbrev--last-buffer) + (buffer-live-p dabbrev--last-buffer)) (<= direction 0) (setq dabbrev--last-direction -1) (dabbrev--try-find abbrev nil @@ -760,7 +761,7 @@ of the start of the occurrence." ;; ------------------------------------------ (progn (setq dabbrev--last-direction -1) - (unless dabbrev--last-buffer + (unless (buffer-live-p dabbrev--last-buffer) ;; If we have just now begun to search other buffers, ;; determine which other buffers we should check. ;; Put that list in dabbrev--friend-buffer-list. commit 3647645e94856344696768bef590b49a24c7ac52 Author: kobarity Date: Fri May 24 22:50:12 2024 +0900 Fix Python font lock of chained assignment statement * lisp/progmodes/python.el (python-font-lock-keywords-maximum-decoration): Allow chaining of single assignment statements. * test/lisp/progmodes/python-tests.el (python-font-lock-assignment-statement-20): New test. (Bug#71093) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 02588d756e9..051f198e192 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -812,8 +812,7 @@ sign in chained assignment." ;; c: Collection = {1, 2, 3} ;; d: Mapping[int, str] = {1: 'bar', 2: 'baz'} (,(python-font-lock-assignment-matcher - (python-rx (or line-start ?\;) (* space) - grouped-assignment-target (* space) + (python-rx grouped-assignment-target (* space) (? ?: (* space) (+ not-simple-operator) (* space)) (group assignment-operator))) (1 font-lock-variable-name-face) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 95db93dd5cc..06943e22f5b 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -474,6 +474,16 @@ def f(x: CustomInt) -> CustomInt: (136 . font-lock-operator-face) (137) (144 . font-lock-keyword-face) (150)))) +(ert-deftest python-font-lock-assignment-statement-20 () + (python-tests-assert-faces + "a = b = c = 1" + '((1 . font-lock-variable-name-face) (2) + (3 . font-lock-operator-face) (4) + (5 . font-lock-variable-name-face) (6) + (7 . font-lock-operator-face) (8) + (9 . font-lock-variable-name-face) (10) + (11 . font-lock-operator-face) (12)))) + (ert-deftest python-font-lock-escape-sequence-string-newline () (python-tests-assert-faces "'\\n' commit 3291dea441f25ca14619bebe493ffb694f53cf9d Author: Brad Knotwell Date: Fri May 24 00:00:37 2024 -0700 Fix example in Calc manual * doc/misc/calc.texi (Defining Simple Commands): Fix typo in command names. (Bug#71166) Copyright-paperwork-exempt: yes diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi index 75f88efe259..47c34a7e39b 100644 --- a/doc/misc/calc.texi +++ b/doc/misc/calc.texi @@ -32480,9 +32480,9 @@ decreases the precision. (put 'calc-define 'inc-prec '(progn (define-key calc-mode-map (format "Y%sI" inc-prec-base-key) - 'increase-precision) + 'calc-increase-precision) (define-key calc-mode-map (format "Y%sD" inc-prec-base-key) - 'decrease-precision) + 'calc-decrease-precision) (setq calc-Y-help-msgs (cons (format "%s + Inc-prec, Dec-prec" inc-prec-base-key) commit 350ae75f5c1c47a03560e43e8699781c04c9078a Author: Eli Zaretskii Date: Wed May 22 14:10:53 2024 +0300 Avoid crashes on MS-Windows due to invalid UNC file names * src/w32.c (parse_root): Avoid crashes due to invalid (too short) UNC names, such as "\\". (Bug#70914) * test/src/fileio-tests.el (fileio-tests-invalid-UNC): New test. diff --git a/src/w32.c b/src/w32.c index d463962b6c3..a78d5569fe6 100644 --- a/src/w32.c +++ b/src/w32.c @@ -2572,7 +2572,7 @@ parse_root (const char * name, const char ** pPath) name += 2; do { - if (IS_DIRECTORY_SEP (*name) && --slashes == 0) + if (!*name || (IS_DIRECTORY_SEP (*name) && --slashes == 0)) break; name++; } diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index 764ae662e15..136d3813a2b 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -218,4 +218,10 @@ Also check that an encoding error can appear in a symlink." (should (equal (expand-file-name file nil) file)) (file-name-case-insensitive-p file))) +(ert-deftest fileio-tests-invalid-UNC () + (skip-unless (eq system-type 'windows-nt)) + ;; These should not crash, see bug#70914. + (should-not (file-exists-p "//")) + (should (file-attributes "//"))) + ;;; fileio-tests.el ends here commit ccf8dba44a3071d56e54a20276e00a6cdcc4b135 Author: Eli Zaretskii Date: Tue May 21 15:40:51 2024 +0300 ; * lisp/face-remap.el (text-scale-adjust): Doc fix. diff --git a/lisp/face-remap.el b/lisp/face-remap.el index d269d85301c..b9fdad2be17 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -387,9 +387,10 @@ this are the `default' and `header-line' faces: they will both be scaled even if they have an explicit `:height' setting. See also the related command `global-text-scale-adjust'. Unlike -that command, which scales the font size with a increment, -`text-scale-adjust' scales the font size with a factor, -`text-scale-mode-step'. With a small `text-scale-mode-step' +that command, which scales the font size with a increment (and can +also optionally resize frames to keep the same number of lines and +characters per line), `text-scale-adjust' scales the font size with +a factor, `text-scale-mode-step'. With a small `text-scale-mode-step' factor, the two commands behave similarly." (interactive "p") (let ((ev last-command-event) commit 5ab144c77cda1d56f0dd62606c316c712a0d2563 Author: Eli Zaretskii Date: Tue May 21 15:34:50 2024 +0300 ; Improve documentation of backing up files * doc/emacs/files.texi (Backup Copying): Mention that 'backup-by-copying' is safer. Document 'file-precious-flag'. (Bug#71074) diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 393c4728422..01d22564f2e 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -786,6 +786,14 @@ those previous versions. If you want to be able to do that with files hosted by those services when editing them with Emacs, customize @code{backup-by-copying} to a non-@code{nil} value. +@vindex file-precious-flag + Copying the old file for backup is also useful when editing precious +files, because it makes sure the old file keeps its name if something +fails between the backup and the saving of your edits. Alternatively, +you can customize @code{file-precious-flag} to a non-@code{nil} value, +which implies backups by copying and also protects against I/O errors +while saving your edits. + @node Customize Save @subsection Customizing Saving of Files