浏览代码

org-element: code clean-up and some optimizations

* contrib/lisp/org-element.el (org-element-center-block-parser,
  org-element-plain-list-parser, org-element-quote-block-parser,
  org-element-special-block-parser, org-element-comment-parser,
  org-element-comment-block-parser, org-element-example-block-parser,
  org-element-export-block-parser, org-element-fixed-width-parser,
  org-element-horizontal-rule-parser, org-element-keyword-parser,
  org-element-latex-environment-parser, org-element-paragraph-parser,
  org-element-property-drawer-parser, org-element-src-block-parser,
  org-element-table-parser): Since parser will alway be called at the
  beginning of the element, simplify code.
Nicolas Goaziou 13 年之前
父节点
当前提交
49228181ee
共有 1 个文件被更改,包括 139 次插入183 次删除
  1. 139 183
      contrib/lisp/org-element.el

+ 139 - 183
contrib/lisp/org-element.el

@@ -157,20 +157,16 @@ Return a list whose CAR is `center-block' and CDR is a plist
 containing `:begin', `:end', `:hiddenp', `:contents-begin',
 `:contents-end' and `:post-blank' keywords.
 
-Assume point is at beginning or end of the block."
+Assume point is at the beginning of the block."
   (save-excursion
     (let* ((case-fold-search t)
-	   (keywords (progn
-		       (end-of-line)
-		       (re-search-backward
-			(concat "^[ \t]*#\\+BEGIN_CENTER") nil t)
-		       (org-element-collect-affiliated-keywords)))
+	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-begin (progn (forward-line) (point)))
 	   (hidden (org-truely-invisible-p))
-	   (contents-end (progn (re-search-forward
-				 (concat "^[ \t]*#\\+END_CENTER") nil t)
-				(point-at-bol)))
+	   (contents-end
+	    (progn (re-search-forward "^[ \t]*#\\+END_CENTER" nil t)
+		   (point-at-bol)))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
 		       (if (eobp) (point) (point-at-bol)))))
@@ -719,18 +715,17 @@ containing `:type', `:begin', `:end', `:contents-begin' and
 `:contents-end', `:level', `:structure' and `:post-blank'
 keywords.
 
