diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index 3869d0327fd..74108fa9d73 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -1327,7 +1327,8 @@ nxml-compute-indent-from-matching-start-tag
its line. Otherwise return nil."
(save-excursion
(back-to-indentation)
- (let ((bol (point)))
+ (let ((bol (point))
+ bol-token-type)
(let ((inhibit-field-text-motion t))
(end-of-line))
(skip-chars-backward " \t")
@@ -1338,6 +1339,7 @@ nxml-compute-indent-from-matching-start-tag
(save-excursion
(goto-char bol)
(nxml-token-after)
+ (setq bol-token-type xmltok-type)
(= xmltok-start bol))
(eq xmltok-type 'data))
(condition-case nil
@@ -1352,15 +1354,19 @@ nxml-compute-indent-from-matching-start-tag
(goto-char xmltok-start)
(skip-chars-backward " \t")
(bolp))
- (current-indentation)))))
+ (+ (current-indentation)
+ ;; in the case of a line starting with data, keep the
+ ;; indent level above the starting tag.
+ (if (eq bol-token-type 'data)
+ nxml-child-indent
+ 0))))))
(defun nxml-compute-indent-from-previous-line ()
"Compute the indent for a line using the indentation of a previous line."
(save-excursion
(end-of-line)
(let ((eol (point))
- bol prev-bol ref
- before-context after-context)
+ bol prev-bol ref)
(back-to-indentation)
(setq bol (point))
(catch 'indent
@@ -1378,60 +1384,48 @@ nxml-compute-indent-from-previous-line
(not (or (= xmltok-start (point))
(eq xmltok-type 'data))))))
(setq ref (point))
- ;; Now scan over tokens until the end of the line to be indented.
- ;; Determine the context before and after the beginning of the
- ;; line.
- (while (< (point) eol)
- (nxml-tokenize-forward)
- (cond ((<= bol xmltok-start)
- (setq after-context
- (nxml-merge-indent-context-type after-context)))
- ((and (<= (point) bol)
- (not (and (eq xmltok-type 'partial-start-tag)
- (= (point) bol))))
- (setq before-context
- (nxml-merge-indent-context-type before-context)))
- ((eq xmltok-type 'data)
- (setq before-context
- (nxml-merge-indent-context-type before-context))
- (setq after-context
- (nxml-merge-indent-context-type after-context)))
- ;; If in the middle of a token that looks inline,
- ;; then indent relative to the previous non-blank line
- ((eq (nxml-merge-indent-context-type before-context)
- 'mixed)
- (goto-char prev-bol)
- (throw 'indent (current-column)))
- (t
- (throw 'indent
- (nxml-compute-indent-in-token bol))))
- (skip-chars-forward " \t\r\n"))
- (goto-char ref)
- (+ (current-column)
- (* nxml-child-indent
- (+ (if (eq before-context 'start-tag) 1 0)
- (if (eq after-context 'end-tag) -1 0))))))))
-
-(defun nxml-merge-indent-context-type (context)
- "Merge the indent context type CONTEXT with the token in `xmltok-type'.
-Return the merged indent context type. An indent context type is
-either nil or one of the symbols `start-tag', `end-tag', `markup',
-`comment', `mixed'."
- (cond ((memq xmltok-type '(start-tag partial-start-tag))
- (if (memq context '(nil start-tag comment))
- 'start-tag
- 'mixed))
- ((memq xmltok-type '(end-tag partial-end-tag))
- (if (memq context '(nil end-tag comment))
- 'end-tag
- 'mixed))
- ((eq xmltok-type 'comment)
- (cond ((memq context '(start-tag end-tag comment))
- context)
- (context 'mixed)
- (t 'comment)))
- (context 'mixed)
- (t 'markup)))
+ (let ((depth-before 0)
+ (depth-after 0)
+ start-type-before)
+ (nxml-tokenize-forward)
+ (when (> (point) bol) ; one token spans this and the line before
+ (throw 'indent (nxml-compute-indent-in-token bol)))
+
+ ;; Scan over the prevous line to determine the change in element depth
+ (setq start-type-before xmltok-type)
+ (while (< (point) bol) ; examine all tags on the previous line
+ (cond ((eq xmltok-type 'partial-start-tag)
+ (throw 'indent (nxml-compute-indent-in-token bol)))
+ ((eq xmltok-type 'start-tag)
+ (cl-incf depth-before))
+ ((eq xmltok-type 'end-tag)
+ (cl-incf depth-before -1)))
+ (skip-chars-forward " \t\r\n")
+ (nxml-tokenize-forward))
+
+ ;; Scan over the current line to determine the change in element depth
+ (while (and (<= (point) eol) ; examine all tags on the current line.
+ (< (point) (point-max)))
+ (cond ((eq xmltok-type 'start-tag)
+ (cl-incf depth-after))
+ ((eq xmltok-type 'end-tag)
+ (cl-incf depth-after -1)))
+ (skip-chars-forward " \t\r\n")
+ (nxml-tokenize-forward))
+
+ (goto-char ref)
+ (+ (current-column)
+ (* nxml-child-indent
+ (+ (max 0 depth-before)
+ (min 0 depth-after)
+ ;; if our before-line started as a data element we
+ ;; must back out that indentation as well as long
+ ;; as we are not beginning additional tags
+ (if (and (memq start-type-before '(data cdata-section))
+ (>= depth-after 0)
+ (< depth-before 0))
+ -1
+ 0)))))))))
(defun nxml-compute-indent-in-token (pos)
"Return the indent for a line that starts inside a token.
diff --git a/test/lisp/nxml/nxml-mode-tests.el b/test/lisp/nxml/nxml-mode-tests.el
index 973f2ebb67e..532c39e8608 100644
--- a/test/lisp/nxml/nxml-mode-tests.el
+++ b/test/lisp/nxml/nxml-mode-tests.el
@@ -31,6 +31,17 @@ nxml-mode-tests-correctly-indented-string
(ert-deftest nxml-indent-line-after-attribute ()
(should (nxml-mode-tests-correctly-indented-string "
+
+
+ ...
+
+
+"))
+ (should (nxml-mode-tests-correctly-indented-string "
+
+ more
+ data
+
+
+ more
+ data
+
+
+
+ more
+
+ data
+
+
+
+
+
+ data
+
+
+
+ data
+
+
+
+
+ data
+
+
+
+")))
+
+
+(ert-deftest nxml-mode-test-multiple-start-tags-single-line ()
+ "Test for indent depth where multiple tags are on one line."
+ (should (nxml-mode-tests-correctly-indented-string "
+
+
+ abc
+ 123
+
+
+
+"))
+ (should (nxml-mode-tests-correctly-indented-string "
+
+
+ abc
+
+
+
+"))
+ (should (nxml-mode-tests-correctly-indented-string "
+
+
+
+ data
+
+
+ data
+
+
+
+
+
+
+ four
+
+
+
+
+
+
+ four
+
+
+ three
+ five
+
+
+
+
+")))
+
(provide 'nxml-mode-tests)
;;; nxml-mode-tests.el ends here