> Applied, onto main.
Great!

> May you elaborate on the edge cases you encountered?
> It may be a good idea to add such cases to the tests as well.

I think they all reduced to the case where adding the spaces increased
the minimum indent of the block, in which case `org-indent-line' would
remove `block-content-ind' spaces from all other lines in the block. I
attached a patch with a simple test where I also cleaned up the use of
obsolete function `org-get-indentation' in `test-org.el'.

As a final thing on this patch in particular, I thought for a second
that I might have caused a regression in modes where the
indent-function cycles indentation (e.g. python-mode). Seems like
python-mode in particular relies on `last-command' and not current
indentation so it never worked.  Idk if there's a good solution to
this issue from our side. Still, I think it makes sense to at least
refrain from moving stuff around unnecessarily, just in case some
modes do rely on current indentation.

LRA



Mar 29, 2025, 11:07 by yanta...@posteo.net:

> l...@phdk.org writes:
>
>> Thanks for the comments, I've attached the updated patch.
>>
>>> 1. Use `insert' rather than `insert-char' that is for interactive use.
>>> 2. Use more readable ?\t notation
>>>
>>
>> I realized that just inserting the spaces actually did mess up things
>> in some edge-cases so I changed approach. It feels ugly having almost
>> the exact same bit of code within a couple lines, but I don't see an
>> obvious solution.
>>
>
> Applied, onto main.
> Fixed.
> https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=4750b37809
>
> May you elaborate on the edge cases you encountered?
> It may be a good idea to add such cases to the tests as well.
>
> -- 
> Ihor Radchenko // yantar92,
> Org mode maintainer,
> Learn more about Org mode at <https://orgmode.org/>.
> Support Org development at <https://liberapay.com/org-mode>,
> or support my work at <https://liberapay.com/yantar92>
>

>From ac097ddbaed6b504f72760a5ffe0b128533fccdd Mon Sep 17 00:00:00 2001
From: Lukas Rudd Andersen <l...@phdk.org>
Date: Mon, 31 Mar 2025 16:20:35 +0200
Subject: [PATCH] org-indent-line: Avoid unnecessary temporary changes to
 indentation

* lisp/org.el (org-indent-line): Add a check to ensure that org
  doesn't indent when it isn't needed.

* testing/lisp/test-org.el (test-org/indent-line): Add additional test
  and clean up use of obsolete function `org-get-indentation'.

Link: https://orgmode.org/list/omp_5ys--...@phdk.org
TINYCHANGE
---
 lisp/org.el              |   3 +-
 testing/lisp/test-org.el | 120 +++++++++++++++++++++------------------
 2 files changed, 67 insertions(+), 56 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index ec6aa7580..ee8f66d04 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -19480,7 +19480,8 @@ Also align node properties according to `org-property-format'."
                            org-edit-src-content-indentation)))))
                ;; Avoid over-indenting when beginning of a new line is not empty.
                ;; https://list.orgmode.org/omcpuwz--...@phdk.org/
-               (when block-content-ind
+               (when (and block-content-ind
+                          (< (current-indentation) block-content-ind))
                  (save-excursion (indent-line-to block-content-ind)))
                (ignore-errors ; do not err when there is no proper major mode
                  ;; It is important to call `indent-according-to-mode'
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index a55c4162e..9966aae44 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -1079,40 +1079,40 @@ Otherwise, evaluate RESULT as an sexp and return its result."
    (zerop
     (org-test-with-temp-text "%%(org-calendar-holiday)"
       (org-indent-line)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "[fn:1] fn"
       (let ((org-adapt-indentation t)) (org-indent-line))
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H"
       (org-indent-line)
-      (org-get-indentation))))
+      (current-indentation))))
   ;; Do not indent before first headline.
   (should
    (zerop
     (org-test-with-temp-text ""
       (org-indent-line)
-      (org-get-indentation))))
+      (current-indentation))))
   ;; Indent according to headline level otherwise, unless
   ;; `org-adapt-indentation' is nil.
   (should
    (= 2
       (org-test-with-temp-text "* H\n<point>A"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text "* H\n<point>\nA"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H\n<point>A"
       (let ((org-adapt-indentation nil)) (org-indent-line))
-      (org-get-indentation))))
+      (current-indentation))))
   ;; Indenting preserves point position.
   (should
    (org-test-with-temp-text "* H\nA<point>B"
@@ -1123,13 +1123,13 @@ Otherwise, evaluate RESULT as an sexp and return its result."
    (= 1
       (org-test-with-temp-text "* H\n<point> - A"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 1
       (org-test-with-temp-text
 	  "\\begin{equation}\n <point>1+1=2\n\\end{equation}"
 	(org-indent-line)
-	(org-get-indentation))))
+	(current-indentation))))
   ;; On blank lines at the end of a list, indent like last element
   ;; within it if the line is still in the list.  If the last element
   ;; is an item, indent like its contents.  Otherwise, indent like the
