diff --git a/fsm.lua b/fsm.lua index 939222c..879592d 100644 --- a/fsm.lua +++ b/fsm.lua @@ -1,23 +1,23 @@ --- Sporel Launcher — pure-Lua finite state machine. --- No engine.* calls; testable directly by lib-management.launcher-test. - local M = {} -M.STATE_LIST = "list" -M.STATE_QUIT_CONFIRM = "quit_confirm" -M.EXIT = "exit" -- sentinel: caller should engine.exit(0) +M.STATE_LIST = "list" +M.STATE_QUIT_CONFIRM = "quit_confirm" +M.STATE_MODAL_CONFLICT = "modal_conflict" +M.EXIT = "exit" --- Events: "esc", "enter", "click_yes", "click_no", "click_module" function M.next(state, event) if state == M.STATE_LIST then - if event == "esc" then return M.STATE_QUIT_CONFIRM end - return M.STATE_LIST + if event == "esc" then return M.STATE_QUIT_CONFIRM end + if event == "open_conflict" then return M.STATE_MODAL_CONFLICT end elseif state == M.STATE_QUIT_CONFIRM then - if event == "esc" then return M.STATE_LIST end - if event == "enter" then return M.EXIT end - if event == "click_yes" then return M.EXIT end - if event == "click_no" then return M.STATE_LIST end - return M.STATE_QUIT_CONFIRM + if event == "esc" then return M.STATE_LIST end + if event == "enter" then return M.EXIT end + if event == "click_yes" then return M.EXIT end + if event == "click_no" then return M.STATE_LIST end + elseif state == M.STATE_MODAL_CONFLICT then + if event == "esc" then return M.STATE_LIST end + if event == "cancel" then return M.STATE_LIST end + if event == "launch_anyway" then return M.STATE_LIST end -- side-effect end return state end diff --git a/init.lua b/init.lua index 80ff5e5..fa9206c 100644 --- a/init.lua +++ b/init.lua @@ -32,6 +32,12 @@ function M.run_tests(ctx) engine.test.equals(fsm.next(fsm.STATE_LIST, "click_module"), fsm.STATE_LIST, "list+click_module -> list (switch is side-effect)") engine.test.equals(fsm.next("garbage_state", "esc"), "garbage_state", "unknown state passes through unchanged") + -- ----- Conflict-modal FSM transitions (4) ----- + engine.test.equals(fsm.next(fsm.STATE_LIST, "open_conflict"), fsm.STATE_MODAL_CONFLICT, "list+open_conflict -> modal_conflict") + engine.test.equals(fsm.next(fsm.STATE_MODAL_CONFLICT, "esc"), fsm.STATE_LIST, "modal_conflict+esc -> list") + engine.test.equals(fsm.next(fsm.STATE_MODAL_CONFLICT, "cancel"), fsm.STATE_LIST, "modal_conflict+cancel -> list") + engine.test.equals(fsm.next(fsm.STATE_MODAL_CONFLICT, "launch_anyway"), fsm.STATE_LIST, "modal_conflict+launch_anyway -> list") + -- ----- Engine-surface existence (unchanged) ----- engine.test.assert(type(engine.module.list) == "function", "engine.module.list is function") engine.test.assert(type(engine.module.dir_of) == "function", "engine.module.dir_of is function")