{"id":17011070,"url":"https://github.com/davisdude/stately","last_synced_at":"2026-03-09T03:34:48.649Z","repository":{"id":26644057,"uuid":"30100040","full_name":"davisdude/Stately","owner":"davisdude","description":"A state module for Classic","archived":false,"fork":false,"pushed_at":"2019-10-10T03:26:59.000Z","size":39,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-20T04:04:04.225Z","etag":null,"topics":["class","lua","state"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davisdude.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-31T02:48:37.000Z","updated_at":"2021-10-17T14:14:23.000Z","dependencies_parsed_at":"2022-09-01T15:01:39.354Z","dependency_job_id":null,"html_url":"https://github.com/davisdude/Stately","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/davisdude/Stately","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davisdude%2FStately","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davisdude%2FStately/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davisdude%2FStately/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davisdude%2FStately/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davisdude","download_url":"https://codeload.github.com/davisdude/Stately/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davisdude%2FStately/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30281562,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["class","lua","state"],"created_at":"2024-10-14T06:06:09.785Z","updated_at":"2026-03-09T03:34:43.631Z","avatar_url":"https://github.com/davisdude.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stately\n\n* This is intended to be [stateful] but for [classic].\n* There are some minor differences between __stately__ and [stateful].\n\n# Table of Contents\n\n* [Example](#example)\n* [Installation](#installation)\n* [Differences](#differences)\n* [Functions](#functions)\n* [Specs](#specs)\n\n# Example\n\n```lua\nlocal Class = require 'classic.classic'\nlocal State = require 'stately' ( Class )\n\nlocal Enemy = Class:extend()\n\nfunction Enemy:new( health )\n\tself.health = health\nend\n\nfunction Enemy:speak()\n\treturn 'My health is ' .. tostring( self.health )\nend\n\nlocal Immortal = Enemy:addState( 'Immortal' )\n\n-- Overridden function\nfunction Immortal:speak()\n\treturn 'I am UNBREAKABLE!!'\nend\n\n-- Added function\nfunction Immortal:die()\n\treturn 'I cannot die now!'\nend\n\nlocal peter = Enemy( 10 )\npeter:speak() -- My health is 10\npeter:gotoState( 'Immortal' )\npeter:speak() -- I am UNBREAKABLE!!\npeter:die() -- I cannot die now!\npeter:gotoState() -- Go to default state when nil is passed\npeter:speak() -- My health is 10\npeter:die() -- Error - not a function\n```\n\n# Installation\n\nYou need a copy of [classic] in your project. Then, download this repo and put it in that folder, too.\n\nTo use it, simply require it.\n\n```lua\nlocal Class = require 'path.to.classic'\n-- Make sure to pass the table of classic when you require stately.\nlocal State = require 'path.to.stately' ( Class )\n```\n\nBe __SURE__ to require `classic` _before_ `stately`.\n\n# Differences\n\nThere are some minor differences between __stately__ and [stateful]:\n\n* [Class:gotoState](#classgotostate), [Class:pushState](#classpushstate), and [Class:popState](#classpopstate) all accept the state table return by [Class:addState](#classaddstate) as well as the string used to identify it.\n* There is no need to `:implement` like with [stateful]; instead, you need to pass the table returned by Classic when you `require` it (see [Installation](#installation) for more).\n\n# Functions\n\n### Class:addState\n\n* `State = Class:addState( name, parent )`\n\t* Adds a new state to the class.\n\t* `name`: string. The name of the state.\n\t* `parent`: `nil` or `State`. The parent class that this state should inherit.\n\t* `State`: `State`. The state of the class.\n\n#### State:enteredState\n\n* `function State:enteredState( ... ) end`\n\t* This callback is invoked by [Class:gotoState[(#classgotostate) (if the state to go to is defined) and [Class:pushState](#classpushstate). You can define this function, but cannot call it; it is used internally.\n\t* `State`: `State`. A state object.\n\t* `...`: varargs. Whatever is passed to [Class:gotoState](#classgotostate) or [Class:pushState](#classpushstate).\n\n#### State:exitedState\n\n* `function State:exitedState( ... ) end`\n\t* This callback is invoked by [Class:popState](#classpopstate) (which itself is invoked by [Class:gotoState](#classgotostate) and [Class:popAllStates](#classpopallstates)). You can define this function, but cannot call it; it is used internally.\n\t* `State`: `State`. A state object.\n\t* `...`: varargs. Whatever is passed to [Class:popState](#classpopstate) or [Class:gotoState](#classgotostate) and [Class:popState](#classpopstate).\n\n#### State:pushedState\n\n* `function State:pushedState( ... ) end`\n\t* This callback is invoked by [Class:pushState](#classpushstate). You can define this function, but cannot call it; it is used internally.\n\t* `State`: `State`. A state object.\n\t* `...`: varargs. Whatever is passed to [Class:pushState](#classpushstate).\n\n#### State:poppedState\n\n* `function State:poppedState( ... ) end`\n\t* This callback is invoked by [Class:popState](#classpopstate) (which itself is invoked by [Class:gotoState](#classgotostate) and [Class:popAllStates](#classpopallstates)) . You can define this function, but cannot call it; it is used internally.\n\t* `State`: `State`. A state object.\n\t* `...`: varargs. Whatever is passed to [Class:popState](#classpopstate) and [Class:popAllStates](#classpopallstates).\n\n#### State:pausedState\n\n* `function State:pausedState( ... ) end`\n\t* This callback is invoked by [Class:pushstate](#classpushstate). You can define this function, but cannot call it; it is used internally.\n\t* `State`: `State`. A state object.\n\t* `...`: varargs. Whatever is passed to [Class:pushState](#classpushstate).\n\n#### State:continuedState\n\n* `function State:continuedState( ... ) end`\n\t* This callback is invoked by [Class:popState](#classpopstate) (which itself is invoked by [Class:gotoState](#classgotostate) and [Class:popAllStates](#classpopallstates)). You can define this function, but cannot call it; it is used internally.\n\t* `State`: `State`. A state object.\n\t* `...`: varargs. Whatever is passed to [Class:popState](#classpopstate) or [Class:gotoState](#classgotostate) and [Class:popState](#classpopstate).\n\n### Class:gotoState\n\n* `Class:gotoState( State, ... )`\n\t* [Flushes](#classpopallstates) the current state stack and sets the state.\n\t* `State`: `nil`, string, `State`.\n\t\t* `nil`: Go to the default of the class, with no state set.\n\t\t* string: Go to the state of that name.\n\t\t* `State`: Go to that state object.\n\t* `...`: variables. Data top be passed to any of the other `Class` functions.\n\n### Class:pushState\n\n* `Class:pushState( State, ... )`\n\t* Pushes a new state to the stack.\n\t* `State`: string, `State`.\n\t\t* string: Push the state by that particular name to the stack.\n\t\t* `State`: Push that state to the stack.\n\t* `...`: variables. Data top be passed to any of the other `Class` functions.\n\n### Class:popState\n\n* `Class:popState( State, ... )`\n\t* Pops a specific state from the stack.\n\t* `State`: `nil`, string, `State`.\n\t\t* `nil`: Pop the last state in the stack.\n\t\t* string: Pop the last state in the stack with that particular name.\n\t\t* `State`: Pop the last occurrence of that state in the stack.\n\t* `...`: variables. Data top be passed to any of the other `Class` functions.\n\n### Class:popAllStates\n\n* `Class:popAllStates( ... )`\n\t* Flushes the state stack, [popping](#classpopstate) each class in order as it does so.\n\t* `...`: variables. Data top be passed to any of the other `Class` functions.\n\n### Class:getStateStackDebugInfo\n\n* `info = Class:getStateStackDebugInfo()`\n\t* Gets the names of the states in the stack in the order they were pushed.\n\t* `info`: table. Contains the names of all the states in the order they were pushed.\n\n# Specs\n\nThis project uses [telescope] for the specifications. To run, make sure you can run Lua via the command line.\nNext, within the spec folder, clone in [telescope], then clone in [classic] inside of the folder holding [telescope].\nCopy the files [acceptance_spec.lua](spec/acceptance_spec.lua) and [unit_spec.lua](spec/unit_spec.lua) to that same folder.\nFinally, test each file with the command `lua tsc -f \u003cname.lua\u003e`.\n\nI've automated it with the following file (put in the [spec](spec) folder):\n\n```batch\n@echo off\ncd %~dp0\n\ngit clone https://github.com/norman/telescope\ncopy * telescope\ncopy ..\\stately.lua telescope\\stately.lua\n\npushd telescope\n\ngit clone https://github.com/rxi/classic\n\nlua tsc -f acceptance_spec.lua\npause\n\nlua tsc -f unit_spec.lua\npause\n\npopd\n\nrmdir /s /q telescope\n```\n\nAlternatively, if you already have [telescope] and [classic] installed in the same directory as stately, the following should work:\n\n```batch\n@echo off\npushd %~dp0\\..\\..\\telescope\n\nset p=\"..\\Stately\"\n\ncopy %p%\\spec\\\"*.lua\" \u003e nul\ncopy %p%\\stately.lua \u003e nul\nif not exist classic mkdir classic\ncopy \"..\\classic\\classic.lua\" \"classic\\classic.lua\" \u003e nul\n\nfor %%f in (%p%\\spec\\\"*lua\") do cmd /c \"lua -e \"package.path = './?.lua;' .. package.path\" tsc -f \"%%~nxf\" \u0026 pause\"\n\nfor %%f in (%p%\\spec\\*.lua) do del \"%%~nxf\"\ndel Stately.lua\nrmdir /s /q classic\npopd\n```\n\n[stateful]: https://github.com/kikito/stateful.lua\n[classic]: https://github.com/rxi/classic\n[telescope]: https://github.com/norman/telescope\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavisdude%2Fstately","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavisdude%2Fstately","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavisdude%2Fstately/lists"}