@@ -1138,39 +1138,39 @@ Otherwise, evaluate RESULT as an sexp and return its result."
    (= 4
       (org-test-with-temp-text "* H\n- A\n  - AA\n<point>"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 4
       (org-test-with-temp-text "* H\n- A\n  -\n\n<point>"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H\n- A\n  - AA\n\n\n\n<point>"
       (let ((org-adapt-indentation t)) (org-indent-line))
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (= 4
       (org-test-with-temp-text "* H\n- A\n  - \n<point>"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 4
       (org-test-with-temp-text
 	  "* H\n  - \n    #+BEGIN_SRC emacs-lisp\n  t\n    #+END_SRC\n<point>"
 	(let ((org-adapt-indentation t)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text "- A\n  B\n\n<point>"
 	(let ((org-adapt-indentation nil)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text
 	  "- A\n  \begin{cases}    1 + 1\n  \end{cases}\n\n<point>"
 	(let ((org-adapt-indentation nil)) (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   ;; Likewise, on a blank line at the end of a footnote definition,
   ;; indent at column 0 if line belongs to the definition.  Otherwise,
   ;; indent like the definition itself.
@@ -1178,12 +1178,12 @@ Otherwise, evaluate RESULT as an sexp and return its result."
    (zerop
     (org-test-with-temp-text "* H\n[fn:1] Definition\n<point>"
       (let ((org-adapt-indentation t)) (org-indent-line))
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H\n[fn:1] Definition\n\n\n\n<point>"
       (let ((org-adapt-indentation t)) (org-indent-line))
-      (org-get-indentation))))
+      (current-indentation))))
   ;; After the end of the contents of a greater element, indent like
   ;; the beginning of the element.
   (should
@@ -1191,14 +1191,14 @@ Otherwise, evaluate RESULT as an sexp and return its result."
       (org-test-with-temp-text
 	  " #+BEGIN_CENTER\n  Contents\n<point>#+END_CENTER"
 	(org-indent-line)
-	(org-get-indentation))))
+	(current-indentation))))
   ;; On blank lines after a paragraph, indent like its last non-empty
   ;; line.
   (should
    (= 1
       (org-test-with-temp-text " Paragraph\n\n<point>"
 	(org-indent-line)
-	(org-get-indentation))))
+	(current-indentation))))
   ;; At the first line of an element, indent like previous element's
   ;; first line, ignoring footnotes definitions and inline tasks, or
   ;; according to parent.
@@ -1207,22 +1207,23 @@ Otherwise, evaluate RESULT as an sexp and return its result."
      (= 2
         (org-test-with-temp-text "A\n\n  B\n\nC<point>"
 	                         (org-indent-line)
-	                         (org-get-indentation))))
+	                         (current-indentation))))
     (should
      (= 1
         (org-test-with-temp-text " A\n\n[fn:1] B\n\n\nC<point>"
 	                         (org-indent-line)
-	                         (org-get-indentation))))
+	                         (current-indentation))))
     (should
      (= 1
         (org-test-with-temp-text
 	 " #+BEGIN_CENTER\n<point>  Contents\n#+END_CENTER"
 	 (org-indent-line)
-	 (org-get-indentation)))))
+	 (current-indentation)))))
   ;; Within code part of a source block, use language major mode if
   ;; `org-src-tab-acts-natively' is non-nil, only add
   ;; `org-edit-src-content-indentation' to lines with indentation that
