diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 750c4b47894..052a10e3797 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -5111,8 +5111,11 @@ This anchor is a function that is called with 3 arguments: @var{node}, @var{parent}, and @var{bol}. It tries to go to the beginning of the previous non-empty line, and matches @code{adaptive-fill-regexp}. If there is a match, this function returns the end of the match, -otherwise it returns nil. This anchor is useful for a -@code{indent-relative}-like indent behavior for block comments. +otherwise it returns nil. However, if the current line begins with a +prefix (e.g., ``-''), return the beginning of the prefix of the +previous line instead, so that the two prefixes aligns. This anchor +is useful for a @code{indent-relative}-like indent behavior for block +comments. @end ftable @end defvar diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index 7be8b630412..850930a290f 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -1214,7 +1214,7 @@ Suffix specifications have this form: @lisp ([@var{LEVEL}] - [@var{KEY}] [@var{DESCRIPTION}] + [@var{KEY} [@var{DESCRIPTION}]] @var{COMMAND}|@var{ARGUMENT} [@var{KEYWORD} @var{VALUE}]...) @end lisp @@ -1253,8 +1253,7 @@ Any command will do; it does not need to have an object associated with it (as would be the case if @code{transient-define-suffix} or @code{transient-define-infix} were used to define it). -Anonymous, dynamically defined suffix commands are also supported. -See information about the @code{:setup-children} function in @ref{Group Specifications}. +COMMAND can also be a @code{lambda} expression. As mentioned above, the object that is associated with a command can be used to set the default for certain values that otherwise have to diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 872c757be1f..9674b5c30e9 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -3813,8 +3813,8 @@ Return the trampoline if found or nil otherwise." ;; found. finally (cl-return (expand-file-name - (make-temp-file-internal (file-name-sans-extension rel-filename) - 0 ".eln" nil) + (make-temp-file (file-name-sans-extension rel-filename) 0 ".eln" + nil) temporary-file-directory)))) (defun comp-trampoline-compile (subr-name) diff --git a/lisp/org/ob-octave.el b/lisp/org/ob-octave.el index 9bf16b9849c..1de263a52d0 100644 --- a/lisp/org/ob-octave.el +++ b/lisp/org/ob-octave.el @@ -243,8 +243,8 @@ value of the last statement in BODY, as elisp." (`output (setq results (if matlabp - (cdr (reverse (delq "" (mapcar #'org-strip-quotes - (mapcar #'org-trim raw))))) + (cdr (reverse (delete "" (mapcar #'org-strip-quotes + (mapcar #'org-trim raw))))) (cdr (member org-babel-octave-eoe-output (reverse (mapcar #'org-strip-quotes (mapcar #'org-trim raw))))))) diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index 3db33c4d63e..a33d84f1cd4 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -7330,7 +7330,7 @@ Any match of REMOVE-RE will be removed from TXT." (let ((s (org-format-outline-path (org-get-outline-path) (1- (frame-width)) nil org-agenda-breadcrumbs-separator))) - (if (eq "" s) "" (concat s org-agenda-breadcrumbs-separator)))))) + (if (equal "" s) "" (concat s org-agenda-breadcrumbs-separator)))))) (setq time (cond (s2 (concat (org-agenda-time-of-day-to-ampm-maybe s1) "-" (org-agenda-time-of-day-to-ampm-maybe s2) diff --git a/lisp/org/org-cycle.el b/lisp/org/org-cycle.el index 828c84cd0ac..90fc95f41f7 100644 --- a/lisp/org/org-cycle.el +++ b/lisp/org/org-cycle.el @@ -648,6 +648,9 @@ With a numeric prefix, show all headlines up to that level." (org-fold-show-hidden-entry) (org-fold-show-children)) ("content" + ;; Newline before heading will be outside the + ;; narrowing. Make sure that it is revealed. + (org-fold-heading nil) (save-excursion (save-restriction (org-narrow-to-subtree) diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el index 4f4eebfcc2d..8524dd29d83 100644 --- a/lisp/org/org-element.el +++ b/lisp/org/org-element.el @@ -7562,15 +7562,15 @@ the cache." ;; beginning. (next-element-re (pcase granularity ((or `headline - (guard (eq '(headline) - restrict-elements))) + (guard (equal '(headline) + restrict-elements))) (cons (org-with-limited-levels org-element-headline-re) 'match-beg)) (`headline+inlinetask (cons - (if (eq '(inlinetask) restrict-elements) + (if (equal '(inlinetask) restrict-elements) (org-inlinetask-outline-regexp) org-element-headline-re) 'match-beg)) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 5f587fb3fd8..5f93356709e 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made." (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.6.1-31-gaf1bb1")) + (let ((org-git-version "release_9.6.1-34-geea8da")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el index 8e3a0456299..4ff482cc3f5 100644 --- a/lisp/org/ox-texinfo.el +++ b/lisp/org/ox-texinfo.el @@ -32,6 +32,8 @@ (require 'cl-lib) (require 'ox) +(eval-when-compile (require 'subr-x)) + (defvar orgtbl-exp-regexp) (defvar org-texinfo-supports-math--cache) @@ -2025,12 +2027,14 @@ Once computed, the results remain cached." (unless (boundp 'org-texinfo-supports-math--cache) (setq org-texinfo-supports-math--cache (let ((math-example "1 + 1 = 2")) - (let* ((input-file - (make-temp-file "test" nil ".info")) - (input-content - (concat (format "@setfilename %s" input-file) "\n" - "@node Top" "\n" - (format "@displaymath{%s}" math-example) "\n"))) + (let* ((input-file (make-temp-file "test" nil ".info")) + (input-content (string-join + (list (format "@setfilename %s" input-file) + "@node Top" + "@displaymath" + math-example + "@end displaymath") + "\n"))) (with-temp-file input-file (insert input-content)) (let* ((output-file (org-texinfo-compile input-file)) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 8a4cc2fac18..b7a487687a8 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -87,6 +87,25 @@ :safe 'integerp :group 'c) +(defun c-ts-mode-toggle-comment-style () + "Toggle the comment style between block and line comments. +Optional numeric ARG, if supplied, switches to block comment +style when positive, to line comment style when negative, and +just toggles it when zero or left out." + (interactive) + (pcase-let ((`(,starter . ,ender) + (if (string= comment-start "// ") + (cons "/* " " */") + (cons "// " "")))) + (setq-local comment-start starter + comment-end ender)) + (c-ts-mode-set-modeline)) + +(defun c-ts-mode-set-modeline () + (setq mode-name + (concat (if (eq major-mode 'c-ts-mode) "C" "C++") comment-start)) + (force-mode-line-update)) + (defun c-ts-mode--indent-style-setter (sym val) "Custom setter for `c-ts-mode-set-style'. @@ -214,6 +233,25 @@ delimiters < and >'s." ;;; Indent +(defun c-ts-mode--preproc-offset (_n _p &rest _) + "This anchor is used for preprocessor directives. + +Because node is nil at the moment of indentation, we use +`treesit-node-on' to capture the anonymous node covering the +newline. If the grand-parent of that node is the +translation_unit itself, we don't indent. Otherwise, just indent +one step according to the great-grand-parent indent level. The +reason there is a difference between grand-parent and +great-grand-parent here is that the node containing the newline +is actually the parent of point at the moment of indentation." + (when-let ((node (treesit-node-on (point) (point)))) + (if (string-equal "translation_unit" + (treesit-node-type + (treesit-node-parent + (treesit-node-parent node)))) + 0 + c-ts-mode-indent-offset))) + (defun c-ts-mode--indent-styles (mode) "Indent rules supported by `c-ts-mode'. MODE is either `c' or `cpp'." @@ -246,13 +284,14 @@ MODE is either `c' or `cpp'." ((match nil "do_statement" "body") parent-bol c-ts-mode-indent-offset) ((match nil "for_statement" "body") parent-bol c-ts-mode-indent-offset) - ((match "preproc_ifdef" "compound_statement") point-min 0) - ((match "#endif" "preproc_ifdef") point-min 0) - ((match "preproc_if" "compound_statement") point-min 0) - ((match "#endif" "preproc_if") point-min 0) - ((match "preproc_function_def" "compound_statement") point-min 0) + ((node-is "preproc") point-min 0) + ((node-is "#endif") point-min 0) ((match "preproc_call" "compound_statement") point-min 0) + ((n-p-gp nil "preproc" "translation_unit") point-min 0) + ((n-p-gp nil "\n" "preproc") great-grand-parent c-ts-mode--preproc-offset) + ((parent-is "preproc") grand-parent c-ts-mode-indent-offset) + ((parent-is "function_definition") parent-bol 0) ((parent-is "conditional_expression") first-sibling 0) ((parent-is "assignment_expression") parent-bol c-ts-mode-indent-offset) @@ -740,7 +779,8 @@ the semicolon. This function skips the semicolon." :parent prog-mode-map "C-c C-q" #'c-ts-mode-indent-defun "C-c ." #'c-ts-mode-set-style - "C-c C-c" #'comment-region) + "C-c C-c" #'comment-region + "C-c C-k" #'c-ts-mode-toggle-comment-style) ;;;###autoload (define-derived-mode c-ts-base-mode prog-mode "C" @@ -805,7 +845,8 @@ the semicolon. This function skips the semicolon." `((block . ,(rx (or "compound_statement" "field_declaration_list" "enumerator_list" - "initializer_list"))) + "initializer_list" + "declaration_list"))) (if . "if_statement") (else . ("if_statement" . "alternative")) (do . "do_statement") @@ -855,6 +896,7 @@ To use tree-sitter C/C++ modes by default, evaluate in your configuration." :group 'c + :after-hook (c-ts-mode-set-modeline) (when (treesit-ready-p 'c) (treesit-parser-create 'c) @@ -887,6 +929,7 @@ To use tree-sitter C/C++ modes by default, evaluate in your configuration." :group 'c++ + :after-hook (c-ts-mode-set-modeline) (when (treesit-ready-p 'cpp) (setq-local treesit-text-type-regexp diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 07ec25a477a..239c85ce25f 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -474,28 +474,37 @@ compilation and evaluation time conflicts." (and (eq (char-before) ?\]) (not (eq (char-after) ?\;)))))) `((annotation-top-cont ,(c-point 'iopl)))) - ((and ;; Heuristics to find object initializers (save-excursion ;; Next non-whitespace character should be '{' (goto-char (c-point 'boi)) - (eq (char-after) ?{)) - (save-excursion - ;; 'new' should be part of the line - (goto-char (c-point 'iopl)) - (looking-at ".*new.*")) + (unless (eq (char-after) ?{) + (backward-up-list 1 t t)) + (save-excursion + ;; 'new' should be part of the line + (goto-char (c-point 'iopl)) + (looking-at ".*new.*"))) ;; Line should not already be terminated (save-excursion (goto-char (c-point 'eopl)) (or (not (eq (char-before) ?\;)) (not (eq (char-before) ?\{))))) - (if (save-excursion - ;; if we have a hanging brace on line before - (goto-char (c-point 'eopl)) - (eq (char-before) ?\{)) - `((brace-list-intro ,(c-point 'iopl))) - `((block-open) (statement ,(c-point 'iopl))))) + (cond + ((save-excursion + ;; if we have a hanging brace on line before + (goto-char (c-point 'eopl)) + (eq (char-before) ?\{)) + `((brace-list-intro ,(c-point 'iopl)))) + ((save-excursion + ;; if we have a hanging brace on line before + (goto-char (c-point 'boi)) + (and (eq (char-after) ?\}) + `((brace-list-close ,(save-excursion + (backward-up-list 1 t t) + (point))))))) + (t + `((block-open) (statement ,(c-point 'iopl)))))) (t (apply orig-fun args)))) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index a9f236f674f..906cd2434f6 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1760,11 +1760,6 @@ Use `eglot-managed-p' to determine if current buffer is managed.") (add-hook 'change-major-mode-hook #'eglot--managed-mode-off nil t) (add-hook 'post-self-insert-hook 'eglot--post-self-insert-hook nil t) (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t) - (eglot--setq-saving eldoc-documentation-functions - '(eglot-signature-eldoc-function - eglot-hover-eldoc-function)) - (eglot--setq-saving eldoc-documentation-strategy - #'eldoc-documentation-enthusiast) (eglot--setq-saving xref-prompt-for-identifier nil) (eglot--setq-saving flymake-diagnostic-functions '(eglot-flymake-backend)) (eglot--setq-saving company-backends '(company-capf)) @@ -1773,7 +1768,12 @@ Use `eglot-managed-p' to determine if current buffer is managed.") (add-function :before-until (local 'imenu-create-index-function) #'eglot-imenu)) (unless (eglot--stay-out-of-p 'flymake) (flymake-mode 1)) - (unless (eglot--stay-out-of-p 'eldoc) (eldoc-mode 1)) + (unless (eglot--stay-out-of-p 'eldoc) + (add-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function + nil t) + (add-hook 'eldoc-documentation-functions #'eglot-signature-eldoc-function + nil t) + (eldoc-mode 1)) (cl-pushnew (current-buffer) (eglot--managed-buffers (eglot-current-server)))) (t (remove-hook 'after-change-functions 'eglot--after-change t) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 90813c8de34..dc49d7e818c 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3458,12 +3458,14 @@ This function is intended for use in `after-change-functions'." ((match "<" "jsx_fragment") parent 0) ((parent-is "jsx_fragment") parent js-indent-level) ((node-is "jsx_closing_element") parent 0) - ((node-is "jsx_element") parent js-indent-level) + ((match "jsx_element" "statement") parent js-indent-level) ((parent-is "jsx_element") parent js-indent-level) + ((parent-is "jsx_text") parent-bol js-indent-level) ((parent-is "jsx_opening_element") parent js-indent-level) ((parent-is "jsx_expression") parent-bol js-indent-level) ((match "/" "jsx_self_closing_element") parent 0) ((parent-is "jsx_self_closing_element") parent js-indent-level) + ;; FIXME(Theo): This no-node catch-all should be removed. When is it needed? (no-node parent-bol 0))))) (defvar js--treesit-keywords @@ -3873,7 +3875,7 @@ See `treesit-sexp-type-regexp' for more information.") ;; Electric-indent. (setq-local electric-indent-chars - (append "{}():;," electric-indent-chars)) ;FIXME: js2-mode adds "[]*". + (append "{}():;,<>/" electric-indent-chars)) ;FIXME: js2-mode adds "[]*". (setq-local electric-layout-rules '((?\; . after) (?\{ . after) (?\} . before))) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index e53cdb5ce7d..ee73ebf7a9f 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -36,6 +36,7 @@ (declare-function treesit-node-child "treesit.c") (declare-function treesit-node-child-by-field-name "treesit.c") (declare-function treesit-node-start "treesit.c") +(declare-function treesit-node-end "treesit.c") (declare-function treesit-node-type "treesit.c") (declare-function treesit-node-parent "treesit.c") (declare-function treesit-query-compile "treesit.c") @@ -209,50 +210,15 @@ `((scoped_use_list path: (identifier) @font-lock-constant-face) (scoped_use_list path: (scoped_identifier name: (identifier) @font-lock-constant-face)) - ((use_as_clause alias: (identifier) @font-lock-type-face) (:match "^[A-Z]" @font-lock-type-face)) ((use_as_clause path: (identifier) @font-lock-type-face) (:match "^[A-Z]" @font-lock-type-face)) - ((use_as_clause path: - (scoped_identifier path: (_) - name: (identifier) @font-lock-type-face)) - (:match "^[A-Z]" @font-lock-type-face)) - (use_as_clause path: (scoped_identifier name: (identifier) @default)) - - ((use_declaration - argument: (scoped_identifier - path: (_) @font-lock-constant-face - name: (identifier) @font-lock-type-face)) - (:match "^[A-Z]" @font-lock-type-face)) - (use_declaration - argument: (scoped_identifier - name: (identifier) @default)) - - (use_declaration - argument: (scoped_identifier - path: (scoped_identifier - path: (_) @font-lock-constant-face - name: (identifier) @font-lock-constant-face) - name: (identifier) @default)) - - (use_declaration - argument: (scoped_use_list - path: (scoped_identifier - path: (_) @font-lock-constant-face - name: (identifier) @font-lock-constant-face))) - ((use_list (identifier) @font-lock-type-face) (:match "^[A-Z]" @font-lock-type-face)) - (use_list (identifier) @default) - ((use_list (scoped_identifier path: (_) - name: (identifier) @font-lock-type-face)) - (:match "^[A-Z]" @font-lock-type-face)) - (use_list (scoped_identifier path: (_) - name: (identifier) @default)) - (use_wildcard (scoped_identifier - name: (identifier) @font-lock-constant-face)) - + (use_wildcard [(identifier) @rust-ts-mode--fontify-scope + (scoped_identifier + name: (identifier) @rust-ts-mode--fontify-scope)]) (enum_variant name: (identifier) @font-lock-type-face) (match_arm pattern: (match_pattern (_ type: (identifier) @font-lock-type-face))) @@ -263,31 +229,13 @@ (mod_item name: (identifier) @font-lock-constant-face) (primitive_type) @font-lock-type-face (type_identifier) @font-lock-type-face - ((scoped_identifier name: (identifier) @font-lock-type-face) - (:match "^[A-Z]" @font-lock-type-face)) - ((scoped_identifier path: (identifier) @font-lock-type-face) - (:match "^[A-Z]" @font-lock-type-face)) - ((scoped_identifier - path: [(identifier) @font-lock-type-face - (scoped_identifier - name: (identifier) @font-lock-type-face)]) - (:match "^[A-Z]" @font-lock-type-face)) + ((scoped_identifier name: (identifier) @rust-ts-mode--fontify-tail)) ((scoped_identifier path: (identifier) @font-lock-type-face) (:match "^\\(u8\\|u16\\|u32\\|u64\\|u128\\|usize\\|i8\\|i16\\|i32\\|i64\\|i128\\|isize\\|char\\|str\\)$" @font-lock-type-face)) - (scoped_identifier path: (_) @font-lock-constant-face - name: (identifier) @font-lock-type-face) - (scoped_identifier path: (scoped_identifier - name: (identifier) @font-lock-constant-face)) - (scoped_type_identifier path: (_) @font-lock-constant-face) - (scoped_type_identifier - path: (scoped_identifier - path: (_) @font-lock-constant-face - name: (identifier) @font-lock-constant-face)) - (type_identifier) @font-lock-type-face - ;; Ensure function calls aren't highlighted as types. - (call_expression function: (scoped_identifier name: (identifier) @default))) + ((scoped_identifier path: (identifier) @rust-ts-mode--fontify-scope)) + (type_identifier) @font-lock-type-face) :language 'rust :feature 'property @@ -303,9 +251,25 @@ :language 'rust :feature 'variable - '((identifier) @font-lock-variable-name-face - ;; Everything in a token_tree is an identifier. - (token_tree (identifier) @default)) + '((arguments (identifier) @font-lock-variable-name-face) + (array_expression (identifier) @font-lock-variable-name-face) + (assignment_expression right: (identifier) @font-lock-variable-name-face) + (binary_expression left: (identifier) @font-lock-variable-name-face) + (binary_expression right: (identifier) @font-lock-variable-name-face) + (block (identifier) @font-lock-variable-name-face) + (compound_assignment_expr right: (identifier) @font-lock-variable-name-face) + (field_expression value: (identifier) @font-lock-variable-name-face) + (field_initializer value: (identifier) @font-lock-variable-name-face) + (if_expression condition: (identifier) @font-lock-variable-name-face) + (let_condition value: (identifier) @font-lock-variable-name-face) + (let_declaration value: (identifier) @font-lock-variable-name-face) + (match_arm value: (identifier) @font-lock-variable-name-face) + (match_expression value: (identifier) @font-lock-variable-name-face) + (reference_expression value: (identifier) @font-lock-variable-name-face) + (return_expression (identifier) @font-lock-variable-name-face) + (tuple_expression (identifier) @font-lock-variable-name-face) + (unary_expression (identifier) @font-lock-variable-name-face) + (while_expression condition: (identifier) @font-lock-variable-name-face)) :language 'rust :feature 'escape-sequence @@ -318,6 +282,28 @@ '((ERROR) @font-lock-warning-face)) "Tree-sitter font-lock settings for `rust-ts-mode'.") +(defun rust-ts-mode--fontify-scope (node override start end &optional tail-p) + (let* ((case-fold-search nil) + (face + (cond + ((string-match-p "^[A-Z]" (treesit-node-text node)) + 'font-lock-type-face) + ((and + tail-p + (string-match-p + "\\`\\(?:use_list\\|call_expression\\|use_as_clause\\|use_declaration\\)\\'" + (treesit-node-type (treesit-node-parent (treesit-node-parent node))))) + nil) + (t 'font-lock-constant-face)))) + (when face + (treesit-fontify-with-override + (treesit-node-start node) (treesit-node-end node) + face + override start end)))) + +(defun rust-ts-mode--fontify-tail (node override start end) + (rust-ts-mode--fontify-scope node override start end t)) + (defalias 'rust-ts-mode--fontify-pattern (and (treesit-available-p) diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index afc8ff47db3..1646776ce95 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -81,6 +81,8 @@ Argument LANGUAGE is either `typescript' or `tsx'." ((parent-is "member_expression") parent-bol typescript-ts-mode-indent-offset) ((parent-is "named_imports") parent-bol typescript-ts-mode-indent-offset) ((parent-is "statement_block") parent-bol typescript-ts-mode-indent-offset) + ((parent-is "switch_case") parent-bol typescript-ts-mode-indent-offset) + ((parent-is "switch_default") parent-bol typescript-ts-mode-indent-offset) ((parent-is "type_arguments") parent-bol typescript-ts-mode-indent-offset) ((parent-is "variable_declarator") parent-bol typescript-ts-mode-indent-offset) ((parent-is "arguments") parent-bol typescript-ts-mode-indent-offset) @@ -101,12 +103,14 @@ Argument LANGUAGE is either `typescript' or `tsx'." `(((match "<" "jsx_fragment") parent 0) ((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset) ((node-is "jsx_closing_element") parent 0) - ((node-is "jsx_element") parent typescript-ts-mode-indent-offset) + ((match "jsx_element" "statement") parent typescript-ts-mode-indent-offset) ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset) + ((parent-is "jsx_text") parent-bol typescript-ts-mode-indent-offset) ((parent-is "jsx_opening_element") parent typescript-ts-mode-indent-offset) ((parent-is "jsx_expression") parent-bol typescript-ts-mode-indent-offset) ((match "/" "jsx_self_closing_element") parent 0) ((parent-is "jsx_self_closing_element") parent typescript-ts-mode-indent-offset))) + ;; FIXME(Theo): This no-node catch-all should be removed. When is it needed? (no-node parent-bol 0)))) (defvar typescript-ts-mode--keywords @@ -377,8 +381,9 @@ See `treesit-sexp-type-regexp' for more information.") ;; Electric (setq-local electric-indent-chars - (append "{}():;," electric-indent-chars)) - + (append "{}():;,<>/" electric-indent-chars)) + (setq-local electric-layout-rules + '((?\; . after) (?\{ . after) (?\} . before))) ;; Navigation. (setq-local treesit-defun-type-regexp (regexp-opt '("class_declaration" diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 581eda0513e..38c424402a0 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -1,7 +1,7 @@ ;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*- ;; Copyright (C) 2014-2023 Free Software Foundation, Inc. -;; Version: 1.6.1 +;; Version: 1.6.2 ;; Package-Requires: ((emacs "26.1")) ;; This is a GNU ELPA :core package. Avoid functionality that is not diff --git a/lisp/simple.el b/lisp/simple.el index 45bd1be5440..94578635a02 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9918,7 +9918,12 @@ minibuffer, but don't quit the completions window." (with-current-buffer buffer (choose-completion-string choice buffer - (or (and completion-use-base-affixes base-affixes) + ;; Don't allow affixes to replace the whole buffer when not + ;; in the minibuffer. Thus check for `completion-in-region-mode' + ;; to ignore non-nil value of `completion-use-base-affixes' set by + ;; `minibuffer-choose-completion'. + (or (and (not completion-in-region-mode) + completion-use-base-affixes base-affixes) base-position ;; If all else fails, just guess. (list (choose-completion-guess-base-position choice))) diff --git a/lisp/transient.el b/lisp/transient.el index c0ecd2950d7..96e711e950c 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -1048,26 +1048,30 @@ example, sets a variable, use `transient-define-infix' instead. (setq args (plist-put args :key pop))) (cond ((or (stringp car) - (eq (car-safe car) 'lambda)) + (and (eq (car-safe car) 'lambda) + (not (commandp car)))) (setq args (plist-put args :description pop))) ((and (symbolp car) + (not (keywordp car)) (not (commandp car)) (commandp (cadr spec))) (setq args (plist-put args :description (macroexp-quote pop))))) (cond ((keywordp car) - (error "Need command, got %S" car)) + (error "Need command, got `%s'" car)) ((symbolp car) (setq args (plist-put args :command (macroexp-quote pop)))) ((and (commandp car) (not (stringp car))) (let ((cmd pop) - (sym (intern (format "transient:%s:%s" - prefix - (or (plist-get args :description) - (plist-get args :key)))))) - (defalias sym cmd) - (setq args (plist-put args :command (macroexp-quote sym))))) + (sym (intern + (format "transient:%s:%s" + prefix + (let ((desc (plist-get args :description))) + (if (and desc (or (stringp desc) (symbolp desc))) + desc + (plist-get args :key))))))) + (setq args (plist-put args :command `(defalias ',sym ,cmd))))) ((or (stringp car) (and car (listp car))) (let ((arg pop)) diff --git a/lisp/treesit.el b/lisp/treesit.el index 077f1da6e47..644a8018ad2 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1186,12 +1186,18 @@ See `treesit-simple-indent-presets'.") (skip-syntax-backward "-") (point)))) (cons 'prev-adaptive-prefix - (lambda (_n parent &rest _) - (let ((comment-start-bol - (save-excursion - (goto-char (treesit-node-start parent)) - (line-beginning-position)))) + (lambda (_n parent bol &rest _) + (let (comment-start-bol + this-line-has-prefix) (save-excursion + (goto-char (treesit-node-start parent)) + (setq comment-start-bol (line-beginning-position)) + + (goto-char bol) + (setq this-line-has-prefix + (and (looking-at adaptive-fill-regexp) + (match-string 1))) + (forward-line -1) (and (>= (point) comment-start-bol) adaptive-fill-regexp @@ -1199,7 +1205,14 @@ See `treesit-simple-indent-presets'.") ;; If previous line is an empty line, don't ;; indent. (not (looking-at (rx (* whitespace) eol))) - (match-end 0)))))) + ;; Return the anchor. If the indenting line + ;; has a prefix and the previous line also + ;; has a prefix, indent to the beginning of + ;; prev line's prefix rather than the end of + ;; prev line's prefix. (Bug#61314). + (or (and this-line-has-prefix + (match-beginning 1)) + (match-end 0))))))) ;; TODO: Document. (cons 'grand-parent (lambda (_n parent &rest _) @@ -1336,8 +1349,11 @@ prev-adaptive-prefix Goes to the beginning of previous non-empty line, and tries to match `adaptive-fill-regexp'. If it matches, return the - end of the match, otherwise return nil. This is useful for a - `indent-relative'-like indent behavior for block comments.") + end of the match, otherwise return nil. However, if the + current line begins with a prefix, return the beginning of + the prefix of the previous line instead, so that the two + prefixes aligns. This is useful for a `indent-relative'-like + indent behavior for block comments.") (defun treesit--simple-indent-eval (exp) "Evaluate EXP. diff --git a/src/comp.c b/src/comp.c index 1b55226b0c3..5cbe441dd7f 100644 --- a/src/comp.c +++ b/src/comp.c @@ -514,6 +514,10 @@ load_gccjit_if_necessary (bool mandatory) #define CALL2I(fun, arg1, arg2) \ CALLN (Ffuncall, intern_c_string (STR (fun)), arg1, arg2) +/* Like call4 but stringify and intern. */ +#define CALL4I(fun, arg1, arg2, arg3, arg4) \ + CALLN (Ffuncall, intern_c_string (STR (fun)), arg1, arg2, arg3, arg4) + #define DECL_BLOCK(name, func) \ gcc_jit_block *(name) = \ gcc_jit_function_new_block ((func), STR (name)) @@ -4991,8 +4995,8 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file, format_string ("%s_libgccjit_repro.c", SSDATA (ebase_name))); Lisp_Object tmp_file = - Fmake_temp_file_internal (base_name, make_fixnum (0), - build_string (".eln.tmp"), Qnil); + CALL4I (make-temp-file, base_name, Qnil, build_string (".eln.tmp"), Qnil); + Lisp_Object encoded_tmp_file = ENCODE_FILE (tmp_file); #ifdef WINDOWSNT encoded_tmp_file = ansi_encode_filename (encoded_tmp_file); diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 2dca0d16ad9..2571812cb39 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -3653,6 +3653,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1, re_opcode_t op2; bool multibyte = RE_MULTIBYTE_P (bufp); unsigned char *pend = bufp->buffer + bufp->used; + re_char *p2_orig = p2; eassert (p1 >= bufp->buffer && p1 < pend && p2 >= bufp->buffer && p2 <= pend); @@ -3822,6 +3823,23 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1, case notcategoryspec: return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]); + case on_failure_jump_nastyloop: + case on_failure_jump_smart: + case on_failure_jump_loop: + case on_failure_keep_string_jump: + case on_failure_jump: + { + int mcnt; + p2++; + EXTRACT_NUMBER_AND_INCR (mcnt, p2); + /* Don't just test `mcnt > 0` because non-greedy loops have + their test at the end with an unconditional jump at the start. */ + if (p2 + mcnt > p2_orig) /* Ensure forward progress. */ + return (mutually_exclusive_p (bufp, p1, p2) + && mutually_exclusive_p (bufp, p1, p2 + mcnt)); + break; + } + default: ; } diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts new file mode 100644 index 00000000000..5a4996f642e --- /dev/null +++ b/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts @@ -0,0 +1,45 @@ +Code: + (lambda () + (c-ts-mode) + (newline) + (indent-for-tab-command)) + +Point-Char: | + +Name: Indents inside #if preproc + +=-= +static void +free_glyph_pool (struct glyph_pool *pool) +{ + if (pool) + { +#if defined GLYPH_DEBUG| +#endif + } +} +=-= +static void +free_glyph_pool (struct glyph_pool *pool) +{ + if (pool) + { +#if defined GLYPH_DEBUG + | +#endif + } +} +=-=-= + +Name: Indents to 0 if #if preproc at root + +=-= +#if 0| +/* */ +static void +=-= +#if 0 +| +/* */ +static void +=-=-= diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 05d59c10a42..36d7af4faf1 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -242,6 +242,21 @@ line 2 */ =-=-= +Name: Block Comment prefixes (Bug#61314) + +=-=-= +/* +- item1 +- item2 +- item3 +*/ +=-=-= +/* + - item1 + - item2 + - item3 + */ +=-=-= Code: (lambda () @@ -354,3 +369,19 @@ int main() }; } =-=-= + +Code: + (lambda () + (c++-ts-mode) + (setq-local indent-tabs-mode nil) + (setq-local c-ts-mode-indent-offset 2) + (indent-region (point-min) (point-max))) + +Name: Declaration List (Namespace) (Bug#61635) + +=-= +namespace test { + class Name { + }; +} +=-=-= diff --git a/test/lisp/progmodes/c-ts-mode-tests.el b/test/lisp/progmodes/c-ts-mode-tests.el index ddf64b40736..ea5fab4cbef 100644 --- a/test/lisp/progmodes/c-ts-mode-tests.el +++ b/test/lisp/progmodes/c-ts-mode-tests.el @@ -27,6 +27,10 @@ (skip-unless (treesit-ready-p 'c)) (ert-test-erts-file (ert-resource-file "indent.erts"))) +(ert-deftest c-ts-mode-test-indentation-preproc () + (skip-unless (treesit-ready-p 'c)) + (ert-test-erts-file (ert-resource-file "indent-preproc.erts"))) + (ert-deftest c-ts-mode-test-indentation-bsd () (skip-unless (treesit-ready-p 'c)) (ert-test-erts-file (ert-resource-file "indent-bsd.erts"))) diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el index 34fa35e32ff..52d43775b8e 100644 --- a/test/src/regex-emacs-tests.el +++ b/test/src/regex-emacs-tests.el @@ -872,4 +872,15 @@ This evaluates the TESTS test cases from glibc." (should (equal (string-match "\\`\\(?:ab\\)*\\'" "a") nil)) (should (equal (string-match "\\`a\\{2\\}*\\'" "a") nil))) +(ert-deftest regexp-tests-backtrack-optimization () ;bug#61514 + ;; Make sure we don't use up the regexp stack needlessly. + (with-current-buffer (get-buffer-create "*bug*") + (erase-buffer) + (insert (make-string 1000000 ?x) "=") + (goto-char (point-min)) + (should (looking-at "x*=*")) + (should (looking-at "x*\\(=\\|:\\)")) + (should (looking-at "x*\\(=\\|:\\)*")) + (should (looking-at "x*=*?")))) + ;;; regex-emacs-tests.el ends here