summaryrefslogtreecommitdiff
path: root/tex/context/base/m-spreadsheet.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/m-spreadsheet.mkiv')
-rw-r--r--tex/context/base/m-spreadsheet.mkiv295
1 files changed, 172 insertions, 123 deletions
diff --git a/tex/context/base/m-spreadsheet.mkiv b/tex/context/base/m-spreadsheet.mkiv
index ed9a92d05..839214096 100644
--- a/tex/context/base/m-spreadsheet.mkiv
+++ b/tex/context/base/m-spreadsheet.mkiv
@@ -13,139 +13,192 @@
%D This is an experimental follow up on discussion on the mailing list.
-\registerctxluafile{m-spreadsheet}{1.001}
+\startluacode
+local byte, format = string.byte, string.format
+local R, P, C, Cs, Cc, Carg, lpegmatch = lpeg.R, lpeg.P, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match
+
+local spreadsheets = { }
+moduledata.spreadsheets = spreadsheets
+
+local data = { }
+spreadsheets.data = data
+
+local stack, current = { }, "default"
+
+local mt ; mt = {
+ __index = function(t,k)
+ local v = { }
+ setmetatable(v,mt)
+ t[k] = v
+ return v
+ end,
+}
+
+function spreadsheets.reset(name)
+ if not name or name == "" then name = "default" end
+ local d = { }
+ setmetatable(d,mt)
+ data[name] = d
+end
+
+function spreadsheets.start(name)
+ if not name or name == "" then name = "default" end
+ table.insert(stack,current)
+ current = name
+ if not data[current] then
+ local d = { }
+ setmetatable(d,mt)
+ data[current] = d
+ end
+end
+
+function spreadsheets.stop()
+ current = table.remove(stack)
+end
+
+spreadsheets.reset()
+
+local offset = byte("A") - 1
+
+local function assign(s,n)
+ return format("moduledata.spreadsheets.data['%s'][%s]",n,byte(s)-offset)
+end
+
+-------- datacell(name,a,b,...)
+function datacell(a,b,...)
+ local n = 0
+ if b then
+ local t = { a, b, ... }
+ for i=1,#t do
+ n = n * (i-1) * 26 + byte(t[i]) - offset
+ end
+ else
+ n = byte(a) - offset
+ end
+ -- return format("dat['%s'][%s]",name,n)
+ return format("dat[%s]",n)
+end
+
+----- cell = (Carg(1) * C(R("AZ"))^1) / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1))
+local cell = C(R("AZ"))^1 / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1))
+local pattern = Cs(Cc("return ") * (cell + P(1))^0)
+
+local functions = { }
+spreadsheets.functions = functions
+
+function functions.sum(c,f,t)
+ if f and t then
+ local r = 0
+ for i=f,t do
+ r = r + c[i]
+ end
+ return r
+ else
+ return 0
+ end
+end
+
+function functions.fmt(pattern,n)
+ return format("%"..pattern,n)
+end
+
+local template = [[
+ local spr = moduledata.spreadsheets.functions
+ local dat = moduledata.spreadsheets.data['%s']
+ local sum = spr.sum
+ local fmt = spr.fmt
+ %s
+]]
+
+local function execute(name,r,c,str)
+ if name == "" then name = current if name == "" then name = "default" end end
+ str = lpegmatch(pattern,str,1,name)
+ str = format(template,name,str)
+ -- print(str)
+ local result = loadstring(str)
+ result = result and result() or 0
+ data[name][c][r] = result
+ return result
+end
+
+function spreadsheets.set(name,r,c,str)
+ if name == "" then name = current if name == "" then name = "default" end end
+ execute(name,r,c,str)
+end
+
+function spreadsheets.get(name,r,c,str)
+ if name == "" then name = current if name == "" then name = "default" end end
+ if not str or str == "" then
+ context(data[name][c][r] or 0)
+ else
+ local result = execute(name,r,c,str)
+ if result then
+ if type(result) == "number" then
+ data[name][c][r] = result
+ end
+ context(result)
+ end
+ end
+end
+
+function spreadsheets.doifelsecell(name,r,c)
+ if name == "" then name = current if name == "" then name = "default" end end
+ local d = data[name]
+ commands.testcase(d and d[c][r])
+end
+
+function spreadsheets.show(name)
+ if name == "" then name = current if name == "" then name = "default" end end
+ table.print(data[name],name)
+end
+\stopluacode
\unprotect
% todo: get(...) set(..) ctx(...)
-\installcorenamespace{spreadsheet}
-
-\installcommandhandler \??spreadsheet {spreadsheet} \??spreadsheet
-
-\appendtoks
- \ctxlua{moduledata.spreadsheets.setup{ % global !
- period = "\spreadsheetparameter\c!period",
- comma = "\spreadsheetparameter\c!comma",
- split = "\spreadsheetparameter\c!split",
- }}%
-\to \everysetupspreadsheet
-
-\setupspreadsheet
- [%\c!comma=,
- %\c!period=,
- \c!split=\v!no]
-
-\unexpanded\def\resetspreadsheet
- {\dosingleempty\module_spreadsheet_reset}
-
-\unexpanded\def\module_spreadsheet_reset[#1]%
- {\ctxlua{moduledata.spreadsheets.reset("#1")}}
-
-\unexpanded\def\startspreadsheet
- {\dosingleempty\module_spreadsheet_start}
-
-\unexpanded\def\module_spreadsheet_start[#1]%
- {\pushmacro\currentspreadsheet
- \edef\currentspreadsheet{#1}%
- \checkspreadsheetparent
- \edef\m_spreadsheet_period{\spreadsheetparameter\c!period}%
- \edef\m_spreadsheet_comma {\spreadsheetparameter\c!comma}%
- \ctxlua{moduledata.spreadsheets.start("#1", {
- period = \!!bs\detokenize\expandafter{\m_spreadsheet_period}\!!es,
- comma = \!!bs\detokenize\expandafter{\m_spreadsheet_comma}\!!es,
- split = "\spreadsheetparameter\c!split",
- })}}
-
-\unexpanded\def\stopspreadsheet
- {\ctxlua{moduledata.spreadsheets.stop()}%
- \popmacro\currentspreadsheet}
-
-\unexpanded\def\showspreadsheet
- {\dosingleempty\module_spreadsheet_show}
-
-\unexpanded\def\module_spreadsheet_show[#1]%
- {\ctxlua{moduledata.spreadsheets.tocontext("#1")}}
-
-\unexpanded\def\inspectspreadsheet
- {\dosingleempty\module_spreadsheet_inspect}
-
-\unexpanded\def\module_spreadsheet_inspect[#1]%
- {\ctxlua{moduledata.spreadsheets.inspect("#1")}}
-
-\unexpanded\def\setspreadsheet
- {\dosingleempty\module_spreadsheet_set}
-
-\unexpanded\def\module_spreadsheet_set[#1]#2#3#4%
- {\ctxlua{moduledata.spreadsheets.set("#1",\number#2,\number#3,"#4")}}
-
-\unexpanded\def\getspreadsheet
- {\dosingleempty\module_spreadsheet_get}
-
-\unexpanded\def\module_spreadsheet_get[#1]#2#3#4%
- {\ctxlua{moduledata.spreadsheets.get("#1",\number#2,\number#3,"#4")}}
-
-\unexpanded\def\doifelsespreadsheetcell
- {\dosingleempty\module_spreadsheet_doifelse_cell}
-
-\unexpanded\def\module_spreadsheet_doifelse_cell[#1]#2#3%
- {\ctxlua{moduledata.spreadsheets.doifelsecell("#1",\number#2,\number#3)}}
-
-\ifdefined\tblrow
-
- \def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
- \def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
-
-\else
-
- \def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\c_tabl_ntb_row+1,\number\c_tabl_ntb_col,\!!bs#1\!!es)}}
- \def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\c_tabl_ntb_row+1,\number\c_tabl_ntb_col,\!!bs#1\!!es)}}
-
-\fi
+\unexpanded\def\resetspreadsheet {\dosingleempty\doresetspreadsheet}
+\unexpanded\def\doresetspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.reset("#1")}}
+\unexpanded\def\startspreadsheet {\dosingleempty\dostartspreadsheet}
+\unexpanded\def\dostartspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.start("#1")}}
+\unexpanded\def\stopspreadsheet {\ctxlua{moduledata.spreadsheets.stop()}}
+\unexpanded\def\showspreadsheet {\dosingleempty\doshowspreadsheet}
+\unexpanded\def\doshowspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.show("#1")}}
+\unexpanded\def\getspreadsheet {\dosingleempty\dogetspreadsheet}
+\unexpanded\def\dosetspreadsheet [#1]#2#3#4{\ctxlua{moduledata.spreadsheets.set ("#1",\number#2,\number#3,"#4")}}
+\unexpanded\def\setspreadsheet {\dosingleempty\dosetspreadsheet}
+\unexpanded\def\dogetspreadsheet [#1]#2#3#4{\ctxlua{moduledata.spreadsheets.get ("#1",\number#2,\number#3,"#4")}}
+\unexpanded\def\doifelsespreadsheetcell {\dosingleempty\dodoifelsespreadsheetcell}
+\unexpanded\def\dodoifelsespreadsheetcell[#1]#2#3{\ctxlua{moduledata.spreadsheets.doifelsecell("#1","#2","#3")}}
+
+\def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
+\def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
\appendtoks
- \module_spreadsheet_reset[\currentspreadsheet]%
+ \resetspreadsheet
\let\setspr\TABLEsetspreadsheet
\let\getspr\TABLEgetspreadsheet
\to \everyTABLEpass
\unexpanded\def\startspreadsheettable % quick and dirty
- {\dodoubleempty\module_spreadsheet_start_table}
+ {\dosingleempty\dostartspreadsheettable}
-\unexpanded\def\module_spreadsheet_start_table[#1][#2]%
+\unexpanded\def\dostartspreadsheettable[#1]%
{\bgroup
- \let\startrow \module_spreadsheet_row_start
- \let\stoprow \module_spreadsheet_row_stop
- \let\startcell\module_spreadsheet_cell_start
- \let\stopcell \module_spreadsheet_cell_stop
- \doifassignmentelse{#1}
- {\module_spreadsheet_start
- \bTABLE[\c!align=\v!flushright,#1]}
- {\module_spreadsheet_start[#1]%
- \bTABLE[\c!align=\v!flushright,#2]}}
+ \startspreadsheet[#1]%%
+ \def\startrow{\bTR}%
+ \def\stoprow {\eTR}%
+ \def\startcell##1\stopcell{\bTD\getspr{##1}\eTD}%
+ \bTABLE[\c!align=flushright]}
\unexpanded\def\stopspreadsheettable
{\eTABLE
\stopspreadsheet
\egroup}
-\unexpanded\def\module_spreadsheet_row_start{\bTR}
-\unexpanded\def\module_spreadsheet_row_stop {\eTR}
-
-\unexpanded\def\module_spreadsheet_cell_start
- {\doifnextoptionalelse\module_spreadsheet_cell_start_yes\module_spreadsheet_cell_start_nop}
-
-\unexpanded\def\module_spreadsheet_cell_start_yes[#1]#2\stopcell
- {\bTD[#1]\getspr{#2}\eTD}
-
-\unexpanded\def\module_spreadsheet_cell_start_nop#1\stopcell
- {\bTD\getspr{#1}\eTD}
-
-\let\module_spreadsheet_cell_stop\relax
-
\protect
-\continueifinputfile{m-spreadsheet.mkiv}
+\doifnotmode{demo}{\endinput}
\starttext
@@ -167,12 +220,10 @@
\bTD[nx=2] \bf \getspr{string.format("\letterpercent0.3f",(A[3] + B[3]) /100)} \eTD
\eTR
\bTR
- \bTD[nx=2] \bf \getspr{fmt("@0.3f",(sum(A,1,2)) / 10)} \eTD
+ \bTD[nx=2] \bf \getspr{fmt("0.3f",(sum(A,1,2)) / 10)} \eTD
\eTR
\eTABLE
-\setupspreadsheet[mysheet]
-
\startspreadsheet[mysheet]
\bTABLE[align=middle]
@@ -180,7 +231,7 @@
\bTD \getspr{100} \eTD \bTD test \setspr{30} \eTD
\eTR
\bTR
- \bTD \getspr{20} \eTD \bTD \getspr{4+3.5} \eTD
+ \bTD \getspr{20} \eTD \bTD \getspr{4+3} \eTD
\eTR
\bTR
\bTD \getspr{A[1] + A[2]} \eTD
@@ -193,19 +244,17 @@
\stopspreadsheet
-\blank
-
-\setupspreadsheet[test][period={{\bf\middlered .}},comma={{\bf\middlegreen ,}},split=yes]
-
-\startspreadsheettable[test]
+\startspreadsheettable
\startrow
- \startcell 123456.78 \stopcell
- \startcell 1234567.89 \stopcell
+ \startcell 3 \stopcell
+ \startcell 9 \stopcell
\startcell A[1] + B[1] \stopcell
\stoprow
\stopspreadsheettable
-\blank
+bla bla \getspreadsheet[mysheet]{2}{2}{}
+
+bla bla \getspreadsheet[mysheet]{4}{1}{}
% \showspreadsheet
% \showspreadsheet[mysheet]