diff --git a/lisp/ox.el b/lisp/ox.el index 0c822e0f4..ac8d8ce68 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -4573,7 +4573,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))) @@ -4592,30 +4592,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))) @@ -4638,15 +4636,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. @@ -4663,7 +4662,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))) @@ -4688,9 +4687,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))))) diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index e35b762f0..33792e694 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -3446,12 +3446,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)")) @@ -3459,14 +3459,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) @@ -3477,23 +3477,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 @@ -3502,7 +3522,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))))))