Browse Source

org-element: Verse blocks now contain objects

* contrib/lisp/org-element.el (org-element-verse-block-parser): Verse
  blocks now contain objects.
(org-element-verse-block-interpreter, org-element-current-element):
Apply changes to verse blocks.
(org-element-secondary-value-alist): Remove verse blocks from elements
with a secondary string.
* contrib/lisp/org-e-odt.el (org-e-odt-verse-block): Apply changes to
  verse blocks.
* contrib/lisp/org-e-latex.el (org-e-latex-verse-block): Apply changes
  to verse blocks.
* contrib/lisp/org-e-html.el (org-e-html-verse-block): Apply changes
  to verse blocks.
* contrib/lisp/org-e-ascii.el (org-e-ascii-verse-block): Apply changes
  to verse blocks.
* testing/lisp/test-org-element.el: Add tests.
Nicolas Goaziou 8 years ago
parent
commit
c6dc6e3d32

+ 3 - 5
contrib/lisp/org-e-ascii.el

@@ -1730,13 +1730,11 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 
 (defun org-e-ascii-verse-block (verse-block contents info)
   "Transcode a VERSE-BLOCK element from Org to ASCII.
-CONTENTS is nil.  INFO is a plist holding contextual information."
+CONTENTS is verse block contents.  INFO is a plist holding
+contextual information."
   (let ((verse-width (org-e-ascii--current-text-width verse-block info)))
     (org-e-ascii--indent-string
-     (org-e-ascii--justify-string
-      (org-export-secondary-string
-       (org-element-property :value verse-block) 'e-ascii info)
-      verse-width 'left)
+     (org-e-ascii--justify-string contents verse-width 'left)
      org-e-ascii-quote-margin)))
 
 

+ 3 - 6
contrib/lisp/org-e-html.el

@@ -2949,17 +2949,14 @@ channel."
 
 (defun org-e-html-verse-block (verse-block contents info)
   "Transcode a VERSE-BLOCK element from Org to HTML.
-CONTENTS is nil.  INFO is a plist holding contextual information."
+CONTENTS is verse block contents.  INFO is a plist holding
+contextual information."
   ;; Replace each newline character with line break.  Also replace
   ;; each blank line with a line break.
   (setq contents (replace-regexp-in-string
 		  "^ *\\\\\\\\$" "<br/>\n"
 		  (replace-regexp-in-string
-		   "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
-		   (org-remove-indentation
-		    (org-export-secondary-string
-		     (org-element-property :value verse-block)
-		     'e-html info)))))
+		   "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n" contents)))
   ;; Replace each white space at beginning of a line with a
   ;; non-breaking space.
   (while (string-match "^[ \t]+" contents)

+ 3 - 6
contrib/lisp/org-e-latex.el

@@ -2118,7 +2118,8 @@ channel."
 
 (defun org-e-latex-verse-block (verse-block contents info)
   "Transcode a VERSE-BLOCK element from Org to LaTeX.
-CONTENTS is nil.  INFO is a plist holding contextual information."
+CONTENTS is verse block contents. INFO is a plist holding
+contextual information."
   (org-e-latex--wrap-label
    verse-block
    ;; In a verse environment, add a line break to each newline
@@ -2129,11 +2130,7 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
      (setq contents (replace-regexp-in-string
 		     "^ *\\\\\\\\$" "\\\\vspace*{1em}"
 		     (replace-regexp-in-string
-		      "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
-		      (org-remove-indentation
-		       (org-export-secondary-string
-			(org-element-property :value verse-block)
-			'e-latex info)))))
+		      "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" contents)))
      (while (string-match "^[ \t]+" contents)
        (let ((new-str (format "\\hspace*{%dem}"
 			      (length (match-string 0 contents)))))

+ 3 - 6
contrib/lisp/org-e-odt.el

@@ -4148,17 +4148,14 @@ channel."
 
 (defun org-e-odt-verse-block (verse-block contents info)
   "Transcode a VERSE-BLOCK element from Org to HTML.
-CONTENTS is nil.  INFO is a plist holding contextual information."
+CONTENTS is verse block contents.  INFO is a plist holding
+contextual information."
   ;; Replace each newline character with line break.  Also replace
   ;; each blank line with a line break.
   (setq contents (replace-regexp-in-string
 		  "^ *\\\\\\\\$" "<br/>\n"
 		  (replace-regexp-in-string
-		   "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
-		   (org-remove-indentation
-		    (org-export-secondary-string
-		     (org-element-property :value verse-block)
-		     'e-odt info)))))
+		   "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n" contents)))
 
   ;; Replace each white space at beginning of a line with a
   ;; non-breaking space.

+ 60 - 77
contrib/lisp/org-element.el

@@ -25,45 +25,51 @@
 ;; Org syntax can be divided into three categories: "Greater
 ;; elements", "Elements" and "Objects".
 
-;; An object can be defined anywhere on a line.  It may span over more
-;; than a line but never contains a blank one.  Objects belong to the
-;; following types: `emphasis', `entity', `export-snippet',
-;; `footnote-reference', `inline-babel-call', `inline-src-block',
-;; `latex-fragment', `line-break', `link', `macro', `radio-target',
-;; `statistics-cookie', `subscript', `superscript', `table-cell',
-;; `target', `time-stamp' and `verbatim'.
-
-;; An element always starts and ends at the beginning of a line
-;; (excepted for `table-cell').  The only element's type containing
-;; objects is called a `paragraph'.  Other types are: `comment',
-;; `comment-block', `example-block', `export-block', `fixed-width',
-;; `horizontal-rule', `keyword', `latex-environment', `babel-call',
-;; `property-drawer', `quote-section', `src-block', `table',
-;; `table-row' and `verse-block'.
-
-;; Elements containing paragraphs are called greater elements.
-;; Concerned types are: `center-block', `drawer', `dynamic-block',
-;; `footnote-definition', `headline', `inlinetask', `item',
-;; `plain-list', `quote-block', `section' and `special-block'
-
-;; Greater elements (excepted `headline', `item' and `section' types)
-;; and elements (excepted `keyword', `babel-call', `property-drawer'
-;; and `table-row' types) can have a fixed set of keywords as
-;; attributes.  Those are called "affiliated keywords", to distinguish
-;; them from others keywords, which are full-fledged elements.  In
-;; particular, the "name" affiliated keyword allows to label almost
-;; any element in an Org buffer.
-
+;; Elements are related to the structure of the document.  Indeed, all
+;; elements are a cover for the document: each position within belongs
+;; to at least one element.
+
+;; An element always starts and ends at the beginning of a line.  With
+;; a few exceptions (namely `headline', `item', `section', `keyword',
+;; `babel-call' and `property-drawer' types), it can also accept
+;; a fixed set of keywords as attributes.  Those are called
+;; "affiliated keywords" to distinguish them from other keywords,
+;; which are full-fledged elements.
+;;
+;; Element containing other elements (and only elements) are called
+;; greater elements.  Concerned types are: `center-block', `drawer',
+;; `dynamic-block', `footnote-definition', `headline', `inlinetask',
+;; `item', `plain-list', `quote-block', `section' and `special-block'.
+;;
+;; Other element types are: `babel-call', `comment', `comment-block',
+;; `example-block', `export-block', `fixed-width', `horizontal-rule',
+;; `keyword', `latex-environment', `paragraph', `property-drawer',
+;; `quote-section', `src-block', `table', `table-cell', `table-row'
+;; and `verse-blocks'.  Among them, `paragraph', `table-cell' and
+;; `verse-block' types can contain Org objects and plain text.
+;;
+;; Objects are related to document's contents.  Some of them are
+;; recursive.  Associated types are of the following: `emphasis',
+;; `entity', `export-snippet', `footnote-reference',
+;; `inline-babel-call', `inline-src-block', `latex-fragment',
+;; `line-break', `link', `macro', `radio-target', `statistics-cookie',
+;; `subscript', `superscript', `table-cell', `target', `time-stamp'
+;; and `verbatim'.
+;;
+;; Some elements also have special properties whose value can hold
+;; objects themselves (i.e. an item tag or an headline name).  Such
+;; values are called "secondary strings".  Any object belongs to
+;; either an element or a secondary string.
+;;
 ;; Notwithstanding affiliated keywords, each greater element, element
 ;; and object has a fixed set of properties attached to it.  Among
 ;; them, three are shared by all types: `:begin' and `:end', which
 ;; refer to the beginning and ending buffer positions of the
 ;; considered element or object, and `:post-blank', which holds the
-;; number of blank lines, or white spaces, at its end.
-
-;; Some elements also have special properties whose value can hold
-;; objects themselves (i.e. an item tag, an headline name, a table
-;; cell).  Such values are called "secondary strings".
+;; number of blank lines, or white spaces, at its end.  Greater
+;; elements and elements containing objects will also have
+;; `:contents-begin' and `:contents-end' properties to delimit
+;; contents.
 
 ;; Lisp-wise, an element or an object can be represented as a list.
 ;; It follows the pattern (TYPE PROPERTIES CONTENTS), where:
@@ -81,7 +87,7 @@
 ;; for each type of Org syntax.
 
 ;; The next two parts introduce four accessors and a function
-;; retrieving the smallest element starting at point (respectively
+;; retrieving the element starting at point (respectively
 ;; `org-element-type', `org-element-property', `org-element-contents',
 ;; `org-element-restriction' and `org-element-current-element').
 
@@ -1584,56 +1590,40 @@ CONTENTS is the contents of the table row."
 
 ;;;; Verse Block
 
-(defun org-element-verse-block-parser (&optional raw-secondary-p)
+(defun org-element-verse-block-parser ()
   "Parse a verse block.
 
-Return a list whose car is `verse-block' and cdr is a plist
-containing `:begin', `:end', `:hiddenp', `:value' and
-`:post-blank' keywords.
-
-When optional argument RAW-SECONDARY-P is non-nil, verse-block's
-value will not be parsed as a secondary string, but as a plain
-string instead.
+Return a list whose CAR is `verse-block' and CDR is a plist
+containing `:begin', `:end', `:contents-begin', `:contents-end',
+`:hiddenp' and `:post-blank' keywords.
 
-Assume point is at beginning or end of the block."
+Assume point is at beginning of the block."
   (save-excursion
     (let* ((case-fold-search t)
-	   (keywords (progn
-		       (end-of-line)
-		       (re-search-backward
-			(concat "^[ \t]*#\\+BEGIN_VERSE") nil t)
-		       (org-element-collect-affiliated-keywords)))
+	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (hidden (progn (forward-line) (org-truely-invisible-p)))
-	   (value-begin (point))
-	   (value-end
+	   (contents-begin (point))
+	   (contents-end
 	    (progn
 	      (re-search-forward (concat "^[ \t]*#\\+END_VERSE") nil t)
 	      (point-at-bol)))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
-		       (if (eobp) (point) (point-at-bol))))
-	   (value
-	    (if raw-secondary-p
-		(buffer-substring-no-properties value-begin value-end)
-	      (org-element-parse-secondary-string
-	       (buffer-substring-no-properties value-begin value-end)
-	       (org-element-restriction 'verse-block)))))
+		       (if (eobp) (point) (point-at-bol)))))
       `(verse-block
 	(:begin ,begin
 		:end ,end
+		:contents-begin ,contents-begin
+		:contents-end ,contents-end
 		:hiddenp ,hidden
-		:value ,value
 		:post-blank ,(count-lines pos-before-blank end)
 		,@(cadr keywords))))))
 
 (defun org-element-verse-block-interpreter (verse-block contents)
   "Interpret VERSE-BLOCK element as Org syntax.
-CONTENTS is nil."
-  (format "#+BEGIN_VERSE\n%s#+END_VERSE"
-	  (org-remove-indentation
-	   (org-element-interpret-secondary
-	    (org-element-property :value verse-block)))))
+CONTENTS is verse block contents."
+  (format "#+BEGIN_VERSE\n%s#+END_VERSE" contents))
 
 
 
@@ -2767,8 +2757,7 @@ still has an entry since one of its properties (`:title') does.")
   '((headline . :title)
     (inlinetask . :title)
     (item . :tag)
-    (footnote-reference . :inline-definition)
-    (verse-block . :value))
+    (footnote-reference . :inline-definition))
   "Alist between element types and location of secondary value.")
 
 
@@ -2884,17 +2873,11 @@ it is quicker than its counterpart, albeit more restrictive."
             (if (save-excursion
                   (re-search-forward
                    (format "[ \t]*#\\+END_%s\\(?: \\|$\\)" type) nil t))
-                ;; Build appropriate parser.  `verse-block' type
-		;; elements require an additional argument, so they
-		;; must be treated separately.
-                (if (string= "VERSE" type)
-		    (org-element-verse-block-parser raw-secondary-p)
-		  (funcall
-		   (intern
-		    (format
-		     "org-element-%s-parser"
-		     (cdr (assoc type
-				 org-element-non-recursive-block-alist))))))
+                (funcall
+		 (intern
+		  (format
+		   "org-element-%s-parser"
+		   (cdr (assoc type org-element-non-recursive-block-alist)))))
               (org-element-paragraph-parser)))))
        ;; Inlinetask.
        ((org-at-heading-p) (org-element-inlinetask-parser raw-secondary-p))

+ 53 - 0
testing/lisp/test-org-element.el

@@ -261,6 +261,44 @@
 
 
 
+;;;; Verse blocks
+
+(ert-deftest test-org-element/verse-block ()
+  "Test verse block parsing."
+  ;; Standard test.
+  (org-test-with-temp-text "#+BEGIN_VERSE\nVerse block\n#+END_VERSE"
+    (should
+     (equal
+      (org-element-map (org-element-parse-buffer) 'verse-block 'identity nil t)
+      '(verse-block
+	(:begin 1 :end 38 :contents-begin 15 :contents-end 27 :hiddenp nil
+		:post-blank 0)
+	"Verse block\n"))))
+  ;; Ignore case.
+  (org-test-with-temp-text "#+begin_verse\nVerse block\n#+end_verse"
+    (should
+     (equal
+      (org-element-map (org-element-parse-buffer) 'verse-block 'identity nil t)
+      '(verse-block
+	(:begin 1 :end 38 :contents-begin 15 :contents-end 27 :hiddenp nil
+		:post-blank 0)
+	"Verse block\n"))))
+  ;; Parse folding.
+  (org-test-with-temp-text "#+BEGIN_VERSE\nVerse block\n#+END_VERSE"
+    (org-hide-block-all)
+    (should
+     (equal
+      (org-element-map (org-element-parse-buffer) 'verse-block 'identity nil t)
+      '(verse-block
+	(:begin 1 :end 38 :contents-begin 15 :contents-end 27
+		:hiddenp org-hide-block :post-blank 0)
+	"Verse block\n"))))
+  ;; Parse objects in verse blocks.
+  (org-test-with-temp-text "#+BEGIN_VERSE\nVerse \\alpha\n#+END_VERSE"
+    (should (org-element-map (org-element-parse-buffer) 'entity 'identity))))
+
+
+
 ;;;; Granularity
 
 (ert-deftest test-org-element/granularity ()
@@ -367,6 +405,21 @@ Paragraph \\alpha."
      '(org-data nil (paragraph (:caption (("long") "short")) "Paragraph")))
     "#+CAPTION[short]: long\nParagraph\n")))
 
+(ert-deftest test-org-element/interpret-elements ()
+  "Test interpretation of elements and objects."
+  (let ((parse-and-interpret
+	 (function
+	  ;; Parse TEXT string in an Org buffer and transcode it back
+	  ;; to Org syntax.
+	  (lambda (text)
+	    (with-temp-buffer
+	      (org-mode)
+	      (insert text)
+	      (org-element-interpret-data (org-element-parse-buffer)))))))
+    ;; Verse blocks.
+    (equal (funcall parse-and-interpret "#+BEGIN_VERSE\nTest\n#+END_VERSE")
+	   "#+BEGIN_VERSE\nTest\n#+END_VERSE\n")))
+
 
 
 ;;;; Normalize contents