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:
parent
4125a4c99b
commit
aa8dfbd498
4 changed files with 70 additions and 28 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
19
test/results/choice text interleaved.ans
Normal file
19
test/results/choice text interleaved.ans
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
--# run #--
|
||||
--- choice ---
|
||||
=> | {}"a" |
|
||||
--- text ---
|
||||
| {}"-> a" |
|
||||
--- choice ---
|
||||
=> | {}"aa" |
|
||||
> | {}"ab" |
|
||||
--- text ---
|
||||
| {}"-> aa" |
|
||||
| {}"x" |
|
||||
--- choice ---
|
||||
=> | {}"b" |
|
||||
--- text ---
|
||||
| {}"-> b" |
|
||||
--- return ---
|
||||
()
|
||||
--# saved #--
|
||||
{}
|
||||
14
test/tests/choice text interleaved.ans
Normal file
14
test/tests/choice text interleaved.ans
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
:@choice = 1
|
||||
|
||||
:f = $_
|
||||
| a |>
|
||||
|-> a
|
||||
| aa |>
|
||||
|-> aa
|
||||
| ab |>
|
||||
|-> ab
|
||||
| x
|
||||
| b |>
|
||||
|-> b
|
||||
|
||||
f!
|
||||
Loading…
Add table
Add a link
Reference in a new issue