Hi, This patch enables user to applies a temporal TBLFM line where you are in. It is useful when you switch a formula to another. I hope you liked this.
When you have the following table, #+TBLNAME: test2 | 1 | 2 | | | 4 | 5 | | | 7 | 8 | 9 | #+TBLFM: @1$3='(+ 10 7) #+TBLFM: @2$3='(+ 11 9) hitting =C-c C-c= in the 2nd TBLFM line containg "#+TBLFM: @2$3='(+ 11 9)" gives you this result: #+TBLNAME: test2 | 1 | 2 | | | 4 | 5 | 19 | | 7 | 8 | 9 | #+TBLFM: @1$3='(+ 10 7) #+TBLFM: @2$3='(+ 11 9) This patch consists of 4 parts as shown below:
>From e905aea041a2d306a37921797364a9056eadfa48 Mon Sep 17 00:00:00 2001 From: Ippei FURUHASHI <top.tuna+orgm...@gmail.com> Date: Tue, 2 Apr 2013 18:05:46 +0900 Subject: [PATCH 1/4] org.el (org-at-TBLFM-p): Add functon * org.el (org-at-TBLFM-p): Add function. * testing/lisp/test-org-table.el: Add test. --- lisp/org.el | 12 ++++++++++++ testing/lisp/test-org-table.el | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 0 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index 04ce386..ef27944 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -4197,6 +4197,9 @@ (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]" (org-autoload "org-table" '(org-table-begin org-table-blank-field org-table-end))) +(defconst org-TBLFM-regexp "^[ \t]*#\\+TBLFM: " + "Detect a #+TBLFM line.") + ;;;###autoload (defun turn-on-orgtbl () "Unconditionally turn on `orgtbl-mode'." @@ -4291,6 +4294,15 @@ (defun org-table-map-tables (function &optional quietly) (declare-function org-clock-update-mode-line "org-clock" ()) (declare-function org-resolve-clocks "org-clock" (&optional also-non-dangling-p prompt last-valid)) + +(defun org-at-TBLFM-p (&optional pos) + "Return t when point (or POS) is in #+TBLFM line. If not, return nil." + (save-excursion + (let ((pos pos))) + (goto-char (or pos (point))) + (beginning-of-line 1) + (looking-at org-TBLFM-regexp))) + (defvar org-clock-start-time) (defvar org-clock-marker (make-marker) "Marker recording the last clock-in.") diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el index 4c09239..ea8c4d8 100644 --- a/testing/lisp/test-org-table.el +++ b/testing/lisp/test-org-table.el @@ -749,6 +749,25 @@ (defconst references/target-special " ;; "Remote reference." ;; (should ;; (string= "$3 = remote(FOO, @@#$2)" (org-table-convert-refs-to-rc "C& = remote(FOO, @@#B&)")))) +(ert-deftest test-org-table/org-at-TBLFM-p () + (org-test-with-temp-text-in-file + " +| 1 | +| 2 | +#+TBLFM: $2=$1*2 + +" + (goto-char (point-min)) + (forward-line 2) + (should (equal (org-at-TBLFM-p) nil)) + + (goto-char (point-min)) + (forward-line 3) + (should (equal (org-at-TBLFM-p) t)) + + (goto-char (point-min)) + (forward-line 4) + (should (equal (org-at-TBLFM-p) nil)))) (provide 'test-org-table) -- 1.7.9.msysgit.0
>From 37369815b555ba1f2df168ac45c83237c628d609 Mon Sep 17 00:00:00 2001 From: Ippei FURUHASHI <top.tuna+orgm...@gmail.com> Date: Tue, 2 Apr 2013 18:09:26 +0900 Subject: [PATCH 2/4] org-table.el (org-TBLFM-begin): Add function * org-table.el (org-TBLFM-begin): Add function. * testing/lisp/test-org-table.el: Add test. --- lisp/org-table.el | 14 +++++ testing/lisp/test-org-table.el | 123 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 0 deletions(-) diff --git a/lisp/org-table.el b/lisp/org-table.el index f087cf7..78fbb2e 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -52,6 +52,8 @@ (defvar orgtbl-after-send-table-hook nil to the receiver position, otherwise, if table is not sent, the functions are not run.") +(defvar org-TBLFM-begin-regexp "|\n[ \t]*#\\+TBLFM: ") + (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized) "Non-nil means use the optimized table editor version for `orgtbl-mode'. In the optimized version, the table editor takes over all simple keys that @@ -3169,6 +3171,18 @@ (defun org-table-iterate-buffer-tables () (setq checksum c1))) (user-error "No convergence after %d iterations" imax)))))) +(defun org-TBLFM-begin () + "Find the beginning of the TBLFM lines and return its position. +Return nil when the beginning of TBLFM line was not found." + (save-excursion + (if (progn (forward-line 1) + (re-search-backward + org-TBLFM-begin-regexp + nil t)) + (progn (beginning-of-line 2) + (point)) + nil))) + (defun org-table-expand-lhs-ranges (equations) "Expand list of formulas. If some of the RHS in the formulas are ranges or a row reference, expand diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el index ea8c4d8..805f57a 100644 --- a/testing/lisp/test-org-table.el +++ b/testing/lisp/test-org-table.el @@ -769,6 +769,129 @@ (defconst references/target-special " (forward-line 4) (should (equal (org-at-TBLFM-p) nil)))) +(ert-deftest test-org-table/org-TBLFM-begin () + (org-test-with-temp-text-in-file + " +| 1 | +| 2 | +#+TBLFM: $2=$1*2 + +" + (goto-char (point-min)) + (should (equal (org-TBLFM-begin) + nil)) + + (goto-char (point-min)) + (forward-line 1) + (should (equal (org-TBLFM-begin) + nil)) + + (goto-char (point-min)) + (forward-line 3) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 4) + (should (= (org-TBLFM-begin) + 14)) + + )) + +(ert-deftest test-org-table/org-TBLFM-begin-for-multiple-TBLFM-lines () + "For multiple #+TBLFM lines." + (org-test-with-temp-text-in-file + " +| 1 | +| 2 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 + +" + (goto-char (point-min)) + (should (equal (org-TBLFM-begin) + nil)) + + (goto-char (point-min)) + (forward-line 1) + (should (equal (org-TBLFM-begin) + nil)) + + (goto-char (point-min)) + (forward-line 3) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 4) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 5) + (should (= (org-TBLFM-begin) + 14)) + + )) + +(ert-deftest test-org-table/org-TBLFM-begin-for-pultiple-TBLFM-lines-blocks () + (org-test-with-temp-text-in-file + " +| 1 | +| 2 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 + +| 6 | +| 7 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 + +" + (goto-char (point-min)) + (should (equal (org-TBLFM-begin) + nil)) + + (goto-char (point-min)) + (forward-line 1) + (should (equal (org-TBLFM-begin) + nil)) + + (goto-char (point-min)) + (forward-line 3) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 4) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 5) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 6) + (should (= (org-TBLFM-begin) + 14)) + + (goto-char (point-min)) + (forward-line 8) + (should (= (org-TBLFM-begin) + 61)) + + (goto-char (point-min)) + (forward-line 9) + (should (= (org-TBLFM-begin) + 61)) + + (goto-char (point-min)) + (forward-line 10) + (should (= (org-TBLFM-begin) + 61)))) + (provide 'test-org-table) ;;; test-org-table.el ends here -- 1.7.9.msysgit.0
>From 12cd28d44a67f1b3efe666fe981430bf15aafc15 Mon Sep 17 00:00:00 2001 From: Ippei FURUHASHI <top.tuna+orgm...@gmail.com> Date: Tue, 2 Apr 2013 18:11:26 +0900 Subject: [PATCH 3/4] org-table.el (org-calc-current-TBLFM): Add function * org-table.el (org-calc-current-TBLFM): re-calculate the table by applying the #+TBLFM in the line where the point is. * org.el (org-ctrl-c-ctrl-c): Call `org-calc-current-TBLFM' when the point is in the #+TBLFM line. * testing/lisp/test-org-table.el: Add test. --- lisp/org-table.el | 24 ++++++++++++++++++++++++ lisp/org.el | 7 ++++--- testing/lisp/test-org-table.el | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/lisp/org-table.el b/lisp/org-table.el index 78fbb2e..4b97760 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -3171,6 +3171,30 @@ (defun org-table-iterate-buffer-tables () (setq checksum c1))) (user-error "No convergence after %d iterations" imax)))))) +(defun org-calc-current-TBLFM (&optional arg) + "Apply the #+TBLFM in the line to the table." + (interactive "P") + (if (not (org-at-TBLFM-p)) (error "Not at #+TBLFM line")) + (let ((formula (buffer-substring + (point-at-bol) + (point-at-eol))) + s e) + (save-excursion + ;; insert a temporary formula at right after the table + (goto-char (org-TBLFM-begin)) + (setq s (set-marker (make-marker) (point))) + (insert (concat formula "\n")) + (setq e (set-marker (make-marker) (point))) + + ;; recalculate the table + (beginning-of-line 0) ;move to the inserted line + (skip-chars-backward " \r\n\t") + (if (org-at-table-p) + (org-call-with-arg 'org-table-recalculate (or arg t))) + + ;; delete the formula inserted temporarily + (delete-region s e)))) + (defun org-TBLFM-begin () "Find the beginning of the TBLFM lines and return its position. Return nil when the beginning of TBLFM line was not found." diff --git a/lisp/org.el b/lisp/org.el index ef27944..51b8812 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -20174,9 +20174,10 @@ (defun org-ctrl-c-ctrl-c (&optional arg) (and (eq type 'table-row) (= (point) (org-element-property :end context)))) (save-excursion - (goto-char (org-element-property :contents-begin context)) - (org-call-with-arg 'org-table-recalculate (or arg t)) - (orgtbl-send-table 'maybe)) + (if (org-at-TBLFM-p) (org-calc-current-TBLFM) + (goto-char (org-element-property :contents-begin context)) + (org-call-with-arg 'org-table-recalculate (or arg t)) + (orgtbl-send-table 'maybe))) (org-table-maybe-eval-formula) (cond (arg (call-interactively 'org-table-recalculate)) ((org-table-maybe-recalculate-line)) diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el index 805f57a..dda8561 100644 --- a/testing/lisp/test-org-table.el +++ b/testing/lisp/test-org-table.el @@ -892,6 +892,43 @@ (defconst references/target-special " (should (= (org-TBLFM-begin) 61)))) +(ert-deftest test-org-table/org-calc-current-TBLFM () + (org-test-with-temp-text-in-file + " +| 1 | | +| 2 | | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +#+TBLFM: $2=$1*3 +" + (let ((got (progn (goto-char (point-min)) + (forward-line 3) + (org-calc-current-TBLFM) + (buffer-string))) + (expect " +| 1 | 1 | +| 2 | 2 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +#+TBLFM: $2=$1*3 +")) + (should (string= got + expect))) + + (let ((got (progn (goto-char (point-min)) + (forward-line 4) + (org-calc-current-TBLFM) + (buffer-string))) + (expect " +| 1 | 2 | +| 2 | 4 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +#+TBLFM: $2=$1*3 +")) + (should (string= got + expect))))) + (provide 'test-org-table) ;;; test-org-table.el ends here -- 1.7.9.msysgit.0
>From 34b2661238801fa99a284ea500a32f6d5c68c52d Mon Sep 17 00:00:00 2001 From: Ippei FURUHASHI <top.tuna+orgm...@gmail.com> Date: Tue, 2 Apr 2013 17:12:02 +0900 Subject: [PATCH 4/4] doc/org.texi: Document applying current TBLFM to table * org.texi (Editing and debugging formulas): Document an example when a table has multiple #+TBLFM lines. --- doc/org.texi | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 53 insertions(+), 0 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 6791570..7c0e17f 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -3003,6 +3003,52 @@ @subsection Editing and debugging formulas equations with @kbd{C-c C-c} in that line or with the normal recalculation commands in the table. +@anchor{Using multiple #+TBLFM lines} +@subsubheading Using multiple #+TBLFM lines +@cindex #+TBLFM line, multiple +@cindex #+TBLFM +@cindex #+TBLFM, switching +@kindex C-c C-c + +You may apply the formula temporarily. This is useful when you +switch the formula. Place multiple @samp{#+TBLFM} lines right +after the table, and then press @kbd{C-c C-c} on the formula to +apply. Here is an example: + +@example +| x | y | +|---+---| +| 1 | | +| 2 | | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +@end example + +@noindent +Pressing @kbd{C-c C-c} in the line of @samp{#+TBLFM: $2=$1*2} yields: + +@example +| x | y | +|---+---| +| 1 | 2 | +| 2 | 4 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +@end example + +@noindent +Note: If you recalculate this table (with @kbd{C-u C-c *}, for example), you +will get the following result of applying only the first @samp{#+TBLFM} line. + +@example +| x | y | +|---+---| +| 1 | 1 | +| 2 | 2 | +#+TBLFM: $2=$1*1 +#+TBLFM: $2=$1*2 +@end example + @subsubheading Debugging formulas @cindex formula debugging @cindex debugging, of table formulas @@ -14889,8 +14935,15 @@ @section Summary of in-buffer settings These lines (several such lines are allowed) specify the valid tags in this file, and (potentially) the corresponding @emph{fast tag selection} keys. The corresponding variable is @code{org-tag-alist}. +@cindex #+TBLFM @item #+TBLFM: This line contains the formulas for the table directly above the line. + +Table can have multiple lines containing @samp{#+TBLFM:}. Note +that only the first line of @samp{#+TBLFM:} will be applied when +you reculculate the table. For more details see @ref{Using +multiple #+TBLFM lines} in @ref{Editing and debugging formulas}. + @item #+TITLE:, #+AUTHOR:, #+EMAIL:, #+LANGUAGE:, #+DATE:, @itemx #+OPTIONS:, #+BIND:, @itemx #+DESCRIPTION:, #+KEYWORDS:, -- 1.7.9.msysgit.0
Thanks, IP