1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 16:49:31 +00:00

Fix interleaved text and choices

This commit is contained in:
Étienne Fildadut 2023-12-31 14:25:37 +01:00
parent 4125a4c99b
commit aa8dfbd498
4 changed files with 70 additions and 28 deletions

View file

@ -1,7 +1,7 @@
local class = require("anselme.lib.class")
local ast = require("anselme.ast")
local Nil, String, List, Identifier, Boolean = ast.Nil, ast.String, ast.List, ast.Identifier, ast.Boolean
local Nil, String, List, Identifier = ast.Nil, ast.String, ast.List, ast.Identifier
-- list of event data
local event_buffer_identifier = Identifier:new("_event_buffer")
@ -11,9 +11,9 @@ local event_buffer_symbol = event_buffer_identifier:to_symbol{ confined_to_branc
local last_event_type_identifier = Identifier:new("_last_event_type")
local last_event_type_symbol = last_event_type_identifier:to_symbol{ confined_to_branch = true }
-- indicate if the next flush should be ignored for the current buffered event
local discard_next_flush_identifier = Identifier:new("_discard_next_flush")
local discard_next_flush_symbol = discard_next_flush_identifier:to_symbol{ confined_to_branch = true }
-- (per-scope) indicate if we should discard write to an event type
local discard_next_events_identifier = Identifier:new("_discard_next_events")
local discard_next_events_symbol = discard_next_events_identifier:to_symbol{ confined_to_branch = true }
return class {
init = false,
@ -21,38 +21,48 @@ return class {
setup = function(self, state)
state.scope:define(event_buffer_symbol, List:new(state))
state.scope:define(last_event_type_symbol, Nil:new())
state.scope:define(discard_next_flush_symbol, Nil:new())
end,
reset = function(self, state)
state.scope:set(event_buffer_identifier, List:new(state))
state.scope:set(last_event_type_identifier, Nil:new())
state.scope:set(discard_next_flush_identifier, Nil:new())
end,
-- write an event into the event buffer
-- will flush if an event of a different type is present in the buffer
write = function(self, state, event)
-- discard if requested
if state.scope:defined_in_current(discard_next_events_symbol) then
local discard_type = state.scope:get(discard_next_events_identifier):to_lua()
if discard_type == event.type then
return
elseif discard_type ~= nil then
state.scope:set(discard_next_events_identifier, Nil:new()) -- fake flush the discarded events
end
end
-- flush until no event or same type
repeat
local current_type = state.scope:get(last_event_type_identifier):to_lua(state)
if current_type ~= nil and current_type ~= event.type then
self:flush(state)
end
until current_type == nil or current_type == event.type
-- write
state.scope:set(last_event_type_identifier, String:new(event.type))
state.scope:get(event_buffer_identifier):insert(state, event)
end,
-- same as :write, but the buffer will be discarded instead of yielded on the next flush
write_and_discard_on_flush = function(self, state, event)
self:write(state, event)
state.scope:set(discard_next_flush_identifier, Boolean:new(true))
-- same as :write, but will not actually write the event, instead discarding all immediately following event of the same type in the same scope
write_and_discard_following = function(self, state, event)
if not state.scope:defined_in_current(discard_next_events_symbol) then
state.scope:define(discard_next_events_symbol, String:new(event.type))
else
state.scope:set(discard_next_events_identifier, String:new(event.type))
end
end,
-- flush the event buffer: build the event data and yield it
flush = function(self, state)
local last_type = state.scope:get(last_event_type_identifier):to_lua(state)
if last_type then
local discard_next_flush = state.scope:get(discard_next_flush_identifier):truthy()
if discard_next_flush then
self:reset(state)
else
local last_buffer = state.scope:get(event_buffer_identifier)
local event_president = last_buffer:get(state, 1) -- elected representative of all concerned events
-- yield event data
@ -63,7 +73,6 @@ return class {
-- post callback
if event_president.post_flush_callback then event_president:post_flush_callback(state, last_buffer, data) end
end
end
end,
-- keep flushing until nothing is left (a flush may re-fill the buffer during its execution)
final_flush = function(self, state)

View file

@ -21,7 +21,7 @@ return {
function(state, text, func)
if func:contains_current_resume_target(state) then
func:call(state, ArgumentTuple:new())
event_manager:write_and_discard_on_flush(state, Choice:new(text, func))
event_manager:write_and_discard_following(state, Choice:new(text, func))
else
event_manager:write(state, Choice:new(text, func))
end

View file

@ -0,0 +1,19 @@
--# run #--
--- choice ---
=> | {}"a" |
--- text ---
| {}"-> a" |
--- choice ---
=> | {}"aa" |
> | {}"ab" |
--- text ---
| {}"-> aa" |
| {}"x" |
--- choice ---
=> | {}"b" |
--- text ---
| {}"-> b" |
--- return ---
()
--# saved #--
{}

View file

@ -0,0 +1,14 @@
:@choice = 1
:f = $_
| a |>
|-> a
| aa |>
|-> aa
| ab |>
|-> ab
| x
| b |>
|-> b
f!