Re: [PATCH] lisp/org-table.el: Allow named columns on lhs

2023-08-31 Thread Gavin Downard
Ihor Radchenko  writes:
> It has been over one month since the last message in this thread.
> Gavin, may I know if you are still interested to work on the patch?

Apologies for the lack of communication. I do plan on working on this
patch in the near future.



Re: [PATCH] lisp/org-table.el: Allow named columns on lhs

2023-07-26 Thread Gavin Downard
Max Nikulin  writes:
> The regexp for parsing formulas does not allow named references after @.
> I have no idea if other code should be modified as well. I consider it
> as more important than detection of duplicated definitions.

Yeah, besides changing the regexp, the main thing that will need to be
changed is the interface of `org-table-get-stored-formulas'. Currently,
a field name on the lhs can only exist by itself (that is, it can't be a
part of any other expression, such as a range), so the leading '$' is
removed. So, '$name=1+2' is parsed as '("name" . "1+2")'. This is at
odds with field/column names in the middle of an expression.

I think the best way to do this is to change
`org-table-get-stored-formulas' to not strip the leading '$', and
instead of using '(assoc FIELD-NAME org-table-named-field-locations)' or
'(assoc COL-NAME org-table-column-names)', we can a modified* version of
`org-table-formula-substitute-names' (which is used for field and column
names on the rhs of a formula). That would work as a replacement for the
existent handling of field names that would also work for column names
as we want them.

As a side note, this would allow ranges on the lhs that contain field
names in them:

|   | 1 | 2 |   3 |
| # |   |   | |
| ^ | begin |   | end |
#+TBLFM: $begin..$end=@1*@1

(*): the issue with `org-table-formula-substitute-names' as it is, is
that it will replace field names with the field /value/, not the field
index. Hopefully modifying the function to replace field names with
their indices won't break anything, so we can use the same function for
both sides of the formula.

> A crazy idea: several columns may have the same name:
>
> |   | Jun sum | Jun count | Jun avg | Jul sum | Jul count | Jul avg |
> | ! | |   | average | |   | average |
> |---+-+---+-+-+---+-|
> |   |  150| 10| | 200 |14 | |
>
> #+tblfm: $average=$-2/$-1
>
> It has no sense for numeric references but with names it can help to
> avoid repeated expressions.

Or, if you want to get really crazy, we can let fields and columns with
the same name share a formula. :)

| ! | Apple budget |  Pear Budget | Orange Budget | total |
|---+--+--+---+---|
| # |1 |2 | 3 | 6 |
| # |4 |5 | 6 |15 |
|---+--+--+---+---|
| # |2 |3 | 5 |26 |
| ^ | extra-cost-1 | extra-cost-2 | total | ultimatetotal |
#+TBLFM: $total=vsum($<<..$-1) :: $ultimatetotal=vsum(@I..II) + $-1

But in all seriousness, that does seem like it could be useful. I guess
on the rhs we could give each of those "shared names" the value of an array of
that name's connected columns (or fields). But I think support for that should
probably be added in a separate patch, since it's a bit separate from
the main issue.



Re: [PATCH] lisp/org-table.el: Allow named columns on lhs

2023-07-25 Thread Gavin Downard
Max Nikulin  writes:
> I have tried the patch. The formula for the named column "$three=" does
> not work.
>
> | ! | one | two | three | four |
> |---+-+-+---+--|
> | # |   1 |   2 |   |3 |
>
> #+tblfm: @>$5=$one+$two::@>$three=$one+$two

Yeah, I guess my current patch only supports column names in column
formulas. Allowing column names inside of arbitrary references will take
some more comprehensive changes. I'll see what I can do.



Re: [PATCH] lisp/org-table.el: Allow named columns on lhs

2023-07-23 Thread Gavin Downard
Ihor Radchenko  writes:
> Do we have any tests covering this part of the code?

Not that I know of. I can add a test case for this specific instance,
but I'm not sure if I should add more comprehensive tests in this patch.
What do you think?

> In Emacs 26, we will need (require 'subr-x), but otherwise it is not a
> problem to use `if-let'.

Oh, I didn't realize that. Sorry about that.



Re: [PATCH] lisp/org-table.el: Allow named columns on lhs

2023-07-22 Thread Gavin Downard
Max Nikulin  writes:
> On 19/07/2023 09:36, Gavin Downard wrote:
>> +++ b/lisp/org-table.el
>> @@ -2253,8 +2253,7 @@ LOCATION is a buffer position, consider the formulas 
>> there."
>>  ((not (match-end 2)) m)
>>  ;; Is it a column reference?
>>  ((string-match-p "\\`\\$\\([0-9]+\\|[<>]+\\)\\'" m) m)
>> -;; Since named columns are not possible in
>> -;; LHS, assume this is a named field.
>> +;; This is either a named field or column.
>>  (t (match-string 2 string)
>>  (rhs (match-string 3 string)))
>>  (push (cons lhs rhs) eq-alist)
>
> Notice
>  "Double definition `%s=' in TBLFM line, please fix by hand"
>
> below. A bit more code is required to keep this sanity check for named 
> columns.
>

Oh, good catch. Specifically, I think this should be caught inside of
`org-table-recalculate', where it catches conflicting direct column
references (eg "$1") and end-relative column references ("$<").
>   let* ((rhs (org-table-formula-substitute-names
>(org-table-formula-handle-first/last-rc (cdr eq
>  (old-lhs (car eq))
>  (lhs
>   (org-table-formula-handle-first/last-rc
>(cond
> ((string-match "\\`@-?I+" old-lhs)
>  (user-error "Can't assign to hline relative reference"))
> ((string-match "\\`\\$[<>]" old-lhs)
>  (let ((new (org-table-formula-handle-first/last-rc
>  old-lhs)))
>(when (assoc new eqlist)
>  (user-error "\"%s=\" formula tries to overwrite \
> existing formula for column %s"
^ right here
>  old-lhs
>  new))
>new))
> (t old-lhs)

