From 0b077de733082fc171ee67760b0f04dd306f7a5a Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Fri, 25 Mar 2016 22:17:08 +0100 Subject: [PATCH 1/3] org-table: Fix #ERROR in table formula with "@>" * lisp/org-table.el (org-table-eval-formula): Expand first and last references into proper fields coordinates before replacing ranges. Reported-by: Pablo S. Casas --- lisp/org-table.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lisp/org-table.el b/lisp/org-table.el index ba063353d..c6eb337cd 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -2738,9 +2738,10 @@ not overwrite the stored one." (setq fmt (replace-match "" t t fmt))) (unless (string-match "\\S-" fmt) (setq fmt nil)))) - (if (and (not suppress-const) org-table-formula-use-constants) - (setq formula (org-table-formula-substitute-names formula))) + (when (and (not suppress-const) org-table-formula-use-constants) + (setq formula (org-table-formula-substitute-names formula))) (setq orig (or (get-text-property 1 :orig-formula formula) "?")) + (setq formula (org-table-formula-handle-first/last-rc formula)) (while (> ndown 0) (setq fields (org-split-string (org-trim From 28a8d2e24e19932338ec3b445f0c1341fefd95ab Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Fri, 25 Mar 2016 23:11:34 +0100 Subject: [PATCH 2/3] org-table: Fix docstrings * lisp/org-table.el (org-table-eval-formula): Nowadays, Calc is installed with Emacs, so there is no need to specify this. Also remove hard-coded "C-u". (org-table-recalculate): Fix code typo. --- lisp/org-table.el | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lisp/org-table.el b/lisp/org-table.el index c6eb337cd..0d0e2169f 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -2641,20 +2641,18 @@ This function assumes the table is already analyzed (i.e., using suppress-store suppress-analysis) "Replace the table field value at the cursor by the result of a calculation. -This function makes use of Dave Gillespie's Calc package, in my view the -most exciting program ever written for GNU Emacs. So you need to have Calc -installed in order to use this function. - In a table, this command replaces the value in the current field with the result of a formula. It also installs the formula as the \"current\" column formula, by storing it in a special line below the table. When called -with a `C-u' prefix, the current field must be a named field, and the -formula is installed as valid in only this specific field. +with a `\\[universal-argument]' prefix the formula is installed as a \ +field formula. -When called with two `C-u' prefixes, insert the active equation -for the field back into the current field, so that it can be -edited there. This is useful in order to use \\[org-table-show-reference] -to check the referenced fields. +When called with a `\\[universal-argument] \\[universal-argument]' prefix, \ +insert the active equation for the field +back into the current field, so that it can be edited there. This is \ +useful +in order to use \\`\\[org-table-show-reference]' to \ +check the referenced fields. When called, the command first prompts for a formula, which is read in the minibuffer. Previously entered formulas are available through the @@ -2663,7 +2661,7 @@ These stored formulas are adapted correctly when moving, inserting, or deleting columns with the corresponding commands. The formula can be any algebraic expression understood by the Calc package. -For details, see the Org-mode manual. +For details, see the Org mode manual. This function can also be called from Lisp programs and offers additional arguments: EQUATION can be the formula to apply. If this @@ -2673,7 +2671,8 @@ SUPPRESS-CONST suppresses the interpretation of constants in the formula, assuming that this has been done already outside the function. SUPPRESS-STORE means the formula should not be stored, either because it is already stored, or because it is a modified equation that should -not overwrite the stored one." +not overwrite the stored one. SUPPRESS-ANALYSIS prevents any call to +`org-table-analyze'." (interactive "P") (org-table-check-inside-data-field) (or suppress-analysis (org-table-analyze)) @@ -3128,10 +3127,13 @@ T1 is nil, always messages." ;;;###autoload (defun org-table-recalculate (&optional all noalign) "Recalculate the current table line by applying all stored formulas. + With prefix arg ALL, do this for all lines in the table. -With the prefix argument ALL is `(16)' \ -\(a double \\[universal-prefix] \\[universal-prefix] prefix), or if -it is the symbol `iterate', recompute the table until it no longer changes. + +When called with a `\\[universal-argument] \\[universal-argument]' prefix, or \ +if ALL is the symbol `iterate', +recompute the table until it no longer changes. + If NOALIGN is not nil, do not re-align the table after the computations are done. This is typically used internally to save time, if it is known that the table will be realigned a little later anyway." From a737f20ca42738170e89129a2f4b5baeb9492f9a Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 26 Mar 2016 00:20:08 +0100 Subject: [PATCH 3/3] org-table: Add tests * testing/lisp/test-org-table.el (test-org-table/eval-formula): (test-org-table/last-rc): New tests. (test-org-table/first-rc): Add tests. --- testing/lisp/test-org-table.el | 63 ++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el index 2bfebb44f..efa88fd2d 100644 --- a/testing/lisp/test-org-table.el +++ b/testing/lisp/test-org-table.el @@ -1673,7 +1673,41 @@ See also `test-org-table/copy-field'." (buffer-string))))) -;;; Field formulas +;;; Formulas + +(ert-deftest test-org-table/eval-formula () + "Test `org-table-eval-formula' specifications." + ;; Error when not on a table field. + (should-error + (org-test-with-temp-text "Text" + (org-table-eval-formula))) + (should-error + (org-test-with-temp-text "| a |\n|---|" + (org-table-eval-formula))) + (should-error + (org-test-with-temp-text "| a |\n#+TBLFM:" + (org-table-eval-formula))) + ;; Handle @<, @>, $< and $>. + (should + (equal "| 1 |\n| 1 |" + (org-test-with-temp-text "| |\n| 1 |" + (org-table-eval-formula nil "@>" nil nil t) + (buffer-string)))) + (should + (equal "| 1 |\n| 1 |" + (org-test-with-temp-text "| 1 |\n| |" + (org-table-eval-formula nil "@<" nil nil t) + (buffer-string)))) + (should + (equal "| 1 | 1 |" + (org-test-with-temp-text "| | 1 |" + (org-table-eval-formula nil "$>" nil nil t) + (buffer-string)))) + (should + (equal "| 1 | 1 |" + (org-test-with-temp-text "| 1 | |" + (org-table-eval-formula nil "$<" nil nil t) + (buffer-string))))) (ert-deftest test-org-table/field-formula-outside-table () "If `org-table-formula-create-columns' is nil, then a formula @@ -1840,7 +1874,7 @@ is t, then new columns should be added as needed" (buffer-string))))) (ert-deftest test-org-table/first-rc () - "Test \"$<\" constructs in formulas." + "Test \"$<\" and \"@<\" constructs in formulas." (should (org-string-match-p "| 1 | 2 |" @@ -1848,6 +1882,31 @@ is t, then new columns should be added as needed" "| | 2 | #+TBLFM: $<=1" (org-table-calc-current-TBLFM) + (buffer-string)))) + (should + (org-string-match-p + "| 2 |\n| 2 |" + (org-test-with-temp-text + "| 2 |\n| | +#+TBLFM: @2$1=@<" + (org-table-calc-current-TBLFM) + (buffer-string))))) + +(ert-deftest test-org-table/last-rc () + "Test \"$>\" and \"@>\" constructs in formulas." + (should + (org-string-match-p + "| 2 | 1 |" + (org-test-with-temp-text + "| 2 | |\n#+TBLFM: $>=1" + (org-table-calc-current-TBLFM) + (buffer-string)))) + (should + (org-string-match-p + "| 2 |\n| 2 |" + (org-test-with-temp-text + "| 2 |\n| |\n#+TBLFM: @>$1=@<" + (org-table-calc-current-TBLFM) (buffer-string)))))