From 72da7a3f04684886b2be52c7dd465282128ece4b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 6 Aug 2020 15:14:35 -0400 Subject: [PATCH] editor/format: add org src-block support Src blocks can now be reformatted. `+format/buffer` will reformat the whole src block at point. `+format/region` will format only the selection (even a subset of a src block). Closes #3484 --- modules/editor/format/autoload/format.el | 70 ++++++++++++++++-------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/modules/editor/format/autoload/format.el b/modules/editor/format/autoload/format.el index 6584db5dd..fb0934bcd 100644 --- a/modules/editor/format/autoload/format.el +++ b/modules/editor/format/autoload/format.el @@ -201,20 +201,43 @@ See `+format/buffer' for the interactive version of this function, and ;; ;;; Commands +(defun +format--org-region (beg end) + "Reformat the region within BEG and END. +If nil, BEG and/or END will default to the boundaries of the src block at point." + (let ((element (org-element-at-point))) + (save-excursion + (let* ((block-beg (save-excursion + (goto-char (org-babel-where-is-src-block-head element)) + (line-beginning-position 2))) + (block-end (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \t\n") + (line-beginning-position))) + (beg (if beg (max beg block-beg) block-beg)) + (end (if end (min end block-end) block-end)) + (lang (org-element-property :language element)) + (major-mode (org-src-get-lang-mode lang))) + (if (eq major-mode 'org-mode) + (user-error "Cannot reformat an org src block in org-mode") + (+format/region beg end)))))) + ;;;###autoload (defun +format/buffer () "Reformat the current buffer using LSP or `format-all-buffer'." (interactive) - (call-interactively - (cond ((and +format-with-lsp - (bound-and-true-p lsp-mode) - (lsp-feature? "textDocument/formatting")) - #'lsp-format-buffer) - ((and +format-with-lsp - (bound-and-true-p eglot--managed-mode) - (eglot--server-capable :documentFormattingProvider)) - #'eglot-format-buffer) - (#'format-all-buffer)))) + (if (and (eq major-mode 'org-mode) + (org-in-src-block-p t)) + (+format--org-region nil nil) + (call-interactively + (cond ((and +format-with-lsp + (bound-and-true-p lsp-mode) + (lsp-feature? "textDocument/formatting")) + #'lsp-format-buffer) + ((and +format-with-lsp + (bound-and-true-p eglot--managed-mode) + (eglot--server-capable :documentFormattingProvider)) + #'eglot-format-buffer) + (#'format-all-buffer))))) ;;;###autoload (defun +format/region (beg end) @@ -224,18 +247,21 @@ WARNING: this may not work everywhere. It will throw errors if the region contains a syntax error in isolation. It is mostly useful for formatting snippets or single lines." (interactive "rP") - (cond ((and +format-with-lsp - (bound-and-true-p lsp-mode) - (lsp-feature? "textDocument/rangeFormatting")) - (call-interactively #'lsp-format-region)) - ((and +format-with-lsp - (bound-and-true-p eglot--managed-mode) - (eglot--server-capable :documentRangeFormattingProvider)) - (call-interactively #'eglot-format)) - ((save-restriction - (narrow-to-region beg end) - (let ((+format-region-p t)) - (+format/buffer)))))) + (if (and (eq major-mode 'org-mode) + (org-in-src-block-p t)) + (+format--org-region beg end) + (cond ((and +format-with-lsp + (bound-and-true-p lsp-mode) + (lsp-feature? "textDocument/rangeFormatting")) + (call-interactively #'lsp-format-region)) + ((and +format-with-lsp + (bound-and-true-p eglot--managed-mode) + (eglot--server-capable :documentRangeFormattingProvider)) + (call-interactively #'eglot-format)) + ((save-restriction + (narrow-to-region beg end) + (let ((+format-region-p t)) + (+format/buffer))))))) ;;;###autoload (defun +format/region-or-buffer ()