Browse Source

org-element: Syntax change for caption

* contrib/lisp/org-element.el (org-element-dual-keywords): Move
  caption in the dual keywords category.
(org-element--affiliated-re): Change regexp matching a dual keyword.
(org-element-collect-affiliated-keywords): Dual parsed keywords also
  get their optional value parsed as a secondary string.
* EXPERIMENTAL/org-e-latex.el (org-e-latex--caption/label-string,
  org-e-latex-src-block): Apply caption status change.
* EXPERIMENTAL/org-e-ascii.el (org-e-ascii--build-caption): Apply
  caption status change.
(org-e-ascii--list-listings, org-e-ascii--list-tables): Apply caption
  status change.  Also use short caption name when available.

The status change implies a syntax change.  Captions can now share
#+results: syntax, which mean that they can have a secondary
value. Thus, the following Org snippets are valid, the first two being
equivalent.

#+caption: long name
#+caption[]: long name
#+caption[short name]: long name
Nicolas Goaziou 13 years ago
parent
commit
711d2ef0e0
3 changed files with 56 additions and 38 deletions
  1. 9 5
      EXPERIMENTAL/org-e-ascii.el
  2. 24 19
      EXPERIMENTAL/org-e-latex.el
  3. 23 14
      contrib/lisp/org-element.el

+ 9 - 5
EXPERIMENTAL/org-e-ascii.el

@@ -629,9 +629,9 @@ keyword."
 			  (src-block "Listing %d: %s")) info)))
 	(org-e-ascii--fill-string
 	 (format
-	  title-fmt
-	  reference
-	  (if caption (org-export-secondary-string caption 'e-ascii info) name))
+	  title-fmt reference
+	  (if (not caption) name
+	    (org-export-secondary-string (car caption) 'e-ascii info)))
 	 (org-e-ascii--current-text-width element info) info)))))
 
 (defun org-e-ascii--build-toc (info &optional n keyword)
@@ -696,7 +696,9 @@ generation.  INFO is a plist used as a communication channel."
 	       (org-e-ascii--fill-string
 		(let ((caption (org-element-get-property :caption src-block)))
 		  (if (not caption) (org-element-get-property :name src-block)
-		    (org-export-secondary-string caption 'e-ascii info)))
+		    (org-export-secondary-string
+		     ;; Use short name in priority, if available.
+		     (or (cdr caption) (car caption)) 'e-ascii info)))
 		(- text-width (length initial-text)) info)
 	       (length initial-text))))))
 	(org-export-collect-listings info) "\n")))))
@@ -733,7 +735,9 @@ generation.  INFO is a plist used as a communication channel."
 	       (org-e-ascii--fill-string
 		(let ((caption (org-element-get-property :caption table)))
 		  (if (not caption) (org-element-get-property :name table)
-		    (org-export-secondary-string caption 'e-ascii info)))
+		    ;; Use short name in priority, if available.
+		    (org-export-secondary-string
+		     (or (cdr caption) (car caption)) 'e-ascii info)))
 		(- text-width (length initial-text)) info)
 	       (length initial-text))))))
 	(org-export-collect-tables info) "\n")))))

+ 24 - 19
EXPERIMENTAL/org-e-latex.el

