forked from mirrors/org-mode
org-element: Fix indentation normalization
* lisp/org-element.el (org-element-normalize-contents): Do not ignore empty lines when an object follows. * testing/lisp/test-org-element.el (test-org-element/normalize-contents): Add test.
This commit is contained in:
parent
ff41c56d11
commit
7f287d1b62
|
@ -4609,71 +4609,65 @@ indentation to compute maximal common indentation.
|
|||
Return the normalized element that is element with global
|
||||
indentation removed from its contents. The function assumes that
|
||||
indentation is not done with TAB characters."
|
||||
(let* (ind-list ; for byte-compiler
|
||||
collect-inds ; for byte-compiler
|
||||
(collect-inds
|
||||
(let* ((min-ind most-positive-fixnum)
|
||||
find-min-ind ; For byte-compiler.
|
||||
(find-min-ind
|
||||
(function
|
||||
;; Return list of indentations within BLOB. This is done by
|
||||
;; walking recursively BLOB and updating IND-LIST along the
|
||||
;; way. FIRST-FLAG is non-nil when the first string hasn't
|
||||
;; been seen yet. It is required as this string is the only
|
||||
;; one whose indentation doesn't happen after a newline
|
||||
;; character.
|
||||
;; Return minimal common indentation within BLOB. This is
|
||||
;; done by walking recursively BLOB and updating MIN-IND
|
||||
;; along the way. FIRST-FLAG is non-nil when the first
|
||||
;; string hasn't been seen yet. It is required as this
|
||||
;; string is the only one whose indentation doesn't happen
|
||||
;; after a newline character.
|
||||
(lambda (blob first-flag)
|
||||
(mapc
|
||||
(lambda (object)
|
||||
(when (and first-flag (stringp object))
|
||||
(setq first-flag nil)
|
||||
(string-match "\\`\\( *\\)" object)
|
||||
(let ((len (length (match-string 1 object))))
|
||||
;; An indentation of zero means no string will be
|
||||
;; modified. Quit the process.
|
||||
(if (zerop len) (throw 'zero (setq ind-list nil))
|
||||
(push len ind-list))))
|
||||
(cond
|
||||
((stringp object)
|
||||
(let ((start 0))
|
||||
;; Avoid matching blank or empty lines.
|
||||
(while (and (string-match "\n\\( *\\)\\(.\\)" object start)
|
||||
(not (equal (match-string 2 object) " ")))
|
||||
(setq start (match-end 0))
|
||||
(push (length (match-string 1 object)) ind-list))))
|
||||
((memq (org-element-type object) org-element-recursive-objects)
|
||||
(funcall collect-inds object first-flag))))
|
||||
(org-element-contents blob))))))
|
||||
;; Collect indentation list in ELEMENT. Possibly remove first
|
||||
;; value if IGNORE-FIRST is non-nil.
|
||||
(catch 'zero (funcall collect-inds element (not ignore-first)))
|
||||
(if (not ind-list) element
|
||||
(dolist (object (org-element-contents blob))
|
||||
(when (and first-flag (stringp object))
|
||||
(setq first-flag nil)
|
||||
(string-match "\\`\\( *\\)" object)
|
||||
(let ((len (length (match-string 1 object))))
|
||||
;; An indentation of zero means no string will be
|
||||
;; modified. Quit the process.
|
||||
(if (zerop len) (throw 'zero (setq min-ind 0))
|
||||
(setq min-ind (min len min-ind)))))
|
||||
(cond
|
||||
((stringp object)
|
||||
(dolist (line (delq "" (cdr (org-split-string object " *\n"))))
|
||||
(setq min-ind (min (org-get-indentation line) min-ind))))
|
||||
((memq (org-element-type object) org-element-recursive-objects)
|
||||
(funcall find-min-ind object first-flag))))))))
|
||||
;; Find minimal indentation in ELEMENT.
|
||||
(catch 'zero (funcall find-min-ind element (not ignore-first)))
|
||||
(if (or (zerop min-ind) (= min-ind most-positive-fixnum)) element
|
||||
;; Build ELEMENT back, replacing each string with the same
|
||||
;; string minus common indentation.
|
||||
(let* (build ; For byte compiler.
|
||||
(build
|
||||
(function
|
||||
(lambda (blob mci first-flag)
|
||||
(lambda (blob first-flag)
|
||||
;; Return BLOB with all its strings indentation
|
||||
;; shortened from MCI white spaces. FIRST-FLAG is
|
||||
;; non-nil when the first string hasn't been seen
|
||||
;; shortened from MIN-IND white spaces. FIRST-FLAG
|
||||
;; is non-nil when the first string hasn't been seen
|
||||
;; yet.
|
||||
(setcdr (cdr blob)
|
||||
(mapcar
|
||||
(lambda (object)
|
||||
(when (and first-flag (stringp object))
|
||||
(setq first-flag nil)
|
||||
(setq object
|
||||
(replace-regexp-in-string
|
||||
(format "\\` \\{%d\\}" mci) "" object)))
|
||||
(cond
|
||||
((stringp object)
|
||||
(replace-regexp-in-string
|
||||
(format "\n \\{%d\\}" mci) "\n" object))
|
||||
((memq (org-element-type object)
|
||||
org-element-recursive-objects)
|
||||
(funcall build object mci first-flag))
|
||||
(t object)))
|
||||
#'(lambda (object)
|
||||
(when (and first-flag (stringp object))
|
||||
(setq first-flag nil)
|
||||
(setq object
|
||||
(replace-regexp-in-string
|
||||
(format "\\` \\{%d\\}" min-ind)
|
||||
"" object)))
|
||||
(cond
|
||||
((stringp object)
|
||||
(replace-regexp-in-string
|
||||
(format "\n \\{%d\\}" min-ind) "\n" object))
|
||||
((memq (org-element-type object)
|
||||
org-element-recursive-objects)
|
||||
(funcall build object first-flag))
|
||||
(t object)))
|
||||
(org-element-contents blob)))
|
||||
blob))))
|
||||
(funcall build element (apply 'min ind-list) (not ignore-first))))))
|
||||
(funcall build element (not ignore-first))))))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2869,34 +2869,38 @@ Paragraph \\alpha."
|
|||
|
||||
(ert-deftest test-org-element/normalize-contents ()
|
||||
"Test `org-element-normalize-contents' specifications."
|
||||
;; 1. Remove maximum common indentation from element's contents.
|
||||
;; Remove maximum common indentation from element's contents.
|
||||
(should
|
||||
(equal
|
||||
(org-element-normalize-contents
|
||||
'(paragraph nil " Two spaces\n Three spaces"))
|
||||
'(paragraph nil "Two spaces\n Three spaces")))
|
||||
;; 2. Ignore objects within contents when computing maximum common
|
||||
;; indentation.
|
||||
;; Ignore objects within contents when computing maximum common
|
||||
;; indentation.
|
||||
(should
|
||||
(equal
|
||||
(org-element-normalize-contents
|
||||
'(paragraph nil " One " (emphasis nil "space") "\n Two spaces"))
|
||||
'(paragraph nil "One " (emphasis nil "space") "\n Two spaces")))
|
||||
;; 3. Ignore blank lines.
|
||||
;; Ignore blank lines.
|
||||
(should
|
||||
(equal
|
||||
(org-element-normalize-contents
|
||||
'(paragraph nil " Two spaces\n\n \n Two spaces"))
|
||||
'(paragraph nil "Two spaces\n\n \nTwo spaces")))
|
||||
;; 4. Recursively enter objects in order to compute common
|
||||
;; indentation.
|
||||
(should
|
||||
(equal
|
||||
'(paragraph nil " Two spaces\n" (verbatim nil "V") "\n Two spaces")
|
||||
(org-element-normalize-contents
|
||||
'(paragraph nil " Two spaces\n " (verbatim nil "V") "\n Two spaces"))))
|
||||
;; Recursively enter objects in order to compute common indentation.
|
||||
(should
|
||||
(equal
|
||||
(org-element-normalize-contents
|
||||
'(paragraph nil " Two spaces " (bold nil " and\n One space")))
|
||||
'(paragraph nil " Two spaces " (bold nil " and\nOne space"))))
|
||||
;; 5. When optional argument is provided, ignore first line
|
||||
;; indentation.
|
||||
;; When optional argument is provided, ignore first line
|
||||
;; indentation.
|
||||
(should
|
||||
(equal
|
||||
(org-element-normalize-contents
|
||||
|
|
Loading…
Reference in New Issue