Pārlūkot izejas kodu

Fix cba2f0a

* lisp/org.el (org-adapt-indentation): Update docstring.
(org-fixup-indentation): Ignore contents of source blocks and example
blocks when indentation should be preserved.

* testing/lisp/test-org.el (test-org/demote, test-org/promote): Add
  tests.
Nicolas Goaziou 10 gadi atpakaļ
vecāks
revīzija
83d8a2b16d
2 mainītis faili ar 162 papildinājumiem un 52 dzēšanām
  1. 78 47
      lisp/org.el
  2. 84 5
      testing/lisp/test-org.el

+ 78 - 47
lisp/org.el

@@ -1461,23 +1461,25 @@ lines to the buffer:
   "Non-nil means adapt indentation to outline node level.
 
 When this variable is set, Org assumes that you write outlines by
-indenting text in each node to align with the headline (after the stars).
-The following issues are influenced by this variable:
+indenting text in each node to align with the headline (after the
+stars).  The following issues are influenced by this variable:
 
-- When this is set and the *entire* text in an entry is indented, the
-  indentation is increased by one space in a demotion command, and
-  decreased by one in a promotion command.  If any line in the entry
-  body starts with text at column 0, indentation is not changed at all.
+- The indentation is increased by one space in a demotion
+  command, and decreased by one in a promotion command.  However,
+  in the latter case, if shifting some line in the entry body
+  would alter document structure (e.g., insert a new headline),
+  indentation is not changed at all.
 
-- Property drawers and planning information is inserted indented when
-  this variable is set.  When nil, they will not be indented.
+- Property drawers and planning information is inserted indented
+  when this variable is set.  When nil, they will not be indented.
 
-- TAB indents a line relative to context.  The lines below a headline
-  will be indented when this variable is set.
+- TAB indents a line relative to current level.  The lines below
+  a headline will be indented when this variable is set.
 
-Note that this is all about true indentation, by adding and removing
-space characters.  See also `org-indent.el' which does level-dependent
-indentation in a virtual way, i.e. at display time in Emacs."
+Note that this is all about true indentation, by adding and
+removing space characters.  See also `org-indent.el' which does
+level-dependent indentation in a virtual way, i.e. at display
+time in Emacs."
   :group 'org-edit-structure
   :type 'boolean)
 
