Browse Source

Fix remote references that contain pointers to first/last rows/columns

* lisp/org-table.el (org-table-formula-handle-first/last-rc): Do not
expand pointers to first/last row/column that are inside a call
to `remote'.
(org-table-get-remote-range): Expand pointers to first/last
row/column.

Wu Feng writes:

> Hello,
>
> First, please check below simple example, I defined two tables (T1 and
> T2). In table-2, I remotely refer to the @>$1 (last row, column 1) and
> $LR2 (last row, column 2) of T1.
>
> #+TBLNAME: T1
> | 11 | 12 |
> | 21 | 22 |
> | 31 | 32 |
>
> #+TBLNAME: T2
> | xxx | xxx | xxx | xxx |
> | #   |  21 |  32 |     |
> #+TBLFM: @>$3=remote(T1,$LR2)::@>$2=remote(T1,@>$1)
>
> Obviously, the expected results are:
>
> - remote(T1,@>$1) is replaced by 31
> - remote(T1,$LR2) is replaced by 32
>
> But I got 21 for remote(T1,@>$1). The $LR version works perfectly
> (though the manual says $LR is out-dated)
>
> Below are debug info when evaluating remote(T1,@>$1). Looks like @> in
> the remote reference is mapped to the last row of the current table, not
> of the remote table.
>
> Substitution history of formula
> Orig:   remote(T1,@2$1)
> $xyz->  remote(T1,@2$1)
> @r$c->  (21)
> $1->    (21)
> Result: 21
> Format: NONE
> Final:  21
>
> Emacs  : GNU Emacs 23.3.1 (i686-pc-linux-gnu, GTK+ Version 2.24.6)
> of 2011-09-13 on shirley
> Package: Org-mode version 7.7
Carsten Dominik 8 years ago
parent
commit
1432e4bc79
1 changed files with 22 additions and 15 deletions
  1. 22 15
      lisp/org-table.el

+ 22 - 15
lisp/org-table.el

@@ -2986,20 +2986,24 @@ when a line/row is swaped out of that privileged position.  So for
 formulas that use a range of rows or columns, it may often be better
 to anchor the formula with \"I\" row markers, or to offset from the
 borders of the table using the @< @> $< $> makers."
-  (let (n nmax len char)
-    (while (string-match "\\([@$]\\)\\(<+\\|>+\\)" s)
-      (setq nmax (if (equal (match-string 1 s) "@")
-		     (1- (length org-table-dlines))
-		   org-table-current-ncol)
-	    len (- (match-end 2) (match-beginning 2))
-	    char (string-to-char (match-string 2 s))
-	    n (if (= char ?<)
-		  len
-		(- nmax len -1)))
-      (if (or (< n 1) (> n nmax))
-	  (error "Reference \"%s\" in expression \"%s\" points outside table"
-		 (match-string 0 s) s))
-      (setq s (replace-match (format "%s%d" (match-string 1 s) n) t t s))))
+  (let (n nmax len char (start 0))
+    (while (string-match "\\([@$]\\)\\(<+\\|>+\\)\\|\\(remote([^\)]+)\\)"
+			 s start)
+      (if (match-end 3)
+	  (setq start (match-end 3))
+	(setq nmax (if (equal (match-string 1 s) "@")
+		       (1- (length org-table-dlines))
+		     org-table-current-ncol)
+	      len (- (match-end 2) (match-beginning 2))
+	      char (string-to-char (match-string 2 s))
+	      n (if (= char ?<)
+		    len
+		  (- nmax len -1)))
+	(if (or (< n 1) (> n nmax))
+	    (error "Reference \"%s\" in expression \"%s\" points outside table"
+		   (match-string 0 s) s))
+	(setq start (match-beginning 0))
+	(setq s (replace-match (format "%s%d" (match-string 1 s) n) t t s)))))
   s)
 
 (defun org-table-formula-substitute-names (f)
@@ -4668,6 +4672,8 @@ The return value is either a single string for a single field, or a
 list of the fields in the rectangle ."
   (save-match-data
     (let ((id-loc nil)
+	  ;; Protect a bunch of variables from being overwritten
+	  ;; by the context of the remote table
 	  org-table-column-names org-table-column-name-regexp
 	  org-table-local-parameters org-table-named-field-locations
 	  org-table-current-line-types org-table-current-begin-line
@@ -4704,7 +4710,8 @@ list of the fields in the rectangle ."
 		  (error "Cannot find a table at NAME or ID %s" name-or-id))
 		(setq tbeg (point-at-bol))
 		(org-table-get-specials)
-		(setq form (org-table-formula-substitute-names form))
+		(setq form (org-table-formula-substitute-names
+			    (org-table-formula-handle-first/last-rc form)))
 		(if (and (string-match org-table-range-regexp form)
 			 (> (length (match-string 0 form)) 1))
 		    (save-match-data