@@ -685,28 +685,28 @@ These are the .aux, .log, .out, and .toc files."
 (defun org-e-latex--caption/label-string (caption label info)
   "Return caption and label LaTeX string for floats.
 
-CAPTION is a secondary string \(a list of strings and Org
-objects\) and LABEL a string representing the label.  INFO is
-a plist holding contextual information.
+CAPTION is a cons cell of secondary strings, the car being the
+standard caption and the cdr its short form.  LABEL is a string
+representing the label.  INFO is a plist holding contextual
+information.
 
 If there's no caption nor label, return the empty string.
 
 For non-floats, see `org-e-latex--wrap-label'."
-  (let ((caption-str (and caption
-			  (org-export-secondary-string
-			   caption 'e-latex info)))
-	(label-str (if label (format "\\label{%s}" label) "")))
+  (let ((label-str (if label (format "\\label{%s}" label) "")))
     (cond
-     ((and (not caption-str) (not label)) "")
-     ((not caption-str) (format "\\label{%s}\n" label))
+     ((and (not caption) (not label)) "")
+     ((not caption) (format "\\label{%s}\n" label))
      ;; Option caption format with short name.
-     ((string-match "\\[\\([^][]*\\)\\]{\\([^{}]*\\)}" caption-str)
+     ((cdr caption)
       (format "\\caption[%s]{%s%s}\n"
-	      (org-match-string-no-properties 1 caption-str)
+	      (org-export-secondary-string (cdr caption) 'e-latex info)
 	      label-str
-	      (org-match-string-no-properties 2 caption-str)))
+	      (org-export-secondary-string (car caption) 'e-latex info)))
      ;; Standard caption format.
-     (t (format "\\caption{%s%s}\n" label-str caption-str)))))
+     (t (format "\\caption{%s%s}\n"
+		label-str
+		(org-export-secondary-string (car caption) 'e-latex info))))))
 
 (defun org-e-latex--guess-inputenc (header)
   "Set the coding system in inputenc to what the buffer is.
@@ -1629,12 +1629,17 @@ contextual information."
 	(if float-env (format float-env body) body)))
      ;; Use listings package.
      (t
-      (let ((lst-lang (or (cadr (assq (intern lang) org-e-latex-listings-langs))
-			  lang))
-	    (caption-str (and caption
-			      (org-export-secondary-string
-			       (org-element-get-property :caption src-block)
-			       'e-latex info))))
+      (let ((lst-lang
+	     (or (cadr (assq (intern lang) org-e-latex-listings-langs)) lang))
+	    (caption-str
+	     (when caption
+	       (let ((main (org-export-secondary-string
+			    (car caption) 'e-latex info)))
+		 (if (not (cdr caption)) (format "{%s}" main)
+		   (format
+		    "{[%s]%s}"
+		    (org-export-secondary-string (cdr caption) 'e-latex info)
+		    main))))))
 	(concat (format "\\lstset{%s}\n"
 			(org-e-latex--make-option-string
 			 (append org-e-latex-listings-options

+ 23 - 14
contrib/lisp/org-element.el

@@ -2500,7 +2500,7 @@ strings and objects.
 This list is checked after translations have been applied.  See
 `org-element-keyword-translation-alist'.")
 
-(defconst org-element-dual-keywords '("results")
+(defconst org-element-dual-keywords '("caption" "results")
   "List of keywords which can have a secondary value.
 
 In Org syntax, they can be written with optional square brackets
@@ -2589,7 +2589,7 @@ matching `org-element-parsed-keywords'.")
 	  (mapconcat
 	   (lambda (keyword)
 	     (if (member keyword org-element-dual-keywords)
-		 (format "\\(%s\\)\\(?:\\[\\(.*?\\)\\]\\)?"
+		 (format "\\(%s\\)\\(?:\\[\\(.*\\)\\]\\)?"
 			 (regexp-quote keyword))
 	       (regexp-quote keyword)))
 	   org-element-affiliated-keywords "\\|"))
@@ -2834,8 +2834,8 @@ it's value will be a list of parsed strings.  It defaults to
 DUALS is a list of strings.  Any keyword member of this list can
 have two parts: one mandatory and one optional.  Its value is
 a cons cell whose car is the former, and the cdr the latter.  If
-a keyword is a member of both PARSED and DUALS, only the primary
-part will be parsed.  It defaults to `org-element-dual-keywords'.
+a keyword is a member of both PARSED and DUALS, both values will
+be parsed.  It defaults to `org-element-dual-keywords'.
 
 Return a list whose car is the position at the first of them and
 cdr a plist of keywords and values."
@@ -2846,6 +2846,9 @@ cdr a plist of keywords and values."
 	  (consed (or consed org-element-multiple-keywords))
 	  (parsed (or parsed org-element-parsed-keywords))
 	  (duals (or duals org-element-dual-keywords))
+	  ;; RESTRICT is the list of objects allowed in parsed
+	  ;; keywords value.
+	  (restrict (cdr (assq 'keyword org-element-string-restrictions)))
 	  output)
       (unless (bobp)
 	(while (and (not (bobp))
@@ -2854,21 +2857,27 @@ cdr a plist of keywords and values."
 		 ;; Apply translation to RAW-KWD.  From there, KWD is
 		 ;; the official keyword.
 		 (kwd (or (cdr (assoc raw-kwd trans-list)) raw-kwd))
-		 ;; If KWD is a dual keyword, find it secondary value.
-		 (dual-value (and (member kwd duals)
-				  (org-match-string-no-properties 3)))
 		 ;; Find main value for any keyword.
-		 (value (org-trim (buffer-substring-no-properties
-				   (match-end 0) (point-at-eol))))
+		 (value
+		  (save-match-data
+		    (org-trim
+		     (buffer-substring-no-properties
+		      (match-end 0) (point-at-eol)))))
+		 ;; If KWD is a dual keyword, find its secondary
+		 ;; value.  Maybe parse it.
+		 (dual-value
+		  (and (member kwd duals)
+		       (let ((sec (org-match-string-no-properties 3)))
+			 (if (or (not sec) (not (member kwd parsed))) sec
+			   (org-element-parse-secondary-string sec restrict)))))
 		 ;; Attribute a property name to KWD.
 		 (kwd-sym (and kwd (intern (concat ":" kwd)))))
 	    ;; Now set final shape for VALUE.
 	    (when (member kwd parsed)
-	      (setq value
-		    (org-element-parse-secondary-string
-		     value
-		     (cdr (assq 'keyword org-element-string-restrictions)))))
-	    (when (member kwd duals) (setq value (cons value dual-value)))
+	      (setq value (org-element-parse-secondary-string value restrict)))
+	    (when (member kwd duals)
+	      ;; VALUE is mandatory.  Set it to nil if there is none.
+	      (setq value (and value (cons value dual-value))))
 	    (when (member kwd consed)
 	      (setq value (cons value (plist-get output kwd-sym))))
 	    ;; Eventually store the new value in OUTPUT.