* 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.
This commit is contained in:
Nicolas Goaziou 2014-11-10 20:36:01 +01:00
parent ece68a7a6f
commit 83d8a2b16d
2 changed files with 162 additions and 52 deletions

View File

@ -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.

View File

@ -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