-  ;; is lower. Otherwise, indent according to line above.
+  ;; is lower, do so in a way that does not increase the blocks
+  ;; minimum indent. Otherwise, indent according to line above.
   (should
    (= 6
       (org-test-with-temp-text
@@ -1230,7 +1231,7 @@ Otherwise, evaluate RESULT as an sexp and return its result."
 	(let ((org-src-tab-acts-natively t)
 	      (org-edit-src-content-indentation 0))
 	  (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text
@@ -1239,7 +1240,16 @@ Otherwise, evaluate RESULT as an sexp and return its result."
 	      (org-edit-src-content-indentation 2))
 	  (org-indent-line))
         (forward-line -1)
-	(org-get-indentation))))
+	(current-indentation))))
+  (should
+   (= 7
+      (org-test-with-temp-text
+	  "#+BEGIN_SRC emacs-lisp\n  (and A<point>\n       B)\n#+END_SRC"
+	(let ((org-src-tab-acts-natively t)
+	      (org-edit-src-content-indentation 2))
+	  (org-indent-line))
+        (forward-line 1)
+	(current-indentation))))
   (should
    (= 1
       (org-test-with-temp-text
@@ -1247,14 +1257,14 @@ Otherwise, evaluate RESULT as an sexp and return its result."
 	(let ((org-src-tab-acts-natively nil)
 	      (org-edit-src-content-indentation 0))
 	  (org-indent-line))
-	(org-get-indentation))))
+	(current-indentation))))
   ;; Otherwise, indent like the first non-blank line above.
   (should
    (zerop
     (org-test-with-temp-text
 	"#+BEGIN_CENTER\nline1\n\n<point>  line2\n#+END_CENTER"
       (org-indent-line)
-      (org-get-indentation))))
+      (current-indentation))))
   ;; Align node properties according to `org-property-format'.  Handle
   ;; nicely empty values.
   (should
@@ -5875,7 +5885,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-demote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 3
       (org-test-with-temp-text "* H\n  :PROPERTIES:\n  :FOO: Bar\n  :END:"
@@ -5883,7 +5893,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-demote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should-not
    (= 3
       (org-test-with-temp-text "* H\n  SCHEDULED: <2014-03-04 tue.>"
@@ -5891,7 +5901,7 @@ Text.
 	      (org-adapt-indentation nil))
 	  (org-demote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   ;; When `org-adapt-indentation' is non-nil, shift all lines in
   ;; section accordingly.  Ignore, however, footnote definitions and
   ;; inlinetasks boundaries.
@@ -5902,7 +5912,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-demote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text "* H\n  Paragraph"
@@ -5910,7 +5920,7 @@ Text.
 	      (org-adapt-indentation nil))
 	  (org-demote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H\n[fn:1] def line 1\ndef line 2"
@@ -5918,7 +5928,7 @@ Text.
 	    (org-adapt-indentation t))
 	(org-demote))
       (goto-char (point-max))
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (= 3
       (org-test-with-temp-text "* H\n[fn:1] Def.\n\n\n  After def."
@@ -5926,7 +5936,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-demote))
 	(goto-char (point-max))
