diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /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.lua | 279 |
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 |