emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[O] [PATCH] Was: How to apply multiple TBLFM rules?


From: Ippei FURUHASHI
Subject: [O] [PATCH] Was: How to apply multiple TBLFM rules?
Date: Tue, 02 Apr 2013 22:33:27 +0900
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (windows-nt)

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 <address@hidden>
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 <address@hidden>
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 <address@hidden>
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 <address@hidden>
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.
 
address@hidden multiple #+TBLFM lines}
address@hidden Using multiple #+TBLFM lines
address@hidden #+TBLFM line, multiple
address@hidden #+TBLFM
address@hidden #+TBLFM, switching
address@hidden 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:
+
address@hidden
+| x | y |
+|---+---|
+| 1 |   |
+| 2 |   |
+#+TBLFM: $2=$1*1
+#+TBLFM: $2=$1*2
address@hidden example
+
address@hidden
+Pressing @kbd{C-c C-c} in the line of @samp{#+TBLFM: $2=$1*2} yields:
+
address@hidden
+| x | y |
+|---+---|
+| 1 | 2 |
+| 2 | 4 |
+#+TBLFM: $2=$1*1
+#+TBLFM: $2=$1*2
address@hidden example
+
address@hidden
+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.
+
address@hidden
+| x | y |
+|---+---|
+| 1 | 1 |
+| 2 | 2 |
+#+TBLFM: $2=$1*1
+#+TBLFM: $2=$1*2
address@hidden 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}.
address@hidden #+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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]