Also, this should probably be addressed in a different patch, but the
above code doesn't catch two different end-relative column references
that refer to the same column, such as "$<" and "$>>" in a two-column table.

I have also modified the manual to reflect the addition of named
columns; I'll send an updated patch after I add the check for double 
definitions.

Max Nikulin  writes:
>
> `if-let' is not available in Emacs-26
>

Are you sure? It looks like `if-let' was introduced in Emacs 25.



Re: [PATCH] lisp/org-table.el: Allow named columns on lhs

2023-07-21 Thread Gavin Downard


Max Nikulin  writes:
> When I tried table formulas a couple of years ago I was surprised that it is 
> not
> possible to use column names to specify target cells. At first glance it 
> should
> be a great feature. Have you searched the mailing list archive whether it was
> requested earlier? There are might be reasons why it has not been implemented.
> Org spreadsheets are quite complicated.

Surprisingly, I wasn't able to find much. Generally all I could find
talked about hline references , which are similarly unsupported.



[PATCH] lisp/org-table.el: Allow named columns on lhs

2023-07-18 Thread Gavin Downard
This patch does prioritize named columns over named fields, which can
break compatibility in tables with a named column and named field with
the same name. Alternatively, we could prioritize named fields to
preserve compatibility, but since named columns are prioritized on the
rhs, it could be pretty confusing.

>From c6ebbf02e0cb89839606338e8bbc4032810ea398 Mon Sep 17 00:00:00 2001
From: Gavin Downard 
Date: Sat, 1 Jul 2023 13:26:46 -0700
Subject: [PATCH] lisp/org-table.el: Allow named columns on lhs

* lisp/org-table.el (org-table-recalculate): Add support for named
columns on the lhs of spreadsheet formulas, prioritizing named columns
over named fields if there is a conflict.
(org-table-edit-formulas): Modify category name to include column
formulas with field formulas.
(org-table-get-stored-formulas): Remove comment mentioning lack of named
columns in the lhs.
* testing/lisp/test-org-table.el (test-org-table/named-column): Add test
case for named columns.
* etc/ORG-NEWS (Spreadsheets now support named columns on the lhs):
Document the change

This change breaks compatibility in tables with a named field and named
column with the same name, when that name is used on the lhs of a formula.
---
 etc/ORG-NEWS   | 4 
 lisp/org-table.el  | 9 +
 testing/lisp/test-org-table.el | 9 +
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index a4725ae8c..42f39fd45 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -534,6 +534,10 @@ special repeaters ~++~ and ~.+~ are skipped.
 A capture template can target ~(here)~ which is the equivalent of
 invoking a capture template with a zero prefix.
 
+*** Spreadsheets now support named columns on the lhs
+
+Spreadsheet formulas can now use named column references on the lhs.
+
 ** New functions and changes in function arguments
 *** =TYPES= argument in ~org-element-lineage~ can now be a symbol
 
diff --git a/lisp/org-table.el b/lisp/org-table.el
index c5efe8f0c..34b0a562e 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -2253,8 +2253,7 @@ LOCATION is a buffer position, consider the formulas there."
 			((not (match-end 2)) m)
 			;; Is it a column reference?
 			((string-match-p "\\`\\$\\([0-9]+\\|[<>]+\\)\\'" m) m)
-			;; Since named columns are not possible in
-			;; LHS, assume this is a named field.
+			;; This is either a named field or column.
 			(t (match-string 2 string)
 		(rhs (match-string 3 string)))
 		(push (cons lhs rhs) eq-alist)
@@ -2963,7 +2962,9 @@ existing formula for column %s"
 		  (t old-lhs)
 	  (if (string-match-p "\\`\\$[0-9]+\\'" lhs)
 		  (push (cons lhs rhs) eqlcol)
-		(push (cons lhs rhs) eqlfield
+(if-let ((named-column (assoc lhs org-table-column-names)))
+(push (cons (concat "$" (cdr named-column)) rhs) eqlcol)
+  (push (cons lhs rhs) eqlfield)
 	  (setq eqlcol (nreverse eqlcol))
 	  ;; Expand ranges in lhs of formulas
 	  (setq eqlfield (org-table-expand-lhs-ranges (nreverse eqlfield)))
@@ -3355,7 +3356,7 @@ Parameters get priority."
 	  (sel-win (selected-window))
 	  (titles '((column . "# Column Formulas\n")
 		(field . "# Field and Range Formulas\n")
-		(named . "# Named Field Formulas\n"
+		(named . "# Named Field and Named Column Formulas\n"
   (org-switch-to-buffer-other-window "*Edit Formulas*")
   (erase-buffer)
   ;; Keep global-font-lock-mode from turning on font-lock-mode
diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el
index 27aeb5ab3..8cd01049a 100644
--- a/testing/lisp/test-org-table.el
+++ b/testing/lisp/test-org-table.el
@@ -2158,6 +2158,15 @@ See also `test-org-table/copy-field'."
 | ! | name |   |
 |   |1 |   |
 #+TBLFM: @2$3=$name"
+  (org-table-calc-current-TBLFM)
+  (buffer-string
+  (should
+   (string-match-p
+"| +# +| +1 +| +1 +|"
+(org-test-with-temp-text "
+| ! | lhs | rhs |
+| # | |   1 |
+#+TBLFM: $lhs=$rhs"
   (org-table-calc-current-TBLFM)
   (buffer-string)
 
-- 
2.40.1