diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index b81ff6ff7a5..50aac95dbc6 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el @@ -166,22 +166,36 @@ instead." (and (re-search-forward "\\s-*\\s<" (line-end-position) t) (nth 8 (syntax-ppss)))))) -(defun prog-fill-reindent-defun (&optional argument) +(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 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." +or follows point. + +If JUSTIFY is non-nil (interactively, with prefix argument), justify as +well." (interactive "P") - (save-excursion - (if (prog--text-at-point-p) - (fill-paragraph argument (region-active-p)) - (beginning-of-defun) - (let ((start (point))) - (end-of-defun) - (indent-region start (point) nil))))) + (funcall prog-fill-reindent-defun-function justify)) (defun prog-first-column () "Return the indentation column normally used for top-level constructs." diff --git a/lisp/treesit.el b/lisp/treesit.el index 30f163aa100..bc6b177e25e 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 @@ -3861,6 +3862,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 @@ -4351,8 +4374,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'. @@ -4415,7 +4438,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