-	(org-get-indentation))))
+	(current-indentation))))
   (when (featurep 'org-inlinetask)
     (should
      (zerop
@@ -5935,7 +5945,7 @@ Text.
 	(org-test-with-temp-text "* H\n***** I\n***** END"
 	  (org-demote)
 	  (forward-line)
-	  (org-get-indentation))))))
+	  (current-indentation))))))
   (when (featurep 'org-inlinetask)
     (should
      (= 3
@@ -5944,7 +5954,7 @@ Text.
 	  (org-test-with-temp-text "* H\n***** I\n  Contents\n***** END"
 	    (org-demote)
 	    (forward-line 2)
-	    (org-get-indentation))))))
+	    (current-indentation))))))
   ;; When `org-adapt-indentation' is non-nil, log drawers are
   ;; adjusted.
   (should
@@ -5981,7 +5991,7 @@ Text.
 	    (org-src-preserve-indentation nil))
 	(org-demote))
       (forward-line 2)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H\n#+BEGIN_EXAMPLE\n(+ 1 1)\n#+END_EXAMPLE"
@@ -5989,7 +5999,7 @@ Text.
 	    (org-src-preserve-indentation t))
 	(org-demote))
       (forward-line 2)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text "* H\n#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
@@ -5997,7 +6007,7 @@ Text.
 	    (org-src-preserve-indentation t))
 	(org-demote))
       (forward-line 2)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text
@@ -6006,7 +6016,7 @@ Text.
 	    (org-src-preserve-indentation nil))
 	(org-demote))
       (forward-line 2)
-      (org-get-indentation)))))
+      (current-indentation)))))
 
 (ert-deftest test-org/promote ()
   "Test `org-promote' specifications."
@@ -6059,7 +6069,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text "** H\n   :PROPERTIES:\n   :FOO: Bar\n   :END:"
@@ -6067,7 +6077,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should-not
    (= 2
       (org-test-with-temp-text "** H\n   SCHEDULED: <2014-03-04 tue.>"
@@ -6075,7 +6085,7 @@ Text.
 	      (org-adapt-indentation nil))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   ;; When `org-adapt-indentation' is non-nil, shift all lines in
   ;; section accordingly.  Ignore, however, footnote definitions and
   ;; inlinetasks boundaries.
@@ -6086,7 +6096,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should-not
    (= 2
       (org-test-with-temp-text "** H\n   Paragraph"
@@ -6094,7 +6104,7 @@ Text.
 	      (org-adapt-indentation nil))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 2
       (org-test-with-temp-text "** H\n   Paragraph\n[fn:1] line1\nline2"
@@ -6102,7 +6112,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (when (featurep 'org-inlinetask)
     (should
      (zerop
@@ -6111,7 +6121,7 @@ Text.
 	(org-test-with-temp-text "** H\n***** I\n***** END"
 	  (org-promote)
 	  (forward-line)
-	  (org-get-indentation))))))
+	  (current-indentation))))))
   (when (featurep 'org-inlinetask)
     (should
      (= 2
@@ -6120,7 +6130,7 @@ Text.
 	  (org-test-with-temp-text "** H\n***** I\n   Contents\n***** END"
 	    (org-promote)
 	    (forward-line 2)
-	    (org-get-indentation))))))
+	    (current-indentation))))))
   ;; Give up shifting if it would break document's structure
   ;; otherwise.
   (should
@@ -6130,7 +6140,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   (should
    (= 3
       (org-test-with-temp-text "** H\n   Paragraph\n * list."
@@ -6138,7 +6148,7 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation))))
+	(current-indentation))))
   ;; When `org-adapt-indentation' is non-nil, log drawers are
   ;; adjusted.
   (should
@@ -6186,7 +6196,7 @@ Text.
 	    (org-odd-levels-only nil))
 	(org-promote))
       (forward-line)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text
@@ -6196,7 +6206,7 @@ Text.
 	    (org-odd-levels-only nil))
 	(org-promote))
       (forward-line)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text
@@ -6206,7 +6216,7 @@ Text.
 	    (org-odd-levels-only nil))
 	(org-promote))
       (forward-line)
-      (org-get-indentation))))
+      (current-indentation))))
   (should
    (zerop
     (org-test-with-temp-text
@@ -6216,7 +6226,7 @@ Text.
 	    (org-odd-levels-only nil))
 	(org-promote))
       (forward-line)
-      (org-get-indentation)))))
+      (current-indentation)))))
 
 (ert-deftest test-org/org-get-valid-level ()
   "Test function `org-get-valid-level' specifications."
-- 
2.47.2

Reply via email to