remind-rb 6.2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +328 -0
- data/README.md +141 -0
- data/ext/remind/shim.c +379 -0
- data/lib/remind/builder.rb +252 -0
- data/lib/remind/library.rb +141 -0
- data/lib/remind/native.rb +257 -0
- data/lib/remind/reminder.rb +527 -0
- data/lib/remind/runtime.rb +130 -0
- data/lib/remind/session.rb +246 -0
- data/lib/remind/source.rb +160 -0
- data/lib/remind/value.rb +170 -0
- data/lib/remind/version.rb +13 -0
- data/lib/remind.rb +147 -0
- data/remind-v06.02.10/COPYRIGHT +300 -0
- data/remind-v06.02.10/configure +5684 -0
- data/remind-v06.02.10/configure.ac +131 -0
- data/remind-v06.02.10/docs/WHATSNEW +3858 -0
- data/remind-v06.02.10/include/ansitext.rem +35 -0
- data/remind-v06.02.10/include/holidays/ad/02.rem +15 -0
- data/remind-v06.02.10/include/holidays/ad/03.rem +14 -0
- data/remind-v06.02.10/include/holidays/ad/04.rem +14 -0
- data/remind-v06.02.10/include/holidays/ad/05.rem +14 -0
- data/remind-v06.02.10/include/holidays/ad/06.rem +16 -0
- data/remind-v06.02.10/include/holidays/ad/07.rem +15 -0
- data/remind-v06.02.10/include/holidays/ad/08.rem +14 -0
- data/remind-v06.02.10/include/holidays/ad.rem +28 -0
- data/remind-v06.02.10/include/holidays/ae.rem +10 -0
- data/remind-v06.02.10/include/holidays/al.rem +33 -0
- data/remind-v06.02.10/include/holidays/am.rem +19 -0
- data/remind-v06.02.10/include/holidays/ao.rem +41 -0
- data/remind-v06.02.10/include/holidays/ar.rem +38 -0
- data/remind-v06.02.10/include/holidays/as.rem +40 -0
- data/remind-v06.02.10/include/holidays/at/1.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/2.rem +16 -0
- data/remind-v06.02.10/include/holidays/at/3.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/4.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/5.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/6.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/7.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/8.rem +15 -0
- data/remind-v06.02.10/include/holidays/at/9.rem +15 -0
- data/remind-v06.02.10/include/holidays/at.rem +32 -0
- data/remind-v06.02.10/include/holidays/au/act.rem +27 -0
- data/remind-v06.02.10/include/holidays/au/nsw.rem +25 -0
- data/remind-v06.02.10/include/holidays/au/nt.rem +28 -0
- data/remind-v06.02.10/include/holidays/au/qld.rem +23 -0
- data/remind-v06.02.10/include/holidays/au/sa.rem +29 -0
- data/remind-v06.02.10/include/holidays/au/tas.rem +16 -0
- data/remind-v06.02.10/include/holidays/au/vic.rem +24 -0
- data/remind-v06.02.10/include/holidays/au/wa.rem +24 -0
- data/remind-v06.02.10/include/holidays/au.rem +21 -0
- data/remind-v06.02.10/include/holidays/aw.rem +19 -0
- data/remind-v06.02.10/include/holidays/az.rem +44 -0
- data/remind-v06.02.10/include/holidays/ba/bih.rem +23 -0
- data/remind-v06.02.10/include/holidays/ba/brc.rem +20 -0
- data/remind-v06.02.10/include/holidays/ba/srp.rem +23 -0
- data/remind-v06.02.10/include/holidays/ba.rem +22 -0
- data/remind-v06.02.10/include/holidays/bb.rem +28 -0
- data/remind-v06.02.10/include/holidays/bd.rem +14 -0
- data/remind-v06.02.10/include/holidays/be.rem +24 -0
- data/remind-v06.02.10/include/holidays/bf.rem +29 -0
- data/remind-v06.02.10/include/holidays/bg.rem +34 -0
- data/remind-v06.02.10/include/holidays/bh.rem +11 -0
- data/remind-v06.02.10/include/holidays/bi.rem +30 -0
- data/remind-v06.02.10/include/holidays/bn.rem +22 -0
- data/remind-v06.02.10/include/holidays/bo/b.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/c.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/h.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/l.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/n.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/o.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/p.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/s.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo/t.rem +13 -0
- data/remind-v06.02.10/include/holidays/bo.rem +32 -0
- data/remind-v06.02.10/include/holidays/br/ac.rem +21 -0
- data/remind-v06.02.10/include/holidays/br/al.rem +16 -0
- data/remind-v06.02.10/include/holidays/br/am.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/ap.rem +15 -0
- data/remind-v06.02.10/include/holidays/br/ba.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/ce.rem +15 -0
- data/remind-v06.02.10/include/holidays/br/df.rem +14 -0
- data/remind-v06.02.10/include/holidays/br/es.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/go.rem +14 -0
- data/remind-v06.02.10/include/holidays/br/ma.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/mg.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/ms.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/pa.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/pb.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/pe.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/pi.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/pr.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/rj.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/rn.rem +14 -0
- data/remind-v06.02.10/include/holidays/br/ro.rem +14 -0
- data/remind-v06.02.10/include/holidays/br/rr.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/rs.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/sc.rem +14 -0
- data/remind-v06.02.10/include/holidays/br/se.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/sp.rem +13 -0
- data/remind-v06.02.10/include/holidays/br/to.rem +15 -0
- data/remind-v06.02.10/include/holidays/br.rem +33 -0
- data/remind-v06.02.10/include/holidays/bs.rem +26 -0
- data/remind-v06.02.10/include/holidays/bw.rem +31 -0
- data/remind-v06.02.10/include/holidays/by.rem +17 -0
- data/remind-v06.02.10/include/holidays/bz.rem +43 -0
- data/remind-v06.02.10/include/holidays/ca/ab.rem +17 -0
- data/remind-v06.02.10/include/holidays/ca/bc.rem +14 -0
- data/remind-v06.02.10/include/holidays/ca/mb.rem +16 -0
- data/remind-v06.02.10/include/holidays/ca/nb.rem +14 -0
- data/remind-v06.02.10/include/holidays/ca/nl.rem +19 -0
- data/remind-v06.02.10/include/holidays/ca/ns.rem +16 -0
- data/remind-v06.02.10/include/holidays/ca/nt.rem +14 -0
- data/remind-v06.02.10/include/holidays/ca/nu.rem +16 -0
- data/remind-v06.02.10/include/holidays/ca/on.rem +16 -0
- data/remind-v06.02.10/include/holidays/ca/pe.rem +13 -0
- data/remind-v06.02.10/include/holidays/ca/qc.rem +18 -0
- data/remind-v06.02.10/include/holidays/ca/sk.rem +14 -0
- data/remind-v06.02.10/include/holidays/ca/yt.rem +17 -0
- data/remind-v06.02.10/include/holidays/ca.rem +37 -0
- data/remind-v06.02.10/include/holidays/cg.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/ag.rem +22 -0
- data/remind-v06.02.10/include/holidays/ch/ai.rem +20 -0
- data/remind-v06.02.10/include/holidays/ch/ar.rem +16 -0
- data/remind-v06.02.10/include/holidays/ch/be.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/bl.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/bs.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/fr.rem +19 -0
- data/remind-v06.02.10/include/holidays/ch/ge.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/gl.rem +22 -0
- data/remind-v06.02.10/include/holidays/ch/gr.rem +18 -0
- data/remind-v06.02.10/include/holidays/ch/ju.rem +21 -0
- data/remind-v06.02.10/include/holidays/ch/lu.rem +21 -0
- data/remind-v06.02.10/include/holidays/ch/ne.rem +18 -0
- data/remind-v06.02.10/include/holidays/ch/nw.rem +24 -0
- data/remind-v06.02.10/include/holidays/ch/ow.rem +24 -0
- data/remind-v06.02.10/include/holidays/ch/sg.rem +20 -0
- data/remind-v06.02.10/include/holidays/ch/sh.rem +20 -0
- data/remind-v06.02.10/include/holidays/ch/so.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/sz.rem +22 -0
- data/remind-v06.02.10/include/holidays/ch/tg.rem +18 -0
- data/remind-v06.02.10/include/holidays/ch/ti.rem +23 -0
- data/remind-v06.02.10/include/holidays/ch/ur.rem +22 -0
- data/remind-v06.02.10/include/holidays/ch/vd.rem +17 -0
- data/remind-v06.02.10/include/holidays/ch/vs.rem +23 -0
- data/remind-v06.02.10/include/holidays/ch/zg.rem +23 -0
- data/remind-v06.02.10/include/holidays/ch/zh.rem +18 -0
- data/remind-v06.02.10/include/holidays/ch.rem +18 -0
- data/remind-v06.02.10/include/holidays/chinese-new-year.rem +86 -0
- data/remind-v06.02.10/include/holidays/cl/ap.rem +13 -0
- data/remind-v06.02.10/include/holidays/cl/nb.rem +13 -0
- data/remind-v06.02.10/include/holidays/cl.rem +46 -0
- data/remind-v06.02.10/include/holidays/cm.rem +21 -0
- data/remind-v06.02.10/include/holidays/co.rem +85 -0
- data/remind-v06.02.10/include/holidays/cr.rem +39 -0
- data/remind-v06.02.10/include/holidays/cu.rem +19 -0
- data/remind-v06.02.10/include/holidays/cw.rem +24 -0
- data/remind-v06.02.10/include/holidays/cy.rem +27 -0
- data/remind-v06.02.10/include/holidays/cz.rem +20 -0
- data/remind-v06.02.10/include/holidays/de/bb.rem +15 -0
- data/remind-v06.02.10/include/holidays/de/be.rem +13 -0
- data/remind-v06.02.10/include/holidays/de/bw.rem +15 -0
- data/remind-v06.02.10/include/holidays/de/by.rem +18 -0
- data/remind-v06.02.10/include/holidays/de/hb.rem +13 -0
- data/remind-v06.02.10/include/holidays/de/he.rem +13 -0
- data/remind-v06.02.10/include/holidays/de/hh.rem +13 -0
- data/remind-v06.02.10/include/holidays/de/mv.rem +14 -0
- data/remind-v06.02.10/include/holidays/de/ni.rem +13 -0
- data/remind-v06.02.10/include/holidays/de/nw.rem +14 -0
- data/remind-v06.02.10/include/holidays/de/rp.rem +14 -0
- data/remind-v06.02.10/include/holidays/de/sh.rem +13 -0
- data/remind-v06.02.10/include/holidays/de/sl.rem +15 -0
- data/remind-v06.02.10/include/holidays/de/sn.rem +14 -0
- data/remind-v06.02.10/include/holidays/de/st.rem +14 -0
- data/remind-v06.02.10/include/holidays/de/th.rem +14 -0
- data/remind-v06.02.10/include/holidays/de.rem +23 -0
- data/remind-v06.02.10/include/holidays/discordian.rem +25 -0
- data/remind-v06.02.10/include/holidays/dj.rem +12 -0
- data/remind-v06.02.10/include/holidays/dk.rem +23 -0
- data/remind-v06.02.10/include/holidays/dm.rem +24 -0
- data/remind-v06.02.10/include/holidays/do.rem +36 -0
- data/remind-v06.02.10/include/holidays/dz.rem +12 -0
- data/remind-v06.02.10/include/holidays/ec.rem +48 -0
- data/remind-v06.02.10/include/holidays/ee.rem +19 -0
- data/remind-v06.02.10/include/holidays/eg.rem +17 -0
- data/remind-v06.02.10/include/holidays/es/an.rem +17 -0
- data/remind-v06.02.10/include/holidays/es/ar.rem +17 -0
- data/remind-v06.02.10/include/holidays/es/as.rem +17 -0
- data/remind-v06.02.10/include/holidays/es/cb.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/ce.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/cl.rem +17 -0
- data/remind-v06.02.10/include/holidays/es/cm.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/cn.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/ct.rem +16 -0
- data/remind-v06.02.10/include/holidays/es/ex.rem +16 -0
- data/remind-v06.02.10/include/holidays/es/ga.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/ib.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/mc.rem +17 -0
- data/remind-v06.02.10/include/holidays/es/md.rem +16 -0
- data/remind-v06.02.10/include/holidays/es/ml.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/nc.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/pv.rem +15 -0
- data/remind-v06.02.10/include/holidays/es/ri.rem +16 -0
- data/remind-v06.02.10/include/holidays/es/vc.rem +16 -0
- data/remind-v06.02.10/include/holidays/es.rem +23 -0
- data/remind-v06.02.10/include/holidays/et.rem +20 -0
- data/remind-v06.02.10/include/holidays/fi.rem +43 -0
- data/remind-v06.02.10/include/holidays/fr/bl.rem +13 -0
- data/remind-v06.02.10/include/holidays/fr/ges.rem +14 -0
- data/remind-v06.02.10/include/holidays/fr/gp.rem +16 -0
- data/remind-v06.02.10/include/holidays/fr/gy.rem +13 -0
- data/remind-v06.02.10/include/holidays/fr/mf.rem +13 -0
- data/remind-v06.02.10/include/holidays/fr/mq.rem +15 -0
- data/remind-v06.02.10/include/holidays/fr/nc.rem +13 -0
- data/remind-v06.02.10/include/holidays/fr/pf.rem +15 -0
- data/remind-v06.02.10/include/holidays/fr/re.rem +13 -0
- data/remind-v06.02.10/include/holidays/fr/wf.rem +14 -0
- data/remind-v06.02.10/include/holidays/fr/yt.rem +13 -0
- data/remind-v06.02.10/include/holidays/fr.rem +18 -0
- data/remind-v06.02.10/include/holidays/ga.rem +18 -0
- data/remind-v06.02.10/include/holidays/gb/eng.rem +14 -0
- data/remind-v06.02.10/include/holidays/gb/nir.rem +20 -0
- data/remind-v06.02.10/include/holidays/gb/sct.rem +20 -0
- data/remind-v06.02.10/include/holidays/gb/wls.rem +14 -0
- data/remind-v06.02.10/include/holidays/gb.rem +27 -0
- data/remind-v06.02.10/include/holidays/ge.rem +24 -0
- data/remind-v06.02.10/include/holidays/gh.rem +34 -0
- data/remind-v06.02.10/include/holidays/gl.rem +25 -0
- data/remind-v06.02.10/include/holidays/gr.rem +37 -0
- data/remind-v06.02.10/include/holidays/gt.rem +24 -0
- data/remind-v06.02.10/include/holidays/gu.rem +37 -0
- data/remind-v06.02.10/include/holidays/hk.rem +25 -0
- data/remind-v06.02.10/include/holidays/hn.rem +18 -0
- data/remind-v06.02.10/include/holidays/hr.rem +21 -0
- data/remind-v06.02.10/include/holidays/ht.rem +34 -0
- data/remind-v06.02.10/include/holidays/hu.rem +20 -0
- data/remind-v06.02.10/include/holidays/id.rem +15 -0
- data/remind-v06.02.10/include/holidays/ie.rem +41 -0
- data/remind-v06.02.10/include/holidays/im.rem +26 -0
- data/remind-v06.02.10/include/holidays/in/ap.rem +14 -0
- data/remind-v06.02.10/include/holidays/in/as.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/br.rem +14 -0
- data/remind-v06.02.10/include/holidays/in/cg.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/gj.rem +15 -0
- data/remind-v06.02.10/include/holidays/in/hr.rem +14 -0
- data/remind-v06.02.10/include/holidays/in/ka.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/kl.rem +14 -0
- data/remind-v06.02.10/include/holidays/in/mh.rem +15 -0
- data/remind-v06.02.10/include/holidays/in/mp.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/od.rem +15 -0
- data/remind-v06.02.10/include/holidays/in/rj.rem +14 -0
- data/remind-v06.02.10/include/holidays/in/sk.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/tn.rem +15 -0
- data/remind-v06.02.10/include/holidays/in/ts.rem +14 -0
- data/remind-v06.02.10/include/holidays/in/uk.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/up.rem +13 -0
- data/remind-v06.02.10/include/holidays/in/wb.rem +16 -0
- data/remind-v06.02.10/include/holidays/in.rem +24 -0
- data/remind-v06.02.10/include/holidays/is.rem +23 -0
- data/remind-v06.02.10/include/holidays/it/ag.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/al.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/an.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/andria.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ao.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ap.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/aq.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ar.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/at.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/av.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ba.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/barletta.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/bg.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/bl.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/bn.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/bo.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/br.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/bs.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/bt.rem +15 -0
- data/remind-v06.02.10/include/holidays/it/bz.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/ca.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cb.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ce.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cesena.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ch.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cl.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cn.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/co.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cs.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ct.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/cz.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/en.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/fc.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/fe.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/fg.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/fi.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/fm.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/forli.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/fr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ge.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/go.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/gr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/im.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/is.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/kr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/lc.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/le.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/li.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/lo.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/lt.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/lu.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/mb.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/mc.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/me.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/mi.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/mn.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/mo.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ms.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/mt.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/na.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/no.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/nu.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/or.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pa.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pc.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pd.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pe.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pesaro.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pg.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/pi.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pn.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/pr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pt.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pu.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/pv.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/pz.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ra.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/rc.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/re.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/rg.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/ri.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/rm.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/rn.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ro.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/sa.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/si.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/so.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/sp.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/sr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ss.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/su.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/sv.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ta.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/te.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/tn.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/to.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/tp.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/tr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/trani.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ts.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/tv.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ud.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/urbino.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/va.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/vb.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/vc.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/ve.rem +14 -0
- data/remind-v06.02.10/include/holidays/it/vi.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/vr.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/vt.rem +13 -0
- data/remind-v06.02.10/include/holidays/it/vv.rem +13 -0
- data/remind-v06.02.10/include/holidays/it.rem +26 -0
- data/remind-v06.02.10/include/holidays/je.rem +19 -0
- data/remind-v06.02.10/include/holidays/jewish.rem +135 -0
- data/remind-v06.02.10/include/holidays/jm.rem +24 -0
- data/remind-v06.02.10/include/holidays/jo.rem +11 -0
- data/remind-v06.02.10/include/holidays/jp.rem +27 -0
- data/remind-v06.02.10/include/holidays/ke.rem +25 -0
- data/remind-v06.02.10/include/holidays/kg.rem +20 -0
- data/remind-v06.02.10/include/holidays/kh.rem +22 -0
- data/remind-v06.02.10/include/holidays/kn.rem +28 -0
- data/remind-v06.02.10/include/holidays/kr.rem +19 -0
- data/remind-v06.02.10/include/holidays/kw.rem +10 -0
- data/remind-v06.02.10/include/holidays/kz.rem +34 -0
- data/remind-v06.02.10/include/holidays/la.rem +47 -0
- data/remind-v06.02.10/include/holidays/lgbtq/au.rem +8 -0
- data/remind-v06.02.10/include/holidays/lgbtq/br.rem +10 -0
- data/remind-v06.02.10/include/holidays/lgbtq/ca.rem +7 -0
- data/remind-v06.02.10/include/holidays/lgbtq/cl.rem +7 -0
- data/remind-v06.02.10/include/holidays/lgbtq/ie.rem +7 -0
- data/remind-v06.02.10/include/holidays/lgbtq/in.rem +7 -0
- data/remind-v06.02.10/include/holidays/lgbtq/nl.rem +7 -0
- data/remind-v06.02.10/include/holidays/lgbtq/ua.rem +7 -0
- data/remind-v06.02.10/include/holidays/lgbtq/uk.rem +8 -0
- data/remind-v06.02.10/include/holidays/lgbtq/us.rem +16 -0
- data/remind-v06.02.10/include/holidays/lgbtq.rem +34 -0
- data/remind-v06.02.10/include/holidays/li.rem +31 -0
- data/remind-v06.02.10/include/holidays/ls.rem +18 -0
- data/remind-v06.02.10/include/holidays/lt.rem +23 -0
- data/remind-v06.02.10/include/holidays/lu.rem +18 -0
- data/remind-v06.02.10/include/holidays/lv.rem +25 -0
- data/remind-v06.02.10/include/holidays/ma.rem +17 -0
- data/remind-v06.02.10/include/holidays/mc.rem +26 -0
- data/remind-v06.02.10/include/holidays/md.rem +21 -0
- data/remind-v06.02.10/include/holidays/me.rem +28 -0
- data/remind-v06.02.10/include/holidays/mg.rem +24 -0
- data/remind-v06.02.10/include/holidays/mh.rem +22 -0
- data/remind-v06.02.10/include/holidays/misc.rem +9 -0
- data/remind-v06.02.10/include/holidays/mk.rem +17 -0
- data/remind-v06.02.10/include/holidays/mp.rem +44 -0
- data/remind-v06.02.10/include/holidays/mr.rem +11 -0
- data/remind-v06.02.10/include/holidays/mt.rem +21 -0
- data/remind-v06.02.10/include/holidays/mv.rem +12 -0
- data/remind-v06.02.10/include/holidays/mw.rem +36 -0
- data/remind-v06.02.10/include/holidays/mx.rem +15 -0
- data/remind-v06.02.10/include/holidays/my/01.rem +13 -0
- data/remind-v06.02.10/include/holidays/my/02.rem +13 -0
- data/remind-v06.02.10/include/holidays/my/03.rem +14 -0
- data/remind-v06.02.10/include/holidays/my/04.rem +18 -0
- data/remind-v06.02.10/include/holidays/my/05.rem +16 -0
- data/remind-v06.02.10/include/holidays/my/06.rem +17 -0
- data/remind-v06.02.10/include/holidays/my/07.rem +17 -0
- data/remind-v06.02.10/include/holidays/my/08.rem +15 -0
- data/remind-v06.02.10/include/holidays/my/09.rem +14 -0
- data/remind-v06.02.10/include/holidays/my/10.rem +16 -0
- data/remind-v06.02.10/include/holidays/my/11.rem +16 -0
- data/remind-v06.02.10/include/holidays/my/12.rem +19 -0
- data/remind-v06.02.10/include/holidays/my/13.rem +22 -0
- data/remind-v06.02.10/include/holidays/my/14.rem +16 -0
- data/remind-v06.02.10/include/holidays/my/15.rem +18 -0
- data/remind-v06.02.10/include/holidays/my/16.rem +16 -0
- data/remind-v06.02.10/include/holidays/my.rem +23 -0
- data/remind-v06.02.10/include/holidays/mz.rem +25 -0
- data/remind-v06.02.10/include/holidays/na.rem +27 -0
- data/remind-v06.02.10/include/holidays/ng.rem +21 -0
- data/remind-v06.02.10/include/holidays/ni/mn.rem +14 -0
- data/remind-v06.02.10/include/holidays/ni.rem +24 -0
- data/remind-v06.02.10/include/holidays/nl.rem +26 -0
- data/remind-v06.02.10/include/holidays/no.rem +19 -0
- data/remind-v06.02.10/include/holidays/nz/auk.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/can.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/cit.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/hkb.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/mbh.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/nsn.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/ntl.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/ota.rem +14 -0
- data/remind-v06.02.10/include/holidays/nz/south_canterbury.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/stl.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/tki.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/wgn.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz/wtc.rem +13 -0
- data/remind-v06.02.10/include/holidays/nz.rem +69 -0
- data/remind-v06.02.10/include/holidays/pa.rem +27 -0
- data/remind-v06.02.10/include/holidays/pagan.rem +65 -0
- data/remind-v06.02.10/include/holidays/pe.rem +22 -0
- data/remind-v06.02.10/include/holidays/pg.rem +24 -0
- data/remind-v06.02.10/include/holidays/ph.rem +26 -0
- data/remind-v06.02.10/include/holidays/pk.rem +13 -0
- data/remind-v06.02.10/include/holidays/pl.rem +20 -0
- data/remind-v06.02.10/include/holidays/pr.rem +40 -0
- data/remind-v06.02.10/include/holidays/pt/01.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/02.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/03.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/04.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/05.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/06.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/07.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/08.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/09.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/10.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/12.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/13.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/14.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/15.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/16.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/18.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/20.rem +13 -0
- data/remind-v06.02.10/include/holidays/pt/30.rem +14 -0
- data/remind-v06.02.10/include/holidays/pt.rem +17 -0
- data/remind-v06.02.10/include/holidays/pw.rem +34 -0
- data/remind-v06.02.10/include/holidays/py.rem +20 -0
- data/remind-v06.02.10/include/holidays/ro.rem +24 -0
- data/remind-v06.02.10/include/holidays/rs.rem +26 -0
- data/remind-v06.02.10/include/holidays/ru.rem +21 -0
- data/remind-v06.02.10/include/holidays/sa.rem +13 -0
- data/remind-v06.02.10/include/holidays/sc.rem +28 -0
- data/remind-v06.02.10/include/holidays/se.rem +23 -0
- data/remind-v06.02.10/include/holidays/sg.rem +16 -0
- data/remind-v06.02.10/include/holidays/si.rem +20 -0
- data/remind-v06.02.10/include/holidays/sk.rem +25 -0
- data/remind-v06.02.10/include/holidays/sm.rem +25 -0
- data/remind-v06.02.10/include/holidays/sv/ss.rem +14 -0
- data/remind-v06.02.10/include/holidays/sv.rem +25 -0
- data/remind-v06.02.10/include/holidays/sz.rem +26 -0
- data/remind-v06.02.10/include/holidays/td.rem +22 -0
- data/remind-v06.02.10/include/holidays/th.rem +72 -0
- data/remind-v06.02.10/include/holidays/tl.rem +31 -0
- data/remind-v06.02.10/include/holidays/tn.rem +15 -0
- data/remind-v06.02.10/include/holidays/to.rem +38 -0
- data/remind-v06.02.10/include/holidays/tr.rem +17 -0
- data/remind-v06.02.10/include/holidays/tw.rem +26 -0
- data/remind-v06.02.10/include/holidays/tz.rem +23 -0
- data/remind-v06.02.10/include/holidays/ua.rem +20 -0
- data/remind-v06.02.10/include/holidays/uk.rem +27 -0
- data/remind-v06.02.10/include/holidays/um.rem +32 -0
- data/remind-v06.02.10/include/holidays/us/ak.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/al.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/ar.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/as.rem +20 -0
- data/remind-v06.02.10/include/holidays/us/az.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/ca.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/co.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/ct.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/dc.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/de.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/fl.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/ga.rem +18 -0
- data/remind-v06.02.10/include/holidays/us/gu.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/hi.rem +19 -0
- data/remind-v06.02.10/include/holidays/us/ia.rem +15 -0
- data/remind-v06.02.10/include/holidays/us/id.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/il.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/in.rem +19 -0
- data/remind-v06.02.10/include/holidays/us/ks.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/ky.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/la.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/ma.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/md-extra.rem +19 -0
- data/remind-v06.02.10/include/holidays/us/md.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/me.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/mi.rem +19 -0
- data/remind-v06.02.10/include/holidays/us/mo.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/mp.rem +23 -0
- data/remind-v06.02.10/include/holidays/us/ms.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/mt.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/nc.rem +22 -0
- data/remind-v06.02.10/include/holidays/us/ne.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/nh.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/nj.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/nm.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/nv.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/ny.rem +17 -0
- data/remind-v06.02.10/include/holidays/us/oh.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/ok.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/pa.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/pr.rem +21 -0
- data/remind-v06.02.10/include/holidays/us/ri.rem +14 -0
- data/remind-v06.02.10/include/holidays/us/sc.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/sd.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/tn.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/tx.rem +25 -0
- data/remind-v06.02.10/include/holidays/us/ut.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/va.rem +13 -0
- data/remind-v06.02.10/include/holidays/us/vi.rem +22 -0
- data/remind-v06.02.10/include/holidays/us/vt.rem +16 -0
- data/remind-v06.02.10/include/holidays/us/wi.rem +20 -0
- data/remind-v06.02.10/include/holidays/us/wv.rem +17 -0
- data/remind-v06.02.10/include/holidays/us.rem +41 -0
- data/remind-v06.02.10/include/holidays/uy.rem +39 -0
- data/remind-v06.02.10/include/holidays/uz.rem +21 -0
- data/remind-v06.02.10/include/holidays/va.rem +23 -0
- data/remind-v06.02.10/include/holidays/ve.rem +21 -0
- data/remind-v06.02.10/include/holidays/vi.rem +41 -0
- data/remind-v06.02.10/include/holidays/vn.rem +17 -0
- data/remind-v06.02.10/include/holidays/vu.rem +32 -0
- data/remind-v06.02.10/include/holidays/ws.rem +18 -0
- data/remind-v06.02.10/include/holidays/za.rem +28 -0
- data/remind-v06.02.10/include/holidays/zm.rem +31 -0
- data/remind-v06.02.10/include/lang/auto.rem +32 -0
- data/remind-v06.02.10/include/lang/ca.rem +60 -0
- data/remind-v06.02.10/include/lang/da.rem +77 -0
- data/remind-v06.02.10/include/lang/de.rem +80 -0
- data/remind-v06.02.10/include/lang/en.rem +4 -0
- data/remind-v06.02.10/include/lang/es.rem +55 -0
- data/remind-v06.02.10/include/lang/fi.rem +202 -0
- data/remind-v06.02.10/include/lang/fr.rem +172 -0
- data/remind-v06.02.10/include/lang/gr.rem +74 -0
- data/remind-v06.02.10/include/lang/is.rem +58 -0
- data/remind-v06.02.10/include/lang/it.rem +76 -0
- data/remind-v06.02.10/include/lang/nl.rem +71 -0
- data/remind-v06.02.10/include/lang/no.rem +66 -0
- data/remind-v06.02.10/include/lang/pl.rem +177 -0
- data/remind-v06.02.10/include/lang/pt.rem +176 -0
- data/remind-v06.02.10/include/lang/ro.rem +74 -0
- data/remind-v06.02.10/include/lunar-eclipses.rem +149 -0
- data/remind-v06.02.10/include/moonphases.rem +19 -0
- data/remind-v06.02.10/include/seasons.rem +21 -0
- data/remind-v06.02.10/include/solar-eclipses.rem +238 -0
- data/remind-v06.02.10/include/sun.rem +12 -0
- data/remind-v06.02.10/include/translations/de/holidays/chinese-new-year.rem +13 -0
- data/remind-v06.02.10/include/translations/de/moonphases.rem +4 -0
- data/remind-v06.02.10/include/translations/de/seasons.rem +4 -0
- data/remind-v06.02.10/include/translations/de/sun.rem +2 -0
- data/remind-v06.02.10/include/translations/nl/holidays/chinese-new-year.rem +13 -0
- data/remind-v06.02.10/include/translations/nl/moonphases.rem +4 -0
- data/remind-v06.02.10/include/translations/nl/seasons.rem +4 -0
- data/remind-v06.02.10/include/translations/nl/sun.rem +2 -0
- data/remind-v06.02.10/include/utils/add-html-anchors.rem +5 -0
- data/remind-v06.02.10/install-sh +238 -0
- data/remind-v06.02.10/man/rem.1.in +21 -0
- data/remind-v06.02.10/man/rem2ps.1.in +816 -0
- data/remind-v06.02.10/man/remind.1.in +7658 -0
- data/remind-v06.02.10/man/tkremind.1.in +612 -0
- data/remind-v06.02.10/rem2html/Makefile.in +30 -0
- data/remind-v06.02.10/rem2html/rem2html.in +1299 -0
- data/remind-v06.02.10/rem2pdf/Makefile.PL.in +25 -0
- data/remind-v06.02.10/rem2pdf/Makefile.top.in +50 -0
- data/remind-v06.02.10/rem2pdf/bin/rem2pdf.in +761 -0
- data/remind-v06.02.10/scripts/tkremind.in +5794 -0
- data/remind-v06.02.10/src/Makefile.in +133 -0
- data/remind-v06.02.10/src/calendar.c +3069 -0
- data/remind-v06.02.10/src/config.h +117 -0
- data/remind-v06.02.10/src/config.h.in +116 -0
- data/remind-v06.02.10/src/custom.h +167 -0
- data/remind-v06.02.10/src/custom.h.in +167 -0
- data/remind-v06.02.10/src/dedupe.c +179 -0
- data/remind-v06.02.10/src/dorem.c +2389 -0
- data/remind-v06.02.10/src/dosubst.c +910 -0
- data/remind-v06.02.10/src/dynbuf.c +198 -0
- data/remind-v06.02.10/src/dynbuf.h +41 -0
- data/remind-v06.02.10/src/err.h +294 -0
- data/remind-v06.02.10/src/expr.c +3408 -0
- data/remind-v06.02.10/src/files.c +1437 -0
- data/remind-v06.02.10/src/funcs.c +5230 -0
- data/remind-v06.02.10/src/globals.c +23 -0
- data/remind-v06.02.10/src/globals.h +277 -0
- data/remind-v06.02.10/src/hashtab.c +428 -0
- data/remind-v06.02.10/src/hashtab.h +88 -0
- data/remind-v06.02.10/src/hashtab_stats.c +101 -0
- data/remind-v06.02.10/src/hbcal.c +579 -0
- data/remind-v06.02.10/src/ifelse.c +236 -0
- data/remind-v06.02.10/src/init.c +1494 -0
- data/remind-v06.02.10/src/json.c +1048 -0
- data/remind-v06.02.10/src/json.h +276 -0
- data/remind-v06.02.10/src/main.c +2310 -0
- data/remind-v06.02.10/src/md5.c +250 -0
- data/remind-v06.02.10/src/md5.h +33 -0
- data/remind-v06.02.10/src/moon.c +957 -0
- data/remind-v06.02.10/src/omit.c +560 -0
- data/remind-v06.02.10/src/protos.h +284 -0
- data/remind-v06.02.10/src/queue.c +1118 -0
- data/remind-v06.02.10/src/rem2ps.c +1383 -0
- data/remind-v06.02.10/src/rem2ps.h +229 -0
- data/remind-v06.02.10/src/sort.c +257 -0
- data/remind-v06.02.10/src/token.c +494 -0
- data/remind-v06.02.10/src/trans.c +544 -0
- data/remind-v06.02.10/src/trigger.c +871 -0
- data/remind-v06.02.10/src/types.h +341 -0
- data/remind-v06.02.10/src/userfns.c +810 -0
- data/remind-v06.02.10/src/utils.c +374 -0
- data/remind-v06.02.10/src/var.c +1762 -0
- data/remind-v06.02.10/src/version.h +1 -0
- data/remind-v06.02.10/src/version.h.in +1 -0
- data/remind-v06.02.10/src/xlat.c +100 -0
- data/remind-v06.02.10/www/Makefile.in +91 -0
- metadata +764 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fiddle"
|
|
4
|
+
|
|
5
|
+
require_relative "native"
|
|
6
|
+
require_relative "session"
|
|
7
|
+
|
|
8
|
+
module Remind
|
|
9
|
+
# One `REM` line, parsed by Remind.
|
|
10
|
+
#
|
|
11
|
+
# This is the binding that exists because converting a reminder file to
|
|
12
|
+
# anything else is otherwise a re-implementation of Remind. A trigger like
|
|
13
|
+
# `REM Mon 13 SKIP OMIT Sat MSG x` means "the Monday of the week the 13th
|
|
14
|
+
# falls in, unless that is a Saturday, in which case skip it" -- and every
|
|
15
|
+
# program that has tried to read that with a regular expression has got some
|
|
16
|
+
# of it wrong. Here the parse is `ParseRem`, the first date is
|
|
17
|
+
# `ComputeTrigger`, the message is `DoSubst`, and the dates after the first
|
|
18
|
+
# are `ComputeTrigger` again from further along. Nothing about the date
|
|
19
|
+
# specification is interpreted on this side.
|
|
20
|
+
#
|
|
21
|
+
# The fields are Remind's, with two translations and no others: months are
|
|
22
|
+
# 1..12 rather than 0..11, and a field the reminder did not mention is nil
|
|
23
|
+
# rather than Remind's sentinel for it.
|
|
24
|
+
class Reminder
|
|
25
|
+
# What Remind numbers the weekday bits from: bit 0 is Monday.
|
|
26
|
+
WEEKDAY_BITS = %w[MO TU WE TH FR SA SU].freeze
|
|
27
|
+
|
|
28
|
+
# A body a calendar can show. RUN reminders execute a shell command, CAL
|
|
29
|
+
# and PS reminders draw on a PostScript calendar; none of them is an
|
|
30
|
+
# event.
|
|
31
|
+
DISPLAY_TYPES = %i[msg msf].freeze
|
|
32
|
+
|
|
33
|
+
TYPE_NAMES = {
|
|
34
|
+
msg_type: :msg,
|
|
35
|
+
msf_type: :msf,
|
|
36
|
+
run_type: :run,
|
|
37
|
+
cal_type: :cal,
|
|
38
|
+
sat_type: :satisfy,
|
|
39
|
+
passthru_type: :passthru,
|
|
40
|
+
}.freeze
|
|
41
|
+
|
|
42
|
+
# How far a walk will go looking for the next occurrence before deciding
|
|
43
|
+
# there isn't one. Remind answers "cannot compute trigger" on its own for
|
|
44
|
+
# most run-out reminders; this bounds the ones it would keep answering.
|
|
45
|
+
DEFAULT_LIMIT = 100
|
|
46
|
+
|
|
47
|
+
attr_reader :line, :session, :first, :description, :type
|
|
48
|
+
|
|
49
|
+
class << self
|
|
50
|
+
# nil when the line is not a reminder Remind can parse into an event:
|
|
51
|
+
# a comment, a SET, a REM with no body, a trigger that never fires.
|
|
52
|
+
def parse(line, session: Session.new)
|
|
53
|
+
new(line, session: session).tap(&:parse).presented
|
|
54
|
+
rescue EvaluationError
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def initialize(line, session: Session.new)
|
|
60
|
+
@line = line
|
|
61
|
+
@session = session
|
|
62
|
+
@native = session.native
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# --- what the trigger said -------------------------------------------
|
|
66
|
+
|
|
67
|
+
# The day of the month, or nil.
|
|
68
|
+
def day
|
|
69
|
+
field(:d, native.no_day)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# 1..12, or nil. Remind counts months from zero; this does not.
|
|
73
|
+
def month
|
|
74
|
+
zero_based = field(:m, native.no_month)
|
|
75
|
+
|
|
76
|
+
if zero_based
|
|
77
|
+
zero_based + 1
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def year
|
|
82
|
+
field(:y, native.no_year)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The weekdays named in the trigger, as RFC 5545 spells them, in Remind's
|
|
86
|
+
# bit order: `REM Mon Wed Fri` is ["MO", "WE", "FR"].
|
|
87
|
+
def weekdays
|
|
88
|
+
bits = trigger_field(:wd)
|
|
89
|
+
|
|
90
|
+
WEEKDAY_BITS.each_index.select { |index| bits.anybits?(1 << index) }
|
|
91
|
+
.map { |index| WEEKDAY_BITS[index] }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# `REM 1 *7` repeats every seven days. nil when the reminder does not.
|
|
95
|
+
def repeat
|
|
96
|
+
positive(trigger_field(:rep))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# The last date the reminder may trigger on -- UNTIL or THROUGH -- as a
|
|
100
|
+
# Date, or nil.
|
|
101
|
+
def until_date
|
|
102
|
+
last = field(:until, native.no_until)
|
|
103
|
+
|
|
104
|
+
if last
|
|
105
|
+
session.date(last)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Advance warning, in days: the `+n` in `REM 15 +3`.
|
|
110
|
+
def warning_days
|
|
111
|
+
positive(trigger_field(:delta))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# The `-n` in `REM 1 -1`: how many days back from the date the trigger
|
|
115
|
+
# names. `REM 1 -1` is the last day of the month before.
|
|
116
|
+
def back
|
|
117
|
+
positive(trigger_field(:back))
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Whether the reminder skips or moves over OMITted days, which is a thing
|
|
121
|
+
# no RRULE can say.
|
|
122
|
+
def skip
|
|
123
|
+
trigger_field(:skip)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def omits_weekdays?
|
|
127
|
+
trigger_field(:localomit) != 0
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def once?
|
|
131
|
+
trigger_field(:once) != 0
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# --- what the AT clause said ------------------------------------------
|
|
135
|
+
|
|
136
|
+
# Minutes since midnight, or nil for an all-day reminder.
|
|
137
|
+
def at
|
|
138
|
+
time = timetrig_field(:time)
|
|
139
|
+
|
|
140
|
+
if time == native.no_time
|
|
141
|
+
nil
|
|
142
|
+
else
|
|
143
|
+
time
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# DURATION, in minutes, or nil. Remind fills this with the same "no time
|
|
148
|
+
# given" sentinel as the AT clause, not with zero.
|
|
149
|
+
def duration
|
|
150
|
+
given = timetrig_field(:duration)
|
|
151
|
+
|
|
152
|
+
if given == native.no_time
|
|
153
|
+
nil
|
|
154
|
+
else
|
|
155
|
+
positive(given)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# The alarm on an AT clause: `AT 9:30 +15`, in minutes.
|
|
160
|
+
def warning_minutes
|
|
161
|
+
positive(timetrig_field(:delta))
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# --- what it triggers on ----------------------------------------------
|
|
165
|
+
|
|
166
|
+
# Every date this reminder triggers on, starting at the first, asked of
|
|
167
|
+
# Remind one at a time. Lazy, because a daily reminder has no last one.
|
|
168
|
+
def occurrences(limit: DEFAULT_LIMIT)
|
|
169
|
+
Enumerator.new do |dates|
|
|
170
|
+
cursor = first_dse
|
|
171
|
+
taken = 0
|
|
172
|
+
|
|
173
|
+
while cursor >= 0 && taken < limit
|
|
174
|
+
dates << session.date(cursor)
|
|
175
|
+
taken += 1
|
|
176
|
+
cursor = next_dse(cursor + 1)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def display?
|
|
182
|
+
DISPLAY_TYPES.include?(type)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# The same reminder as it reads on a given day.
|
|
186
|
+
#
|
|
187
|
+
# A message is not fixed text: `%b` is "in 27 days' time" or "today"
|
|
188
|
+
# depending on when it is read, and Remind expands it against whatever
|
|
189
|
+
# DSEToday says at the moment it renders. `remind` therefore prints a
|
|
190
|
+
# different message for each occurrence, and anything showing one
|
|
191
|
+
# occurrence should show the message that occurrence would have had.
|
|
192
|
+
#
|
|
193
|
+
# Today is process-wide, so it is pinned and put back.
|
|
194
|
+
def as_of(date)
|
|
195
|
+
was = session.today
|
|
196
|
+
|
|
197
|
+
session.today = date
|
|
198
|
+
self.class.parse(line, session: session)
|
|
199
|
+
ensure
|
|
200
|
+
session.today = was
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# --- parsing ----------------------------------------------------------
|
|
204
|
+
|
|
205
|
+
def parse
|
|
206
|
+
@trigger = Fiddle::Pointer.malloc(native.sizeof_trigger, Fiddle::RUBY_FREE)
|
|
207
|
+
@timetrig = Fiddle::Pointer.malloc(native.sizeof_timetrig, Fiddle::RUBY_FREE)
|
|
208
|
+
|
|
209
|
+
@code, @first_dse, @description = expand(native.normal_mode, @trigger, @timetrig)
|
|
210
|
+
@type = TYPE_NAMES[type_name]
|
|
211
|
+
@first = read_first
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# The message as a calendar wants it: `%"…%"` marks the part of a reminder
|
|
215
|
+
# that is the entry's title, and CAL_MODE is the mode that honours it. A
|
|
216
|
+
# reminder that marks nothing has the whole message for a title.
|
|
217
|
+
#
|
|
218
|
+
# It costs a second parse, because DoSubst consumes the parser as it
|
|
219
|
+
# renders and there is only one message in a line either way.
|
|
220
|
+
def summary
|
|
221
|
+
@summary ||= expand(
|
|
222
|
+
native.cal_mode,
|
|
223
|
+
Fiddle::Pointer.malloc(native.sizeof_trigger, Fiddle::RUBY_FREE),
|
|
224
|
+
Fiddle::Pointer.malloc(native.sizeof_timetrig, Fiddle::RUBY_FREE),
|
|
225
|
+
).last
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# nil rather than an unusable object, for the caller that is walking a
|
|
229
|
+
# file and does not want to ask about every line twice.
|
|
230
|
+
def presented
|
|
231
|
+
if parsed?
|
|
232
|
+
self
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def parsed?
|
|
237
|
+
@code&.zero? && @first_dse >= 0
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def error
|
|
241
|
+
if @code&.positive?
|
|
242
|
+
session.error_message(@code)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
private
|
|
247
|
+
|
|
248
|
+
attr_reader :native
|
|
249
|
+
|
|
250
|
+
# One trip through the shim: parse, compute the first date, render the
|
|
251
|
+
# message in the mode asked for.
|
|
252
|
+
def expand(mode, trigger, timetrig)
|
|
253
|
+
dse = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
254
|
+
message = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP, Fiddle::RUBY_FREE)
|
|
255
|
+
|
|
256
|
+
code = Session::LOCK.synchronize do
|
|
257
|
+
native.parse_reminder(
|
|
258
|
+
terminated,
|
|
259
|
+
trigger,
|
|
260
|
+
timetrig,
|
|
261
|
+
dse,
|
|
262
|
+
message,
|
|
263
|
+
mode,
|
|
264
|
+
)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
[code, dse[0, Fiddle::SIZEOF_INT].unpack1("i!"), string_at(message).strip]
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def terminated
|
|
271
|
+
Fiddle::Pointer["#{line.chomp}\0"]
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def read_first
|
|
275
|
+
if parsed?
|
|
276
|
+
session.date(@first_dse)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def first_dse
|
|
281
|
+
@first_dse
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def next_dse(from)
|
|
285
|
+
error_code = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
286
|
+
|
|
287
|
+
Session::LOCK.synchronize do
|
|
288
|
+
native.next_trigger(
|
|
289
|
+
@trigger,
|
|
290
|
+
@timetrig,
|
|
291
|
+
from,
|
|
292
|
+
error_code,
|
|
293
|
+
)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def type_name
|
|
298
|
+
TYPE_NAMES.keys.find { |name| native.public_send(name) == trigger_field(:typ) }
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def trigger_field(name)
|
|
302
|
+
native.public_send(:"trigger_#{name}", @trigger)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def timetrig_field(name)
|
|
306
|
+
native.public_send(:"timetrig_#{name}", @timetrig)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# A field Remind fills with a sentinel when the reminder did not say.
|
|
310
|
+
def field(name, sentinel)
|
|
311
|
+
value = trigger_field(name)
|
|
312
|
+
|
|
313
|
+
if value == sentinel
|
|
314
|
+
nil
|
|
315
|
+
else
|
|
316
|
+
value
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def positive(value)
|
|
321
|
+
if value > 0
|
|
322
|
+
value
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def string_at(slot)
|
|
327
|
+
address = slot[0, Fiddle::SIZEOF_VOIDP].unpack1("J")
|
|
328
|
+
|
|
329
|
+
if address.zero?
|
|
330
|
+
""
|
|
331
|
+
else
|
|
332
|
+
Fiddle::Pointer.new(address).to_s.force_encoding(Encoding::UTF_8)
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
__END__
|
|
339
|
+
|
|
340
|
+
describe "Remind::Reminder" do
|
|
341
|
+
session = Remind::Session.new
|
|
342
|
+
session.today = Date.new(2026, 8, 19) # a Wednesday
|
|
343
|
+
|
|
344
|
+
reminder = proc { |line| Remind::Reminder.parse(line, session: session) }
|
|
345
|
+
dates = proc { |line, count| reminder.(line).occurrences(limit: count).to_a.map(&:to_s) }
|
|
346
|
+
|
|
347
|
+
describe "what it will parse" do
|
|
348
|
+
it "parses a reminder" do
|
|
349
|
+
reminder.("REM 15 Jan MSG dentist").should.not.be.nil
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it "parses one with the REM left off, which Remind allows" do
|
|
353
|
+
reminder.("15 Jan MSG dentist").should.not.be.nil
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it "does not parse one of Remind's other commands" do
|
|
357
|
+
reminder.("SET a 1").should.be.nil
|
|
358
|
+
reminder.("IF 1").should.be.nil
|
|
359
|
+
reminder.("OMIT 25 Dec").should.be.nil
|
|
360
|
+
reminder.("# a comment mentioning REM and MSG").should.be.nil
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
it "parses a line whose first word Remind does not know, as Remind does" do
|
|
364
|
+
reminder.("15 Jan MSG implicit").first.should == Date.new(2027, 1, 15)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
it "does not parse a reminder with no body" do
|
|
368
|
+
reminder.("REM 15 Jan").should.be.nil
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
it "does not parse a trigger that can never fire" do
|
|
372
|
+
reminder.("REM 30 Feb MSG never").should.be.nil
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
describe "the fields, as Remind read them" do
|
|
377
|
+
it "reads a day, a month and a year" do
|
|
378
|
+
parsed = reminder.("REM 15 Jan 2027 MSG dentist")
|
|
379
|
+
|
|
380
|
+
parsed.day.should == 15
|
|
381
|
+
parsed.month.should == 1
|
|
382
|
+
parsed.year.should == 2027
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it "leaves out what the trigger left out" do
|
|
386
|
+
parsed = reminder.("REM 15 MSG rent")
|
|
387
|
+
|
|
388
|
+
parsed.day.should == 15
|
|
389
|
+
parsed.month.should.be.nil
|
|
390
|
+
parsed.year.should.be.nil
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it "reads the weekdays as the RFC spells them" do
|
|
394
|
+
reminder.("REM Mon Wed Fri MSG gym").weekdays.should == %w[MO WE FR]
|
|
395
|
+
reminder.("REM Sun MSG rest").weekdays.should == %w[SU]
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it "reads a repeat interval" do
|
|
399
|
+
reminder.("REM 1 Jan 2027 *14 MSG fortnightly").repeat.should == 14
|
|
400
|
+
reminder.("REM 15 MSG rent").repeat.should.be.nil
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it "reads an UNTIL date" do
|
|
404
|
+
reminder.("REM 1 Jan 2027 *7 UNTIL 1 Mar 2027 MSG weekly").until_date.should ==
|
|
405
|
+
Date.new(2027, 3, 1)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
it "reads advance warning in days" do
|
|
409
|
+
reminder.("REM 15 +3 MSG rent").warning_days.should == 3
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "reads the AT clause and its alarm" do
|
|
413
|
+
parsed = reminder.("REM Mon AT 9:30 +15 DURATION 1:00 MSG standup")
|
|
414
|
+
|
|
415
|
+
parsed.at.should == 570
|
|
416
|
+
parsed.warning_minutes.should == 15
|
|
417
|
+
parsed.duration.should == 60
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
it "leaves the duration nil when the reminder gave none" do
|
|
421
|
+
reminder.("REM Mon AT 9:30 MSG standup").duration.should.be.nil
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it "leaves the time nil for an all-day reminder" do
|
|
425
|
+
reminder.("REM 15 Jan MSG dentist").at.should.be.nil
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it "reads a back-count" do
|
|
429
|
+
reminder.("REM 1 -1 MSG last day of the month").back.should == 1
|
|
430
|
+
reminder.("REM 15 MSG rent").back.should.be.nil
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it "knows a reminder that skips OMITted days from one that does not" do
|
|
434
|
+
reminder.("REM 1 Mar SKIP OMIT Sat Sun MSG payday").skip.should.not == 0
|
|
435
|
+
reminder.("REM 1 Mar MSG payday").skip.should == 0
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
describe "the message, expanded by Remind" do
|
|
440
|
+
it "reads the message" do
|
|
441
|
+
reminder.("REM 15 Jan MSG dentist").description.should == "dentist"
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
it "expands the substitutions against the day it is read on" do
|
|
445
|
+
reminder.("REM 15 +3 MSG rent due %b").description.should.include "in 27 days' time"
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
it "reads as of another day when asked to" do
|
|
449
|
+
parsed = reminder.("REM 15 +3 MSG rent due %b").as_of(Date.new(2026, 9, 15))
|
|
450
|
+
|
|
451
|
+
parsed.description.should == "rent due today"
|
|
452
|
+
parsed.first.should == Date.new(2026, 9, 15)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
it "puts today back after reading as of another day" do
|
|
456
|
+
reminder.("REM 15 MSG rent").as_of(Date.new(2030, 1, 1))
|
|
457
|
+
|
|
458
|
+
session.today.should == Date.new(2026, 8, 19)
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
it "gives the whole message when nothing marks a title" do
|
|
462
|
+
reminder.("REM 15 Jan MSG dentist").summary.should == "dentist"
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
it "takes the title a reminder marked for a calendar" do
|
|
466
|
+
parsed = reminder.(%q{REM 15 Jan MSG %"dentist%" bring the form})
|
|
467
|
+
|
|
468
|
+
parsed.summary.should == "dentist"
|
|
469
|
+
parsed.description.should == "dentist bring the form"
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
describe "the type" do
|
|
474
|
+
it "knows a MSG reminder is something a calendar can show" do
|
|
475
|
+
reminder.("REM 15 Jan MSG dentist").display?.should.be.true
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it "knows a RUN reminder is not" do
|
|
479
|
+
parsed = reminder.("REM 15 Jan RUN backup.sh")
|
|
480
|
+
|
|
481
|
+
parsed.type.should == :run
|
|
482
|
+
parsed.display?.should.be.false
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
describe "the dates, computed by Remind" do
|
|
487
|
+
it "starts at the first date the reminder triggers on" do
|
|
488
|
+
reminder.("REM 15 Jan MSG dentist").first.should == Date.new(2027, 1, 15)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it "walks a weekly reminder" do
|
|
492
|
+
dates.("REM Mon MSG gym", 3).should == %w[2026-08-24 2026-08-31 2026-09-07]
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it "walks a monthly one" do
|
|
496
|
+
dates.("REM 15 MSG rent", 3).should == %w[2026-09-15 2026-10-15 2026-11-15]
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
it "walks a yearly one" do
|
|
500
|
+
dates.("REM 1 Jan MSG new year", 3).should == %w[2027-01-01 2028-01-01 2029-01-01]
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
it "reads weekday-and-day the way Remind does, not the way it looks" do
|
|
504
|
+
# The Monday of the week the 1st falls in, not the first Monday.
|
|
505
|
+
dates.("REM Mon 1 MSG first monday", 3).should == %w[2026-09-07 2026-10-05 2026-11-02]
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
it "stops a reminder that happens once" do
|
|
509
|
+
dates.("REM 25 Dec 2027 MSG christmas", 5).should == %w[2027-12-25]
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it "stops at UNTIL" do
|
|
513
|
+
dates.("REM 1 Jan 2027 *7 UNTIL 20 Jan 2027 MSG weekly", 9)
|
|
514
|
+
.should == %w[2027-01-01 2027-01-08 2027-01-15]
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it "skips what the reminder says to skip" do
|
|
518
|
+
# 1 March 2031 is a Saturday, and this reminder skips it entirely.
|
|
519
|
+
dates.("REM 1 Mar SKIP OMIT Sat Sun MSG payday", 6)
|
|
520
|
+
.should == %w[2027-03-01 2028-03-01 2029-03-01 2030-03-01 2032-03-01 2033-03-01]
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
it "stops where it is told to stop" do
|
|
524
|
+
reminder.("REM Mon MSG gym").occurrences(limit: 2).to_a.length.should == 2
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "native"
|
|
4
|
+
|
|
5
|
+
module Remind
|
|
6
|
+
# The startup Remind does before it looks at its command line.
|
|
7
|
+
#
|
|
8
|
+
# `InitRemind` is one function with two jobs: it brings the interpreter up
|
|
9
|
+
# -- hash tables, dynamic buffers, the translation table, today's date --
|
|
10
|
+
# and then it parses argv, opens files and, on bad input, exits the process.
|
|
11
|
+
# A library wants the first job and never the second, so this repeats the
|
|
12
|
+
# first rather than calling the function that does both.
|
|
13
|
+
#
|
|
14
|
+
# Skipping it is not an option. Remind's tables are static storage with null
|
|
15
|
+
# function pointers in them until something initialises them, so the first
|
|
16
|
+
# expression that takes an error path -- where `GetErr` translates the
|
|
17
|
+
# message -- walks into a null pointer and takes the process with it.
|
|
18
|
+
#
|
|
19
|
+
# It runs once per process, because the state is process-wide.
|
|
20
|
+
module Runtime
|
|
21
|
+
LOCK = Mutex.new
|
|
22
|
+
|
|
23
|
+
# In the order InitRemind does them.
|
|
24
|
+
TABLES = %i[
|
|
25
|
+
init_variables
|
|
26
|
+
init_user_functions
|
|
27
|
+
init_translation_table
|
|
28
|
+
init_files
|
|
29
|
+
init_dedupe_table
|
|
30
|
+
].freeze
|
|
31
|
+
|
|
32
|
+
# Remind reports a parse error by printing the line with a caret under the
|
|
33
|
+
# offending character. A library raises instead, so by default the
|
|
34
|
+
# printing goes nowhere and the exception carries the message; a caller
|
|
35
|
+
# who wants the caret can ask for it.
|
|
36
|
+
DEVNULL = "/dev/null"
|
|
37
|
+
|
|
38
|
+
module_function
|
|
39
|
+
|
|
40
|
+
def booted
|
|
41
|
+
@booted ||= {}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def boot(native, diagnostics: false)
|
|
45
|
+
LOCK.synchronize do
|
|
46
|
+
if booted[native.path]
|
|
47
|
+
false
|
|
48
|
+
else
|
|
49
|
+
start(native, diagnostics)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def start(native, diagnostics)
|
|
55
|
+
point_errors(native, diagnostics)
|
|
56
|
+
TABLES.each { |name| native.public_send(name) }
|
|
57
|
+
Native::BUFFERS.each { |name| native.init_buffer(native.address_of(name)) }
|
|
58
|
+
read_the_clock(native)
|
|
59
|
+
|
|
60
|
+
booted[native.path] = true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# ErrFp starts as a null FILE *, and main() is what points it at stderr.
|
|
64
|
+
# Everything that reports an error writes through it, including the paths
|
|
65
|
+
# that would otherwise dereference the null.
|
|
66
|
+
def point_errors(native, diagnostics)
|
|
67
|
+
if diagnostics
|
|
68
|
+
native.write_pointer(Native::ERROR_STREAM, native.standard_error)
|
|
69
|
+
else
|
|
70
|
+
native.write_pointer(Native::ERROR_STREAM, discard(native))
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# One stream per process, held open: reopening it per expression would
|
|
75
|
+
# leak a descriptor every time.
|
|
76
|
+
def discard(native)
|
|
77
|
+
@discard ||= native.open_stream(
|
|
78
|
+
Fiddle::Pointer["#{DEVNULL}\0"],
|
|
79
|
+
Fiddle::Pointer["w\0"],
|
|
80
|
+
).to_i
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# SystemDate answers today as a day count and fills in the year, month and
|
|
84
|
+
# day Remind completes partial dates with.
|
|
85
|
+
def read_the_clock(native)
|
|
86
|
+
year = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
87
|
+
month = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
88
|
+
day = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
89
|
+
today = native.system_date(year, month, day)
|
|
90
|
+
|
|
91
|
+
native.write_global("RealToday", today)
|
|
92
|
+
native.write_global("DSEToday", today)
|
|
93
|
+
native.write_global("LocalDSEToday", today)
|
|
94
|
+
native.write_global("CurYear", year[0, Fiddle::SIZEOF_INT].unpack1("i!"))
|
|
95
|
+
native.write_global("LocalSysTime", native.system_time(0))
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
__END__
|
|
101
|
+
|
|
102
|
+
require_relative "session"
|
|
103
|
+
|
|
104
|
+
describe "Remind::Runtime" do
|
|
105
|
+
native = Remind::Native.new
|
|
106
|
+
|
|
107
|
+
it "has booted by the time a session exists" do
|
|
108
|
+
Remind::Session.new
|
|
109
|
+
|
|
110
|
+
Remind::Runtime.booted[native.path].should.be.true
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "boots once per library, not once per caller" do
|
|
114
|
+
Remind::Session.new
|
|
115
|
+
|
|
116
|
+
Remind::Runtime.boot(native).should.be.false
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "leaves RealToday reading off the system clock" do
|
|
120
|
+
Remind::Session.new
|
|
121
|
+
|
|
122
|
+
native.read_global("RealToday").should == native.dse(Date.today.year, Date.today.month - 1, Date.today.day)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "survives the error path a null translation table would crash on" do
|
|
126
|
+
session = Remind::Session.new
|
|
127
|
+
|
|
128
|
+
lambda { session.evaluate("1 +") }.should.raise Remind::EvaluationError
|
|
129
|
+
end
|
|
130
|
+
end
|