summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2014-10-13 19:03:14 +0200
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2014-10-13 19:03:14 +0200
commitce2090ccfde4288d8306d108b92d6713b55ee2ab (patch)
tree55ddfedd4a57b1934007a70e3e7fcca8a28acca6
parent352118bf7fd2b8b1ef254545138ec105ab3991cf (diff)
downloadorg-mode-ce2090ccfde4288d8306d108b92d6713b55ee2ab.tar.gz
Fix indentation in lists
* lisp/org-list.el (org-list-item-body-column): Take into consideration empty items and bullets followed by two spaces. * lisp/org.el (org--get-expected-indentation): Fix return value for items in lists. (org-indent-region): Fix infloop when indenting some types of plain lists. Also fix error when region starts with blank lines at the beginning of the buffer. * testing/lisp/test-org.el (test-org/indent-region): Add tests.
-rw-r--r--lisp/org-list.el23
-rwxr-xr-xlisp/org.el90
-rw-r--r--testing/lisp/test-org.el14
3 files changed, 83 insertions, 44 deletions
diff --git a/lisp/org-list.el b/lisp/org-list.el
index 774d87f..b1d47c9 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -2051,16 +2051,19 @@ Possible values are: `folded', `children' or `subtree'. See
(defun org-list-item-body-column (item)
"Return column at which body of ITEM should start."
- (let (bpos bcol tpos tcol)
- (save-excursion
- (goto-char item)
- (looking-at "[ \t]*\\(\\S-+\\)\\(.*[ \t]+::\\)?\\([ \t]+\\|$\\)")
- (setq bpos (match-beginning 1) tpos (match-end 0)
- bcol (progn (goto-char bpos) (current-column))
- tcol (progn (goto-char tpos) (current-column)))
- (when (> tcol (+ bcol org-description-max-indent))
- (setq tcol (+ bcol 5))))
- tcol))
+ (save-excursion
+ (goto-char item)
+ (looking-at "[ \t]*\\(\\S-+\\)\\(.*[ \t]+::\\)?\\([ \t]+\\|$\\)")
+ (if (match-beginning 2)
+ (let ((start (1+ (match-end 2)))
+ (ind (org-get-indentation)))
+ (if (> start (+ ind org-description-max-indent)) (+ ind 5) start))
+ (+ (progn (goto-char (match-end 1)) (current-column))
+ (if (and org-list-two-spaces-after-bullet-regexp
+ (org-string-match-p org-list-two-spaces-after-bullet-regexp
+ (match-string 1)))
+ 2
+ 1)))))
diff --git a/lisp/org.el b/lisp/org.el
index d702cf5..1570063 100755
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -22415,9 +22415,13 @@ ELEMENT."
(if (not org-adapt-indentation) 0
(let ((level (org-current-level)))
(if level (1+ level) 0))))
- ((item plain list)
+ (item
(org-list-item-body-column
(org-element-property :post-affiliated element)))
+ (plain-list
+ (save-excursion
+ (goto-char (org-element-property :post-affiliated element))
+ (org-get-indentation)))
(otherwise
(goto-char start)
(org-get-indentation))))
@@ -22439,19 +22443,25 @@ ELEMENT."
(while t
(if (= (point-min) start) (throw 'exit 0)
(goto-char (1- start))
- (let ((previous (org-element-at-point)))
- (while (let ((parent (org-element-property :parent previous)))
- (and parent
- (setq previous parent)
- (<= (org-element-property :end parent) start))))
- (cond ((or (not previous)
- (> (org-element-property :end previous) start))
- (throw 'exit (org--get-expected-indentation previous t)))
- ((memq (org-element-type previous)
- '(footnote-definition inlinetask))
- (setq start (org-element-property :begin previous)))
- (t (goto-char (org-element-property :begin previous))
- (throw 'exit (org-get-indentation)))))))))
+ (let* ((previous (org-element-at-point))
+ (parent previous))
+ (while (and parent (<= (org-element-property :end parent) start))
+ (setq previous parent
+ parent (org-element-property :parent parent)))
+ (cond
+ ((not previous) (throw 'exit 0))
+ ((> (org-element-property :end previous) start)
+ (throw 'exit (org--get-expected-indentation previous t)))
+ ((memq (org-element-type previous)
+ '(footnote-definition inlinetask))
+ (setq start (org-element-property :begin previous)))
+ (t (goto-char (org-element-property :begin previous))
+ (throw 'exit
+ (if (bolp) (org-get-indentation)
+ ;; At first paragraph in an item or
+ ;; a footnote definition.
+ (org--get-expected-indentation
+ (org-element-property :parent previous) t))))))))))
;; Otherwise, move to the first non-blank line above.
(t
(beginning-of-line)
@@ -22584,13 +22594,14 @@ assumed to be significant there."
(interactive "r")
(save-excursion
(goto-char start)
- (beginning-of-line)
+ (skip-chars-forward " \r\t\n")
+ (unless (eobp) (beginning-of-line))
(let ((indent-to
(lambda (ind pos)
;; Set IND as indentation for all lines between point and
;; POS or END, whichever comes first. Blank lines are
;; ignored. Leave point after POS once done.
- (let ((limit (copy-marker (min end pos))))
+ (let ((limit (copy-marker (min end pos))))
(while (< (point) limit)
(unless (org-looking-at-p "[ \t]*$") (org-indent-line-to ind))
(forward-line))
@@ -22602,17 +22613,18 @@ assumed to be significant there."
(type (org-element-type element))
(element-end (copy-marker (org-element-property :end element)))
(ind (org--get-expected-indentation element nil)))
- (if (or (memq type '(paragraph table table-row))
- (not (or (org-element-property :contents-begin element)
- (memq type
- '(example-block export-block src-block)))))
- ;; Elements here are indented as a single block. Also
- ;; align node properties.
- (progn
- (when (eq type 'node-property)
- (org--align-node-property)
- (beginning-of-line))
- (funcall indent-to ind element-end))
+ (cond
+ ((or (memq type '(paragraph table table-row))
+ (not (or (org-element-property :contents-begin element)
+ (memq type
+ '(example-block export-block src-block)))))
+ ;; Elements here are indented as a single block. Also
+ ;; align node properties.
+ (when (eq type 'node-property)
+ (org--align-node-property)
+ (beginning-of-line))
+ (funcall indent-to ind element-end))
+ (t
;; Elements in this category consist of three parts:
;; before the contents, the contents, and after the
;; contents. The contents are treated specially,
@@ -22636,8 +22648,9 @@ assumed to be significant there."
;; from the second line.
(org-with-wide-buffer
(goto-char post)
- (forward-line)
- (point)))
+ (end-of-line)
+ (skip-chars-forward " \r\t\n")
+ (if (eobp) (point) (line-beginning-position))))
(t (org-element-property :contents-begin element)))))
(cend (copy-marker
(or (org-element-property :contents-end element)
@@ -22646,13 +22659,24 @@ assumed to be significant there."
(goto-char element-end)
(skip-chars-backward " \r\t\n")
(line-beginning-position))))))
- (funcall indent-to ind cbeg)
+ ;; Do not change items indentation individually as it
+ ;; might break the list as a whole. On the other
+ ;; hand, when at a plain list, indent it as a whole.
+ (cond ((eq type 'plain-list)
+ (let ((offset (- ind (org-get-indentation))))
+ (unless (zerop offset)
+ (indent-rigidly (org-element-property :begin element)
+ (org-element-property :end element)
+ offset))
+ (goto-char cbeg)))
+ ((eq type 'item) (goto-char cbeg))
+ (t (funcall indent-to ind cbeg)))
(when (< (point) end)
(case type
((example-block export-block verse-block))
(src-block
- ;; In a source block, indent source code according
- ;; to language major mode, but only if
+ ;; In a source block, indent source code
+ ;; according to language major mode, but only if
;; `org-src-tab-acts-natively' is non-nil.
(when (and (< (point) end) org-src-tab-acts-natively)
(ignore-errors
@@ -22667,7 +22691,7 @@ assumed to be significant there."
(when (< (point) end) (funcall indent-to ind element-end)))
(set-marker post nil)
(set-marker cbeg nil)
- (set-marker cend nil)))
+ (set-marker cend nil))))
(set-marker element-end nil))))
(set-marker end nil))))
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index c91dcbe..6a10383 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -655,16 +655,28 @@
(let ((org-property-format "%-10s %s"))
(org-indent-region (point-min) (point-max)))
(buffer-string))))
- ;; Special case: plain lists and footnote definitions.
+ ;; Indent plain lists.
(should
(equal "- A\n B\n - C\n\n D"
(org-test-with-temp-text "- A\n B\n - C\n\n D"
(org-indent-region (point-min) (point-max))
(buffer-string))))
(should
+ (equal "- A\n\n- B"
+ (org-test-with-temp-text " - A\n\n - B"
+ (org-indent-region (point-min) (point-max))
+ (buffer-string))))
+ ;; Indent footnote definitions.
+ (should
(equal "[fn:1] Definition\n\nDefinition"
(org-test-with-temp-text "[fn:1] Definition\n\n Definition"
(org-indent-region (point-min) (point-max))
+ (buffer-string))))
+ ;; Special case: Start indenting on a blank line.
+ (should
+ (equal "\nParagraph"
+ (org-test-with-temp-text "\n Paragraph"
+ (org-indent-region (point-min) (point-max))
(buffer-string)))))