diff options
Diffstat (limited to 'tex/context/base/m-spreadsheet.mkiv')
-rw-r--r-- | tex/context/base/m-spreadsheet.mkiv | 295 |
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] |