summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2016-01-31 11:36:52 +0100
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2016-01-31 20:38:35 +0100
commit7d6b8f51ec1993a66a385b98b2df42d0853fe289 (patch)
tree27d6b6a0bb26402492fad89415815291dacd9229
parenteb3b1046c6cfd30c3810d48ea1db64b2f9a4b22d (diff)
downloadorg-mode-7d6b8f51ec1993a66a385b98b2df42d0853fe289.tar.gz
ob: Fix `org-babel-update-block-body'
* lisp/ob-core.el (org-babel-update-block-body): Correctly handle block indentation. (org-babel-where-is-src-block-head): Accept an optional argument in order to avoid parsing twice the same element. * testing/lisp/test-ob.el (org-test-ob/update-block-body): New test.
-rw-r--r--lisp/ob-core.el40
-rw-r--r--testing/lisp/test-ob.el54
2 files changed, 86 insertions, 8 deletions
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 30dcb62..31d4e2e 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -39,6 +39,7 @@
(defvar org-babel-library-of-babel)
(declare-function outline-show-all "outline" ())
(declare-function org-every "org" (pred seq))
+(declare-function org-get-indentation "org" (&optional line))
(declare-function org-remove-indentation "org" (code &optional n))
(declare-function org-reduce "org" (CL-FUNC CL-SEQ &rest CL-KEYS))
(declare-function org-mark-ring-push "org" (&optional pos buffer))
@@ -99,6 +100,7 @@
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-type "org-element" (element))
(declare-function org-element-at-point "org-element" ())
+(declare-function org-element-normalize-string "org-element" (s))
(declare-function org-element-property "org-element" (property element))
(declare-function org-every "org" (pred seq))
(declare-function org-macro-escape-arguments "org-macro" (&rest args))
@@ -1709,13 +1711,17 @@ to the table for reinsertion to org-mode."
(org-babel-put-colnames table colnames) table))
table))
-(defun org-babel-where-is-src-block-head ()
+(defun org-babel-where-is-src-block-head (&optional src-block)
"Find where the current source block begins.
+
+If optional argument SRC-BLOCK is `src-block' type element, find
+its current beginning instead.
+
Return the point at the beginning of the current source block.
Specifically at the beginning of the #+BEGIN_SRC line. Also set
match-data relatively to `org-babel-src-block-regexp', which see.
If the point is not on a source block then return nil."
- (let ((element (org-element-at-point)))
+ (let ((element (or src-block (org-element-at-point))))
(when (eq (org-element-type element) 'src-block)
(let ((end (org-element-property :end element)))
(org-with-wide-buffer
@@ -2460,12 +2466,30 @@ file's directory then expand relative links."
(defun org-babel-update-block-body (new-body)
"Update the body of the current code block to NEW-BODY."
- (if (not (org-babel-where-is-src-block-head))
- (error "Not in a source block")
- (save-match-data
- (replace-match (concat (org-babel-trim (org-remove-indentation new-body))
- "\n") nil t nil 5))
- (indent-rigidly (match-beginning 5) (match-end 5) 2)))
+ (let ((element (org-element-at-point)))
+ (unless (eq (org-element-type element) 'src-block)
+ (error "Not in a source block"))
+ (goto-char (org-babel-where-is-src-block-head element))
+ (let* ((ind (org-get-indentation))
+ (body-start (line-beginning-position 2))
+ (body (org-element-normalize-string
+ (if (or org-src-preserve-indentation
+ (org-element-property :preserve-indent element))
+ new-body
+ (with-temp-buffer
+ (insert (org-remove-indentation new-body))
+ (indent-rigidly
+ (point-min)
+ (point-max)
+ (+ ind org-edit-src-content-indentation))
+ (buffer-string))))))
+ (delete-region body-start
+ (org-with-wide-buffer
+ (goto-char (org-element-property :end element))
+ (skip-chars-backward " \t\n")
+ (line-beginning-position)))
+ (goto-char body-start)
+ (insert body))))
(defun org-babel-merge-params (&rest plists)
"Combine all parameter association lists in PLISTS.
diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el
index c2feb39..207fd4f 100644
--- a/testing/lisp/test-ob.el
+++ b/testing/lisp/test-ob.el
@@ -1489,6 +1489,60 @@ echo \"$data\"
(:result-params . 1)
(:result-type . value)))))
+(defun org-test-ob/update-block-body ()
+ "Test `org-babel-update-block-body' specifications."
+ (should
+ (equal "#+begin_src elisp\n 2\n#+end_src"
+ (let ((org-edit-src-content-indentation 2))
+ (org-test-with-temp-text "#+begin_src elisp\n(+ 1 1)\n#+end_src"
+ (org-babel-update-block-body "2")
+ (buffer-string)))))
+ ;; Preserve block indentation.
+ (should
+ (equal " #+begin_src elisp\n 2\n #+end_src"
+ (let ((org-edit-src-content-indentation 1))
+ (org-test-with-temp-text
+ " #+begin_src elisp\n (+ 1 1)\n #+end_src"
+ (org-babel-update-block-body "2")
+ (buffer-string)))))
+ ;; Ignore NEW-BODY global indentation.
+ (should
+ (equal "#+begin_src elisp\n 2\n#+end_src"
+ (let ((org-edit-src-content-indentation 2))
+ (org-test-with-temp-text "#+begin_src elisp\n(+ 1 1)\n#+end_src"
+ (org-babel-update-block-body " 2")
+ (buffer-string)))))
+ ;; When indentation should be preserved ignore the two rules above.
+ (should
+ (equal " #+begin_src elisp\n2\n #+end_src"
+ (let ((org-edit-src-content-indentation 1)
+ (org-src-preserve-indentation t))
+ (org-test-with-temp-text
+ " #+begin_src elisp\n (+ 1 1)\n #+end_src"
+ (org-babel-update-block-body "2")
+ (buffer-string)))))
+ (should
+ (equal " #+begin_src elisp -i\n2\n #+end_src"
+ (let ((org-edit-src-content-indentation 1))
+ (org-test-with-temp-text
+ " #+begin_src elisp -i\n (+ 1 1)\n #+end_src"
+ (org-babel-update-block-body "2")
+ (buffer-string)))))
+ (should
+ (equal "#+begin_src elisp\n 2\n#+end_src"
+ (let ((org-edit-src-content-indentation 2)
+ (org-src-preserve-indentation t))
+ (org-test-with-temp-text "#+begin_src elisp\n(+ 1 1)\n#+end_src"
+ (org-babel-update-block-body " 2")
+ (buffer-string)))))
+ (should
+ (equal "#+begin_src elisp -i\n 2\n#+end_src"
+ (let ((org-edit-src-content-indentation 2)
+ (org-src-preserve-indentation t))
+ (org-test-with-temp-text "#+begin_src elisp -i\n(+ 1 1)\n#+end_src"
+ (org-babel-update-block-body " 2")
+ (buffer-string))))))
+
(provide 'test-ob)
;;; test-ob ends here