Runs the program of the presenter on a state
This module is the reference interpreter that
docs/research/elixir-presenter-report.md describes in its section "The
interpreter". Each function is pure: it takes a state and an event, and it
returns the next state. Thus the tests of the presenter behavior need no
browser.
run/3 does the first three steps that the interpreter in the browser does:
- It finds the first mode whose condition the state matches.
- It finds the commands of the event in that mode.
- It applies the commands to the state, one after the other.
The result holds the new state and the built-in functions to call, such as
:open_speaker. prevented?/3 tells if the browser must not use the event:
that is true when the state changes or a built-in function runs. A key that
changes nothing goes to the browser, so the arrow keys still scroll the pages
of the handout view.
A change of the step gives each field of the option reset of the
presenter its first value. Thus the key d, which turns off the dimming of
code, holds only for the step where the presenter pressed it.
The fragment of the address and the messages between the two windows do not go through the modes. They go to a slide and a step of the deck directly.
Summary
Types
An event
The state of the presenter. Expresso.Presenter.Definition declares the fields.
The kind and the direction of a transition
Functions
Return the slide and the step of the current state, or nil for a deck with no slide
Return the fragment of the address for a state, such as #4.2
Return the first state of a program, with some fields replaced
Tell if the browser must not use an event
Apply one event to a state
Return the transition between two states, or nil
Types
@type event() :: {:key, String.t()} | {:click, :left_third | :right} | {:click, :left_third | :right, [term()] | nil} | {:swipe, :left | :right} | {:hash, String.t()} | {:message, %{slide: integer(), step: integer(), fields: map()}}
An event
A click can hold the commands of the element under it, such as a page of the
overview. A message holds the slide and the step of the other window, and
its fields of the option sync, such as the black screen. The script
already made sure of their types.
The state of the presenter. Expresso.Presenter.Definition declares the fields.
@type transition() :: %{kind: String.t(), direction: :forward | :back}
The kind and the direction of a transition
Functions
@spec entry(Expresso.Presenter.Program.t(), state()) :: {pos_integer(), pos_integer()} | nil
Return the slide and the step of the current state, or nil for a deck with no slide
@spec hash(Expresso.Presenter.Program.t(), state()) :: String.t()
Return the fragment of the address for a state, such as #4.2
For a deck with no slide, the function returns #1.1.
@spec initial(Expresso.Presenter.Program.t(), map()) :: state()
Return the first state of a program, with some fields replaced
The script replaces the view for the speaker view, progress from the deck
and every from the address.
Tell if the browser must not use an event
The result is true when the state changed or the event called a built-in function.
@spec run(Expresso.Presenter.Program.t(), state(), event()) :: {state(), [atom()]}
Apply one event to a state
Returns the new state and the built-in functions that the event calls, in sequence.
@spec transition(Expresso.Presenter.Program.t(), state(), state()) :: transition() | nil
Return the transition between two states, or nil
Only a move to a different slide in the present view has a transition. A
black screen, the overview, the menu and the list of keys cover the slide, so
a move from them or to them has no transition. In the two directions, the
kind comes from the slide with the higher number. The kind "none" has no
transition.