ox: Do not trim leading and trailing blank lines from code

* lisp/ox.el (org-export-get-loc):
(org-export-unravel-code):
(org-export-format-code):
(org-export-format-code-default): Do not trim leading and trailing
blank lines from code during export.

* testing/lisp/test-ox.el (test-org-export/unravel-code): Update tests.
(test-org-export/format-code-default): Add tests.

Reported-by: Li DebugFan <debugfanli@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/113205>
This commit is contained in:
Nicolas Goaziou 2017-04-29 14:32:29 +02:00
parent 91236a3db3
commit 1332bbd616
2 changed files with 55 additions and 36 deletions

View File

@ -4503,7 +4503,7 @@ ELEMENT doesn't allow line numbering."
(let ((linum (org-element-property :number-lines el)))
(when linum
(let ((lines (org-count-lines
(org-trim (org-element-property :value el)))))
(org-element-property :value el))))
;; Accumulate locs or reset them.
(pcase linum
(`(new . ,n) (setq loc (+ n lines)))
@ -4522,30 +4522,28 @@ an alist between relative line number (integer) and name of code
reference on that line (string)."
(let* ((line 0) refs
(value (org-element-property :value element))
;; Get code and clean it. Remove blank lines at its
;; beginning and end.
;; Remove global indentation from code, if necessary. Also
;; remove final newline character, since it doesn't belongs
;; to the code proper.
(code (replace-regexp-in-string
"\\`\\([ \t]*\n\\)+" ""
(replace-regexp-in-string
"\\([ \t]*\n\\)*[ \t]*\\'" "\n"
(if (or org-src-preserve-indentation
(org-element-property :preserve-indent element))
value
(org-remove-indentation value)))))
"\n\\'" ""
(if (or org-src-preserve-indentation
(org-element-property :preserve-indent element))
value
(org-remove-indentation value))))
;; Build a regexp matching a loc with a reference.
(ref-re (org-src-coderef-regexp (org-src-coderef-format element))))
;; Return value.
(cons
;; Code with references removed.
(org-element-normalize-string
(mapconcat
(lambda (loc)
(cl-incf line)
(if (not (string-match ref-re loc)) loc
;; Ref line: remove ref, and signal its position in REFS.
(push (cons line (match-string 3 loc)) refs)
(replace-match "" nil nil loc 1)))
(org-split-string code "\n") "\n"))
(mapconcat
(lambda (loc)
(cl-incf line)
(if (not (string-match ref-re loc)) loc
;; Ref line: remove ref, and add its position in REFS.
(push (cons line (match-string 3 loc)) refs)
(replace-match "" nil nil loc 1)))
(split-string code "\n") "\n")
;; Reference alist.
refs)))
@ -4568,15 +4566,16 @@ number (i.e. ignoring NUM-LINES) and the name of the code
reference on it. If it is nil, FUN's third argument will always
be nil. It can be obtained through the use of
`org-export-unravel-code' function."
(let ((--locs (org-split-string code "\n"))
(let ((--locs (split-string code "\n"))
(--line 0))
(org-element-normalize-string
(concat
(mapconcat
(lambda (--loc)
(cl-incf --line)
(let ((--ref (cdr (assq --line ref-alist))))
(funcall fun --loc (and num-lines (+ num-lines --line)) --ref)))
--locs "\n"))))
--locs "\n")
"\n")))
(defun org-export-format-code-default (element info)
"Return source code from ELEMENT, formatted in a standard way.
@ -4593,7 +4592,7 @@ code."
;; Extract code and references.
(let* ((code-info (org-export-unravel-code element))
(code (car code-info))
(code-lines (org-split-string code "\n")))
(code-lines (split-string code "\n")))
(if (null code-lines) ""
(let* ((refs (and (org-element-property :retain-labels element)
(cdr code-info)))
@ -4618,9 +4617,9 @@ code."
number-str
loc
(and ref
(concat (make-string
(- (+ 6 max-width)
(+ (length loc) (length number-str))) ? )
(concat (make-string (- (+ 6 max-width)
(+ (length loc) (length number-str)))
?\s)
(format "(%s)" ref))))))
num-start refs)))))

View File

@ -3363,12 +3363,12 @@ Another text. (ref:text)
"Test `org-export-unravel-code' function."
;; Code without reference.
(should
(equal '("(+ 1 1)\n")
(equal '("(+ 1 1)")
(org-test-with-temp-text "#+BEGIN_EXAMPLE\n(+ 1 1)\n#+END_EXAMPLE"
(org-export-unravel-code (org-element-at-point)))))
;; Code with reference.
(should
(equal '("(+ 1 1)\n" (1 . "test"))
(equal '("(+ 1 1)" (1 . "test"))
(org-test-with-temp-text
"#+BEGIN_EXAMPLE\n(+ 1 1) (ref:test)\n#+END_EXAMPLE"
(let ((org-coderef-label-format "(ref:%s)"))
@ -3376,14 +3376,14 @@ Another text. (ref:text)
;; Code with user-defined reference.
(should
(equal
'("(+ 1 1)\n" (1 . "test"))
'("(+ 1 1)" (1 . "test"))
(org-test-with-temp-text
"#+BEGIN_EXAMPLE -l \"[ref:%s]\"\n(+ 1 1) [ref:test]\n#+END_EXAMPLE"
(let ((org-coderef-label-format "(ref:%s)"))
(org-export-unravel-code (org-element-at-point))))))
;; Code references keys are relative to the current block.
(should
(equal '("(+ 2 2)\n(+ 3 3)\n" (2 . "one"))
(equal '("(+ 2 2)\n(+ 3 3)" (2 . "one"))
(org-test-with-temp-text "
#+BEGIN_EXAMPLE -n
\(+ 1 1)
@ -3394,23 +3394,43 @@ Another text. (ref:text)
#+END_EXAMPLE"
(goto-line 5)
(let ((org-coderef-label-format "(ref:%s)"))
(org-export-unravel-code (org-element-at-point)))))))
(org-export-unravel-code (org-element-at-point)))))))
(ert-deftest test-org-export/format-code-default ()
"Test `org-export-format-code-default' specifications."
;; Return the empty string when code is empty.
;; Preserve blank lines, even when code is empty.
(should
(equal ""
(equal "\n\n"
(org-test-with-parsed-data "#+BEGIN_SRC emacs-lisp\n\n\n#+END_SRC"
(org-export-format-code-default
(org-element-map tree 'src-block 'identity info t) info))))
(org-element-map tree 'src-block #'identity info t) info))))
;; Likewise, preserve leading and trailing blank lines in the code.
(should
(equal "\n(+ 1 1)\n"
(org-test-with-parsed-data
"#+BEGIN_SRC emacs-lisp\n\n(+ 1 1)\n#+END_SRC"
(org-export-format-code-default
(org-element-map tree 'src-block #'identity info t) info))))
(should
(equal "(+ 1 1)\n\n"
(org-test-with-parsed-data
"#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n\n#+END_SRC"
(org-export-format-code-default
(org-element-map tree 'src-block #'identity info t) info))))
;; Number lines, two whitespace characters before the actual loc.
(should
(equal "1 a\n2 b\n"
(org-test-with-parsed-data
"#+BEGIN_SRC emacs-lisp +n\na\nb\n#+END_SRC"
(org-export-format-code-default
(org-element-map tree 'src-block 'identity info t) info))))
(org-element-map tree 'src-block #'identity info t) info))))
;; Numbering includes blank lines.
(should
(equal "1 \n2 a\n3 \n4 b\n5 \n"
(org-test-with-parsed-data
"#+BEGIN_SRC emacs-lisp +n\n\na\n\nb\n\n#+END_SRC"
(org-export-format-code-default
(org-element-map tree 'src-block #'identity info t) info))))
;; Put references 6 whitespace characters after the widest line,
;; wrapped within parenthesis.
(should
@ -3419,7 +3439,7 @@ Another text. (ref:text)
(org-test-with-parsed-data
"#+BEGIN_SRC emacs-lisp\n123 (ref:a)\n1 (ref:b)\n#+END_SRC"
(org-export-format-code-default
(org-element-map tree 'src-block 'identity info t) info))))))
(org-element-map tree 'src-block #'identity info t) info))))))