Browse Source

org-element: Store fixed-with and comment contents without markers

* contrib/lisp/org-element.el (org-element-comment-parser): Store
  comments without leading hash and maybe plus sign.
(org-element-fixed-width-parser): Store fixed-width contents without
leading colons.
(org-element-comment-interpreter,
org-element-fixed-width-interpreter): Apply changes.
* contrib/lisp/org-e-odt.el (org-e-odt-fixed-width): Apply changes to
  fixed-width `:value' property.
* contrib/lisp/org-e-latex.el (org-e-latex-fixed-width): Apply changes
  to fixed-width `:value' property.
* contrib/lisp/org-e-html.el (org-e-html-fixed-width): Apply changes
  to fixed-width `:value' property.
* contrib/lisp/org-e-ascii.el (org-e-ascii-fixed-width): Apply changes
  to fixed-width `:value' property.
* testing/lisp/test-org-element.el: Add tests.
Nicolas Goaziou 13 years ago
parent
commit
f4791557e2

+ 2 - 2
contrib/lisp/org-e-ascii.el

@@ -1116,8 +1116,8 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
   "Transcode a FIXED-WIDTH element from Org to ASCII.
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (org-e-ascii--box-string
-   (replace-regexp-in-string
-    "^[ \t]*: ?" "" (org-element-property :value fixed-width)) info))
+   (org-remove-indentation
+    (org-element-property :value fixed-width)) info))
 
 
 ;;;; Footnote Definition

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

@@ -1972,13 +1972,12 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 (defun org-e-html-fixed-width (fixed-width contents info)
   "Transcode a FIXED-WIDTH element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let* ((value (org-element-normalize-string
-		 (replace-regexp-in-string
-		  "^[ \t]*: ?" ""
-		  (org-element-property :value fixed-width)))))
-    (org-e-html--wrap-label
-     fixed-width (format "\n<pre class=\"example\">\n%s\n</pre>"
-			 (org-e-html-do-format-code value)))))
+  (org-e-html--wrap-label
+   fixed-width
+   (format "\n<pre class=\"example\">\n%s</pre>"
+	   (org-e-html-do-format-code
+	    (org-remove-indentation
+	     (org-element-property :value fixed-width))))))
 
 
 ;;;; Footnote Definition

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

@@ -1073,12 +1073,11 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 (defun org-e-latex-fixed-width (fixed-width contents info)
   "Transcode a FIXED-WIDTH element from Org to LaTeX.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let* ((value (org-element-normalize-string
-		 (replace-regexp-in-string
-		  "^[ \t]*: ?" ""
-		  (org-element-property :value fixed-width)))))
-    (org-e-latex--wrap-label
-     fixed-width (format "\\begin{verbatim}\n%s\\end{verbatim}" value))))
+  (org-e-latex--wrap-label
+   fixed-width
+   (format "\\begin{verbatim}\n%s\\end{verbatim}"
+	   (org-remove-indentation
+	    (org-element-property :value fixed-width)))))
 
 
 ;;;; Footnote Definition

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

@@ -3051,12 +3051,10 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 (defun org-e-odt-fixed-width (fixed-width contents info)
   "Transcode a FIXED-WIDTH element from Org to HTML.
 CONTENTS is nil.  INFO is a plist holding contextual information."
-  (let* ((value (org-element-normalize-string
-		 (replace-regexp-in-string
-		  "^[ \t]*: ?" ""
-		  (org-element-property :value fixed-width)))))
-    (org-e-odt--wrap-label
-     fixed-width (org-e-odt-format-source-code-or-example value nil))))
+  (org-e-odt--wrap-label
+   fixed-width
+   (org-e-odt-format-source-code-or-example
+    (org-element-property :value fixed-width) nil)))
 
 
 ;;;; Footnote Definition

+ 36 - 18
contrib/lisp/org-element.el

