From c6dc6e3d32619c84d1690b6f67a3b4702b0f2282 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Wed, 25 Apr 2012 22:15:29 +0200 Subject: [PATCH] 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. --- contrib/lisp/org-e-ascii.el | 8 +-- contrib/lisp/org-e-html.el | 9 +-- contrib/lisp/org-e-latex.el | 9 +-- contrib/lisp/org-e-odt.el | 9 +-- contrib/lisp/org-element.el | 137 +++++++++++++++++---------------------- testing/lisp/test-org-element.el | 53 +++++++++++++++ 6 files changed, 125 insertions(+), 100 deletions(-) diff --git a/contrib/lisp/org-e-ascii.el b/contrib/lisp/org-e-ascii.el index d68975ea4..05f430db1 100644 --- a/contrib/lisp/org-e-ascii.el +++ b/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))) diff --git a/contrib/lisp/org-e-html.el b/contrib/lisp/org-e-html.el index 1f20865c7..d9350ff1a 100644 --- a/contrib/lisp/org-e-html.el +++ b/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 "^ *\\\\\\\\$" "
\n" (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" "
\n" - (org-remove-indentation - (org-export-secondary-string - (org-element-property :value verse-block) - 'e-html info))))) + "\\(\\\\\\\\\\)?[ \t]*\n" "
\n" contents))) ;; Replace each white space at beginning of a line with a ;; non-breaking space. (while (string-match "^[ \t]+" contents) diff --git a/contrib/lisp/org-e-latex.el b/contrib/lisp/org-e-latex.el index 44832330f..3c78b6453 100644 --- a/contrib/lisp/org-e-latex.el +++ b/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))))) diff --git a/contrib/lisp/org-e-odt.el b/contrib/lisp/org-e-odt.el index 347c0794f..263c4eb90 100644 --- a/contrib/lisp/org-e-odt.el +++ b/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 "^ *\\\\\\\\$" "
\n" (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" "
\n" - (org-remove-indentation - (org-export-secondary-string - (org-element-property :value verse-block) - 'e-odt info))))) + "\\(\\\\\\\\\\)?[ \t]*\n" "
\n" contents))) ;; Replace each white space at beginning of a line with a ;; non-breaking space. diff --git a/contrib/lisp/org-element.el b/contrib/lisp/org-element.el index 8b38a54b3..c9be73168 100644 --- a/contrib/lisp/org-element.el +++ b/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)) diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 4e184c981..367cddf7d 100644 --- a/testing/lisp/test-org-element.el +++ b/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 -- 2.11.4.GIT