Browse Source

org-capture: Fix formulas when capturing rows

* lisp/org-capture.el (org-capture-finalize): Possibly update formula
  when inserting the captured rows in the table.

* testing/lisp/test-org-capture.el (test-org-capture/table-line): Add
  tests.

Reported-by: "Holst Thomas (PS-EC/ESE4)" <Thomas.Holst@de.bosch.com>
<http://lists.gnu.org/r/emacs-orgmode/2018-06/msg00276.html>
Nicolas Goaziou 6 years ago
parent
commit
031c53103a
2 changed files with 50 additions and 4 deletions
  1. 17 3
      lisp/org-capture.el
  2. 33 1
      testing/lisp/test-org-capture.el

+ 17 - 3
lisp/org-capture.el

@@ -57,6 +57,7 @@
 (declare-function org-encrypt-entry "org-crypt" ())
 (declare-function org-table-analyze "org-table" ())
 (declare-function org-table-current-dline "org-table" ())
+(declare-function org-table-fix-formulas "org-table" (key replace &optional limit delta remove))
 (declare-function org-table-goto-line "org-table" (N))
 
 (defvar dired-buffers)
@@ -65,6 +66,7 @@
 (defvar org-remember-templates)
 (defvar org-table-border-regexp)
 (defvar org-table-current-begin-pos)
+(defvar org-table-fix-formulas-confirm)
 (defvar org-table-hlines)
 
 (defvar org-capture-clock-was-started nil
@@ -763,9 +765,21 @@ captured item after finalizing."
 	;; If we have added a table line, maybe recompute?
 	(when (and (eq (org-capture-get :type 'local) 'table-line)
 		   (org-at-table-p))
-	  (if (org-table-get-stored-formulas)
-	      (org-table-recalculate 'all) ;; FIXME: Should we iterate???
-	    (org-table-align))))
+	  (if (not (org-table-get-stored-formulas)) (org-table-align)
+	    ;; Adjust formulas, if necessary.  We assume a non-nil
+	    ;; `:immediate-finish' means that no confirmation is
+	    ;; required.  Else, obey `org-table-fix-formulas-confirm'.
+	    ;;
+	    ;; The delta required to fix formulas depends on the
+	    ;; number of rows inserted by the template.
+	    (when (or (org-capture-get :immediate-finish)
+		      (not org-table-fix-formulas-confirm)
+		      (funcall org-table-fix-formulas-confirm "Fix formulas? "))
+	      (org-table-fix-formulas
+	       "@" nil (1- (org-table-current-dline))
+	       (count-lines (org-capture-get :begin-marker 'local)
+			    (org-capture-get :end-marker 'local))))
+	    (org-table-recalculate 'all)))) ;FIXME: should we iterate?
       ;; Store this place as the last one where we stored something
       ;; Do the marking in the base buffer, so that it makes sense after
       ;; the indirect buffer has been killed.

+ 33 - 1
testing/lisp/test-org-capture.el

@@ -300,7 +300,39 @@
 	     `(("t" "Table" table-line (file ,file)
 		"| x |" :immediate-finish t :table-line-pos "II+99"))))
        (org-capture nil "t")
-       t))))
+       t)))
+  ;; Update formula when capturing one or more rows.
+  (should
+   (equal
+    '(("@3$1" . "9"))
+    (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
+      (let* ((file (buffer-file-name))
+	     (org-capture-templates
+	      `(("t" "Table" table-line (file ,file)
+		 "| 2 |" :immediate-finish t :table-line-pos "I-1"))))
+	(org-capture nil "t")
+	(org-table-get-stored-formulas)))))
+  (should
+   (equal
+    '(("@4$1" . "9"))
+    (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
+      (let* ((file (buffer-file-name))
+	     (org-capture-templates
+	      `(("t" "Table" table-line (file ,file)
+		 "| 2 |\n| 3 |" :immediate-finish t :table-line-pos "I-1"))))
+	(org-capture nil "t")
+	(org-table-get-stored-formulas)))))
+  ;; Do not update formula when cell in inserted below affected row.
+  (should-not
+   (equal
+    '(("@3$1" . "9"))
+    (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
+      (let* ((file (buffer-file-name))
+	     (org-capture-templates
+	      `(("t" "Table" table-line (file ,file)
+		 "| 2 |" :immediate-finish t))))
+	(org-capture nil "t")
+	(org-table-get-stored-formulas))))))
 
 
 (provide 'test-org-capture)