-Assume point is at one of the list items."
+Assume point is at the beginning of the list."
   (save-excursion
     (let* ((struct (or structure (org-list-struct)))
 	   (prevs (org-list-prevs-alist struct))
 	   (parents (org-list-parents-alist struct))
 	   (type (org-list-get-list-type (point) struct prevs))
-	   (contents-begin (goto-char
-			    (org-list-get-list-begin (point) struct prevs)))
+	   (contents-begin (point))
 	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
-	   (contents-end (goto-char
-			  (org-list-get-list-end (point) struct prevs)))
+	   (contents-end
+	    (goto-char (org-list-get-list-end (point) struct prevs)))
 	   (end (save-excursion (org-skip-whitespace)
 				(if (eobp) (point) (point-at-bol))))
 	   (level 0))
@@ -773,19 +768,14 @@ Return a list whose CAR is `quote-block' and CDR is a plist
 containing `:begin', `:end', `:hiddenp', `:contents-begin',
 `:contents-end' and `:post-blank' keywords.
 
-Assume point is at beginning or end of the block."
+Assume point is at the beginning of the block."
   (save-excursion
     (let* ((case-fold-search t)
-	   (keywords (progn
-		       (end-of-line)
-		       (re-search-backward
-			(concat "^[ \t]*#\\+BEGIN_QUOTE") nil t)
-		       (org-element-collect-affiliated-keywords)))
+	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-begin (progn (forward-line) (point)))
 	   (hidden (org-truely-invisible-p))
-	   (contents-end (progn (re-search-forward
-				 (concat "^[ \t]*#\\+END_QUOTE") nil t)
+	   (contents-end (progn (re-search-forward "^[ \t]*#\\+END_QUOTE" nil t)
 				(point-at-bol)))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
@@ -848,23 +838,18 @@ Return a list whose CAR is `special-block' and CDR is a plist
 containing `:type', `:begin', `:end', `:hiddenp',
 `:contents-begin', `:contents-end' and `:post-blank' keywords.
 
-Assume point is at beginning or end of the block."
+Assume point is at the beginning of the block."
   (save-excursion
     (let* ((case-fold-search t)
-	   (type (progn (looking-at
-			 "[ \t]*#\\+\\(?:BEGIN\\|END\\)_\\([-A-Za-z0-9]+\\)")
+	   (type (progn (looking-at "[ \t]*#\\+BEGIN_\\([-A-Za-z0-9]+\\)")
 			(org-match-string-no-properties 1)))
-	   (keywords (progn
-		       (end-of-line)
-		       (re-search-backward
-			(concat "^[ \t]*#\\+BEGIN_" type) nil t)
-		       (org-element-collect-affiliated-keywords)))
+	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-begin (progn (forward-line) (point)))
 	   (hidden (org-truely-invisible-p))
-	   (contents-end (progn (re-search-forward
-				 (concat "^[ \t]*#\\+END_" type) nil t)
-				(point-at-bol)))
+	   (contents-end
+	    (progn (re-search-forward (concat "^[ \t]*#\\+END_" type) nil t)
+		   (point-at-bol)))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
 		       (if (eobp) (point) (point-at-bol)))))
@@ -986,45 +971,35 @@ CONTENTS is nil."
 
 Return a list whose CAR is `comment' and CDR is a plist
 containing `:begin', `:end', `:value' and `:post-blank'
-keywords."
-  (let (beg-coms begin end end-coms keywords)
-    (save-excursion
-      (if (looking-at "#")
-	  ;; First type of comment: comments at column 0.
-	  (let ((comment-re "^\\([^#]\\|#\\+[a-z]\\)"))
-	    (save-excursion
-	      (re-search-backward comment-re nil 'move)
-	      (if (bobp) (setq keywords nil beg-coms (point))
-		(forward-line)
-		(setq keywords (org-element-collect-affiliated-keywords)
-		      beg-coms (point))))
-	    (re-search-forward comment-re nil 'move)
-	    (setq end-coms (if (eobp) (point) (match-beginning 0))))
-	;; Second type of comment: indented comments.
-	(let ((comment-re "[ \t]*#\\+\\(?: \\|$\\)"))
-	  (unless (bobp)
-	    (while (and (not (bobp)) (looking-at comment-re))
-	      (forward-line -1))
-	    (unless (looking-at comment-re) (forward-line)))
-	  (setq beg-coms (point))
-	  (setq keywords (org-element-collect-affiliated-keywords))
-	  ;; Get comments ending.  This may not be accurate if
-	  ;; commented lines within an item are followed by commented
-	  ;; lines outside of the list.  Though, parser will always
-	  ;; get it right as it already knows surrounding element and
-	  ;; has narrowed buffer to its contents.
-	  (while (looking-at comment-re) (forward-line))
-	  (setq end-coms (point))))
-      ;; Find position after blank.
-      (goto-char end-coms)
-      (org-skip-whitespace)
-      (setq end (if (eobp) (point) (point-at-bol))))
-    `(comment
-      (:begin ,(or (car keywords) beg-coms)
-	      :end ,end
-	      :value ,(buffer-substring-no-properties beg-coms end-coms)
-	      :post-blank ,(count-lines end-coms end)
-	      ,@(cadr keywords)))))
+keywords.
+
+Assume point is at comment beginning."
+  (save-excursion
+    (let* ((com-beg (point))
+	   (keywords (org-element-collect-affiliated-keywords))
+	   (begin (car keywords))
+	   (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]*#\\+\\(?: \\|$\\)")
+		(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)
+		:end ,end
+		:value ,(buffer-substring-no-properties com-beg com-end)
+		:post-blank ,(count-lines com-end end)
+		,@(cadr keywords))))))
 
 (defun org-element-comment-interpreter (comment contents)
   "Interpret COMMENT element as Org syntax.
@@ -1039,19 +1014,18 @@ CONTENTS is nil."
 
 Return a list whose CAR is `comment-block' and CDR is a plist
 containing `:begin', `:end', `:hiddenp', `:value' and
-`:post-blank' keywords."
+`:post-blank' keywords.
+
+Assume point is at comment block beginning."
   (save-excursion
-    (end-of-line)
     (let* ((case-fold-search t)
-	   (keywords (progn
-		       (re-search-backward "^[ \t]*#\\+BEGIN_COMMENT" nil t)
-		       (org-element-collect-affiliated-keywords)))
+	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-begin (progn (forward-line) (point)))
 	   (hidden (org-truely-invisible-p))
-	   (contents-end (progn (re-search-forward
-				 "^[ \t]*#\\+END_COMMENT" nil t)
-				(point-at-bol)))
+	   (contents-end
+	    (progn (re-search-forward "^[ \t]*#\\+END_COMMENT" nil t)
+		   (point-at-bol)))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
 		       (if (eobp) (point) (point-at-bol))))
@@ -1081,12 +1055,10 @@ containing `:begin', `:end', `:number-lines', `:preserve-indent',
 `:retain-labels', `:use-labels', `:label-fmt', `:hiddenp',
 `:switches', `:value' and `:post-blank' keywords."
   (save-excursion
-    (end-of-line)
     (let* ((case-fold-search t)
-	   (switches (progn
-		       (re-search-backward
-			"^[ \t]*#\\+BEGIN_EXAMPLE\\(?: +\\(.*\\)\\)?" nil t)
-		       (org-match-string-no-properties 1)))
+	   (switches
+	    (progn (looking-at "^[ \t]*#\\+BEGIN_EXAMPLE\\(?: +\\(.*\\)\\)?")
+		   (org-match-string-no-properties 1)))
 	   ;; Switches analysis
 	   (number-lines (cond ((not switches) nil)
 			       ((string-match "-n\\>" switches) 'new)
@@ -1104,16 +1076,16 @@ containing `:begin', `:end', `:number-lines', `:preserve-indent',
 	    (or (not switches)
 		(and retain-labels (not (string-match "-k\\>" switches)))))
 	   (label-fmt (and switches
-			     (string-match "-l +\"\\([^\"\n]+\\)\"" switches)
-			     (match-string 1 switches)))
+			   (string-match "-l +\"\\([^\"\n]+\\)\"" switches)
+			   (match-string 1 switches)))
 	   ;; Standard block parsing.
 	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-begin (progn (forward-line) (point)))
 	   (hidden (org-truely-invisible-p))
-	   (contents-end (progn
-			   (re-search-forward "^[ \t]*#\\+END_EXAMPLE" nil t)
-			   (point-at-bol)))
+	   (contents-end
+	    (progn (re-search-forward "^[ \t]*#\\+END_EXAMPLE" nil t)
+		   (point-at-bol)))
 	   (value (buffer-substring-no-properties contents-begin contents-end))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
@@ -1149,22 +1121,20 @@ CONTENTS is nil."
 
 Return a list whose CAR is `export-block' and CDR is a plist
 containing `:begin', `:end', `:type', `:hiddenp', `:value' and
-`:post-blank' keywords."
+`:post-blank' keywords.
+
+Assume point is at export-block beginning."
   (save-excursion
-    (end-of-line)
     (let* ((case-fold-search t)
-	   (contents)
-	   (type (progn (re-search-backward
-			 (concat "[ \t]*#\\+BEGIN_"
-				 (org-re "\\([[:alnum:]]+\\)")))
+	   (type (progn (looking-at "[ \t]*#\\+BEGIN_\\([A-Za-z0-9]+\\)")
 			(upcase (org-match-string-no-properties 1))))
 	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-begin (progn (forward-line) (point)))
 	   (hidden (org-truely-invisible-p))
-	   (contents-end (progn (re-search-forward
-				 (concat "^[ \t]*#\\+END_" type) nil t)
-				(point-at-bol)))
+	   (contents-end
+	    (progn (re-search-forward (concat "^[ \t]*#\\+END_" type) nil t)
+		   (point-at-bol)))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
 		       (if (eobp) (point) (point-at-bol))))
@@ -1193,42 +1163,26 @@ CONTENTS is nil."
   "Parse a fixed-width section.
 
 Return a list whose CAR is `fixed-width' and CDR is a plist
-containing `:begin', `:end', `:value' and `:post-blank'
-keywords."
-  (let ((fixed-re "[ \t]*:\\( \\|$\\)")
-	beg-area begin end value pos-before-blank keywords)
-    (save-excursion
-      ;; Move to the beginning of the fixed-width area.
-      (unless (bobp)
-	(while (and (not (bobp)) (looking-at fixed-re))
-	  (forward-line -1))
-	(unless (looking-at fixed-re) (forward-line 1)))
-      (setq beg-area (point))
-      ;; Get affiliated keywords, if any.
-      (setq keywords (org-element-collect-affiliated-keywords))
-      ;; Store true beginning of element.
-      (setq begin (car keywords))
-      ;; Get ending of fixed-width area.  If point is in a list,
-      ;; ensure to not get outside of it.
-      (let* ((itemp (org-in-item-p))
-	     (max-pos (if itemp
-			  (org-list-get-bottom-point
-			   (save-excursion (goto-char itemp) (org-list-struct)))
-			(point-max))))
-	(while (and (looking-at fixed-re) (< (point) max-pos))
-	  (forward-line)))
-      (setq pos-before-blank (point))
-      ;; Find position after blank
-      (org-skip-whitespace)
-      (setq end (if (eobp) (point) (point-at-bol)))
-      ;; Extract value.
-      (setq value (buffer-substring-no-properties beg-area pos-before-blank)))
-    `(fixed-width
-      (:begin ,begin
-	      :end ,end
-	      :value ,value
-	      :post-blank ,(count-lines pos-before-blank end)
-	      ,@(cadr keywords)))))
+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))
+	   (begin (car keywords))
+	   (end-area
+	    (progn (while (looking-at "[ \t]*:\\( \\|$\\)")
+		     (forward-line))
+		   (point)))
+	   (end (progn (org-skip-whitespace)
+		       (if (eobp) (point) (point-at-bol))))
+	   (value (buffer-substring-no-properties beg-area end-area)))
+      `(fixed-width
+	(:begin ,begin
+		:end ,end
+		:value ,value
+		:post-blank ,(count-lines end-area end)
+		,@(cadr keywords))))))
 
 (defun org-element-fixed-width-interpreter (fixed-width contents)
   "Interpret FIXED-WIDTH element as Org syntax.
@@ -1241,9 +1195,8 @@ CONTENTS is nil."
 (defun org-element-horizontal-rule-parser ()
   "Parse an horizontal rule.
 
-   Return a list whose CAR is `horizontal-rule' and CDR is
-   a plist containing `:begin', `:end' and `:post-blank'
-   keywords."
+Return a list whose CAR is `horizontal-rule' and CDR is a plist
+containing `:begin', `:end' and `:post-blank' keywords."
   (save-excursion
     (let* ((keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
@@ -1271,7 +1224,8 @@ Return a list whose CAR is `keyword' and CDR is a plist
 containing `:key', `:value', `:begin', `:end' and `:post-blank'
 keywords."
   (save-excursion
-    (let* ((begin (point))
+    (let* ((case-fold-search t)
+	   (begin (point))
 	   (key (progn (looking-at
 			"[ \t]*#\\+\\(\\(?:[a-z]+\\)\\(?:_[a-z]+\\)*\\):")
 		       (upcase (org-match-string-no-properties 1))))
@@ -1302,11 +1256,12 @@ CONTENTS is nil."
 
 Return a list whose CAR is `latex-environment' and CDR is a plist
 containing `:begin', `:end', `:value' and `:post-blank'
-keywords."
+keywords.
+
+Assume point is at the beginning of the latex environment."
   (save-excursion
-    (end-of-line)
     (let* ((case-fold-search t)
-	   (contents-begin (re-search-backward "^[ \t]*\\\\begin" nil t))
+	   (contents-begin (point))
 	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (contents-end (progn (re-search-forward "^[ \t]*\\\\end")
@@ -1342,12 +1297,11 @@ Assume point is at the beginning of the paragraph."
     (let* ((contents-begin (point))
 	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
-	   (contents-end (progn
-			   (end-of-line)
-			   (if (re-search-forward
-				org-element-paragraph-separate nil 'm)
-			       (progn (forward-line -1) (end-of-line) (point))
-			     (point))))
+	   (contents-end
+	    (progn (end-of-line)
+		   (if (re-search-forward org-element-paragraph-separate nil 'm)
+		       (progn (forward-line -1) (end-of-line) (point))
+		     (point))))
 	   (pos-before-blank (progn (forward-line) (point)))
 	   (end (progn (org-skip-whitespace)
 		       (if (eobp) (point) (point-at-bol)))))
@@ -1422,28 +1376,27 @@ CONTENTS is nil."
 
 Return a list whose CAR is `property-drawer' and CDR is a plist
 containing `:begin', `:end', `:hiddenp', `:contents-begin',
-`:contents-end', `:properties' and `:post-blank' keywords."
+`:contents-end', `:properties' and `:post-blank' keywords.
+
+Assume point is at the beginning of the property drawer."
   (save-excursion
     (let ((case-fold-search t)
-	  (begin (progn (end-of-line)
-			(re-search-backward org-property-start-re)
-			(match-beginning 0)))
-	  (contents-begin (progn (forward-line) (point)))
+	  (begin (point))
+	  (prop-begin (progn (forward-line) (point)))
 	  (hidden (org-truely-invisible-p))
-	  (properties (let (val)
-			(while (not (looking-at "^[ \t]*:END:"))
-			  (when (looking-at
-				 (org-re
-				  "[ \t]*:\\([[:alpha:]][[:alnum:]_-]*\\):"))
-			    (push (cons (match-string 1)
-					(org-trim
-					 (buffer-substring
-					  (match-end 0) (point-at-eol))))
-				  val))
-			  (forward-line))
-			val))
-	  (contents-end (progn (re-search-forward "^[ \t]*:END:" nil t)
-			       (point-at-bol)))
+	  (properties
+	   (let (val)
+	     (while (not (looking-at "^[ \t]*:END:"))
+	       (when (looking-at "[ \t]*:\\([A-Za-z][-_A-Za-z0-9]*\\):")
+		 (push (cons (org-match-string-no-properties 1)
+			     (org-trim
+			      (buffer-substring-no-properties
+			       (match-end 0) (point-at-eol))))
+		       val))
+	       (forward-line))
+	     val))
+	  (prop-end (progn (re-search-forward "^[ \t]*:END:" nil t)
+			   (point-at-bol)))
 	  (pos-before-blank (progn (forward-line) (point)))
 	  (end (progn (org-skip-whitespace)
 		      (if (eobp) (point) (point-at-bol)))))
@@ -1508,16 +1461,21 @@ containing `:language', `:switches', `:parameters', `:begin',
 
 Assume point is at the beginning of the block."
   (save-excursion
-    (looking-at
-     (concat
-      "^[ \t]*#\\+BEGIN_SRC"
-      "\\(?: +\\(\\S-+\\)\\)?"				    ; language
-      "\\(\\(?: +\\(?:-l \".*?\"\\|[-+][A-Za-z]\\)\\)+\\)?" ; switches
-      "\\(.*\\)[ \t]*$"))		; parameters
     (let* ((case-fold-search t)
 	   (contents-begin (point))
+	   ;; Get affiliated keywords.
+	   (keywords (org-element-collect-affiliated-keywords))
+	   ;; Get beginning position.
+	   (begin (car keywords))
 	   ;; Get language as a string.
-	   (language (org-match-string-no-properties 1))
+	   (language
+	    (progn
+	      (looking-at
+	       (concat "^[ \t]*#\\+BEGIN_SRC"
+		       "\\(?: +\\(\\S-+\\)\\)?"
+		       "\\(\\(?: +\\(?:-l \".*?\"\\|[-+][A-Za-z]\\)\\)+\\)?"
+		       "\\(.*\\)[ \t]*$"))
+	      (org-match-string-no-properties 1)))
 	   ;; Get switches.
 	   (switches (org-match-string-no-properties 2))
 	   ;; Get parameters.
@@ -1541,10 +1499,6 @@ Assume point is at the beginning of the block."
 	   (use-labels
 	    (or (not switches)
 		(and retain-labels (not (string-match "-k\\>" switches)))))
-	   ;; Get affiliated keywords.
-	   (keywords (org-element-collect-affiliated-keywords))
-	   ;; Get beginning position.
-	   (begin (car keywords))
 	   ;; Get position at end of block.
 	   (contents-end (progn (re-search-forward "^[ \t]*#\\+END_SRC" nil t)
 				(forward-line)
@@ -1613,10 +1567,12 @@ CONTENTS is nil."
 
 Return a list whose CAR is `table' and CDR is a plist containing
 `:begin', `:end', `:tblfm', `:type', `:contents-begin',
-`:contents-end', `:value' and `:post-blank' keywords."
+`:contents-end', `:value' and `:post-blank' keywords.
+
+Assume point is at the beginning of the table."
   (save-excursion
     (let* ((case-fold-search t)
-	   (table-begin (goto-char (org-table-begin t)))
+	   (table-begin (point))
 	   (type (if (org-at-table.el-p) 'table.el 'org))
 	   (keywords (org-element-collect-affiliated-keywords))
 	   (begin (car keywords))
@@ -1632,9 +1588,9 @@ Return a list whose CAR is `table' and CDR is a plist containing
 		:end ,end
 		:type ,type
 		:tblfm ,tblfm
-		;; Only `org' tables have contents.  `table.el'
-		;; tables use a `:value' property to store raw
-		;; table as a string.
+		;; Only `org' tables have contents.  `table.el' tables
+		;; use a `:value' property to store raw table as
+		;; a string.
 		:contents-begin ,(and (eq type 'org) table-begin)
 		:contents-end ,(and (eq type 'org) table-end)
 		:value ,(and (eq type 'table.el)