Browse Source

Tables: Implement last-row references.

After the failed implementation of `@0' as a reference for the last
line, this is a second attempt to provide such references.  I would
have liked to allow `@last' as the reference, that would have been
beautiful.  However, too many regular expressions directly search for
`@' followed by a number, so this is too hard to implement.

Therefore, I am now turning the last row into a row of implicitly
named fields.  From now on, $LR1, $LR2,... can be used to refer to
fields in the last row.  These names may also appear on the left hand
side of formulas.
Carsten Dominik 16 years ago
parent
commit
dadc9a1af1
4 changed files with 52 additions and 7 deletions
  1. 4 0
      doc/ChangeLog
  2. 6 0
      doc/org.texi
  3. 10 0
      lisp/ChangeLog
  4. 32 7
      lisp/org-table.el

+ 4 - 0
doc/ChangeLog

@@ -1,3 +1,7 @@
+2008-12-19  Carsten Dominik  <carsten.dominik@gmail.com>
+
+	* org.texi (References): Document special last-row references.
+
 2008-12-17  Carsten Dominik  <carsten.dominik@gmail.com>
 
 	* org.texi: Fix typos and grammatical issues.

+ 6 - 0
doc/org.texi

@@ -1818,6 +1818,10 @@ Org's references with @emph{signed} numbers are floating
 references because the same reference operator can reference different
 fields depending on the field being calculated by the formula.
 
+As a special case references like @samp{$LR5} and @samp{$LR12} can be used to
+refer in a stable way to the 5th and 12th field in the last row of the
+table.
+
 Here are a few examples:
 
 @example
@@ -2000,6 +2004,8 @@ with the appropriate commands, @i{absolute references} (but not relative
 ones) in stored formulas are modified in order to still reference the
 same field.  Of cause this is not true if you edit the table structure
 with normal editing commands - then you must fix the equations yourself.
+The left hand side of a formula may also be a named field (@pxref{Advanced
+features}), or a last-row reference like @samp{$LR3}.
 
 Instead of typing an equation into the field, you may also use the
 following command

+ 10 - 0
lisp/ChangeLog

@@ -1,5 +1,15 @@
 2008-12-19  Carsten Dominik  <carsten.dominik@gmail.com>
 
+	* org-table.el (org-table-get-specials): Set
+	`org-table-current-last-data-line'.
+	(org-table-current-last-data-line): New variable.
+	(org-table-insert-column, org-table-delete-column)
+	(org-table-move-column, org-table-fix-formulas): Call
+	`org-table-fix-formulas' a second time to fix the $LR references.
+	(org-table-get-specials): Add the $LR references to the tables.
+	(org-table-get-formula): Do not offer last-row names as LHS of
+	formulas.
+
 	* org.el (org-store-link): Capture link description from
 	`org-id-store-link'.
 

+ 32 - 7
lisp/org-table.el

@@ -1060,7 +1060,8 @@ However, when FORCE is non-nil, create new columns if necessary."
     (goto-line linepos)
     (org-table-goto-column colpos)
     (org-table-align)
-    (org-table-fix-formulas "$" nil (1- col) 1)))
+    (org-table-fix-formulas "$" nil (1- col) 1)
+    (org-table-fix-formulas "$LR" nil (1- col) 1)))
 
 (defun org-table-find-dataline ()
   "Find a dataline in the current table, which is needed for column commands."
@@ -1107,6 +1108,8 @@ However, when FORCE is non-nil, create new columns if necessary."
     (org-table-goto-column colpos)
     (org-table-align)
     (org-table-fix-formulas "$" (list (cons (number-to-string col) "INVALID"))
+			    col -1 col)
+    (org-table-fix-formulas "$LR" (list (cons (number-to-string col) "INVALID"))
 			    col -1 col)))
 
 (defun org-table-move-column-right ()
@@ -1150,7 +1153,10 @@ However, when FORCE is non-nil, create new columns if necessary."
     (org-table-align)
     (org-table-fix-formulas
      "$" (list (cons (number-to-string col) (number-to-string colpos))
-	       (cons (number-to-string colpos) (number-to-string col))))))
+	       (cons (number-to-string colpos) (number-to-string col))))
+    (org-table-fix-formulas
+     "$LR" (list (cons (number-to-string col) (number-to-string colpos))
+		 (cons (number-to-string colpos) (number-to-string col))))))
 
 (defun org-table-move-row-down ()
   "Move table row down."
@@ -1717,7 +1723,9 @@ When NAMED is non-nil, look for a named equation."
 		      (org-table-current-column)))
 	 (refass (assoc ref stored-list))
 	 (scol (if named
-		   (if name name ref)
+		   (if (and name (not (string-match "^LR[0-9]+$" name)))
+		       name
+		     ref)
 		 (int-to-string (org-table-current-column))))
 	 (dummy (and (or name refass) (not named)
 		     (not (y-or-n-p "Replace field formula with column formula? " ))
@@ -1826,8 +1834,9 @@ For all numbers larger than LIMIT, shift them by DELTA."
       (let ((re (concat key "\\([0-9]+\\)"))
 	    (re2
 	     (when remove
-	       (if (equal key "$")
-		   (format "\\(@[0-9]+\\)?\\$%d=.*?\\(::\\|$\\)" remove)
+	       (if (or (equal key "$") (equal key "$LR"))
+		   (format "\\(@[0-9]+\\)?%s%d=.*?\\(::\\|$\\)"
+			   (regexp-quote key) remove)
 		 (format "@%d\\$[0-9]+=.*?\\(::\\|$\\)" remove))))
 	    s n a)
 	(when remove
@@ -1846,7 +1855,7 @@ For all numbers larger than LIMIT, shift them by DELTA."
   (save-excursion
     (let ((beg (org-table-begin)) (end (org-table-end))
 	  names name fields fields1 field cnt
-	  c v l line col types dlines hlines)
+	  c v l line col types dlines hlines last-dline)
       (setq org-table-column-names nil
 	    org-table-local-parameters nil
 	    org-table-named-field-locations nil
@@ -1897,8 +1906,24 @@ For all numbers larger than LIMIT, shift them by DELTA."
 	(beginning-of-line 2)
 	(setq l (1+ l)))
       (setq org-table-current-line-types (apply 'vector (nreverse types))
+	    last-dline (car dlines)
 	    org-table-dlines (apply 'vector (cons nil (nreverse dlines)))
-	    org-table-hlines (apply 'vector (cons nil (nreverse hlines)))))))
+	    org-table-hlines (apply 'vector (cons nil (nreverse hlines))))
+      (goto-line last-dline)
+      (let* ((l last-dline)
+	     (fields (org-split-string
+		      (buffer-substring (point-at-bol) (point-at-eol))
+		      "|"))
+	     (nfields (length fields))
+	     al al2)
+	(loop for i from 1 to nfields do
+	      (push (list (format "LR%d" i) l i) al)
+	      (push (cons (format "LR%d" i) (nth (1- i) fields)) al2))
+	(setq org-table-named-field-locations
+	      (append org-table-named-field-locations al))
+	(setq org-table-local-parameters
+	      (append org-table-local-parameters al2))))))
+
 
 (defun org-table-maybe-eval-formula ()
   "Check if the current field starts with \"=\" or \":=\".