@@ -972,36 +972,42 @@ keywords.
 
 Assume point is at comment beginning."
   (save-excursion
-    (let* ((com-beg (point))
-	   (keywords (org-element-collect-affiliated-keywords))
+    (let* ((keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
+	   value
 	   (com-end
 	    ;; Get comments ending.  This may not be accurate if
 	    ;; commented lines within an item are followed by
 	    ;; commented lines outside of a list.  Though, parser will
 	    ;; always get it right as it already knows surrounding
 	    ;; element and has narrowed buffer to its contents.
-	    (if (looking-at "#")
-		(if (re-search-forward "^\\([^#]\\|#\\+[a-z]\\)" nil 'move)
-		    (progn (goto-char (match-beginning 0)) (point))
-		  (point))
-	      (while (looking-at "[ \t]*#\\+\\(?: \\|$\\)")
+	    (progn
+	      (while (looking-at "\\(\\(# ?\\)[^+]\\|[ \t]*#\\+\\( \\|$\\)\\)")
+		;; Accumulate lines without leading hash and plus sign
+		;; if any.  First whitespace is also ignored.
+		(setq value
+		      (concat value
+			      (buffer-substring-no-properties
+			       (or (match-end 2) (match-end 3)) (point-at-eol))
+			      "\n"))
 		(forward-line))
 	      (point)))
 	   (end (progn (goto-char com-end)
 		       (org-skip-whitespace)
 		       (if (eobp) (point) (point-at-bol)))))
       `(comment
-	(:begin ,(or (car keywords) com-beg)
+	(:begin ,begin
 		:end ,end
-		:value ,(buffer-substring-no-properties com-beg com-end)
+		:value ,value
 		:post-blank ,(count-lines com-end end)
 		,@(cadr keywords))))))
 
 (defun org-element-comment-interpreter (comment contents)
   "Interpret COMMENT element as Org syntax.
 CONTENTS is nil."
-  (org-element-property :value comment))
+  (replace-regexp-in-string
+   "^" "#+ "
+   (substring (org-element-property :value comment) 0 -1)))
 
 
 ;;;; Comment Block
@@ -1164,16 +1170,27 @@ containing `:begin', `:end', `:value' and `:post-blank' keywords.
 
 Assume point is at the beginning of the fixed-width area."
   (save-excursion
-    (let* ((beg-area (point))
-	   (keywords (org-element-collect-affiliated-keywords))
+    (let* ((keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
+	   value
 	   (end-area
-	    (progn (while (looking-at "[ \t]*:\\( \\|$\\)")
-		     (forward-line))
-		   (point)))
+	    ;; Ending position may not be accurate if fixed-width
+	    ;; lines within an item are followed by fixed-width lines
+	    ;; outside of a list.  Though, parser will always get it
+	    ;; right as it already knows surrounding element and has
+	    ;; narrowed buffer to its contents.
+	    (progn
+	      (while (looking-at "[ \t]*:\\( \\|$\\)")
+		;, Accumulate text without starting colons.
+		(setq value
+		      (concat value
+			      (buffer-substring-no-properties
+			       (match-end 0) (point-at-eol))
+			      "\n"))
+		(forward-line))
+	      (point)))
 	   (end (progn (org-skip-whitespace)
-		       (if (eobp) (point) (point-at-bol))))
-	   (value (buffer-substring-no-properties beg-area end-area)))
+		       (if (eobp) (point) (point-at-bol)))))
       `(fixed-width
 	(:begin ,begin
 		:end ,end
@@ -1184,7 +1201,8 @@ Assume point is at the beginning of the fixed-width area."
 (defun org-element-fixed-width-interpreter (fixed-width contents)
   "Interpret FIXED-WIDTH element as Org syntax.
 CONTENTS is nil."
-  (org-remove-indentation (org-element-property :value fixed-width)))
+  (replace-regexp-in-string
+   "^" ": " (substring (org-element-property :value fixed-width) 0 -1)))
 
 
 ;;;; Horizontal Rule

+ 78 - 3
testing/lisp/test-org-element.el

@@ -36,6 +36,37 @@ Return interpreted string."
 
 ;;; Test Parsers
 
+;;;; Comments
+
+(ert-deftest test-org-element/comment-parser ()
+  "Test `comment' parsing."
+  ;; Regular comment.
+  (should
+   (equal
+    (org-test-with-temp-text "# Comment"
+      (org-element-map (org-element-parse-buffer) 'comment 'identity nil t))
+    '(comment (:begin 1 :end 10 :value "Comment\n" :post-blank 0))))
+  ;; Inline comment.
+  (should
+   (equal
+    (org-test-with-temp-text "#+ Comment"
+      (org-element-map (org-element-parse-buffer) 'comment 'identity nil t))
+    '(comment (:begin 1 :end 11 :value "Comment\n" :post-blank 0))))
+  ;; Preserve indentation.
+  (should
+   (equal
+    (org-test-with-temp-text "#+ No blank\n#+  One blank"
+      (org-element-map (org-element-parse-buffer) 'comment 'identity nil t))
+    '(comment (:begin 1 :end 26 :value "No blank\n One blank\n" :post-blank 0))))
+  ;; Comment with blank lines.
+  (should
+   (equal
+    (org-test-with-temp-text "#+ First part\n#+ \n#+\n#+ Second part"
+      (org-element-map (org-element-parse-buffer) 'comment 'identity nil t))
+    '(comment
+      (:begin 1 :end 36 :value "First part\n\n\nSecond part\n" :post-blank 0)))))
+
+
 ;;;; Example-blocks and Src-blocks
 
 (ert-deftest test-org-element/block-switches ()
@@ -152,6 +183,43 @@ Return interpreted string."
 		 :value "contents" :begin 1 :end 20 :post-blank 0)))))
 
 
+;;;; Fixed width
+
+(ert-deftest test-org-element/fixed-width ()
+  "Test fixed-width area parsing."
+  ;; Preserve indentation.
+  (should
+   (equal
+    (org-test-with-temp-text ": no blank\n:  one blank"
+      (org-element-map (org-element-parse-buffer) 'fixed-width 'identity nil t))
+    '(fixed-width
+      (:begin 1 :end 24 :value "no blank\n one blank\n" :post-blank 0))))
+  ;; Fixed-width with empty lines.
+  (should
+   (equal
+    (org-test-with-temp-text ": first part\n:\n: \n: second part"
+      (org-element-map (org-element-parse-buffer) 'fixed-width 'identity nil t))
+    '(fixed-width
+      (:begin 1 :end 32 :value "first part\n\n\nsecond part\n" :post-blank 0))))
+  ;; Parse indented fixed-width markers.
+  (should
+   (equal
+    (org-test-with-temp-text "Text\n  : no blank\n  :  one blank"
+      (org-element-map (org-element-parse-buffer) 'fixed-width 'identity nil t))
+    '(fixed-width
+      (:begin 6 :end 33 :value "no blank\n one blank\n" :post-blank 0))))
+  ;; Distinguish fixed-width areas within a list and outside of it.
+  (should
+   (= 2
+      (length
+       (org-test-with-temp-text "
+- Item
+  : fixed-width inside
+: fixed-width outside"
+	 (org-element-map
+	  (org-element-parse-buffer) 'fixed-width 'identity))))))
+
+
 ;;;; Footnotes references
 
 (ert-deftest test-org-element/footnote-reference-parser ()
@@ -613,10 +681,13 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] =>  0:01"))
 (ert-deftest test-org-element/comment-interpreter ()
   "Test comment interpreter."
   ;; Regular comment.
-  (should (equal (org-test-parse-and-interpret "#Comment") "#Comment\n"))
+  (should (equal (org-test-parse-and-interpret "#Comment") "#+ Comment\n"))
   ;; Inline comment.
   (should (equal (org-test-parse-and-interpret "  #+ Comment")
-		 "  #+ Comment\n")))
+		 "#+ Comment\n"))
+  ;; Preserve indentation.
+  (should (equal (org-test-parse-and-interpret "  #+ No blank\n#+  One blank")
+		 "#+ No blank\n#+  One blank\n")))
 
 (ert-deftest test-org-element/comment-block-interpreter ()
   "Test comment block interpreter."
@@ -644,7 +715,11 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] =>  0:01"))
 
 (ert-deftest test-org-element/fixed-width-interpreter ()
   "Test fixed width interpreter."
-  (should (equal (org-test-parse-and-interpret ": Test") ": Test\n")))
+  ;; Standard test.
+  (should (equal (org-test-parse-and-interpret ": Test") ": Test\n"))
+  ;; Preserve indentation.
+  (should (equal (org-test-parse-and-interpret ":  2 blanks\n: 1 blank")
+		 ":  2 blanks\n: 1 blank\n")))
 
 (ert-deftest test-org-element/horizontal-rule-interpreter ()
   "Test horizontal rule interpreter."