From 3e4eb83bb10eb75f6faf06bf4b2c45d15e2bd10a Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Mon, 9 Jun 2025 22:35:34 -0700 Subject: [PATCH] Add tree-sitter version of prog-fill-reindent-defun (bug#78703) Add a tree-sitter version of prog-fill-reindent-defun that indents the defun that encloses point, rather than the sibling defun after point when there is one. * lisp/progmodes/prog-mode.el: (prog-fill-reindent-defun): Turns into a wrapper function. (prog-fill-reindent-defun-function): New variable. (prog-fill-reindent-defun-default): Old prog-fill-reindent-defun becomes this function. * lisp/treesit.el (treesit-fill-reindent-defun): New function. (treesit-major-mode-setup): Setup prog-fill-reindent-defun-function. (cherry picked from commit f904ff5ca2535356e1353e5fc95d9b0643b8570b) --- lisp/progmodes/prog-mode.el | 32 +++++++++++++++++++++++--------- lisp/treesit.el | 31 ++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index 09775a55ab3..d792011a2ae 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el @@ -168,23 +168,37 @@ instead." (and (re-search-forward "\\s-*\\s<" (line-end-position) t) (nth 8 (syntax-ppss)))))) -(defun prog-fill-reindent-defun (&optional argument) - "Refill or reindent the paragraph or defun that contains point. - -If the point is in a string or a comment, fill the paragraph that -contains point or follows point. - -Otherwise, reindent the function definition that contains point -or follows point." +(defvar prog-fill-reindent-defun-function + #'prog-fill-reindent-defun-default + "Function called by `prog-fill-reindent-defun' to do the actual work. +It should take the same argument as `prog-fill-reindent-defun'.") + +(defun prog-fill-reindent-defun-default (&optional justify) + "Default implementation of `prog-fill-reindent-defun'. +JUSTIFY is the same as in `fill-paragraph'." (interactive "P") (save-excursion (if (prog--text-at-point-p) - (fill-paragraph argument (region-active-p)) + (fill-paragraph justify (region-active-p)) (beginning-of-defun) (let ((start (point))) (end-of-defun) (indent-region start (point) nil))))) +(defun prog-fill-reindent-defun (&optional justify) + "Refill or reindent the paragraph or defun that contains point. + +If the point is in a string or a comment, fill the paragraph that +contains point or follows point. + +Otherwise, reindent the function definition that contains point +or follows point. + +If JUSTIFY is non-nil (interactively, with prefix argument), justify as +well." + (interactive "P") + (funcall prog-fill-reindent-defun-function justify)) + (defun prog-first-column () "Return the indentation column normally used for top-level constructs." (or (car prog-indentation-context) 0)) diff --git a/lisp/treesit.el b/lisp/treesit.el index a757c0759a2..1d06efb2e6d 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -58,6 +58,7 @@ (require 'cl-lib) (require 'font-lock) (require 'seq) +(require 'prog-mode) ; For `prog--text-at-point-p'. ;;; Function declarations @@ -3853,6 +3854,28 @@ The delimiter between nested defun names is controlled by (setq node (treesit-node-parent node))) name)) +;;; Prog mode + +(defun treesit-fill-reindent-defun (&optional justify) + "Refill/reindent the paragraph/defun that contains point. + +This is a tree-sitter implementation of `prog-fill-reindent-defun'. + +`treesit-major-mode-setup' assigns this function to +`prog-fill-reindent-defun-function' if the major mode defines the +`defun' thing. + +JUSTIFY is the same as in `fill-paragraph'." + (interactive "P") + (save-excursion + (if (prog--text-at-point-p) + (fill-paragraph justify (region-active-p)) + (let* ((treesit-defun-tactic 'parent-first) + (node (treesit-defun-at-point))) + (indent-region (treesit-node-start node) + (treesit-node-end node) + nil))))) + ;;; Imenu (defvar treesit-simple-imenu-settings nil @@ -4344,8 +4367,8 @@ and enable `font-lock-mode'. If `treesit-simple-indent-rules' is non-nil, set up indentation. If `treesit-defun-type-regexp' is non-nil or `defun' is defined -in `treesit-thing-settings', set up `beginning-of-defun-function' -and `end-of-defun-function'. +in `treesit-thing-settings', set up `beginning-of-defun-function', +`end-of-defun-function', and `prog-fill-reindent-defun-function'. If `treesit-defun-name-function' is non-nil, set up `add-log-current-defun'. @@ -4408,7 +4431,9 @@ before calling this function." ;; the variables. In future we should update `end-of-defun' to ;; work with nested defuns. (setq-local beginning-of-defun-function #'treesit-beginning-of-defun) - (setq-local end-of-defun-function #'treesit-end-of-defun)) + (setq-local end-of-defun-function #'treesit-end-of-defun) + (setq-local prog-fill-reindent-defun-function + #'treesit-fill-reindent-defun)) ;; Defun name. (when treesit-defun-name-function (setq-local add-log-current-defun-function -- 2.39.5