commit e650a04dc415467806b77d4b3801f9e6eeb9dfaf (HEAD, refs/remotes/origin/master) Author: Andrea Corallo Date: Fri May 24 08:37:41 2024 +0200 * src/comp.c (check_comp_unit_relocs): Remove unneccesary double access. diff --git a/src/comp.c b/src/comp.c index e8945df63ff..545a8046377 100644 --- a/src/comp.c +++ b/src/comp.c @@ -5302,7 +5302,7 @@ check_comp_unit_relocs (struct Lisp_Native_Comp_Unit *comp_u) if (NILP (Fgethash (x, comp_u->lambda_gc_guard_h, Qnil))) return false; } - else if (!EQ (data_imp_relocs[i], AREF (comp_u->data_impure_vec, i))) + else if (!EQ (x, AREF (comp_u->data_impure_vec, i))) return false; } return true; commit 9d3fb195af40f26a3751c368af55677667af3eba Author: Eshel Yaron Date: Thu May 23 21:59:38 2024 +0200 Fix argument name highlighting in 'describe-function' output This fixes a regression introduced in dd38097f0b9458eea882043fa06b27248e505b22, which prevented proper argument name highlighting in function docstrings in the output buffer of 'describe-function'. * lisp/help-fns.el (help-do-arg-highlight): New optional arg that says if we're highlighting arguments in the usage string or in the docstring. Tweak generated regex to only expect argument name to be preceded by function name in usage string. (help-highlight-arguments): Use new argument for usage string. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 182b22549b5..a202c2d247e 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -362,14 +362,17 @@ if the variable `help-downcase-arguments' is non-nil." (propertize (if help-downcase-arguments (downcase arg) arg) 'face 'help-argument-name)) -(defun help-do-arg-highlight (doc args) +(defun help-do-arg-highlight (doc args &optional usage-p) (with-syntax-table (make-syntax-table emacs-lisp-mode-syntax-table) (modify-syntax-entry ?\- "w") (dolist (arg args) (setq doc (replace-regexp-in-string ;; This is heuristic, but covers all common cases ;; except ARG1-ARG2 - (concat "([^ ]+ .*" ; skip function name + (concat (when usage-p + ;; Skip function name in usage string + ;; (Bug#65580). + "([^ ]+ .*") "\\<" ; beginning of word "\\(?:[a-z-]*-\\)?" ; for xxx-ARG "\\(" @@ -404,7 +407,7 @@ if the variable `help-downcase-arguments' is non-nil." (search-backward "(") (goto-char (scan-sexps (point) 1))))) ;; Highlight arguments in the USAGE string - (setq usage (help-do-arg-highlight (buffer-string) args)) + (setq usage (help-do-arg-highlight (buffer-string) args t)) ;; Highlight arguments in the DOC string (setq doc (and doc (help-do-arg-highlight doc args)))))) ;; Return value is like the one from help-split-fundoc, but highlighted commit 52acabcbe8eeb688640e18884ba8a15635ca7062 Author: Eshel Yaron Date: Thu May 23 15:02:05 2024 +0200 Fix 'help-view-source' for variables defined in C This fixes an issue that Juri Linkov mentioned in Bug#71117. * lisp/help-mode.el (help-function-def--button-function): When searching for the definition of a variable, make sure to call 'help-C-file-name' with KIND argument set to 'var'. diff --git a/lisp/help-mode.el b/lisp/help-mode.el index 48433d899ab..e16408be7b0 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -265,7 +265,9 @@ The format is (FUNCTION ARGS...).") (require 'find-func) (when (eq file 'C-source) (setq file - (help-C-file-name (indirect-function fun) 'fun))) + (if (memq type '(variable defvar)) + (help-C-file-name fun 'var) + (help-C-file-name (indirect-function fun) 'fun)))) ;; Don't use find-function-noselect because it follows ;; aliases (which fails for built-in functions). (let* ((location commit e1789f66ac9ada9344fb22b2a191d61216f95459 Author: Eli Zaretskii Date: Thu May 23 21:14:13 2024 +0300 Improve Dired context menu * lisp/dired.el (dired-context-menu): Add 'w32-shell-execute' menu item on MS-Windows. Improve help-echo. diff --git a/lisp/dired.el b/lisp/dired.el index 28ec187e666..21085de97f2 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2642,7 +2642,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." :help "Edit file at mouse click in other window"] ,@(when shell-command-guess-open '(["Open" dired-do-open - :help "Open externally"])) + :help "Open this file with the default application"])) ,@(when commands (list (cons "Open With" (append @@ -2653,7 +2653,13 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." (interactive) (dired-do-async-shell-command ,command nil (list ,filename)))]) - commands))))))) + commands))))) + ,@(when (eq system-type 'windows-nt) + `(["Select system app" + (lambda () + (interactive) + (w32-shell-execute "openas" ,filename)) + :help "Choose one of the apps available on your system"])))) (dolist (item (reverse (lookup-key easy-menu [menu-bar immediate]))) (when (consp item) (define-key menu (vector (car item)) (cdr item)))))) commit b53a20c61d30d4bef43f069b795b8c79bbaf091a Author: Eli Zaretskii Date: Thu May 23 16:23:57 2024 +0300 Documentation followup for last change * etc/NEWS: Announce the change in 'key-translate'. * doc/lispref/commands.texi (Event Mod): Update documentation of 'key-translate'. (Bug#70139) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index e743038a778..3425281febd 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -3738,8 +3738,11 @@ if you want to translate characters after input methods operate. @defun key-translate from to This function modifies @code{keyboard-translate-table} to translate -character code @var{from} into character code @var{to}. It creates -the keyboard translate table if necessary. +character code @var{from} into character code @var{to}. It creates the +keyboard translate table if necessary. Both @var{from} and @var{to} +should be strings that satisfy @code{key-valid-p} (@pxref{Key +Sequences}). If @var{to} is @code{nil}, the function removes any +existing translation for @var{from}. @end defun Here's an example of using the @code{keyboard-translate-table} to diff --git a/etc/NEWS b/etc/NEWS index 53119307f82..a79a5844a22 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2233,6 +2233,11 @@ rather than signaling an error. It is bound to the key sequence that caused a call to a function bound within 'function-key-map' or 'input-decode-map' around those calls. ++++ +** The function 'key-translate' can now remove translations. +If the second argument TO is nil, the existing key translation is +removed. + +++ ** New variables describing the names of built in programs. The new variables 'ctags-program-name', 'ebrowse-program-name', commit 8f010e9a2926bd3886c54a0360ff341bc66f8088 Author: Charalampos Mitrodimas Date: Tue Apr 2 19:02:46 2024 +0000 Improve 'key-translate' to support removing translations This patch enhances the key-translate function to allow removing keyboard translations by passing nil as the second argument (TO). If TO is nil, any existing translation for the FROM key will be removed. The compiler macro is updated to only check TO when it is non-nil. This change makes key-translate more consistent with the behavior of 'keyboard-translate', providing a way to remove translations without having to specify the same key for both FROM and TO. The documentation string is updated to reflect the new behavior. * lisp/keymap.el (key-translate): Support removing translations by passing nil as the second argument (TO). Also signal an error if multiple items are passed. (Bug#70139) diff --git a/lisp/keymap.el b/lisp/keymap.el index cbd26f1060e..737c11dbd83 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -379,20 +379,35 @@ which is (defun key-translate (from to) "Translate character FROM to TO on the current terminal. + This function creates a `keyboard-translate-table' if necessary and then modifies one entry in it. -Both FROM and TO should be specified by strings that satisfy `key-valid-p'." +Both FROM and TO should be specified by strings that satisfy `key-valid-p'. +If TO is nil, remove any existing translation for FROM." (declare (compiler-macro (lambda (form) (keymap--compile-check from to) form))) (keymap--check from) - (keymap--check to) - (or (char-table-p keyboard-translate-table) - (setq keyboard-translate-table - (make-char-table 'keyboard-translate-table nil))) - (aset keyboard-translate-table - (aref (key-parse from) 0) - (aref (key-parse to) 0))) + (when to + (keymap--check to)) + (let ((from-key (key-parse from)) + (to-key (and to (key-parse to)))) + (cond + ((= (length from-key) 0) + (error "FROM key is empty")) + ((> (length from-key) 1) + (error "FROM key %s is not a single key" from))) + (cond + ((and to (= (length to-key) 0)) + (error "TO key is empty")) + ((and to (> (length to-key) 1)) + (error "TO key %s is not a single key" to))) + (or (char-table-p keyboard-translate-table) + (setq keyboard-translate-table + (make-char-table 'keyboard-translate-table nil))) + (aset keyboard-translate-table + (aref from-key 0) + (and to (aref to-key 0))))) (defun keymap-lookup (keymap key &optional accept-default no-remap position) "Return the binding for command KEY in KEYMAP. commit a2ca5d01989cbe8d43f7763aa5ac374b49980c39 Author: Lin Sun Date: Fri May 3 06:52:22 2024 +0000 Enhance python-tests to adapt different Python interpreters (bug#70815) * test/lisp/progmodes/python-tests.el (python-tests-get-shell-interpreter): New function to get Python interpreter for testing; and also introduce new env variable EMACS_PYTHON_INTERPRETER to support customer Python interpreter. Co-authored-by: kobarity diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 2960cca2c06..b19c5c31f16 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -21,6 +21,7 @@ ;;; Code: +(require 'cl-extra) (require 'ert) (require 'ert-x) (require 'python) @@ -58,7 +59,8 @@ turned off. Shell buffer will be killed on exit." (let ((dir (make-symbol "dir"))) `(with-temp-buffer (let ((python-indent-guess-indent-offset nil) - (python-shell-completion-native-enable nil)) + (python-shell-completion-native-enable nil) + (python-shell-interpreter (python-tests-get-shell-interpreter))) (python-mode) (unwind-protect ;; Prevent test failures when Jedi is used as a completion @@ -3738,7 +3740,19 @@ if x: ;;; Shell integration -(defvar python-tests-shell-interpreter "python") +(defvar python-tests-shell-interpreter nil) + +(defun python-tests-get-shell-interpreter () + "Get the shell interpreter. +If env string EMACS_PYTHON_INTERPRETER exists, use it as preferred one." + (if python-tests-shell-interpreter + python-tests-shell-interpreter + (setq python-tests-shell-interpreter + (or (when-let ((interpreter (getenv "EMACS_PYTHON_INTERPRETER"))) + (or (executable-find interpreter) + (error "Couldn't find EMACS_PYTHON_INTERPRETER(%s) in path" + interpreter))) + (cl-some #'executable-find '("python" "python3" "python2")))))) (ert-deftest python-shell-get-process-name-1 () "Check process name calculation sans `buffer-file-name'." @@ -4000,13 +4014,13 @@ if x: (ert-deftest python-shell-make-comint-1 () "Check comint creation for global shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) ;; The interpreter can get killed too quickly to allow it to clean ;; up the tempfiles that the default python-shell-setup-codes create, ;; so it leaves tempfiles behind, which is a minor irritation. (let* ((python-shell-setup-codes nil) (python-shell-interpreter - (executable-find python-tests-shell-interpreter)) + (python-tests-get-shell-interpreter)) (proc-name (python-shell-get-process-name nil)) (shell-buffer (python-tests-with-temp-buffer @@ -4024,10 +4038,10 @@ if x: (ert-deftest python-shell-make-comint-2 () "Check comint creation for internal shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((python-shell-setup-codes nil) (python-shell-interpreter - (executable-find python-tests-shell-interpreter)) + (python-tests-get-shell-interpreter)) (proc-name (python-shell-internal-get-process-name)) (shell-buffer (python-tests-with-temp-buffer @@ -4048,13 +4062,13 @@ if x: The command passed to `python-shell-make-comint' as argument must locally override global values set in `python-shell-interpreter' and `python-shell-interpreter-args' in the new shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((python-shell-setup-codes nil) (python-shell-interpreter "interpreter") (python-shell-interpreter-args "--some-args") (proc-name (python-shell-get-process-name nil)) (interpreter-override - (concat (executable-find python-tests-shell-interpreter) " " "-i")) + (concat (python-tests-get-shell-interpreter) " " "-i")) (shell-buffer (python-tests-with-temp-buffer "" (python-shell-make-comint interpreter-override proc-name nil))) @@ -4067,17 +4081,17 @@ and `python-shell-interpreter-args' in the new shell buffer." (should (eq major-mode 'inferior-python-mode)) (should (file-equal-p python-shell-interpreter - (executable-find python-tests-shell-interpreter))) + (python-tests-get-shell-interpreter))) (should (string= python-shell-interpreter-args "-i")))) (kill-buffer shell-buffer)))) (ert-deftest python-shell-make-comint-4 () "Check shell calculated prompts regexps are set." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((process-environment process-environment) (python-shell-setup-codes nil) (python-shell-interpreter - (executable-find python-tests-shell-interpreter)) + (python-tests-get-shell-interpreter)) (python-shell-interpreter-args "-i") (python-shell--prompt-calculated-input-regexp nil) (python-shell--prompt-calculated-output-regexp nil) @@ -4119,12 +4133,12 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-get-process-1 () "Check dedicated shell process preference over global." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-file "" (let* ((python-shell-setup-codes nil) (python-shell-interpreter - (executable-find python-tests-shell-interpreter)) + (python-tests-get-shell-interpreter)) (global-proc-name (python-shell-get-process-name nil)) (dedicated-proc-name (python-shell-get-process-name t)) (global-shell-buffer @@ -4152,12 +4166,12 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-internal-get-or-create-process-1 () "Check internal shell process creation fallback." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-file "" (should (not (process-live-p (python-shell-internal-get-process-name)))) (let* ((python-shell-interpreter - (executable-find python-tests-shell-interpreter)) + (python-tests-get-shell-interpreter)) (internal-process-name (python-shell-internal-get-process-name)) (internal-process (python-shell-internal-get-or-create-process)) (internal-shell-buffer (process-buffer internal-process))) @@ -4175,8 +4189,9 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-detect-1 () "Check prompt autodetection." - (skip-unless (executable-find python-tests-shell-interpreter)) - (let ((process-environment process-environment)) + (skip-unless (python-tests-get-shell-interpreter)) + (let ((process-environment process-environment) + (python-shell-interpreter (python-tests-get-shell-interpreter))) ;; Ensure no startup file is enabled (setenv "PYTHONSTARTUP" "") (should python-shell-prompt-detect-enabled) @@ -4184,8 +4199,9 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-detect-2 () "Check prompt autodetection with startup file. Bug#17370." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((process-environment process-environment) + (python-shell-interpreter (python-tests-get-shell-interpreter)) (startup-code (concat "import sys\n" "sys.ps1 = 'py> '\n" "sys.ps2 = '..> '\n" @@ -4201,7 +4217,7 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-detect-3 () "Check prompts are not autodetected when feature is disabled." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let ((process-environment process-environment) (python-shell-prompt-detect-enabled nil)) ;; Ensure no startup file is enabled @@ -4210,7 +4226,7 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-detect-4 () "Check warning is shown when detection fails." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((process-environment process-environment) ;; Trigger failure by removing prompts in the startup file (startup-code (concat "import sys\n" @@ -4231,7 +4247,7 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-detect-5 () "Check disabled warnings are not shown when detection fails." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((process-environment process-environment) (startup-code (concat "import sys\n" "sys.ps1 = ''\n" @@ -4252,7 +4268,7 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-detect-6 () "Warnings are not shown when detection is disabled." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((process-environment process-environment) (startup-code (concat "import sys\n" "sys.ps1 = ''\n" @@ -4416,7 +4432,7 @@ and `python-shell-interpreter-args' in the new shell buffer." (ert-deftest python-shell-prompt-set-calculated-regexps-6 () "Check detected prompts are included `regexp-quote'd." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (let* ((python-shell-prompt-input-regexps '("")) (python-shell-prompt-output-regexps '("")) (python-shell-prompt-regexp "") @@ -4426,6 +4442,7 @@ and `python-shell-interpreter-args' in the new shell buffer." (python-shell--prompt-calculated-input-regexp nil) (python-shell--prompt-calculated-output-regexp nil) (python-shell-prompt-detect-enabled t) + (python-shell-interpreter (python-tests-get-shell-interpreter)) (process-environment process-environment) (startup-code (concat "import sys\n" "sys.ps1 = 'p.> '\n" @@ -4799,7 +4816,7 @@ def foo(): (should (python-shell-completion-native-interpreter-disabled-p)))) (ert-deftest python-shell-completion-at-point-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell "" (python-shell-with-shell-buffer @@ -4813,7 +4830,7 @@ def foo(): (should-not (nth 2 (python-shell-completion-at-point)))))) (ert-deftest python-shell-completion-at-point-native-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell "" (python-shell-completion-native-turn-on) @@ -4892,14 +4909,14 @@ def foo(): "Return Jedi readline setup file if PYTHONSTARTUP is not set." (or (getenv "PYTHONSTARTUP") (with-temp-buffer - (if (eql 0 (call-process python-tests-shell-interpreter + (if (eql 0 (call-process (python-tests-get-shell-interpreter) nil t nil "-m" "jedi" "repl")) (string-trim (buffer-string)) "")))) (ert-deftest python-shell-completion-at-point-jedi-completer () "Check if Python shell completion works when Jedi completer is used." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (with-environment-variables (("PYTHONSTARTUP" (python-tests--pythonstartup-file))) (python-tests-with-temp-buffer-with-shell @@ -4944,7 +4961,7 @@ def foo(): ;;; Symbol completion (ert-deftest python-completion-at-point-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -4962,7 +4979,7 @@ import abc (ert-deftest python-completion-at-point-2 () "Should work regardless of the point in the Shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -4980,7 +4997,7 @@ import abc (ert-deftest python-completion-at-point-pdb-1 () "Should not complete PDB commands in Python buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import pdb @@ -4999,7 +5016,7 @@ print('Hello') (ert-deftest python-completion-at-point-while-running-1 () "Should not try to complete when a program is running in the Shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import time @@ -5015,7 +5032,7 @@ time.sleep(3) (should-not (with-timeout (1 t) (completion-at-point)))))) (ert-deftest python-completion-at-point-native-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -5034,7 +5051,7 @@ import abc (ert-deftest python-completion-at-point-native-2 () "Should work regardless of the point in the Shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -5052,7 +5069,7 @@ import abc (should (completion-at-point))))) (ert-deftest python-completion-at-point-native-with-ffap-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -5070,7 +5087,7 @@ import abc (should (completion-at-point))))) (ert-deftest python-completion-at-point-native-with-eldoc-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -5097,7 +5114,7 @@ import abc ;;; FFAP (ert-deftest python-ffap-module-path-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -5109,7 +5126,7 @@ import abc (ert-deftest python-ffap-module-path-while-running-1 () "Should not get module path when a program is running in the Shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import abc @@ -5185,7 +5202,7 @@ some_symbol some_other_symbol "some_symbol")))) (ert-deftest python-eldoc--get-doc-at-point-1 () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import time @@ -5198,7 +5215,7 @@ import time (ert-deftest python-eldoc--get-doc-at-point-while-running-1 () "Should not get documentation when a program is running in the Shell buffer." - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell " import time @@ -7416,8 +7433,9 @@ buffer with overlapping strings." ;; interpreter. (ert-deftest python-tests--run-python-selects-window () "Test for bug#31398. See also bug#44421 and bug#52380." - (skip-unless (executable-find python-tests-shell-interpreter)) - (let* ((buffer (process-buffer (run-python nil nil 'show))) + (skip-unless (python-tests-get-shell-interpreter)) + (let* ((python-shell-interpreter (python-tests-get-shell-interpreter)) + (buffer (process-buffer (run-python nil nil 'show))) (window (get-buffer-window buffer))) ;; We look at `selected-window' rather than `current-buffer' ;; because as `(elisp)Current buffer' says, the latter will only @@ -7487,7 +7505,7 @@ buffer with overlapping strings." "W0611: Unused import a.b.c (unused-import)")))))) (ert-deftest python-test--shell-send-block () - (skip-unless (executable-find python-tests-shell-interpreter)) + (skip-unless (python-tests-get-shell-interpreter)) (python-tests-with-temp-buffer-with-shell "print('current 0') for x in range(1,3): commit f75fec5cacce47c9714f10592d75c8fb9c63999d Author: Eli Zaretskii Date: Thu May 23 12:51:19 2024 +0300 Fix uncompressing a .tar.gz archive whose files have no leading dir * lisp/dired-aux.el (dired-compress): Handle the case when NEW-FILE is not produced in the current directory by uncompressing a compressed file. (Bug#47058) diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 22c6881ae35..d1d5ed9b144 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1522,14 +1522,23 @@ A FMT of \"\" will suppress the messaging." ;; Remove any preexisting entry for the name NEW-FILE. (ignore-errors (dired-remove-entry new-file)) (goto-char start) - ;; Now replace the current line with an entry for NEW-FILE. - ;; But don't remove the current line if either FROM-FILE or - ;; NEW-FILE is a directory, because compressing/uncompressing - ;; directories doesn't remove the original. - (if (or (file-directory-p from-file) - (file-directory-p new-file)) - (dired-add-entry new-file nil t) - (dired-update-file-line new-file)) + ;; Now replace the current line with an entry for NEW-FILE, + ;; if it exists. But don't remove the current line if + ;; either FROM-FILE or NEW-FILE is a directory, because + ;; compressing/uncompressing directories doesn't remove the + ;; original. If NEW-FILE doesn't exist, assume that we are + ;; out of sync with the current directory, and revert it. + ;; This can happen, for example, when unpacking a .tar.gz + ;; archive which adds files to the current directory (as + ;; opposed to adding them to a directory whose name is + ;; NEW-FILE). + (if (file-exists-p new-file) + (if (or (file-directory-p from-file) + (file-directory-p new-file)) + (dired-add-entry new-file nil t) + (dired-update-file-line new-file)) + (dired-fun-in-all-buffers (dired-current-directory) + nil #'revert-buffer)) nil) (dired-log (concat "Failed to (un)compress " from-file)) from-file))) commit e96e4906c8cb2a8810f969579446f6d151954586 Author: Po Lu Date: Thu May 23 17:46:48 2024 +0800 Work around one Android bug and document another * etc/PROBLEMS (Runtime problems specific to Android): Document deficiency of "Android Keyboard (AOSP)." * java/org/gnu/emacs/EmacsView.java (showOnScreenKeyboard): Revert yesterday's change. * java/org/gnu/emacs/EmacsWindow.java (toggleOnScreenKeyboard): Sync with the UI thread after displaying the on-screen keyboard. diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 77856087367..da861ebe6e7 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -3650,6 +3650,20 @@ result that the next redisplay recenters the window around this outdated position. There is no solution but installing a more cooperative--and preferably free--input method. +** The default input method sometimes performs edits out of place in large buffers. + +When first reactivated in a window after having been dismissed, certain +heuristics applied by the "Android Keyboard (AOSP)" input method to +detect unresponsive text editors, which are ill-adapted to buffers +greater than a few thousand characters in length, conclude that Emacs is +misbehaving, so that the input method ignores updates to the position of +point reported around the time of its activation, and edits suggested by +the input method are inserted in a previously reported location that +might be wildly removed from the current insertion point. This is a bug +in the input method that can be easily reproduced by inserting lengthy +documents into any text editor, with no real solution except avoiding +edit suggestions from recently-reactivated input methods. + * Build-time problems ** Configuration diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index db270b796e8..244a3a02166 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -777,15 +777,6 @@ else if (child.getVisibility () != GONE) imManager.showSoftInput (this, 0); isCurrentlyTextEditor = true; - - /* The OS text editing widget unconditionally reports the current - values of the selection to the input method after calls to - showSoftInput, which is redundant if inputConnection exists but - is now relied upon in such circumstances by the OS's default - input method, and must therefore be faithfully reproduced on our - part. */ - if (inputConnection != null) - EmacsNative.requestSelectionUpdate (window.handle); } public void diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 483ba0dbced..5a4e04ae169 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -20,12 +20,16 @@ package org.gnu.emacs; import java.lang.IllegalStateException; + import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; -import java.util.LinkedHashMap; import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + import android.app.Activity; import android.content.ClipData; @@ -1620,23 +1624,38 @@ else if (EmacsWindow.this.isMapped) public void toggleOnScreenKeyboard (final boolean on) { + FutureTask task; + /* Even though InputMethodManager functions are thread safe, `showOnScreenKeyboard' etc must be called from the UI thread in order to avoid deadlocks if the calls happen in tandem with a call to a synchronizing function within `onCreateInputConnection'. */ - EmacsService.SERVICE.runOnUiThread (new Runnable () { + task = new FutureTask (new Callable () { @Override - public void - run () + public Void + call () { if (on) view.showOnScreenKeyboard (); else view.hideOnScreenKeyboard (); + return null; } }); + + /* Block Lisp until this request to display the on-screen keyboard + is registered by the UI thread, or updates arising from a + redisplay that are reported between the two events will be liable + to run afoul of the IMM's cache of selection positions and never + reach the input method, if it is currently hidden, as input + methods receive outdated selection information reported during + the previous call to `onCreateInputConnection' when first + displayed. + + Chances are this is a long-standing bug in the system. */ + EmacsService.syncRunnable (task); } public String commit 64cced2c37a9926fe6ff1c6ad9b9540abd47e21c Author: Po Lu Date: Thu May 23 15:19:46 2024 +0800 Restore specbound keyboard-locals in the correct KBOARD * doc/lispref/variables.texi (Intro to Buffer-Local): Fix typo in documentation. * src/data.c (KBOARD_OBJFWDP): Move to lisp.h. (kboard_for_bindings): New variable. (do_symval_forwarding, store_symval_forwarding): Call kboard_for_bindings rather than retrieving this value directly. (set_default_internal): New argument WHERE; if valcontents be a Lisp_Kboard_Objfwd and WHERE be specified, save the binding there. All callers changed. * src/eval.c (specpdl_where): Adjust for changes in structure layout. (specpdl_kboard): New function. (do_specbind): Clear let->where.kbd in ordinary SPECPDL_LETs, and set it to the kboard where the binding will be installed if binding keyboard forwards. (specbind, do_one_unbind, specpdl_unrewind): Provide specpdl_kboard in invocation of set_default_internal. * src/keyboard.c (delete_kboard): Clean thread specpdls of references to kboards. * src/keyboard.h (KBOARD_OBJFWDP): Move from data.c. * src/lisp.h (union specbinding) : Convert into union of KBOARD and Lisp_Object. * src/thread.c (all_threads): Export. * src/thread.h: Adjust correspondingly. diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index 16b6b52e5f1..e05d3bb0f81 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -1523,7 +1523,7 @@ buffer-local binding of buffer @samp{b}. values when you visit the file. @xref{File Variables,,, emacs, The GNU Emacs Manual}. - A buffer-local variable cannot be made terminal-local + A terminal-local variable cannot be made buffer-local (@pxref{Multiple Terminals}). @node Creating Buffer-Local diff --git a/src/data.c b/src/data.c index 30d8eab7359..be7ae023d8d 100644 --- a/src/data.c +++ b/src/data.c @@ -49,11 +49,6 @@ INTFWDP (lispfwd a) return XFWDTYPE (a) == Lisp_Fwd_Int; } static bool -KBOARD_OBJFWDP (lispfwd a) -{ - return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj; -} -static bool OBJFWDP (lispfwd a) { return XFWDTYPE (a) == Lisp_Fwd_Obj; @@ -1304,6 +1299,26 @@ If OBJECT is not a symbol, just return it. */) return object; } +/* Return the KBOARD to which bindings currently established and values + set should apply. */ + +KBOARD * +kboard_for_bindings (void) +{ + /* We used to simply use current_kboard here, but from Lisp code, its + value is often unexpected. It seems nicer to allow constructions + like this to work as intuitively expected: + + (with-selected-frame frame + (define-key local-function-map "\eOP" [f1])) + + On the other hand, this affects the semantics of last-command and + real-last-command, and people may rely on that. I took a quick + look at the Lisp codebase, and I don't think anything will break. + --lorentey */ + + return FRAME_KBOARD (SELECTED_FRAME ()); +} /* Given the raw contents of a symbol value cell, return the Lisp value of the symbol. @@ -1329,19 +1344,8 @@ do_symval_forwarding (lispfwd valcontents) XBUFFER_OBJFWD (valcontents)->offset); case Lisp_Fwd_Kboard_Obj: - /* We used to simply use current_kboard here, but from Lisp - code, its value is often unexpected. It seems nicer to - allow constructions like this to work as intuitively expected: - - (with-selected-frame frame - (define-key local-function-map "\eOP" [f1])) - - On the other hand, this affects the semantics of - last-command and real-last-command, and people may rely on - that. I took a quick look at the Lisp codebase, and I - don't think anything will break. --lorentey */ - return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset - + (char *)FRAME_KBOARD (SELECTED_FRAME ())); + return *(Lisp_Object *) (XKBOARD_OBJFWD (valcontents)->offset + + (char *) kboard_for_bindings ()); default: emacs_abort (); } } @@ -1489,7 +1493,7 @@ store_symval_forwarding (lispfwd valcontents, Lisp_Object newval, case Lisp_Fwd_Kboard_Obj: { - char *base = (char *) FRAME_KBOARD (SELECTED_FRAME ()); + char *base = (char *) kboard_for_bindings (); char *p = base + XKBOARD_OBJFWD (valcontents)->offset; *(Lisp_Object *) p = newval; } @@ -1768,7 +1772,8 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, && !PER_BUFFER_VALUE_P (buf, idx)) { if (let_shadows_buffer_binding_p (sym)) - set_default_internal (symbol, newval, bindflag); + set_default_internal (symbol, newval, bindflag, + NULL); else SET_PER_BUFFER_VALUE_P (buf, idx, 1); } @@ -1991,7 +1996,7 @@ local bindings in certain buffers. */) void set_default_internal (Lisp_Object symbol, Lisp_Object value, - enum Set_Internal_Bind bindflag) + enum Set_Internal_Bind bindflag, KBOARD *where) { CHECK_SYMBOL (symbol); struct Lisp_Symbol *sym = XSYMBOL (symbol); @@ -2071,6 +2076,13 @@ set_default_internal (Lisp_Object symbol, Lisp_Object value, } } } + else if (KBOARD_OBJFWDP (valcontents)) + { + char *base = (char *) (where ? where + : kboard_for_bindings ()); + char *p = base + XKBOARD_OBJFWD (valcontents)->offset; + *(Lisp_Object *) p = value; + } else set_internal (symbol, value, Qnil, bindflag); return; @@ -2085,7 +2097,7 @@ The default value is seen in buffers that do not have their own values for this variable. */) (Lisp_Object symbol, Lisp_Object value) { - set_default_internal (symbol, value, SET_INTERNAL_SET); + set_default_internal (symbol, value, SET_INTERNAL_SET, NULL); return value; } diff --git a/src/eval.c b/src/eval.c index 637c874871d..8cabe2d2cc7 100644 --- a/src/eval.c +++ b/src/eval.c @@ -100,7 +100,14 @@ static Lisp_Object specpdl_where (union specbinding *pdl) { eassert (pdl->kind > SPECPDL_LET); - return pdl->let.where; + return pdl->let.where.buf; +} + +static KBOARD * +specpdl_kboard (union specbinding *pdl) +{ + eassert (pdl->kind == SPECPDL_LET); + return pdl->let.where.kbd; } static Lisp_Object @@ -3483,7 +3490,8 @@ do_specbind (struct Lisp_Symbol *sym, union specbinding *bind, if (BUFFER_OBJFWDP (SYMBOL_FWD (sym)) && specpdl_kind (bind) == SPECPDL_LET_DEFAULT) { - set_default_internal (specpdl_symbol (bind), value, bindflag); + set_default_internal (specpdl_symbol (bind), value, bindflag, + NULL); return; } FALLTHROUGH; @@ -3525,6 +3533,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) specpdl_ptr->let.kind = SPECPDL_LET; specpdl_ptr->let.symbol = symbol; specpdl_ptr->let.old_value = SYMBOL_VAL (sym); + specpdl_ptr->let.where.kbd = NULL; break; case SYMBOL_LOCALIZED: case SYMBOL_FORWARDED: @@ -3533,7 +3542,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) specpdl_ptr->let.kind = SPECPDL_LET_LOCAL; specpdl_ptr->let.symbol = symbol; specpdl_ptr->let.old_value = ovalue; - specpdl_ptr->let.where = Fcurrent_buffer (); + specpdl_ptr->let.where.buf = Fcurrent_buffer (); eassert (sym->u.s.redirect != SYMBOL_LOCALIZED || (BASE_EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); @@ -3553,6 +3562,11 @@ specbind (Lisp_Object symbol, Lisp_Object value) if (NILP (Flocal_variable_p (symbol, Qnil))) specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; } + else if (KBOARD_OBJFWDP (SYMBOL_FWD (sym))) + { + specpdl_ptr->let.where.kbd = kboard_for_bindings (); + specpdl_ptr->let.kind = SPECPDL_LET; + } else specpdl_ptr->let.kind = SPECPDL_LET; @@ -3656,6 +3670,8 @@ static void do_one_unbind (union specbinding *this_binding, bool unwinding, enum Set_Internal_Bind bindflag) { + KBOARD *kbdwhere = NULL; + eassert (unwinding || this_binding->kind >= SPECPDL_LET); switch (this_binding->kind) { @@ -3708,12 +3724,13 @@ do_one_unbind (union specbinding *this_binding, bool unwinding, } } /* Come here only if make_local_foo was used for the first time - on this var within this let. */ + on this var within this let or the symbol is not a plainval. */ + kbdwhere = specpdl_kboard (this_binding); FALLTHROUGH; case SPECPDL_LET_DEFAULT: set_default_internal (specpdl_symbol (this_binding), specpdl_old_value (this_binding), - bindflag); + bindflag, kbdwhere); break; case SPECPDL_LET_LOCAL: { @@ -3982,6 +3999,8 @@ specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only) { union specbinding *tmp = pdl; int step = -1; + KBOARD *kbdwhere; + if (distance < 0) { /* It's a rewind rather than unwind. */ tmp += distance - 1; @@ -3992,6 +4011,8 @@ specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only) for (; distance > 0; distance--) { tmp += step; + kbdwhere = NULL; + switch (tmp->kind) { /* FIXME: Ideally we'd like to "temporarily unwind" (some of) those @@ -4032,14 +4053,16 @@ specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only) } } /* Come here only if make_local_foo was used for the first - time on this var within this let. */ + time on this var within this let or the symbol is forwarded. */ + kbdwhere = specpdl_kboard (tmp); FALLTHROUGH; case SPECPDL_LET_DEFAULT: { Lisp_Object sym = specpdl_symbol (tmp); Lisp_Object old_value = specpdl_old_value (tmp); set_specpdl_old_value (tmp, default_value (sym)); - set_default_internal (sym, old_value, SET_INTERNAL_THREAD_SWITCH); + set_default_internal (sym, old_value, SET_INTERNAL_THREAD_SWITCH, + kbdwhere); } break; case SPECPDL_LET_LOCAL: diff --git a/src/keyboard.c b/src/keyboard.c index d5892115e4b..3551a77a9c9 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -12612,6 +12612,7 @@ void delete_kboard (KBOARD *kb) { KBOARD **kbp; + struct thread_state *thread; for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard) if (*kbp == NULL) @@ -12629,6 +12630,21 @@ delete_kboard (KBOARD *kb) emacs_abort (); } + /* Clean thread specpdls of references to this KBOARD. */ + for (thread = all_threads; thread; thread = thread->next_thread) + { + union specbinding *p; + + for (p = thread->m_specpdl_ptr; p > thread->m_specpdl;) + { + p -= 1; + + if (p->kind == SPECPDL_LET + && p->let.where.kbd == kb) + p->let.where.kbd = NULL; + } + } + wipe_kboard (kb); xfree (kb); } diff --git a/src/keyboard.h b/src/keyboard.h index 42637ca1cf7..c7ae1f7f0fa 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -78,7 +78,6 @@ INLINE_HEADER_BEGIN When Emacs goes back to the any-kboard state, it looks at all the KBOARDs to find those; and it tries processing their input right away. */ -typedef struct kboard KBOARD; struct kboard { KBOARD *next_kboard; diff --git a/src/lisp.h b/src/lisp.h index 4b4ff2a2c60..534a36499f1 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3184,6 +3184,13 @@ XBUFFER_OBJFWD (lispfwd a) eassert (BUFFER_OBJFWDP (a)); return a.fwdptr; } + +INLINE bool +KBOARD_OBJFWDP (lispfwd a) +{ + return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj; +} + /* Lisp floating point type. */ struct Lisp_Float @@ -3597,13 +3604,16 @@ enum specbind_tag { #ifdef HAVE_MODULES SPECPDL_MODULE_RUNTIME, /* A live module runtime. */ SPECPDL_MODULE_ENVIRONMENT, /* A live module environment. */ -#endif +#endif /* !HAVE_MODULES */ SPECPDL_LET, /* A plain and simple dynamic let-binding. */ /* Tags greater than SPECPDL_LET must be "subkinds" of LET. */ SPECPDL_LET_LOCAL, /* A buffer-local let-binding. */ SPECPDL_LET_DEFAULT /* A global binding for a localized var. */ }; +/* struct kboard is defined in keyboard.h. */ +typedef struct kboard KBOARD; + union specbinding { /* Aligning similar members consistently might help efficiency slightly @@ -3646,8 +3656,17 @@ union specbinding } unwind_void; struct { ENUM_BF (specbind_tag) kind : CHAR_BIT; - /* `where' is not used in the case of SPECPDL_LET. */ - Lisp_Object symbol, old_value, where; + /* `where' is not used in the case of SPECPDL_LET, + unless the symbol is forwarded to a KBOARD. */ + Lisp_Object symbol, old_value; + union { + /* KBOARD object to which SYMBOL forwards, in the case of + SPECPDL_LET. */ + KBOARD *kbd; + + /* Buffer otherwise. */ + Lisp_Object buf; + } where; } let; struct { ENUM_BF (specbind_tag) kind : CHAR_BIT; @@ -4216,17 +4235,19 @@ extern uintmax_t cons_to_unsigned (Lisp_Object, uintmax_t); extern AVOID args_out_of_range (Lisp_Object, Lisp_Object); extern AVOID circular_list (Lisp_Object); +extern KBOARD *kboard_for_bindings (void); extern Lisp_Object do_symval_forwarding (lispfwd); -enum Set_Internal_Bind { - SET_INTERNAL_SET, - SET_INTERNAL_BIND, - SET_INTERNAL_UNBIND, - SET_INTERNAL_THREAD_SWITCH -}; +enum Set_Internal_Bind + { + SET_INTERNAL_SET, + SET_INTERNAL_BIND, + SET_INTERNAL_UNBIND, + SET_INTERNAL_THREAD_SWITCH, + }; extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object, enum Set_Internal_Bind); extern void set_default_internal (Lisp_Object, Lisp_Object, - enum Set_Internal_Bind bindflag); + enum Set_Internal_Bind, KBOARD *); extern Lisp_Object expt_integer (Lisp_Object, Lisp_Object); extern void syms_of_data (void); extern void swap_in_global_binding (struct Lisp_Symbol *); diff --git a/src/thread.c b/src/thread.c index 2f5d7a08838..dd4ef870026 100644 --- a/src/thread.c +++ b/src/thread.c @@ -63,7 +63,7 @@ static union aligned_thread_state main_thread struct thread_state *current_thread = &main_thread.s; -static struct thread_state *all_threads = &main_thread.s; +struct thread_state *all_threads = &main_thread.s; static sys_mutex_t global_lock; diff --git a/src/thread.h b/src/thread.h index 1844cf03967..eaa7b265168 100644 --- a/src/thread.h +++ b/src/thread.h @@ -317,6 +317,7 @@ XCONDVAR (Lisp_Object a) } extern struct thread_state *current_thread; +extern struct thread_state *all_threads; extern void finalize_one_thread (struct thread_state *state); extern void finalize_one_mutex (struct Lisp_Mutex *); commit ad0b9b9ab5dc58ee4e6277b642b325970c63a4f7 Author: Po Lu Date: Thu May 23 13:54:48 2024 +0800 ; * src/unexelf.c (unexec): Fix compiler warning. diff --git a/src/unexelf.c b/src/unexelf.c index feb26ffaeaf..a9a8f2d6ce9 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -306,6 +306,8 @@ unexec (const char *new_name, const char *old_name) old_bss_seg = seg; } eassume (old_bss_seg); + if (!old_bss_seg) + emacs_abort (); /* Note that old_bss_addr may be lower than the first bss section address, since the section may need aligning. */