@@ -8262,41 +8264,70 @@ Assume point is at a heading or an inlinetask beginning."
      ;; If DIFF is negative, first check if a shift is possible at all
      ;; (e.g., it doesn't break structure).  This can only happen if
      ;; some contents are not properly indented.
-     (when (< diff 0)
-       (let ((diff (- diff))
-	     (forbidden-re (concat org-outline-regexp
-				   "\\|"
-				   (substring org-footnote-definition-re 1))))
-	 (save-excursion
-	   (while (not (eobp))
-	     (cond
-	      ((org-looking-at-p "[ \t]*$") (forward-line))
-	      ((and (org-looking-at-p org-footnote-definition-re)
+     (let ((case-fold-search t))
+       (when (< diff 0)
+	 (let ((diff (- diff))
+	       (forbidden-re (concat org-outline-regexp
+				     "\\|"
+				     (substring org-footnote-definition-re 1))))
+	   (save-excursion
+	     (while (not (eobp))
+	       (cond
+		((org-looking-at-p "[ \t]*$") (forward-line))
+		((and (org-looking-at-p org-footnote-definition-re)
+		      (let ((e (org-element-at-point)))
+			(and (eq (org-element-type e) 'footnote-definition)
+			     (goto-char (org-element-property :end e))))))
+		((org-looking-at-p org-outline-regexp) (forward-line))
+		;; Give up if shifting would move before column 0 or
+		;; if it would introduce a headline or a footnote
+		;; definition.
+		(t
+		 (skip-chars-forward " \t")
+		 (let ((ind (current-column)))
+		   (when (or (< ind diff)
+			     (and (= ind diff) (org-looking-at-p forbidden-re)))
+		     (throw 'no-shift nil)))
+		 ;; Ignore contents of example blocks and source
+		 ;; blocks if their indentation is meant to be
+		 ;; preserved.  Jump to block's closing line.
+		 (beginning-of-line)
+		 (or (and (org-looking-at-p "[ \t]*#\\+BEGIN_\\(EXAMPLE\\|SRC\\)")
+			  (let ((e (org-element-at-point)))
+			    (and (memq (org-element-type e)
+				       '(example-block src-block))
+				 (or org-src-preserve-indentation
+				     (org-element-property :preserve-indent e))
+				 (goto-char (org-element-property :end e))
+				 (progn (skip-chars-backward " \r\t\n")
+					(beginning-of-line)
+					t))))
+		     (forward-line))))))))
+       ;; Shift lines but footnote definitions, inlinetasks boundaries
+       ;; by DIFF.  Also skip contents of source or example blocks
+       ;; when indentation is meant to be preserved.
+       (while (not (eobp))
+	 (cond
+	  ((and (org-looking-at-p org-footnote-definition-re)
+		(let ((e (org-element-at-point)))
+		  (and (eq (org-element-type e) 'footnote-definition)
+		       (goto-char (org-element-property :end e))))))
+	  ((org-looking-at-p org-outline-regexp) (forward-line))
+	  ((org-looking-at-p "[ \t]*$") (forward-line))
+	  (t
+	   (org-indent-line-to (+ (org-get-indentation) diff))
+	   (beginning-of-line)
+	   (or (and (org-looking-at-p "[ \t]*#\\+BEGIN_\\(EXAMPLE\\|SRC\\)")
 		    (let ((e (org-element-at-point)))
-		      (and (eq (org-element-type e) 'footnote-definition)
-			   (goto-char (org-element-property :end e))))))
-	      ((org-looking-at-p org-outline-regexp) (forward-line))
-	      ;; Give up if shifting would move before column 0 or if
-	      ;; it would introduce a headline or a footnote
-	      ;; definition.
-	      (t
-	       (skip-chars-forward " \t")
-	       (let ((ind (current-column)))
-		 (when (or (< ind diff)
-			   (and (= ind diff) (org-looking-at-p forbidden-re)))
-		   (throw 'no-shift nil)))
-	       (forward-line)))))))
-     ;; Shift lines but footnote definitions and inlinetasks by DIFF.
-     (while (not (eobp))
-       (cond
-	((and (org-looking-at-p org-footnote-definition-re)
-	      (let ((e (org-element-at-point)))
-		(and (eq (org-element-type e) 'footnote-definition)
-		     (goto-char (org-element-property :end e))))))
-	((org-looking-at-p org-outline-regexp) (forward-line))
-	((org-looking-at-p "[ \t]*$") (forward-line))
-	(t (org-indent-line-to (+ (org-get-indentation) diff))
-	   (forward-line)))))))
+		      (and (memq (org-element-type e)
+				 '(example-block src-block))
+			   (or org-src-preserve-indentation
+			       (org-element-property :preserve-indent e))
+			   (goto-char (org-element-property :end e))
+			   (progn (skip-chars-backward " \r\t\n")
+				  (beginning-of-line)
+				  t))))
+	       (forward-line)))))))))
 
 (defun org-convert-to-odd-levels ()
   "Convert an org-mode file with all levels allowed to one with odd levels.

+ 84 - 5
testing/lisp/test-org.el

@@ -2037,11 +2037,11 @@ Text.
 	(org-get-indentation))))
   (should
    (zerop
-    (org-test-with-temp-text "* H\n[fn:1] Definition."
+    (org-test-with-temp-text "* H\n[fn:1] def line 1\ndef line 2"
       (let ((org-odd-levels-only nil)
 	    (org-adapt-indentation t))
 	(org-demote))
-      (forward-line)
+      (goto-char (point-max))
       (org-get-indentation))))
   (should
    (= 3
@@ -2068,7 +2068,43 @@ Text.
 	  (org-test-with-temp-text "* H\n***** I\n  Contents\n***** END"
 	    (org-demote)
 	    (forward-line 2)
-	    (org-get-indentation)))))))
+	    (org-get-indentation))))))
+  ;; Ignore contents of source blocks or example blocks when
+  ;; indentation should be preserved (through
+  ;; `org-src-preserve-indentation' or "-i" flag).
+  (should-not
+   (zerop
+    (org-test-with-temp-text "* H\n#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation nil))
+	(org-demote))
+      (forward-line 2)
+      (org-get-indentation))))
+  (should
+   (zerop
+    (org-test-with-temp-text "* H\n#+BEGIN_EXAMPLE\n(+ 1 1)\n#+END_EXAMPLE"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation t))
+	(org-demote))
+      (forward-line 2)
+      (org-get-indentation))))
+  (should
+   (zerop
+    (org-test-with-temp-text "* H\n#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation t))
+	(org-demote))
+      (forward-line 2)
+      (org-get-indentation))))
+  (should
+   (zerop
+    (org-test-with-temp-text
+	"* H\n#+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n#+END_SRC"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation nil))
+	(org-demote))
+      (forward-line 2)
+      (org-get-indentation)))))
 
 (ert-deftest test-org/promote ()
   "Test `org-promote' specifications."
@@ -2159,7 +2195,7 @@ Text.
 	(org-get-indentation))))
   (should
    (= 2
-      (org-test-with-temp-text "** H\n   Paragraph\n[fn:1] Definition."
+      (org-test-with-temp-text "** H\n   Paragraph\n[fn:1] line1\nline2"
 	(let ((org-odd-levels-only nil)
 	      (org-adapt-indentation t))
 	  (org-promote))
@@ -2200,7 +2236,50 @@ Text.
 	      (org-adapt-indentation t))
 	  (org-promote))
 	(forward-line)
-	(org-get-indentation)))))
+	(org-get-indentation))))
+  ;; Ignore contents of source blocks or example blocks when
+  ;; indentation should be preserved (through
+  ;; `org-src-preserve-indentation' or "-i" flag).
+  (should-not
+   (zerop
+    (org-test-with-temp-text
+	"** H\n #+BEGIN_SRC emacs-lisp\n(+ 1 1)\n #+END_SRC"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation nil)
+	    (org-odd-levels-only nil))
+	(org-promote))
+      (forward-line)
+      (org-get-indentation))))
+  (should
+   (zerop
+    (org-test-with-temp-text
+	"** H\n #+BEGIN_EXAMPLE\nContents\n #+END_EXAMPLE"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation t)
+	    (org-odd-levels-only nil))
+	(org-promote))
+      (forward-line)
+      (org-get-indentation))))
+  (should
+   (zerop
+    (org-test-with-temp-text
+	"** H\n #+BEGIN_SRC emacs-lisp\n(+ 1 1)\n #+END_SRC"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation t)
+	    (org-odd-levels-only nil))
+	(org-promote))
+      (forward-line)
+      (org-get-indentation))))
+  (should
+   (zerop
+    (org-test-with-temp-text
+	"** H\n #+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n #+END_SRC"
+      (let ((org-adapt-indentation t)
+	    (org-src-preserve-indentation nil)
+	    (org-odd-levels-only nil))
+	(org-promote))
+      (forward-line)
+      (org-get-indentation)))))
 
 
 ;;; Planning