emacs-orgmode
[Top][All Lists]
Advanced

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

Re: [PATCH] Add support for tables in Calc src block :var


From: Visuwesh
Subject: Re: [PATCH] Add support for tables in Calc src block :var
Date: Fri, 13 Dec 2024 13:01:38 +0530
User-agent: Gnus/5.13 (Gnus v5.13)

Sorry for getting back after so long!

[புதன் ஏப்ரல் 03, 2024] Fraga, Eric wrote:

> On Saturday, 30 Mar 2024 at 18:34, Visuwesh wrote:
>>> Specifically, I would love to make reference to calc variables,
>>> especially those defined using embedded calc, in org tables.
>>
>> Can you please provide a minimal example for me to play around with?  I
>> realise I would like something like this too [*] but I don't know
>> concretely what this would/should look like.
>
> So, embedded calc processes expressions in any buffer, including org
> mode, which might look like this:
>
> x := 3
>
> y := 5
>
> z := 3 x - y => 4
>
> where, in this case, the value of z has been determined by calc and the
> answer given after the => in the line.  The beauty of embedded calc is
> you can change the value of x and the subsequent expressions will be
> updated automatically (well, with C-x * u).
>
> I would then love to be able to have a table that would allow me to
> include the value of any variable, e.g. z above, something like
>
> | var | value |
> |-----+-------|
> | x   |     3 |
> | z   |     4 |
>
> where the values in the second column are obtained by querying Calc.

Here's a hack I cooked up:

    (defun vz/calc-embedded-get-var (var)
      "Return the value of active `calc-embedded' VAR in current buffer."
      (let* ((info (cdr (assq (current-buffer) calc-embedded-active)))
             (var-info
              (seq-find
               (lambda (x)
                 ;; 9 is the variable name: (var XXX var-XXX)
                 (eq var (nth 1 (aref x 9))))
               info))
             old-val)
        (when (and info var-info)
          ;; This is called the `old-val' in `calc-embedded-update'.
          ;; This can be nil when the formula isn't evaled I think?
          ;; (aref VAR-INFO 8) is again repeated in 11th slot when the
          ;; variable is simply as assignment.
          (or (if (consp (setq old-val (aref var-info 11)))
                  (car (last old-val))
                old-val)
              ;; 8 is the eval form: (calcFun-evalto ...) or
              ;; (calcFun-assign ...)
              (car (last (aref var-info 8)))))))

    (define-advice org-table-get-constant (:around (oldfun name) 
vz/consider-calc-embedded-var)
      "Check if NAME is a `calc-embedded' at last."
      (let ((val (funcall oldfun name)))
        (if (equal val "#UNDEFINED_NAME")
            (or (number-to-string (vz/calc-embedded-get-var (intern name)))
                val)
          val)))

Some caveats:

  1. You need to ensure that all the calc-embedded variables that you
     use in the formula need to be active and evaluated beforehand.
  2. The calc-embedded var is considered at last after everything else
     in org-table-get-constant in the advice.  This would be the best
     way to go forward.

It would be nice to lift the restrict in (1) but I think it would be
better to leave it to the user to ensure everything stays updated since
the user may want to use the old value.  However, ensuring all the vars
are active and eval-ed would be a royal pain when you're quickly
evaluating a table formula.

Here's the case I used to test this hack:

    x := 3

    y := 5

    z := 5 x - y => 10


    | 1 | 20 |
    #+TBLFM: $2=$z*2



reply via email to

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