Module: Remind

Defined in:
lib/remind.rb,
lib/remind/value.rb,
lib/remind/native.rb,
lib/remind/source.rb,
lib/remind/builder.rb,
lib/remind/library.rb,
lib/remind/runtime.rb,
lib/remind/session.rb,
lib/remind/version.rb,
lib/remind/reminder.rb

Overview

Ruby bindings for Remind, through Fiddle.

Remind is a calendar program, and underneath the calendar is an interpreter: an expression language with dates as a first-class type, and a trigger language that says things like "the Monday of the week the 13th falls in, unless that is a holiday, in which case the day before". The usual way to reach any of that from another language is to shell out to remind and parse what comes back.

These bindings call the C instead, and the reason to is Remind::Reminder. Every program that has read a reminder file with regular expressions has got part of the trigger language wrong -- there is a lot of it, and Remind's manual describes eighteen worked examples before it gets to the exceptions. Here, ParseRem parses the trigger, ComputeTrigger says which dates it fires on, and DoSubst renders the message for each of them. Nothing about the language is interpreted on this side.

Remind.today = Date.new(2026, 8, 19)

reminder = Remind.parse("REM Mon 13 SKIP OMIT Sat MSG payday")
reminder.summary                      # => "payday"
reminder.occurrences.first(3)         # => Remind's own dates

Remind.evaluate("moonphase(today())") # => 46

Why Fiddle, and not a C extension

There is nothing to extend. Remind's sources compile into a shared library unchanged -- Builder does it with the flags ./configure already chose -- and everything worth calling is a plain function over ints and pointers. The one C file in this gem, ext/shim.c, is there for struct layout and for the sequence of six calls that parses a REM line; not because Fiddle needed help calling anything.

The state

Remind keeps "today" in a global, because a program that runs once and exits has no reason not to. So Remind.today = moves the ground under every calculation -- deliberately, because a reminder that says Mon means a different date tomorrow than it does today, and pinning the date is what makes a conversion reproducible.

Defined Under Namespace

Modules: Library, Runtime, Value Classes: BuildError, Builder, Error, EvaluationError, LibraryMissing, Native, Reminder, Session, Source

Constant Summary collapse

VERSION =

.. The first three segments say which version of Remind this gem vendors and binds; the fourth is ours, bumped for changes on the Ruby side against that same release. Managed by bin/increment-version -- edit that, not this.

"6.2.10.1"
REMIND_VERSION =

The vendored source directory is named for the release, in Remind's own zero-padded spelling.

"06.02.10"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.sessionObject

The process-wide interpreter: there is one set of globals to talk to, so there is one of these.



58
59
60
# File 'lib/remind.rb', line 58

def session
  @session ||= Session.new
end

Class Method Details

.date(dse) ⇒ Object



95
96
97
# File 'lib/remind.rb', line 95

def date(dse)
  session.date(dse)
end

.dse(date) ⇒ Object



91
92
93
# File 'lib/remind.rb', line 91

def dse(date)
  session.dse(date)
end

.evaluate(expression) ⇒ Object



75
76
77
# File 'lib/remind.rb', line 75

def evaluate(expression)
  session.evaluate(expression)
end

.library_pathObject



104
105
106
# File 'lib/remind.rb', line 104

def library_path
  Library.path
end

.now=(time) ⇒ Object



87
88
89
# File 'lib/remind.rb', line 87

def now=(time)
  session.now = time
end

.parse(line) ⇒ Object

One REM line, or nil if the line is not a reminder.



65
66
67
# File 'lib/remind.rb', line 65

def parse(line)
  Reminder.parse(line, session: session)
end

.read(path) ⇒ Object

Every reminder in a file, with continuations joined and INCLUDEs followed, as Remind reads them.



71
72
73
# File 'lib/remind.rb', line 71

def read(path)
  Source.new(path, session: session).reminders
end

.todayObject



79
80
81
# File 'lib/remind.rb', line 79

def today
  session.today
end

.today=(date) ⇒ Object



83
84
85
# File 'lib/remind.rb', line 83

def today=(date)
  session.today = date
end

.versionObject

The Remind release the library was built from.



100
101
102
# File 'lib/remind.rb', line 100

def version
  session.version
end