summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua
Initial commit
Diffstat (limited to 'macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua')
-rw-r--r--macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua279
1 files changed, 279 insertions, 0 deletions
diff --git a/macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua b/macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua
new file mode 100644
index 0000000000..99314dd0bf
--- /dev/null
+++ b/macros/luatex/latex/wallcalendar/wallcalendar-helpers.lua
@@ -0,0 +1,279 @@
+-- paths are relative to wallcalendar.cls
+local csv = require("wallcalendar-csv.lua")
+local date = require("wallcalendar-date.lua")
+local tp = tex.print
+local tsp = tex.sprint
+
+function loadCsv(csv_path)
+ local f = csv.open(csv_path, {separator = ";", header = true})
+ local data = {}
+ for fields in f:lines() do
+ data[#data + 1] = fields
+ end
+ return data
+end
+
+function ok(x)
+ return x ~= nil and x ~= ""
+end
+
+function hasNote(event)
+ return ok(event.note)
+end
+
+function monthNameToNum(monthName)
+ local months = {january = 1, february = 2, march = 3, april = 4, may = 5, june = 6, july = 7, august = 8, september = 9, october = 10, november = 11, december = 12}
+ return months[string.lower(monthName)]
+end
+
+function getMark(idx, events, markDefaults, isNote)
+ local event = events[idx]
+ local default_mark = {}
+ default_mark.number = {}
+ default_mark.day_text = {}
+ default_mark.note = {}
+
+ default_mark.number.symbol = idx
+ default_mark.number.above_offset = "\\markNumberAbove"
+ default_mark.number.right_offset = "\\markNumberRight"
+
+ default_mark.day_text.symbol = idx
+ default_mark.day_text.above_offset = "\\markDayTextAbove"
+ default_mark.day_text.right_offset = "\\markDayTextRight"
+
+ default_mark.note.symbol = idx
+ default_mark.note.above_offset = "" -- placeholder, not used for note
+ default_mark.note.right_offset = "" -- placeholder, not used for note
+
+ local mark = {}
+
+ for k,v in pairs(default_mark.number) do
+ local m = {}
+ local mark_key = ""
+ local csv_key = ""
+
+ if ok(isNote) then
+ mark_key = "note"
+ elseif ok(event.day_text) then
+ mark_key = "day_text"
+ else
+ mark_key = "number"
+ end
+
+ m = default_mark[mark_key]
+ csv_key = mark_key .. "_" .. k
+
+ if not ok(markDefaults) or not ok(markDefaults[idx]) or not ok(markDefaults[idx][csv_key]) then
+ mark[k] = m[k]
+ else
+ mark[k] = markDefaults[idx][csv_key]
+ end
+ end
+
+ return mark
+end
+
+function getCombinedMark(idx, events, markDefaults, isNote)
+ local event = events[idx]
+ local mark = getMark(idx, events, markDefaults, isNote)
+
+ mark.symbol = ""
+ for i,e in pairs(events) do
+ if e.date == event.date then
+ local m = getMark(i, events, markDefaults, isNote)
+ if mark.symbol == "" then
+ mark.symbol = m.symbol
+ else
+ mark.symbol = mark.symbol .. "\\symbolSeparator " .. m.symbol
+ end
+ end
+ end
+
+ return mark
+end
+
+function collectEvents(byWhat, events, byValue, filterPred)
+ local data = {}
+ for idx,row in pairs(events) do
+ d = date(row.date)
+
+ if filterPred ~= nil then
+ if byWhat == 'month' then
+ if d:getmonth() == byValue and filterPred(row) then
+ data[#data + 1] = row
+ end
+ elseif byWhat == 'year' then
+ if d:getyear() == byValue and filterPred(row) then
+ data[#data + 1] = row
+ end
+ end
+ else
+ if byWhat == 'month' then
+ if d:getmonth() == byValue then
+ data[#data + 1] = row
+ end
+ elseif byWhat == 'year' then
+ if d:getyear() == byValue then
+ data[#data + 1] = row
+ end
+ end
+ end
+
+ end
+ return data
+end
+
+function eventsInMonth(events, month, filterPred)
+ return collectEvents('month', events, month, filterPred)
+end
+
+function eventsInYear(events, year, filterPred)
+ return collectEvents('year', events, year, filterPred)
+end
+
+function formatEvents(events, formatFunc, formatCmd, markDefaultsCsv, minEvents)
+ if ok(minEvents) and #events < minEvents then
+ d = minEvents - #events
+ for i=0,d,1 do
+ events[#events + 1] = {}
+ end
+ end
+
+ local markDefaults = nil
+ if ok(markDefaultsCsv) then
+ markDefaults = loadCsv(markDefaultsCsv)
+ end
+
+ for idx,event in pairs(events) do
+ local mark = {}
+ local d = {}
+
+ if ok(event.date) then
+ -- don't use getCombinedMark here, events on the same day will be printed one after the other
+ mark = getMark(idx, events, markDefaults, true)
+ d = date(event.date)
+ end
+
+ if formatFunc then
+
+ formatFunc(idx, #events, event, d, mark)
+
+ else
+
+ tsp("\\def\\eIdx{"..idx .."}") -- \def\eIdx{1}
+ tsp("\\def\\eMaxIdx{"..#events .."}") -- \def\eMaxIdx{8}
+ tsp("\\def\\eMark{"..mark.symbol .."}") -- \def\eMark{\kiteMark}
+ tsp("\\def\\eIsoDate{"..event.date .."}") -- \def\eIsoDate{2018-01-12}
+ tsp("\\def\\eYear{"..d:getyear() .."}") -- \def\eYear{2018}
+ tsp("\\def\\eMonth{\\x"..d:fmt("%B") .."}") -- \def\eMonth\xJanuary
+ tsp("\\def\\eMonthShort{\\x"..d:fmt("%b").."Short" .."}") -- \def\eMonthShort\xJanShort
+ tsp("\\def\\eDay{"..d:getday() .."}") -- \def\eDay{12}
+ if ok(event.day_text) then
+ tsp("\\def\\eDayText{"..event.day_text .."}") -- \def\eDayText{\dejaVuSans\char"263C}
+ else
+ tsp("\\def\\eDayText{}")
+ end
+ if ok(event.note) then
+ tsp("\\def\\eNote{"..event.note .."}") -- \def\eNote{Anniversary Day}
+ else
+ tsp("\\def\\eNote{}")
+ end
+
+ tsp(formatCmd)
+
+ end
+ end
+end
+
+-- It's better to call it with the name of the month than its number because it
+-- fits the wrapper commands better.
+function monthEvents(monthName, filterPred, formatFunc, formatCmd, eventsCsv, markDefaultsCsv, minEvents)
+ local monthNum = monthNameToNum(monthName)
+ local events = eventsInMonth(loadCsv(eventsCsv), monthNum, filterPred)
+
+ formatEvents(events, formatFunc, formatCmd, markDefaultsCsv, minEvents)
+end
+
+function yearEvents(yearNum, filterPred, formatFunc, formatCmd, eventsCsv, markDefaultsCsv, minEvents)
+ local events = eventsInYear(loadCsv(eventsCsv), yearNum, filterPred)
+
+ formatEvents(events, formatFunc, formatCmd, markDefaultsCsv, minEvents)
+end
+
+-- monthName is better for argument than monthNum
+function monthMarksDayText(monthName, filterPred, eventsCsv)
+ local monthNum = monthNameToNum(monthName)
+ local events = eventsInMonth(loadCsv(eventsCsv), monthNum, filterPred);
+
+ for idx,event in pairs(events) do
+ if ok(event.day_text) then
+ tsp(string.format(" if (equals=%s) [day text={%s}, xshift=\\dayTextXshift, yshift=\\dayTextYshift] ", event.date, event.day_text))
+ end
+ end
+end
+
+function yearMarksDayText(yearNum, filterPred, eventsCsv)
+ local events = eventsInYear(loadCsv(eventsCsv), yearNum, filterPred);
+
+ for idx,event in pairs(events) do
+ if ok(event.day_text) then
+ tsp(string.format(" if (equals=%s) [day text={%s}, xshift=\\dayTextXshift, yshift=\\dayTextYshift] ", event.date, event.day_text))
+ end
+ end
+end
+
+function formatMarksNote(events, filterPred, markDefaultsCsv, isOneCalendar)
+ local markDefaults = nil
+ if ok(markDefaultsCsv) then
+ markDefaults = loadCsv(markDefaultsCsv)
+ end
+
+ local alreadyMarkedDates = {}
+
+ for idx,event in pairs(events) do
+ if ok(event.note) and alreadyMarkedDates[event.date] == nil then
+ alreadyMarkedDates[event.date] = true
+ local d = date(event.date)
+
+ local mark = getCombinedMark(idx, events, markDefaults)
+
+ if ok(isOneCalendar) and isOneCalendar == true then
+ tsp(string.format(" \\draw node [above right=%s and %s of cal-%s.north east] {\\monthMarkFmt %s}; ",
+ mark.above_offset,
+ mark.right_offset,
+ event.date,
+ mark.symbol))
+ else
+ tsp(string.format(" \\draw node [above right=%s and %s of cal%s-%s.north east] {\\monthMarkFmt %s}; ",
+ mark.above_offset,
+ mark.right_offset,
+ d:fmt("%m"),
+ event.date,
+ mark.symbol))
+ end
+ end
+ end
+end
+
+-- monthName is better for argument than monthNum
+function monthMarksNote(monthName, filterPred, eventsCsv, markDefaultsCsv)
+ local monthNum = monthNameToNum(monthName)
+
+ if not ok(filterPred) then
+ filterPred = function(e) return ok(e.note) end
+ end
+
+ local events = eventsInMonth(loadCsv(eventsCsv), monthNum, filterPred);
+
+ formatMarksNote(events, filterPred, markDefaultsCsv, false)
+end
+
+function yearMarksNote(yearNum, filterPred, eventsCsv, markDefaultsCsv, isOneCalendar)
+ if not ok(filterPred) then
+ filterPred = function(e) return ok(e.note) end
+ end
+
+ local events = eventsInYear(loadCsv(eventsCsv), yearNum, filterPred);
+
+ formatMarksNote(events, filterPred, markDefaultsCsv, isOneCalendar)
+end