commit cac13e360547f95ec64d34f38003dfc7ff1a97ee (HEAD, refs/remotes/origin/master) Author: Eric Abrahamsen Date: Mon Feb 20 03:01:41 2023 +0200 Help Elisp xref recognize defclass parent classes * lisp/progmodes/elisp-mode.el (elisp--xref-infer-namespace): Handle defclass parents (bug#61640). * test/lisp/progmodes/elisp-mode-tests.el (elisp-mode-infer-namespace): New case in the test. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 1c339d08148..f7cd9e90926 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -943,6 +943,10 @@ elisp--xref-infer-namespace cl-defmethod cl-defgeneric))) ;; (defun FUNC (... IDENT 'variable) + ((and (eql j 2) + (eq j-head 'defclass)) + ;; (defclass CLASS (... IDENT + 'function) ((eq j-head 'cond) ;; (cond ... (... IDENT 'variable) diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el index 57b39a49801..5b6ef88dceb 100644 --- a/test/lisp/progmodes/elisp-mode-tests.el +++ b/test/lisp/progmodes/elisp-mode-tests.el @@ -1003,6 +1003,11 @@ elisp-mode-infer-namespace (should (equal (elisp--xref-infer-namespace p5) 'variable)) (should (equal (elisp--xref-infer-namespace p6) 'function))) + (elisp-mode-test--with-buffer + (concat "(defclass child-class ({p1}parent-1 {p2}parent-2))\n") + (should (equal (elisp--xref-infer-namespace p1) 'function)) + (should (equal (elisp--xref-infer-namespace p2) 'function))) + (elisp-mode-test--with-buffer (concat "(require '{p1}alpha)\n" "(fboundp '{p2}beta)\n" commit 9e745ed3f2c53f9ca46e763c8eac66a1cf8611c6 Author: Michael Albinus Date: Sun Feb 19 18:35:46 2023 +0100 Tramp cleanup * lisp/net/tramp-smb.el (tramp-smb-action-get-acl) (tramp-smb-action-set-acl): Use timeout. * test/lisp/net/tramp-tests.el (tramp-test26-interactive-file-name-completion): Fix test. diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index b2272f804e0..2a69465224f 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -757,7 +757,7 @@ tramp-smb-action-get-acl "Read ACL data from connection buffer." (unless (process-live-p proc) ;; Accept pending output. - (while (tramp-accept-process-output proc)) + (while (tramp-accept-process-output proc 0)) (with-current-buffer (tramp-get-connection-buffer vec) ;; There might be a hidden password prompt. (widen) @@ -1361,7 +1361,7 @@ tramp-smb-action-set-acl "Set ACL data." (unless (process-live-p proc) ;; Accept pending output. - (while (tramp-accept-process-output proc)) + (while (tramp-accept-process-output proc 0)) (tramp-message vec 10 "\n%s" (tramp-get-buffer-string (tramp-get-connection-buffer vec))) (throw 'tramp-action 'ok))) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index d29e48c0774..97fada91fa2 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -4642,8 +4642,8 @@ tramp-test26-interactive-file-name-completion "Check interactive completion with different `completion-styles'." (tramp-cleanup-connection tramp-test-vec nil 'keep-password) - ;; Method and host name in completion mode. This kind of completion - ;; does not work on MS Windows. + ;; Method, user and host name in completion mode. This kind of + ;; completion does not work on MS Windows. (unless (memq system-type '(cygwin windows-nt)) (let ((method (file-remote-p ert-remote-temporary-file-directory 'method)) (user (file-remote-p ert-remote-temporary-file-directory 'user)) @@ -4673,119 +4673,132 @@ tramp-test26-interactive-file-name-completion '(emacs21 emacs22 basic partial-completion substring flex) '(basic))) - (let (;; Force the real minibuffer in batch mode. - (executing-kbd-macro t) - (completion-styles `(,style)) - (completions-format 'one-column) - completion-category-defaults - completion-category-overrides - ;; This is needed for the `simplified' syntax, - (tramp-default-method method) - (method-string - (unless (string-empty-p tramp-method-regexp) - (concat method tramp-postfix-method-format))) - ;; This is needed for the IPv6 host name syntax. - (ipv6-prefix - (and (string-match-p tramp-ipv6-regexp host) - tramp-prefix-ipv6-format)) - (ipv6-postfix - (and (string-match-p tramp-ipv6-regexp host) - tramp-postfix-ipv6-format)) - ;; The hop string fits only the initial syntax. - (hop (and (eq tramp-syntax orig-syntax) hop)) - test result completions) - - (dolist - (test-and-result - ;; These are triples (TEST-STRING RESULT-CHECK - ;; COMPLETION-CHECK). - (append - ;; Complete method name. - (unless (string-empty-p tramp-method-regexp) - `((,(concat - tramp-prefix-format hop - (substring-no-properties - method 0 (min 2 (length method)))) - ,(concat tramp-prefix-format method-string) - ,method-string))) - ;; Complete user name. - (unless (tramp-string-empty-or-nil-p user) - `((,(concat - tramp-prefix-format hop method-string - (substring-no-properties - user 0 (min 2 (length user)))) - ,(concat - tramp-prefix-format method-string - user tramp-postfix-user-format) - ,(concat - user tramp-postfix-user-format)))) - ;; Complete host name. - (unless (tramp-string-empty-or-nil-p host) - `((,(concat - tramp-prefix-format hop method-string - ipv6-prefix - (substring-no-properties - host 0 (min 2 (length host)))) - ,(concat - tramp-prefix-format method-string - ipv6-prefix host - ipv6-postfix tramp-postfix-host-format) - ,(concat - ipv6-prefix host - ipv6-postfix tramp-postfix-host-format)))) - ;; Complete user and host name. - (unless (or (tramp-string-empty-or-nil-p user) - (tramp-string-empty-or-nil-p host)) - `((,(concat - tramp-prefix-format hop method-string - user tramp-postfix-user-format - ipv6-prefix - (substring-no-properties - host 0 (min 2 (length host)))) - ,(concat - tramp-prefix-format method-string - user tramp-postfix-user-format - ipv6-prefix host - ipv6-postfix tramp-postfix-host-format) - ,(concat - ipv6-prefix host - ipv6-postfix tramp-postfix-host-format)))))) - - (ignore-errors (kill-buffer "*Completions*")) - ;; (and (bufferp trace-buffer) (kill-buffer trace-buffer)) - (discard-input) - (setq test (car test-and-result) - unread-command-events - (mapcar #'identity (concat test "\t\t\n")) - completions nil - result (read-file-name "Prompt: ")) - - (if (not (get-buffer "*Completions*")) - (progn - ;; (tramp--test-message - ;; "syntax: %s style: %s test: %s result: %s" - ;; syntax style test result) - (should (string-prefix-p (cadr test-and-result) result))) - - (with-current-buffer "*Completions*" - ;; We must remove leading `default-directory'. - (goto-char (point-min)) - (let ((inhibit-read-only t)) - (while (re-search-forward "//" nil 'noerror) - (delete-region (line-beginning-position) (point)))) - (goto-char (point-min)) - (re-search-forward - (rx bol (1+ nonl) "possible completions:" eol)) - (forward-line 1) - (setq completions - (split-string - (buffer-substring-no-properties (point) (point-max)) - (rx (any "\r\n")) 'omit))) - - ;; (tramp--test-message - ;; "syntax: %s style: %s test: %s result: %s completions: %S" - ;; syntax style test result completions) - (should (member (caddr test-and-result) completions))))))) + (when (assoc style completion-styles-alist) + (let (;; Force the real minibuffer in batch mode. + (executing-kbd-macro noninteractive) + (completion-styles `(,style)) + (completions-format 'one-column) + completion-category-defaults + completion-category-overrides + ;; This is needed for the `simplified' syntax, + (tramp-default-method method) + (method-string + (unless (string-empty-p tramp-method-regexp) + (concat method tramp-postfix-method-format))) + ;; This is needed for the IPv6 host name syntax. + (ipv6-prefix + (and (string-match-p tramp-ipv6-regexp host) + tramp-prefix-ipv6-format)) + (ipv6-postfix + (and (string-match-p tramp-ipv6-regexp host) + tramp-postfix-ipv6-format)) + ;; The hop string fits only the initial syntax. + (hop (and (eq tramp-syntax orig-syntax) hop)) + test result completions) + + (dolist + (test-and-result + ;; These are triples (TEST-STRING RESULT-CHECK + ;; COMPLETION-CHECK). + (append + ;; Complete method name. + (unless (string-empty-p tramp-method-regexp) + `((,(concat + tramp-prefix-format hop + (substring-no-properties + method 0 (min 2 (length method)))) + ,(concat tramp-prefix-format method-string) + ,method-string))) + ;; Complete user name. + (unless (tramp-string-empty-or-nil-p user) + `((,(concat + tramp-prefix-format hop method-string + (substring-no-properties + user 0 (min 2 (length user)))) + ,(concat + tramp-prefix-format method-string + user tramp-postfix-user-format) + ,(concat + user tramp-postfix-user-format)))) + ;; Complete host name. + (unless (tramp-string-empty-or-nil-p host) + `((,(concat + tramp-prefix-format hop method-string + ipv6-prefix + (substring-no-properties + host 0 (min 2 (length host)))) + ,(concat + tramp-prefix-format method-string + ipv6-prefix host + ipv6-postfix tramp-postfix-host-format) + ,(concat + ipv6-prefix host + ipv6-postfix tramp-postfix-host-format)))) + ;; Complete user and host name. + (unless (or (tramp-string-empty-or-nil-p user) + (tramp-string-empty-or-nil-p host)) + `((,(concat + tramp-prefix-format hop method-string + user tramp-postfix-user-format + ipv6-prefix + (substring-no-properties + host 0 (min 2 (length host)))) + ,(concat + tramp-prefix-format method-string + user tramp-postfix-user-format + ipv6-prefix host + ipv6-postfix tramp-postfix-host-format) + ,(concat + ipv6-prefix host + ipv6-postfix tramp-postfix-host-format)))))) + + (ignore-errors (kill-buffer "*Completions*")) + ;; (and (bufferp trace-buffer) (kill-buffer trace-buffer)) + (discard-input) + (setq test (car test-and-result) + unread-command-events + (mapcar #'identity (concat test "\t\t\n")) + completions nil + result (read-file-name "Prompt: ")) + + (if (or (not (get-buffer "*Completions*")) + (string-match-p + (if (string-empty-p tramp-method-regexp) + (rx (| (regexp tramp-postfix-user-regexp) + (regexp tramp-postfix-host-regexp)) + eos) + (rx (| (regexp tramp-postfix-method-regexp) + (regexp tramp-postfix-user-regexp) + (regexp tramp-postfix-host-regexp)) + eos)) + result)) + (progn + ;; (tramp--test-message + ;; "syntax: %s style: %s test: %s result: %s" + ;; syntax style test result) + (should (string-prefix-p (cadr test-and-result) result))) + + (with-current-buffer "*Completions*" + ;; We must remove leading `default-directory'. + (goto-char (point-min)) + (let ((inhibit-read-only t)) + (while (re-search-forward "//" nil 'noerror) + (delete-region (line-beginning-position) (point)))) + (goto-char (point-min)) + (re-search-forward + (rx bol (0+ nonl) + (any "Pp") "ossible completions" + (0+ nonl) eol)) + (forward-line 1) + (setq completions + (split-string + (buffer-substring-no-properties (point) (point-max)) + (rx (any "\r\n")) 'omit))) + + ;; (tramp--test-message + ;; "syntax: %s style: %s test: %s result: %s completions: %S" + ;; syntax style test result completions) + (should (member (caddr test-and-result) completions)))))))) ;; Cleanup. ;; (tramp--test-message "%s" (tramp-get-buffer-string trace-buffer)) commit 8fba4cff1bd0b953af9e950e872e1eaecff179d7 Author: Alan Mackenzie Date: Sun Feb 19 16:09:32 2023 +0000 imenu: Make the test for a single category of map (e.g. "Class") rigorous This fixes bug #61629. * lisp/imenu.el (imenu--mouse-menu): Test (consp (cdadr menu)) to avoid confusion with a single entry for a single function. (imenu-update-menubar): Change the code to match that above. diff --git a/lisp/imenu.el b/lisp/imenu.el index 25a02004570..fd23a65c7b3 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -756,9 +756,11 @@ imenu--mouse-menu (setq index-alist (imenu--split-submenus index-alist)) (let* ((menu (imenu--split-menu index-alist (or title (buffer-name)))) (map (imenu--create-keymap (car menu) - (cdr (if (< 1 (length (cdr menu))) - menu - (car (cdr menu))))))) + (cdr (if (and (null (cddr menu)) + (stringp (caadr menu)) + (consp (cdadr menu))) + (cadr menu) + menu))))) (popup-menu map event))) (defun imenu-choose-buffer-index (&optional prompt alist) @@ -854,13 +856,12 @@ imenu-update-menubar (buffer-name))) (menu1 (imenu--create-keymap (car menu) - (cdr (if (or (< 1 (length (cdr menu))) - ;; Have we a non-nested single entry? - (atom (cdadr menu)) - (atom (cadadr menu))) - menu - (car (cdr menu)))) - 'imenu--menubar-select))) + (cdr (if (and (null (cddr menu)) + (stringp (caadr menu)) + (consp (cdadr menu))) + (cadr menu) + menu)) + 'imenu--menubar-select))) (setcdr imenu--menubar-keymap (cdr menu1))))))) (defun imenu--menubar-select (item) commit 34f44ae07e0a3ba7ae43d79ab71b03795cb4acf5 Merge: 750bc57cbb8 871cf33a450 Author: Stefan Kangas Date: Sun Feb 19 11:38:09 2023 +0100 Merge from origin/emacs-29 871cf33a450 ; * admin/make-tarball.txt: Minor copyedit. 4faebba2fed Fix invocation of File->Close from the menu bar cd05fca5f78 ; Improve documentation of 'native-comp-enable-subr-tramp... c61a30e1601 Update thumbnail buffer's header more 4c49452cdef (treesit-query-validate): Fix reusing the output buffer d560dc5044a (rust-ts-mode--font-lock-settings): Highlight closure par... c15bc91e1bf * Fix `native-comp-enable-subr-trampolines' semantic 774051873d5 Fix documentation of 'just-one-space' and 'delete-horizon... 7337f072500 ; Remove NEWS entry about deleted variable. fb5299ba099 ; Fix wording of last change. 9f508cef85d Fix 'display-buffer-use-least-recent-window' 5190ea6259a Fix point moving when calling python-shell-send-region 6c0d8210175 (project-try-vc): Remove unused defvar/require 4f9862e4356 ; Fix typo a638c79bc5c Delete redundant question from Gnus FAQ 4a90d67eb68 Slightly improve hashcash documentation 6ea3c105ab1 Fix cursor motion when there's line-prefix and display st... e985466556c Fix comment in treesit_record_change (bug#61369) 1e5cebc88bb Spell out RPN abbreviation in Calc manual intro # Conflicts: # etc/NEWS # lisp/window.el commit 871cf33a450a34fcace7fe7c5448fe3043697005 Author: Stefan Kangas Date: Sun Feb 19 11:35:31 2023 +0100 ; * admin/make-tarball.txt: Minor copyedit. diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt index 45da3ed6be5..232053e5e96 100644 --- a/admin/make-tarball.txt +++ b/admin/make-tarball.txt @@ -150,10 +150,11 @@ General steps (for each step, check for possible errors): 4. autoreconf -i -I m4 --force make bootstrap + The below script checks for any mistakes in the source text of + manual pages. Fix any errors and re-run the script to verify. + ./admin/check-man-pages - The above script checks for any mistakes in the source text of - manual pages. Fix any errors and re-run the script to verify. Then do this: make -C etc/refcards commit 4faebba2fedcb428838fbda8537140841bdd8aa0 Author: Eli Zaretskii Date: Sun Feb 19 11:29:32 2023 +0200 Fix invocation of File->Close from the menu bar * lisp/simple.el (kill-buffer--possibly-save): Don't request LONG-FORM from 'read-multiple-choice' if GUI dialog should be used. * lisp/emacs-lisp/rmc.el (read-multiple-choice): Doc fix. (read-multiple-choice--short-answers): Don't append "?" to CHOICES and don't display the prompt in the echo area if GUI dialog is used. Use 'use-dialog-box-p'. (Bug#61553) diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el index 542c96512f5..bfd7434be9a 100644 --- a/lisp/emacs-lisp/rmc.el +++ b/lisp/emacs-lisp/rmc.el @@ -162,8 +162,10 @@ read-multiple-choice The return value is the matching entry from the CHOICES list. -If LONG-FORM, do a `completing-read' over the NAME elements in -CHOICES instead. +If LONG-FORM is non-nil, do a `completing-read' over the NAME elements +in CHOICES instead. In this case, GUI dialog is not used, regardless +of the value of `use-dialog-box' and whether the function was invoked +via a mouse gesture. Usage example: @@ -177,8 +179,9 @@ read-multiple-choice prompt choices help-string show-help))) (defun read-multiple-choice--short-answers (prompt choices help-string show-help) - (let* ((prompt-choices - (if show-help choices (append choices '((?? "?"))))) + (let* ((dialog-p (use-dialog-box-p)) + (prompt-choices + (if (or show-help dialog-p) choices (append choices '((?? "?"))))) (altered-names (mapcar #'rmc--add-key-description prompt-choices)) (full-prompt (format @@ -192,16 +195,14 @@ read-multiple-choice--short-answers (setq buf (rmc--show-help prompt help-string show-help choices altered-names))) (while (not tchar) - (message "%s%s" - (if wrong-char - "Invalid choice. " - "") - full-prompt) + (unless dialog-p + (message "%s%s" + (if wrong-char + "Invalid choice. " + "") + full-prompt)) (setq tchar - (if (and (display-popup-menus-p) - last-input-event ; not during startup - (consp last-nonmenu-event) - use-dialog-box) + (if dialog-p (x-popup-dialog t (cons prompt diff --git a/lisp/simple.el b/lisp/simple.el index c2d10b4dcb4..27aeb2fa8cc 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10801,7 +10801,8 @@ kill-buffer--possibly-save '((?y "yes" "kill buffer without saving") (?n "no" "exit without doing anything") (?s "save and then kill" "save the buffer and then kill it")) - nil nil (not use-short-answers))))) + nil nil (and (not use-short-answers) + (not (use-dialog-box-p))))))) (if (equal response "no") nil (unless (equal response "yes") commit cd05fca5f78048cb867be2d5f0857f6997f12ccc Author: Eli Zaretskii Date: Sun Feb 19 11:04:57 2023 +0200 ; Improve documentation of 'native-comp-enable-subr-trampolines' * doc/lispref/compile.texi (Native-Compilation Variables): Document the interpretation of non-absolute directory names that are the value of 'native-comp-enable-subr-trampolines'. diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi index cdbf64036da..6ae6755ad76 100644 --- a/doc/lispref/compile.texi +++ b/doc/lispref/compile.texi @@ -1120,16 +1120,18 @@ Native-Compilation Variables needed by your Lisp programs are already compiled and accessible to Emacs. -The value of this variable can also be a string, in which case it is -interpreted as the name of a directory in which to store the generated -trampoline @file{*.eln} files, overriding the directories specified by +The value of this variable can also be a string, in which case it +specifies the name of a directory in which to store the generated +trampoline @file{*.eln} files, overriding the directories in @code{native-comp-eln-load-path}. This is useful if you want the trampolines to be generated as needed, but don't want to store them -under the user's @env{HOME} directory or the other public directories -where @file{*.eln} files are kept. However, unlike with directories -in @code{native-comp-eln-load-path}, the trampolines will be stored in -the directory given by the value of this variable, not in its -version-specific subdirectory. +under the user's @env{HOME} directory or in the other public +directories where @file{*.eln} files are kept. However, unlike with +directories in @code{native-comp-eln-load-path}, the trampolines will +be stored in the directory given by the value of this variable, not in +its version-specific subdirectory. If the name of this directory is +not absolute, it is interpreted relative to +@code{invocation-directory} (@pxref{System Environment}) If this variable is non-@code{nil}, and Emacs needs to produce a trampoline, but it cannot find any writable directory to store the diff --git a/lisp/treesit.el b/lisp/treesit.el index b71b5b486d5..297812f23f7 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1204,6 +1204,11 @@ treesit-simple-indent-presets (cons 'grand-parent (lambda (_n parent &rest _) (treesit-node-start (treesit-node-parent parent)))) + (cons 'great-grand-parent + (lambda (_n parent &rest _) + (treesit-node-start + (treesit-node-parent + (treesit-node-parent parent))))) (cons 'parent-bol (lambda (_n parent &rest _) (save-excursion (goto-char (treesit-node-start parent)) commit c61a30e1601e68741c2d88c9c6b31b03bde07b2f Author: Manuel Giraud Date: Tue Feb 14 15:08:17 2023 +0100 Update thumbnail buffer's header more * lisp/image/image-dired.el (image-dired-display-thumbs): Call image-dired--update-header-line. (Bug#61508) diff --git a/lisp/image/image-dired.el b/lisp/image/image-dired.el index 49b8d9f03c8..cfcd1851188 100644 --- a/lisp/image/image-dired.el +++ b/lisp/image/image-dired.el @@ -593,7 +593,8 @@ image-dired-display-thumbs (if do-not-pop (display-buffer buf) (pop-to-buffer buf)) - (image-dired--line-up-with-method)))) + (image-dired--line-up-with-method) + (image-dired--update-header-line)))) ;;;###autoload (defun image-dired-show-all-from-dir (dir) commit 4c49452cdef9721715838590aff175ef596a08b2 Author: Dmitry Gutov Date: Sat Feb 18 23:52:47 2023 +0200 (treesit-query-validate): Fix reusing the output buffer * lisp/treesit.el (treesit-query-validate): Fix the "Buffer is read-only" error when an output buffer already exists. diff --git a/lisp/treesit.el b/lisp/treesit.el index 09531b838a1..b71b5b486d5 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -2380,7 +2380,8 @@ treesit-query-validate (with-current-buffer buf (let* ((data (cdr err)) (message (nth 0 data)) - (start (nth 1 data))) + (start (nth 1 data)) + (inhibit-read-only t)) (erase-buffer) (insert (treesit-query-expand query)) (goto-char start) commit d560dc5044a69144e45e13ee787b196afa28ba8b Author: Dmitry Gutov Date: Sat Feb 18 23:51:17 2023 +0200 (rust-ts-mode--font-lock-settings): Highlight closure parameters * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings): Highlight closure parameters. diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index ec823d09d8c..e53cdb5ce7d 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -158,6 +158,7 @@ rust-ts-mode--font-lock-settings (macro_definition (identifier) @font-lock-preprocessor-face) (field_declaration name: (field_identifier) @font-lock-property-face) (parameter pattern: (_) @rust-ts-mode--fontify-pattern) + (closure_parameters (_) @rust-ts-mode--fontify-pattern) (let_declaration pattern: (_) @rust-ts-mode--fontify-pattern) (for_expression pattern: (_) @rust-ts-mode--fontify-pattern) (let_condition pattern: (_) @rust-ts-mode--fontify-pattern) commit c15bc91e1bf5a04da48f03866a9461b6046dba15 Author: Andrea Corallo Date: Sat Feb 18 22:44:05 2023 +0100 * Fix `native-comp-enable-subr-trampolines' semantic * lisp/emacs-lisp/comp.el (comp--trampoline-abs-filename): Interpret `native-comp-enable-subr-trampolines' relative to `invocation-directory'. diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 2d9cad6d98c..a2bad6ce6a8 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -3794,7 +3794,8 @@ comp--trampoline-abs-filename "Return the absolute filename for a trampoline for SUBR-NAME." (cl-loop with dirs = (if (stringp native-comp-enable-subr-trampolines) - (list native-comp-enable-subr-trampolines) + (list (expand-file-name native-comp-enable-subr-trampolines + invocation-directory)) (if native-compile-target-directory (list (expand-file-name comp-native-version-dir native-compile-target-directory)) commit 774051873d569590c78ef450ca4630c53452ae64 Author: Eli Zaretskii Date: Sat Feb 18 20:03:33 2023 +0200 Fix documentation of 'just-one-space' and 'delete-horizontal-space' * lisp/simple.el (just-one-space, delete-horizontal-space): Mention the effect of prefix argument. (Bug#61609) diff --git a/lisp/simple.el b/lisp/simple.el index c58acfe3adc..c2d10b4dcb4 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1088,7 +1088,8 @@ fixup-whitespace (defun delete-horizontal-space (&optional backward-only) "Delete all spaces and tabs around point. -If BACKWARD-ONLY is non-nil, delete them only before point." +If BACKWARD-ONLY is non-nil (interactively, the prefix argument), delete +them only before point." (interactive "*P") (delete-space--internal " \t" backward-only)) @@ -1114,6 +1115,7 @@ delete-space--internal (defun just-one-space (&optional n) "Delete all spaces and tabs around point, leaving one space (or N spaces). +Interactively, N is the prefix numeric argument. If N is negative, delete newlines as well, leaving -N spaces. See also `cycle-spacing'." (interactive "*p") commit 7337f0725005f33ca4d8346a205b1c1554302888 Author: Eli Zaretskii Date: Sat Feb 18 19:48:22 2023 +0200 ; Remove NEWS entry about deleted variable. diff --git a/etc/NEWS b/etc/NEWS index b140d1dcbfd..0106953c1e0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1161,12 +1161,6 @@ and 'C-x w 3', respectively. A number of other useful window-related commands are now available with key sequences that start with the 'C-x w' prefix. -+++ -*** New user option 'display-buffer-avoid-small-windows'. -If non-nil, this should be a window height in lines, a number. -Windows smaller than this will be avoided by 'display-buffer', if -possible. - +++ *** New display action 'display-buffer-full-frame'. This action removes other windows from the frame when displaying a commit fb5299ba0993a8f121b5ae62793f291bd565bb1b Author: Eli Zaretskii Date: Sat Feb 18 19:45:33 2023 +0200 ; Fix wording of last change. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 1ec645721ca..01ac6fb901a 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -630,11 +630,11 @@ Selecting Windows with @var{window} as the selected window without needlessly running @code{buffer-list-update-hook}. -Note that this macro temporarily puts the window management code in a -unstable state. In particular, the most recently window (see below) +Note that this macro temporarily puts the window management code in an +unstable state. In particular, the most recently used window (see below) will not necessarily match the selected one. Hence, functions like @code{get-lru-window} and @code{get-mru-window} may return unexpected -results when called from within the scope of this macro. +results when called from the body of this macro. @end defmac @defmac with-selected-frame frame forms@dots{} @@ -662,10 +662,11 @@ Selecting Windows @end defun @defun window-bump-use-time &optional window -This function marks @var{window} as being the second most recently used -one. It does nothing if @var{window} is the selected window or the -selected window does not have the highest use time among all windows -which may happen within the scope of @code{with-selected-window}. +This function marks @var{window} as being the second most recently +used one (after the selected window). It does nothing if @var{window} +is the selected window or the selected window does not have the +highest use time among all windows which may happen within the scope +of @code{with-selected-window}. @end defun @anchor{Window Group}Sometimes several windows collectively and @@ -3068,29 +3069,30 @@ Buffer Display Action Alists @vindex window-min-width@r{, a buffer display action alist entry} @item window-min-width The value specifies a minimum width of the window used, in canonical -frame columns. The special value @code{full-width} means the window -chosen should be one has no other windows on the left or right it in its -frame. +frame columns. The special value @code{full-width} means the chosen +window should be one that has no other windows on the left or right of +it in its frame. This entry is currently honored by @code{display-buffer-use-some-window} -and @code{display-buffer-use-least-recent-window} who try hard to avoid -returning a less recently used window that does not satisfy it. +and @code{display-buffer-use-least-recent-window}, which try hard to avoid +returning a less recently used window that does not satisfy the entry. Note that providing such an entry alone does not necessarily make the window as wide as specified by its value. To actually resize an -existing window or make a new window as wide as specified by that value, -a @code{window-width} entry specifying that value should be provided as -well. Such a @code{window-width} entry can, however, specify a -completely different value or ask the window width to be fit to that of -its buffer in which case the @code{window-min-width} entry provides the -guaranteed minimum width of the window used. +existing window or make a new window as wide as specified by this +entry's value, a @code{window-width} entry specifying that value +should be provided as well. Such a @code{window-width} entry can, +however, specify a completely different value, or ask the window width +to fit that of its buffer, in which case the +@code{window-min-width} entry provides the guaranteed minimum width of +the window. @vindex window-min-height@r{, a buffer display action alist entry} @item window-min-height The value specifies a minimum height of the window used, in canonical -frame lines. The special value @code{full-height} means the window -chosen should be a full-height window, one has no other windows above or -below it in its frame. +frame lines. The special value @code{full-height} means the chosen +window should be a full-height window, one that has no other windows +above or below it in its frame. This entry is currently honored by @code{display-buffer-below-selected} which does not use a window that is not as high as specified by this @@ -3228,7 +3230,7 @@ Buffer Display Action Alists @vindex lru-frames@r{, a buffer display action alist entry} @item lru-frames -The value specifies the set of frames to search for window that can be +The value specifies the set of frames to search for a window that can be used to display the buffer. It is honored by @code{display-buffer-use-some-window} and @code{display-buffer-use-least-recent-window} when trying to find a less @@ -3248,7 +3250,7 @@ Buffer Display Action Alists @item bump-use-time If non-@code{nil}, such an entry will cause @code{display-buffer} to bump the use time (@pxref{Selecting Windows}) of the window it uses. -This should avoid that this window is later used by action functions +This should avoid later use of this window by action functions like @code{display-buffer-use-some-window} and @code{display-buffer-use-least-recent-window} for showing another buffer. @@ -4079,7 +4081,7 @@ The Zen of Buffer Display @code{display-buffer-below-selected} might be preferable because the selected window usually already has the user's attention. -@item Take care about which window is selected +@item Take care which window is selected Many applications call @code{display-buffer} from within window excursions produced by @code{with-selected-window} or @code{select-window} calls with a non-@code{nil} @var{norecord} @@ -4102,6 +4104,7 @@ The Zen of Buffer Display @end group @end example +@noindent will display a window showing the @file{*Messages*} buffer at the bottom and leave the other window selected. Evaluating the next form @@ -4112,6 +4115,7 @@ The Zen of Buffer Display @end group @end example +@noindent will display @file{*Messages*} in a window on the top and select it which is usually not what @code{display-buffer} is supposed to do. @@ -4125,6 +4129,7 @@ The Zen of Buffer Display @end group @end example +@noindent will correctly select the @file{*Messages*} buffer, the next form @example @@ -4136,6 +4141,7 @@ The Zen of Buffer Display @end group @end example +@noindent will not. Also, invocations of action functions like commit 9f508cef85df64ccbafada477bbb17a8439bc839 Author: Martin Rudalics Date: Sun Feb 12 10:33:11 2023 +0100 Fix 'display-buffer-use-least-recent-window' * src/window.c (Fwindow_use_time): Doc fix. (Fwindow_bump_use_time): Bump use time of the seleceted window as well. Doc fix. * lisp/window.el (display-buffer-avoid-small-windows): Remove. All users changed. (window--display-buffer): Bump window use time when requested. (display-buffer--lru-window): New function. (display-buffer-use-some-window): Use it. (display-buffer-use-least-recent-window): Rewrite and enhance doc string. * doc/lispref/windows.texi (Selecting Windows) (Buffer Display Action Functions, Buffer Display Action Alists) (The Zen of Buffer Display): Improve and update documentation of window selection and display facilities. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 441e7f1b16d..1ec645721ca 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -629,6 +629,12 @@ Selecting Windows @code{nil}. Hence, this macro is the preferred way to temporarily work with @var{window} as the selected window without needlessly running @code{buffer-list-update-hook}. + +Note that this macro temporarily puts the window management code in a +unstable state. In particular, the most recently window (see below) +will not necessarily match the selected one. Hence, functions like +@code{get-lru-window} and @code{get-mru-window} may return unexpected +results when called from within the scope of this macro. @end defmac @defmac with-selected-frame frame forms@dots{} @@ -650,15 +656,16 @@ Selecting Windows integer that does increase monotonically with each call of @code{select-window} with a @code{nil} @var{norecord} argument. The window with the lowest use time is usually called the least recently -used window while the window with the highest use time is called the -most recently used one (@pxref{Cyclic Window Ordering}). +used window. The window with the highest use time is called the most +recently used one (@pxref{Cyclic Window Ordering}) and is usually the +selected window unless @code{with-selected-window} has been used. @end defun @defun window-bump-use-time &optional window -This function marks @var{window} as being the most recently used -one. This can be useful when writing certain @code{pop-to-buffer} -scenarios (@pxref{Switching Buffers}). @var{window} must be a live -window and defaults to the selected one. +This function marks @var{window} as being the second most recently used +one. It does nothing if @var{window} is the selected window or the +selected window does not have the highest use time among all windows +which may happen within the scope of @code{with-selected-window}. @end defun @anchor{Window Group}Sometimes several windows collectively and @@ -2755,14 +2762,40 @@ Buffer Display Action Functions @defun display-buffer-use-some-window buffer alist This function tries to display @var{buffer} by choosing an existing -window and displaying the buffer in that window. It can fail if all -windows are dedicated to other buffers (@pxref{Dedicated Windows}). +window and displaying the buffer in that window. It first tries to find +a window that has not been used recently (@pxref{Cyclic Window +Ordering}) on any frame specified by a @code{lru-frames} @var{alist} +entry, falling back to the selected frame if no such entry exists. It +also prefers windows that satisfy the constraints specified by +@code{window-min-width} and @code{window-min-height} @var{alist} +entries; preferring full-width windows if no @code{window-min-width} +entry is found. Finally, it will not return a window whose use time is +higher than that specified by any @code{lru-time} entry provided by +@var{alist}. + +If no less recently used window is found, this function will try to use +some other window, preferably a large window on some visible frame. It +can fail if all windows are dedicated to other buffers (@pxref{Dedicated +Windows}). @end defun @defun display-buffer-use-least-recent-window buffer alist -This function is like @code{display-buffer-use-some-window}, but will -not reuse the current window, and will use the least recently -switched-to window. +This function is similar to @code{display-buffer-use-some-window}, but +will try harder to not use the a recently used window. In particular, +it does not use the selected window. In addition, it will first try to +reuse a window that shows @var{buffer} already, base the decision +whether it should use a window showing another buffer on that window's +use time alone and pop up a new window if no usable window is found. + +Finally, this function will bump the use time (@pxref{Selecting +Windows}) of any window it returns in order to avoid that further +invocations will use that window for showing another buffer. An +application that wants to display several buffers in a row can help this +function by providing a @code{lru-time} @var{alist} entry it has +initially set to the value of the selected window's use time. Each +invocation of this function will then bump the use time of the window +returned to a value higher than that and a subsequent invocation will +inhibit this function to use a window it returned earlier. @end defun @defun display-buffer-in-direction buffer alist @@ -3032,12 +3065,39 @@ Buffer Display Action Alists window. All action functions that choose a window should process this entry. +@vindex window-min-width@r{, a buffer display action alist entry} +@item window-min-width +The value specifies a minimum width of the window used, in canonical +frame columns. The special value @code{full-width} means the window +chosen should be one has no other windows on the left or right it in its +frame. + +This entry is currently honored by @code{display-buffer-use-some-window} +and @code{display-buffer-use-least-recent-window} who try hard to avoid +returning a less recently used window that does not satisfy it. + +Note that providing such an entry alone does not necessarily make the +window as wide as specified by its value. To actually resize an +existing window or make a new window as wide as specified by that value, +a @code{window-width} entry specifying that value should be provided as +well. Such a @code{window-width} entry can, however, specify a +completely different value or ask the window width to be fit to that of +its buffer in which case the @code{window-min-width} entry provides the +guaranteed minimum width of the window used. + @vindex window-min-height@r{, a buffer display action alist entry} @item window-min-height -The value specifies a minimum height of the window used, in lines. If -a window is not or cannot be made as high as specified by this entry, -the window is not considered for use. The only client of this entry -is presently @code{display-buffer-below-selected}. +The value specifies a minimum height of the window used, in canonical +frame lines. The special value @code{full-height} means the window +chosen should be a full-height window, one has no other windows above or +below it in its frame. + +This entry is currently honored by @code{display-buffer-below-selected} +which does not use a window that is not as high as specified by this +entry. It's also honored by @code{display-buffer-use-some-window} and +@code{display-buffer-use-least-recent-window} which try hard to avoid +returning a less recently used window if it does not satisfy this +constraint. Note that providing such an entry alone does not necessarily make the window as tall as specified by its value. To actually resize an @@ -3166,6 +3226,40 @@ Buffer Display Action Alists processed only under certain conditions which are specified right after this list. +@vindex lru-frames@r{, a buffer display action alist entry} +@item lru-frames +The value specifies the set of frames to search for window that can be +used to display the buffer. It is honored by +@code{display-buffer-use-some-window} and +@code{display-buffer-use-least-recent-window} when trying to find a less +recently used window showing some other buffer. Its values are the same +as for the @code{reusable-frames} entry described above. + +@vindex lru-time@r{, a buffer display action alist entry} +@item lru-time +The value is supposed to specify a use time (@pxref{Selecting Windows}). +This entry is honored by @code{display-buffer-use-some-window} and +@code{display-buffer-use-least-recent-window} when trying to find a less +recently used window showing some other buffer. If a window's use time +is higher than the value specified by this option, these action +functions will not consider such a window for displaying the buffer. + +@vindex bump-use-time@r{, a buffer display action alist entry} +@item bump-use-time +If non-@code{nil}, such an entry will cause @code{display-buffer} to +bump the use time (@pxref{Selecting Windows}) of the window it uses. +This should avoid that this window is later used by action functions +like @code{display-buffer-use-some-window} and +@code{display-buffer-use-least-recent-window} for showing another +buffer. + +There is a fine difference between using this entry and using the action +function @code{display-buffer-use-least-recent-window}. Calling the +latter means to only bump the use times of windows that function uses +for displaying the buffer. The entry described here will cause +@code{display-buffer} to bump the use time of @emph{any} window used for +displaying a buffer. + @vindex pop-up-frame-parameters@r{, a buffer display action alist entry} @item pop-up-frame-parameters The value specifies an alist of frame parameters to give a new frame, @@ -3321,13 +3415,6 @@ Choosing Window Options that means not to split this way. @end defopt -@defopt display-buffer-avoid-small-windows -If non-@code{nil}, this should be a number. Windows that have fewer -lines than that will be avoided when choosing an existing window. The -value is interpreted in units of the frame's canonical line height, -like @code{window-total-height} does (@pxref{Window Sizes}). -@end defopt - @defopt even-window-sizes This variable, if non-@code{nil}, causes @code{display-buffer} to even window sizes whenever it reuses an existing window, and that window is @@ -3992,53 +4079,75 @@ The Zen of Buffer Display @code{display-buffer-below-selected} might be preferable because the selected window usually already has the user's attention. -@item Handle subsequent invocations of @code{display-buffer} -@code{display-buffer} is not overly well suited for displaying several -buffers in sequence and making sure that all these buffers are shown -orderly in the resulting window configuration. Again, the standard -action functions @code{display-buffer-pop-up-window} and -@code{display-buffer-use-some-window} are not very suited for this -purpose due to their somewhat chaotic nature in more complex -configurations. +@item Take care about which window is selected +Many applications call @code{display-buffer} from within window +excursions produced by @code{with-selected-window} or +@code{select-window} calls with a non-@code{nil} @var{norecord} +argument. This is almost always a bad idea because the window selected +within such an excursion is usually not the window selected in the +configuration presented to the user. + +If, for example, a user had added an @code{inhibit-same-window} alist +entry, that entry would have avoided the window selected within the +scope of the excursion and not the window selected in the resulting +configuration. Even if no such entry has been added, the resulting +behavior might be strange. While in a frame containing one live +window, evaluating the following form - To produce a window configuration displaying multiple buffers (or -different views of one and the same buffer) in one and the same -display cycle, Lisp programmers will unavoidably have to write -their own action functions. A few tricks listed below might help in -this regard. +@example +@group +(progn + (split-window) + (display-buffer "*Messages*")) +@end group +@end example -@itemize @bullet -@item -Making windows atomic (@pxref{Atomic Windows}) avoids breaking an -existing window composition when popping up a new window. -The new window will pop up outside the composition instead. +will display a window showing the @file{*Messages*} buffer at the bottom +and leave the other window selected. Evaluating the next form -@item -Temporarily dedicating windows to their buffers (@pxref{Dedicated -Windows}) avoids using a window for displaying a different -buffer. A non-dedicated window will be used instead. +@example +@group +(with-selected-window (split-window) + (display-buffer "*Messages*")) +@end group +@end example -@item -Calling @code{window-preserve-size} (@pxref{Preserving Window Sizes}) -will try to keep the size of the argument window unchanged when -popping up a new window. You have to make sure that another window in -the same combination can be shrunk instead, though. +will display @file{*Messages*} in a window on the top and select it +which is usually not what @code{display-buffer} is supposed to do. -@item -Side windows (@pxref{Side Windows}) can be used for displaying -specific buffers always in a window at the same position of a frame. -This permits grouping buffers that do not compete for being shown at -the same time on a frame and showing any such buffer in the same window -without disrupting the display of other buffers. +On the other hand, while evaluating the following form -@item -Child frames (@pxref{Child Frames}) can be used to display a buffer -within the screen estate of the selected frame without disrupting that -frame's window configuration and without the overhead associated with -full-fledged frames as inflicted by @code{display-buffer-pop-up-frame}. -@end itemize -@end table +@example +@group +(progn + (split-window) + (pop-to-buffer "*Messages*")) +@end group +@end example + +will correctly select the @file{*Messages*} buffer, the next form + +@example +@group +(progn + (split-window) + (with-selected-window (selected-window) + (pop-to-buffer "*Messages*"))) +@end group +@end example + +will not. +Also, invocations of action functions like +@code{display-buffer-use-some-window} and +@code{display-buffer-use-least-recent-window} that expect the selected +window to have the highest use time among all windows, may fail to +produce a window according to their specifications. + +Hence, an application that relies on using a window excursion should try +to postpone the @code{display-buffer} call until after the excursion has +terminated. +@end table @node Window History @section Window History diff --git a/lisp/window.el b/lisp/window.el index 2d9f746d8fb..083fa9bfd2f 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -2484,14 +2484,6 @@ get-window-with-predicate (defalias 'some-window 'get-window-with-predicate) -(defcustom display-buffer-avoid-small-windows nil - "If non-nil, windows that have fewer lines than this are avoided. -This is used by `get-lru-window'. The value is interpreted in units -of the frame's canonical line height, like `window-total-height' does." - :type '(choice (const nil) number) - :version "29.1" - :group 'windows) - (defun get-lru-window (&optional all-frames dedicated not-selected no-other) "Return the least recently used window on frames specified by ALL-FRAMES. Return a full-width window if possible. A minibuffer window is @@ -2517,11 +2509,7 @@ get-lru-window - A frame means consider all windows on that frame only. Any other value of ALL-FRAMES means consider all windows on the -selected frame and no others. - -`display-buffer-avoid-small-windows', if non-nil, is also taken into -consideration. Windows whose height is smaller that the value of that -variable will be avoided if larger windows are available." +selected frame and no others." (let ((windows (window-list-1 nil 'nomini all-frames)) best-window best-time second-best-window second-best-time time) (dolist (window windows) @@ -2531,9 +2519,6 @@ get-lru-window (not (window-parameter window 'no-other-window)))) (setq time (window-use-time window)) (if (or (eq window (selected-window)) - (and display-buffer-avoid-small-windows - (< (window-height window) - display-buffer-avoid-small-windows)) (not (window-full-width-p window))) (when (or (not second-best-time) (< time second-best-time)) (setq second-best-time time) @@ -7274,6 +7259,11 @@ window--display-buffer dedicated flag to that value. In any other case, reset WINDOW's dedicated flag to nil. +If ALIST contains a non-nil `bump-use-time' entry, bump use time +of WINDOW so further calls of `display-buffer-use-some-window' +and `display-buffer-use-least-recent-window' will try to avoid +it. + Return WINDOW if BUFFER and WINDOW are live." (when (and (buffer-live-p buffer) (window-live-p window)) (display-buffer-record-window type window buffer) @@ -7281,6 +7271,10 @@ window--display-buffer ;; Unless WINDOW already shows BUFFER reset its dedicated flag. (set-window-dedicated-p window nil) (set-window-buffer window buffer)) + (when (cdr (assq 'bump-use-time alist)) + ;; Bump WINDOW's use time so 'display-buffer--lru-window' will try + ;; to avoid it. + (window-bump-use-time window)) (let ((alist-dedicated (assq 'dedicated alist))) ;; Maybe dedicate WINDOW to BUFFER if asked for. (cond @@ -8502,15 +8496,64 @@ display-buffer-in-previous-window (when (setq window (or best-window second-best-window)) (window--display-buffer buffer window 'reuse alist)))) -(defun display-buffer-use-least-recent-window (buffer alist) - "Display BUFFER in an existing window, but that hasn't been used lately. -This `display-buffer' action function is like -`display-buffer-use-some-window', but will cycle through windows -when displaying buffers repeatedly, and if there's only a single -window, it will split the window." - (when-let ((window (display-buffer-use-some-window - buffer (cons (cons 'inhibit-same-window t) alist)))) - (window-bump-use-time window))) +(defun display-buffer--lru-window (alist) + "Return the least recently used window according to ALIST. +Do not return a minibuffer window or a window dedicated to its +buffer. ALIST is a buffer display action alist as compiled by +`display-buffer'. The following ALIST entries are honored: + +- `lru-frames' specifies the frames to investigate and has the + same meaning as the ALL-FRAMES argument of `get-lru-window'. + +- `lru-time' specifies a use time. Do not return a window whose + use time is higher than this. + +- `window-min-width' specifies a preferred minimum width in + canonical frame columns. If it is the constant `full-width', + prefer a full-width window. + +- `window-min-height' specifies a preferred minimum height in + canonical frame lines. If it is the constant `full-height', + prefer a full-height window. + +If ALIST contains a non-nil `inhibit-same--window' entry, do not +return the selected window." + (let ((windows + (window-list-1 nil 'nomini (cdr (assq 'lru-frames alist)))) + (lru-time (cdr (assq 'lru-time alist))) + (min-width (cdr (assq 'window-min-width alist))) + (min-height (cdr (assq 'window-min-height alist))) + (not-this-window (cdr (assq 'inhibit-same-window alist))) + best-window best-time second-best-window second-best-time time) + (dolist (window windows) + (when (and (not (window-dedicated-p window)) + (or (not not-this-window) + (not (eq window (selected-window))))) + (setq time (window-use-time window)) + (unless (and (numberp lru-time) (> time lru-time)) + (if (or (eq window (selected-window)) + (and min-width + (or (and (numberp min-width) + (< (window-width window) min-width)) + (and (eq min-width 'full-width) + (not (window-full-width-p window))))) + (and min-height + (or (and (numberp min-height) + (< (window-height window) min-height)) + (and (eq min-height 'full-height) + (not (window-full-height-p window)))))) + ;; This window is either selected or does not meet the size + ;; restrictions - so it's only a second best choice. Try to + ;; find a more recently used one that fits. + (when (or (not second-best-time) (< time second-best-time)) + (setq second-best-time time) + (setq second-best-window window)) + ;; This window is not selected and does meet the size + ;; restrictions. It's the best choice so far. + (when (or (not best-time) (< time best-time)) + (setq best-time time) + (setq best-window window)))))) + (or best-window second-best-window))) (defun display-buffer-use-some-window (buffer alist) "Display BUFFER in an existing window. @@ -8534,7 +8577,11 @@ display-buffer-use-some-window (window--frame-usable-p (last-nonminibuffer-frame)))) (window ;; Reuse an existing window. - (or (get-lru-window frame nil not-this-window) + (or (display-buffer--lru-window + ;; If ALIST specifies 'lru-frames' or 'window-min-width' + ;; let them prevail. + (append alist `((lru-frames . ,frame) + (window-min-width . full-width)))) (let ((window (get-buffer-window buffer 'visible))) (unless (and not-this-window (eq window (selected-window))) @@ -8564,6 +8611,76 @@ display-buffer-use-some-window (unless (cdr (assq 'inhibit-switch-frame alist)) (window--maybe-raise-frame (window-frame window))))))) +(defun display-buffer-use-least-recent-window (buffer alist) + "Display BUFFER trying to avoid windows used recently. +This is similar to `display-buffer-use-some-window' but tries +hard to avoid using a window recently used by `display-buffer'. + +Distinctive features are: + +- Do not use the selected window. + +- Try first to reuse a window that shows BUFFER already on a + frame specified by a `reusable-frames' ALIST entry, using the + selected frame if no such entry has been specified. + +- Next try to show BUFFER in the least recently used window. The + frames to search for such a window can be specified via a + `lru-frames' ALIST entry; if no such entry exists, search the + selected frame only. In addition, try to satisfy constraints + specified by the following ALIST entries, if present: + + `lru-time' specifies a use time. Do not return a window whose + use time is higher than this. When calling this action + function repeatedly (presumably to display several buffers in + a row), an application should first save the use time of the + selected window and pass that same value via such an entry in + each call of `display-buffer'. This reduces the probability + that `display-buffer' uses the same window as a previous + call. + + `window-min-width' specifies a preferred minimum width in + canonical frame columns. If it is the constant `full-width', + prefer a full-width window. + + `window-min-height' specifies a preferred minimum height in + canonical frame lines. If it is the constant `full-height', + prefer a full-height window. + +- If the preceding steps fail, try to pop up a new window on the + selected frame. + +If a window is found, bump the use time of that window to the +highest use time after the selected window. This makes it less +probable that a future invocation of this function uses that +window for another buffer." + (let* ((alist (cons (cons 'inhibit-same-window t) alist)) + (window + (or (display-buffer-reuse-window buffer alist) + (let ((window (display-buffer--lru-window alist))) + (when (window-live-p window) + (let* ((quit-restore (window-parameter window 'quit-restore)) + (quad (nth 1 quit-restore))) + ;; If the window was used by `display-buffer' before, try to + ;; resize it to its old height but don't signal an error. + (when (and (listp quad) + (integerp (nth 3 quad)) + (> (nth 3 quad) (window-total-height window))) + (condition-case nil + (window-resize + window (- (nth 3 quad) (window-total-height window))) + (error nil))) + (prog1 + (window--display-buffer buffer window 'reuse alist) + (window--even-window-sizes window) + (unless (cdr (assq 'inhibit-switch-frame alist)) + (window--maybe-raise-frame (window-frame window))))))) + (display-buffer-pop-up-window buffer alist)))) + ;; Don't bump use time twice. + (when (and window (not (cdr (assq 'bump-use-time alist)))) + (window-bump-use-time window)) + window)) + (defun display-buffer-no-window (_buffer alist) "Display BUFFER in no window. ALIST is an association list of action symbols and values. See diff --git a/src/window.c b/src/window.c index 6201a6f4a36..a94e1d611c7 100644 --- a/src/window.c +++ b/src/window.c @@ -762,10 +762,15 @@ DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_windo DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0, doc: /* Return the use time of window WINDOW. -WINDOW must be a live window and defaults to the selected one. -The window with the highest use time is the most recently selected -one. The window with the lowest use time is the least recently -selected one. */) +WINDOW must specify a live window and defaults to the selected one. + +The window with the highest use time is usually the one most recently +selected by calling `select-window' with NORECORD nil. The window with +the lowest use time is usually the least recently selected one chosen in +such a way. + +Note that the use time of a window can be also changed by calling +`window-bump-use-time' for that window. */) (Lisp_Object window) { return make_fixnum (decode_live_window (window)->use_time); @@ -773,15 +778,27 @@ DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0, DEFUN ("window-bump-use-time", Fwindow_bump_use_time, Swindow_bump_use_time, 0, 1, 0, - doc: /* Mark WINDOW as having been most recently used. -WINDOW must be a live window and defaults to the selected one. */) + doc: /* Mark WINDOW as second most recently used. +WINDOW must specify a live window. + +If WINDOW is not selected and the selected window has the highest use +time of all windows, set the use time of WINDOW to that of the selected +window, increase the use time of the selected window by one and return +the new use time of WINDOW. Otherwise, do nothing and return nil. */) (Lisp_Object window) { struct window *w = decode_live_window (window); + struct window *sw = XWINDOW (selected_window); - w->use_time = ++window_select_count; + if (w != sw && sw->use_time == window_select_count) + { + w->use_time = window_select_count; + sw->use_time = ++window_select_count; - return Qnil; + return make_fixnum (w->use_time); + } + else + return Qnil; } DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0, commit 5190ea6259a5fd13ba5e87b92b20f450658cf532 Author: kobarity Date: Tue Feb 14 00:30:15 2023 +0900 Fix point moving when calling python-shell-send-region * lisp/progmodes/python.el (python-shell-buffer-substring): Add `save-excursion' to prevent the point from moving. * test/lisp/progmodes/python-tests.el (python-tests-should-not-move): New helper function to assert that point does not move while calling a function. (python-shell-buffer-substring-*): Use `python-tests-should-not-move'. (Bug#61463) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index df0d1c96965..0d714c31e9e 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -3759,14 +3759,15 @@ python-shell-buffer-substring whitespaces will be removed. Otherwise, wraps indented regions under an \"if True:\" block so the interpreter evaluates them correctly." - (let* ((single-p (save-restriction - (narrow-to-region start end) - (= (progn - (goto-char start) - (python-nav-beginning-of-statement)) - (progn - (goto-char end) - (python-nav-beginning-of-statement))))) + (let* ((single-p (save-excursion + (save-restriction + (narrow-to-region start end) + (= (progn + (goto-char start) + (python-nav-beginning-of-statement)) + (progn + (goto-char end) + (python-nav-beginning-of-statement)))))) (start (save-excursion ;; If we're at the start of the expression, and if ;; the region consists of a single statement, then @@ -3785,10 +3786,11 @@ python-shell-buffer-substring (line-beginning-position) start)))) (substring (buffer-substring-no-properties start end)) - (starts-at-first-line-p (save-restriction - (widen) - (goto-char start) - (= (line-number-at-pos) 1))) + (starts-at-first-line-p (save-excursion + (save-restriction + (widen) + (goto-char start) + (= (line-number-at-pos) 1)))) (encoding (python-info-encoding)) (toplevel-p (zerop (save-excursion (goto-char start) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index df71990278e..4f24c042c6a 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -189,6 +189,14 @@ python-tests-visible-string (overlay-end overlay)))) (buffer-substring-no-properties (point-min) (point-max))))) +(defun python-tests-should-not-move (func &rest args) + "Assert that point does not move while calling FUNC with ARGS. +Returns the value returned by FUNC." + (let ((pos (point)) + (ret (apply func args))) + (should (= pos (point))) + ret)) + (defun python-virt-bin (&optional virt-root) "Return the virtualenv bin dir, starting from VIRT-ROOT. If nil, VIRT-ROOT defaults to `python-shell-virtualenv-root'. @@ -4213,7 +4221,8 @@ python-shell-buffer-substring-1 pass " (should (string= (buffer-string) - (python-shell-buffer-substring (point-min) (point-max)))))) + (python-tests-should-not-move + #'python-shell-buffer-substring (point-min) (point-max)))))) (ert-deftest python-shell-buffer-substring-2 () "Main block should be removed if NOMAIN is non-nil." @@ -4229,7 +4238,8 @@ python-shell-buffer-substring-2 foo = Foo() print (foo) " - (should (string= (python-shell-buffer-substring (point-min) (point-max) t) + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (point-min) (point-max) t) " class Foo(models.Model): pass @@ -4256,7 +4266,8 @@ python-shell-buffer-substring-3 class Bar(models.Model): pass " - (should (string= (python-shell-buffer-substring (point-min) (point-max) t) + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (point-min) (point-max) t) " class Foo(models.Model): pass @@ -4284,7 +4295,8 @@ python-shell-buffer-substring-4 class Bar(models.Model): pass " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "class Foo(models.Model):") (progn (python-nav-forward-sexp) (point))) "# -*- coding: latin-1 -*- @@ -4307,7 +4319,8 @@ python-shell-buffer-substring-5 class Bar(models.Model): pass " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "class Bar(models.Model):") (progn (python-nav-forward-sexp) (point))) "# -*- coding: latin-1 -*- @@ -4338,7 +4351,8 @@ python-shell-buffer-substring-6 class Bar(models.Model): pass " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "# coding: latin-1") (python-tests-look-at "if __name__ == \"__main__\":")) "# -*- coding: latin-1 -*- @@ -4365,7 +4379,8 @@ python-shell-buffer-substring-7 class Bar(models.Model): pass " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "# coding: latin-1") (python-tests-look-at "if __name__ == \"__main__\":")) "# -*- coding: utf-8 -*- @@ -4385,7 +4400,8 @@ python-shell-buffer-substring-8 class Foo(models.Model): pass " - (should (string= (python-shell-buffer-substring (point-min) (point-max)) + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (point-min) (point-max)) "# coding: utf-8 @@ -4404,7 +4420,8 @@ python-shell-buffer-substring-9 class Bar(models.Model): pass " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (point-min) (python-tests-look-at "class Bar(models.Model):")) "# coding: utf-8 @@ -4421,7 +4438,8 @@ python-shell-buffer-substring-10 def foo(): print ('a') " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "print ('a')") (point-max)) "# -*- coding: utf-8 -*-\nif True:\n print ('a')\n\n")))) @@ -4433,7 +4451,8 @@ python-shell-buffer-substring-11 def foo(): print ('a') " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (progn (python-tests-look-at "print ('a')") (backward-char 1) @@ -4451,7 +4470,8 @@ python-shell-buffer-substring-12 print ('a') " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "# Whitespace") (point-max)) "# -*- coding: utf-8 -*-\n\nif True:\n # Whitespace\n\n print ('a')\n\n")))) @@ -4463,7 +4483,8 @@ python-shell-buffer-substring-13 def foo(): a = 1 " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "a = 1") (pos-eol)) "# -*- coding: utf-8 -*-\n\na = 1")))) @@ -4476,7 +4497,8 @@ python-shell-buffer-substring-14 a = \"\"\"Some string\"\"\" " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "a = \"\"\"Some") (pos-eol 2)) "# -*- coding: utf-8 -*-\n\na = \"\"\"Some\n string\"\"\"")))) @@ -4488,7 +4510,8 @@ python-shell-buffer-substring-15 def foo(): a = 1 " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at " a = 1") (python-tests-look-at " = 1")) "# -*- coding: utf-8 -*-\n\na")))) @@ -4500,7 +4523,8 @@ python-shell-buffer-substring-16 def foo(): a = 1 " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "1") (1+ (point))) "# -*- coding: utf-8 -*-\n\n1")))) @@ -4515,7 +4539,8 @@ python-shell-buffer-substring-17 b = 2 \"\"\" " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "a = 1") (python-tests-look-at "\"\"\"")) "# -*- coding: utf-8 -*-\n\nif True:\n a = 1\n b = 2\n\n")))) @@ -4525,7 +4550,8 @@ python-shell-buffer-substring-18 (python-tests-with-temp-buffer "s = 'test' " - (should (string= (python-shell-buffer-substring + (should (string= (python-tests-should-not-move + #'python-shell-buffer-substring (python-tests-look-at "'test'") (pos-eol)) "'test'")))) commit 6c0d8210175e72dcd7cef2ad77b8f8b680b240bc Author: Omar Polo Date: Sat Feb 18 15:10:57 2023 +0200 (project-try-vc): Remove unused defvar/require * lisp/progmodes/project.el (project-try-vc): Remove unused defvar/require (bug#61577). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 1228c73fee8..11228226592 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1,7 +1,7 @@ ;;; project.el --- Operations on the current project -*- lexical-binding: t; -*- ;; Copyright (C) 2015-2023 Free Software Foundation, Inc. -;; Version: 0.9.7 +;; Version: 0.9.8 ;; Package-Requires: ((emacs "26.1") (xref "1.4.0")) ;; This is a GNU ELPA :core package. Avoid using functionality that @@ -512,8 +512,6 @@ project-vc-backend-markers-alist See `project-vc-extra-root-markers' for the marker value format.") (defun project-try-vc (dir) - (defvar vc-svn-admin-directory) - (require 'vc-svn) ;; FIXME: Learn to invalidate when the value of ;; `project-vc-merge-submodules' or `project-vc-extra-root-markers' ;; changes. commit 4f9862e435617c38a8472f3d002e2f3163041ca1 Author: Stefan Kangas Date: Sat Feb 18 13:39:14 2023 +0100 ; Fix typo diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el index 98e50f53b5f..d4200c16c19 100644 --- a/lisp/emacs-lisp/comp-cstr.el +++ b/lisp/emacs-lisp/comp-cstr.el @@ -483,7 +483,7 @@ comp-cstr-sub-2 ;;; Union specific code. (defun comp-cstr-union-homogeneous-no-range (dst &rest srcs) - "As `comp-cstr-union' but escluding the irange component. + "As `comp-cstr-union' but excluding the irange component. All SRCS constraints must be homogeneously negated or non-negated." ;; Type propagation. commit a638c79bc5cde55efa467dd83ae49f404753f549 Author: Stefan Kangas Date: Sat Feb 18 13:35:37 2023 +0100 Delete redundant question from Gnus FAQ * doc/misc/gnus-faq.texi (FAQ 1-2): Delete redundant question. (FAQ 1-1, FAQ 1-3): Adjust accordingly. diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi index f7d528511a0..eb416fe47d6 100644 --- a/doc/misc/gnus-faq.texi +++ b/doc/misc/gnus-faq.texi @@ -76,16 +76,15 @@ FAQ 1 - Installation FAQ @subsection Installation FAQ @menu -* FAQ 1-1:: What is the latest version of Gnus? -* FAQ 1-2:: Where and how to get Gnus? -* FAQ 1-3:: I sometimes read references to No Gnus and Oort Gnus, +* FAQ 1-1:: Where can I get the latest version of Gnus? +* FAQ 1-2:: I sometimes read references to No Gnus and Oort Gnus, what are those? @end menu @node FAQ 1-1 @subsubheading Question 1.1 -What is the latest version of Gnus? +What is the latest version of Gnus and where can I find it? @subsubheading Answer @@ -94,15 +93,6 @@ FAQ 1-1 @node FAQ 1-2 @subsubheading Question 1.2 -Where and how to get Gnus? - -@subsubheading Answer - -Gnus is bundled with Emacs. - -@node FAQ 1-3 -@subsubheading Question 1.3 - I sometimes read references to No Gnus and Oort Gnus, what are those? commit 4a90d67eb6837c2a32f245985a0a2f166d9d1786 Author: Stefan Kangas Date: Sat Feb 18 13:00:04 2023 +0100 Slightly improve hashcash documentation * lisp/mail/hashcash.el: Improve Commentary. (hashcash-program): * lisp/gnus/message.el (message-generate-hashcash): Improve docstring. diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index c697b8d7a7f..f4cfffa2e8a 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -1926,9 +1926,10 @@ message-generate-hashcash "Whether to generate X-Hashcash: headers. If t, always generate hashcash headers. If `opportunistic', only generate hashcash headers if it can be done without the user -waiting (i.e., only asynchronously). +waiting (i.e., only asynchronously). If nil, don't generate +hashcash headers. -You must have the \"hashcash\" binary installed, see `hashcash-path'." +You must have the \"hashcash\" binary installed, see `hashcash-program'." :version "24.1" :group 'message-headers :link '(custom-manual "(message)Mail Headers") diff --git a/lisp/mail/hashcash.el b/lisp/mail/hashcash.el index 72d532d6f62..ecc03bfb537 100644 --- a/lisp/mail/hashcash.el +++ b/lisp/mail/hashcash.el @@ -25,16 +25,16 @@ ;; The hashcash binary is at http://www.hashcash.org/. ;; -;; Call mail-add-payment to add a hashcash payment to a mail message +;; Call `mail-add-payment' to add a hashcash payment to a mail message ;; in the current buffer. ;; -;; Call mail-add-payment-async after writing the addresses but before -;; writing the mail to start calculating the hashcash payment +;; Call `mail-add-payment-async' after writing the addresses but +;; before writing the mail to start calculating the hashcash payment ;; asynchronously. ;; -;; The easiest way to do this automatically for all outgoing mail -;; is to set `message-generate-hashcash' to t. If you want more -;; control, try the following hooks. +;; The easiest way to do this automatically for all outgoing mail is +;; to set `message-generate-hashcash' to `opportunistic' or t. If you +;; want more control, try the following hooks. ;; ;; To automatically add payments to all outgoing mail when sending: ;; (add-hook 'message-send-hook 'mail-add-payment) @@ -44,6 +44,8 @@ ;; ;; To check whether calculations are done before sending: ;; (add-hook 'message-send-hook 'hashcash-wait-or-cancel) +;; +;; For more information, see Info node `(gnus) Hashcash'. ;;; Code: @@ -87,7 +89,9 @@ hashcash-accept-resources (define-obsolete-variable-alias 'hashcash-path 'hashcash-program "24.4") (defcustom hashcash-program "hashcash" "The name of the hashcash executable. -If this is not in your PATH, specify an absolute file name." +If this is not in your PATH, specify an absolute file name. + +See also `message-generate-hashcash'." :type '(choice (const nil) file)) (defcustom hashcash-extra-generate-parameters '("-Z2") commit 6ea3c105ab1377030e470afd02eabbf3e6570c6c Author: Eli Zaretskii Date: Sat Feb 18 13:40:56 2023 +0200 Fix cursor motion when there's line-prefix and display string at BOL * src/xdisp.c (move_it_in_display_line_to): Handle 'line-prefix' and 'wrap-prefix' when the screen line has a display string at its beginning. (Bug#61580) diff --git a/src/xdisp.c b/src/xdisp.c index 1f630de7586..f5d54974b13 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -9609,8 +9609,8 @@ #define BUFFER_POS_REACHED_P() \ else line_number_pending = true; } - /* If there's a line-/wrap-prefix, handle it. */ - if (it->method == GET_FROM_BUFFER) + /* If there's a line-/wrap-prefix, handle it, if we didn't already. */ + if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p) handle_line_prefix (it); } commit e985466556c71743ec9f47ee969bb4f45da141aa Author: Yuan Fu Date: Sat Feb 18 02:20:12 2023 -0800 Fix comment in treesit_record_change (bug#61369) Turns out the previous commit message and comment is not entirely correct: the old behavior is in fact wrong, not just "correct but has problems". Here is why the old code is wrong: |visible range| -> markup for visible range updated range -> markup for updated range ------------- First we have some text |aaaaaa| Now we insert something at the beginning, because we clip new_end_offset to visible_end, out of eight b's inserted, only the first six are known to tree-sitter. |bbbbbbbbaaaa|aa start: 0, old_end: 0, new_end: 6 ------ In treesit_sync_visible_region, we sync up visible region, but the two missing b's are not in the updated range. |bbbbbbbbaaaaaa| start: 12, old_end: 12, new_end: 14 -- The old behavior not only is wrong, but also doesn't make much sense. * src/treesit.c (treesit_record_change): Update comment. diff --git a/src/treesit.c b/src/treesit.c index e1d6f1ef79f..ef0f2407840 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -797,12 +797,10 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, max (visible_beg, old_end_byte)) - visible_beg); /* We don't clip new_end_offset under visible_end, because - inserting in narrowed region always extends the visible - region. If we clip new_end_offset here, and re-add the - clipped "tail" in treesit_sync_visible_region later, - while it is technically equivalent, tree-sitter's - incremental parsing algorithm doesn't seem to like it - (bug#61369). */ + otherwise we would miss updating the clipped part. Plus, + when inserting in narrowed region, the narrowed region + will grow to accommodate the new text, so this is the + correct behavior. (Bug#61369). */ ptrdiff_t new_end_offset = (max (visible_beg, new_end_byte) - visible_beg); eassert (start_offset <= old_end_offset); commit 1e5cebc88bb5f028058e072071fee03529d0b204 Author: Stefan Kangas Date: Sat Feb 18 10:57:27 2023 +0100 Spell out RPN abbreviation in Calc manual intro * doc/misc/calc.texi (What is Calc, Demonstration of Calc) (RPN Tutorial): Spell out "Reverse Polish notation" abbreviation. diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi index c3e32433fc4..ac6604473a8 100644 --- a/doc/misc/calc.texi +++ b/doc/misc/calc.texi @@ -232,7 +232,8 @@ What is Calc @itemize @bullet @item -Choice of algebraic or RPN (stack-based) entry of calculations. +Choice of algebraic or Reverse Polish notation (RPN), +i.e. stack-based, entry of calculations. @item Arbitrary precision integers and floating-point numbers. @@ -421,8 +422,8 @@ Demonstration of Calc @key{RET}, @key{TAB}, @key{DEL}, and @key{SPC} are the Return, Tab, Delete, and Space keys. -@strong{RPN calculation.} In RPN, you type the input number(s) first, -then the command to operate on the numbers. +@strong{RPN calculation.} In Reverse Polish notation (RPN), you type +the input number(s) first, then the command to operate on the numbers. @noindent Type @kbd{2 @key{RET} 3 + Q} to compute @@ -1348,18 +1349,19 @@ RPN Tutorial @subsection RPN Calculations and the Stack @cindex RPN notation +@cindex Reverse Polish notation @noindent @ifnottex -Calc normally uses RPN notation. You may be familiar with the RPN -system from Hewlett-Packard calculators, FORTH, or PostScript. -(Reverse Polish Notation, RPN, is named after the Polish mathematician -Jan Lukasiewicz.) +Calc normally uses Reverse Polish notation (RPN). You may be familiar +with the RPN system from Hewlett-Packard calculators, FORTH, or +PostScript. (Reverse Polish Notation is named after the Polish +mathematician Jan Lukasiewicz.) @end ifnottex @tex -Calc normally uses RPN notation. You may be familiar with the RPN -system from Hewlett-Packard calculators, FORTH, or PostScript. -(Reverse Polish Notation, RPN, is named after the Polish mathematician -Jan \L ukasiewicz.) +Calc normally uses Reverse Polish notation (RPN). You may be familiar +with the RPN system from Hewlett-Packard calculators, FORTH, or +PostScript. (Reverse Polish Notation is named after the Polish +mathematician Jan \L ukasiewicz.) @end tex The central component of an RPN calculator is the @dfn{stack}. A