summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2015-12-30 23:59:57 +0100
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2016-02-10 15:40:10 +0100
commit44e45d528498a05156ed0c10be297b984d4fbd2f (patch)
tree448695cb29c8bb028070774802462d8ed67dbfb5
parenta1d9daa4527951fcca54133ea2fc1d6b645c227a (diff)
downloadorg-mode-44e45d528498a05156ed0c10be297b984d4fbd2f.tar.gz
Parse inline src blocks and babel calls with newlines
* lisp/org-element.el (org-element--pair-round-table): (org-element--pair-curly-table): New variables. (org-element-inline-babel-call-parser): (org-element-inline-src-block-parser): Allow newline characters in contents and parameters. * testing/lisp/test-org-element.el (test-org-element/inline-babel-call-parser): (test-org-element/inline-src-block-parser): Add test.
-rw-r--r--lisp/org-element.el121
-rw-r--r--testing/lisp/test-org-element.el33
2 files changed, 115 insertions, 39 deletions
diff --git a/lisp/org-element.el b/lisp/org-element.el
index c7a96b4..d8a7843 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -393,6 +393,15 @@ still has an entry since one of its properties (`:title') does.")
(item :tag))
"Alist between element types and locations of secondary values.")
+(defconst org-element--pair-round-table
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?\( "()" table)
+ (modify-syntax-entry ?\) ")(" table)
+ (dolist (char '(?\{ ?\} ?\[ ?\] ?\< ?\>) table)
+ (modify-syntax-entry char " " table)))
+ "Table used internally to pair only round brackets.
+Other brackets are treated as spaces.")
+
(defconst org-element--pair-square-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\[ "(]" table)
@@ -402,6 +411,15 @@ still has an entry since one of its properties (`:title') does.")
"Table used internally to pair only square brackets.
Other brackets are treated as spaces.")
+(defconst org-element--pair-curly-table
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?\{ "(}" table)
+ (modify-syntax-entry ?\} "){" table)
+ (dolist (char '(?\[ ?\[ ?\( ?\) ?\< ?\>) table)
+ (modify-syntax-entry char " " table)))
+ "Table used internally to pair only curly brackets.
+Other brackets are treated as spaces.")
+
;;; Accessors and Setters
@@ -2814,27 +2832,45 @@ When at an inline babel call, return a list whose car is
Assume point is at the beginning of the babel call."
(save-excursion
- (unless (bolp) (backward-char))
- (when (let ((case-fold-search t))
- (looking-at org-babel-inline-lob-one-liner-regexp))
- (let ((begin (match-end 1))
- (call (org-match-string-no-properties 2))
- (inside-header (org-string-nw-p (org-match-string-no-properties 4)))
- (arguments (org-string-nw-p (org-match-string-no-properties 6)))
- (end-header (org-string-nw-p (org-match-string-no-properties 8)))
- (value (buffer-substring-no-properties (match-end 1) (match-end 0)))
- (post-blank (progn (goto-char (match-end 0))
- (skip-chars-forward " \t")))
- (end (point)))
- (list 'inline-babel-call
- (list :call call
- :inside-header inside-header
- :arguments arguments
- :end-header end-header
- :begin begin
- :end end
- :value value
- :post-blank post-blank))))))
+ (catch :no-object
+ (when (let ((case-fold-search nil))
+ (looking-at
+ "\\<call_\\([^ \t\n[{]+\\)\\(?:\\[\\([^]]*\\)\\]\\)?("))
+ (let ((begin (point))
+ (call (match-string-no-properties 1))
+ (inside-header
+ (let ((h (org-string-nw-p (match-string-no-properties 2))))
+ (and h (org-trim
+ (replace-regexp-in-string "\n[ \t]*" " " h))))))
+ (goto-char (1- (match-end 0)))
+ (let* ((s (point))
+ (e (with-syntax-table org-element--pair-round-table
+ (or (ignore-errors (scan-lists s 1 0))
+ ;; Invalid inline source block.
+ (throw :no-object nil))))
+ (arguments
+ (let ((a (org-string-nw-p
+ (buffer-substring-no-properties (1+ s) (1- e)))))
+ (and a (org-trim
+ (replace-regexp-in-string "\n[ \t]*" " " a)))))
+ (end-header
+ (progn
+ (goto-char e)
+ (and (looking-at "\\[\\([^]]*\\)\\]")
+ (prog1 (org-string-nw-p (match-string-no-properties 1))
+ (goto-char (match-end 0))))))
+ (value (buffer-substring-no-properties begin (point)))
+ (post-blank (skip-chars-forward " \t"))
+ (end (point)))
+ (list 'inline-babel-call
+ (list :call call
+ :inside-header inside-header
+ :arguments arguments
+ :end-header end-header
+ :begin begin
+ :end end
+ :value value
+ :post-blank post-blank))))))))
(defun org-element-inline-babel-call-interpreter (inline-babel-call _)
"Interpret INLINE-BABEL-CALL object as Org syntax."
@@ -2859,22 +2895,33 @@ keywords. Otherwise, return nil.
Assume point is at the beginning of the inline src block."
(save-excursion
- (unless (bolp) (backward-char))
- (when (looking-at org-babel-inline-src-block-regexp)
- (let ((begin (match-beginning 1))
- (language (org-match-string-no-properties 2))
- (parameters (org-match-string-no-properties 4))
- (value (org-match-string-no-properties 5))
- (post-blank (progn (goto-char (match-end 0))
- (skip-chars-forward " \t")))
- (end (point)))
- (list 'inline-src-block
- (list :language language
- :value value
- :parameters parameters
- :begin begin
- :end end
- :post-blank post-blank))))))
+ (catch :no-object
+ (when (let ((case-fold-search nil))
+ (looking-at "\\<src_\\([^ \t\n[{]+\\)\
+\\(?:\\[[ \t]*\\([^]]*?\\)[ \t]*\\]\\)?{"))
+ (let ((begin (point))
+ (language (match-string-no-properties 1))
+ (parameters
+ (let ((p (org-string-nw-p (match-string-no-properties 2))))
+ (and p (org-trim
+ (replace-regexp-in-string "\n[ \t]*" " " p))))))
+ (goto-char (1- (match-end 0)))
+ (let* ((s (point))
+ (e (with-syntax-table org-element--pair-curly-table
+ (or (ignore-errors (scan-lists s 1 0))
+ ;; Invalid inline source block.
+ (throw :no-object nil))))
+ (value (buffer-substring-no-properties
+ (1+ s) (1- e)))
+ (post-blank (progn (goto-char e)
+ (skip-chars-forward " \t"))))
+ (list 'inline-src-block
+ (list :language language
+ :value value
+ :parameters parameters
+ :begin begin
+ :end (point)
+ :post-blank post-blank))))))))
(defun org-element-inline-src-block-interpreter (inline-src-block _)
"Interpret INLINE-SRC-BLOCK object as Org syntax."
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index fe551dd..c3d8d6e 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -1134,7 +1134,23 @@ Some other text
(equal
":results html"
(org-test-with-temp-text "call_test[:results output](x=2)[:results html]"
- (org-element-property :end-header (org-element-context))))))
+ (org-element-property :end-header (org-element-context)))))
+ ;; Handle multi-line babel calls.
+ (should
+ (eq 'inline-babel-call
+ (org-test-with-temp-text
+ "call_test[:results\noutput](x=2)[:results html]"
+ (org-element-type (org-element-context)))))
+ (should
+ (eq 'inline-babel-call
+ (org-test-with-temp-text
+ "call_test[:results output](x=2\ny=3)[:results html]"
+ (org-element-type (org-element-context)))))
+ (should
+ (eq 'inline-babel-call
+ (org-test-with-temp-text
+ "call_test[:results output](x=2)[:results\nhtml]"
+ (org-element-type (org-element-context))))))
;;;; Inline Src Block
@@ -1169,7 +1185,20 @@ Some other text
;; Test parsing at the beginning of an item.
(should
(org-test-with-temp-text "- src_emacs-lisp{(+ 1 1)}"
- (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))))
+ (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity)))
+ ;; Test parsing multi-line source blocks.
+ (should
+ (eq 'inline-src-block
+ (org-test-with-temp-text "src_emacs-lisp{(+ 1\n 1)}"
+ (org-element-type (org-element-context)))))
+ (should
+ (eq 'inline-src-block
+ (org-test-with-temp-text "src_emacs-lisp[\n:foo bar]{(+ 1 1)}"
+ (org-element-type (org-element-context)))))
+ (should
+ (eq 'inline-src-block
+ (org-test-with-temp-text "src_emacs-lisp[:foo\nbar]{(+ 1 1)}"
+ (org-element-type (org-element-context))))))
;;;; Inlinetask