Skip to content

outlandinc/state-machine-cat

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

217 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

State Machine cat

smcat turns your text into state charts

build status coverage report npm stable version GPLv3 licensed

What?

Makes this

doc/sample.png

from this

initial,
doing: entry/ write unit test
       do/ write code
       exit/ ...,
# smcat recognizes initial
# and final states by name
# and renders them appropriately
final;

initial      => "on backlog" : item adds most value;
"on backlog" => doing        : working on it;
doing        => testing      : built & unit tested;
testing      => "on backlog" : test not ok;
testing      => final        : test ok;

Why

To enable me to make state charts ...

  • ... that look good
  • ... with the least effort possible
  • ... whithout having to interact with drag and drop tools. Entering text is fine, doing my own layout is not.
  • ... without having to dive into GraphViz dot each time. GraphViz is cool, but is was not designed to write & maintain conceptual documents in (You'll know what I'm talking about if you ever tried to get it to draw nested nodes. Or edges between those. )

Usage

On line

A no-frills interpreter on line: sverweij.gitlab.io/state-machine-cat.

Within the Atom editor

There's an Atom package with syntax highlighting, a previewer and some export options. You can install it from within Atom (search for state machine cat in the install section of the settings screen) or use apm i state-machine-cat-preview if you're a command line person.

OTOH. if you're a command line person the command line interface might be something for you too:

Command line interface

Just npm install --global state-machine-cat and run smcat

This is what smcat --help would get you:

Usage: smcat [options] [infile]

Options:

  -h, --help               output usage information
  -V, --version            output the version number
  -T --output-type <type>  smcat|dot|json|ast|svg. Default: svg
  -I --input-type <type>   smcat|json. Default: smcat
  -E --engine <type>       dot|circo|fdp|neato|osage|twopi. Default: dot
  -i --input-from <file>   File to read from. use - for stdin.
  -o --output-to <file>    File to write to. use - for stdout.
  -l --license             Display license and exit

... so to convert the above chart to sample.svg

bin/smcat doc/sample.smcat

Or, if you'd rather have the native GraphViz dot do that for you:

bin/smcat -T dot doc/sample.smcat -o - | dot -T svg -odoc/sample.svg

Leaving the options at the default settings usually deliver the best results already, so if they bewilder you: don't worry.

Programmatically

After you npm i 'd state-machine-cat:

const smcat = require("state-machine-cat");

smcat.render(
    `
        initial => backlog;
        backlog => doing;
        doing => test;
    `,
    {
        outputType: "svg"
    },
    (pError, pSuccess) => console.log(pError || pSuccess)
);

The language

Short tutorial

simplest

on => off;

rendition

  • smcat automatically declares the states. You can explicitly declare them if you want them to have more than a name only - see explicit state declarations below.

labels

on => off: switch;

rendition

UML prescribes to place conditions after events, to place conditions within squares and to place actions after a /: on => off: switch flicked [not an emergency]/ light off;.

You're free to do so, but smcat doesn't check for it. It might take the notation into account somewhere in the future (although I see no reason to make it mandatory).

on => off: switch flicked/
           light off;
off => on: switch flicked/
           light on;

rendition

notes

# this is a note
on => off;

rendition

explicit state declarations

# yep, notes get rendered here as well
# multiple notes translate into multiple
# lines in notes in the diagram
doing: pick up
       ...;

rendition

initial and final

When you name a state initial or final, smcat treats them as the UML 'pseudo states' for inital and final:

initial => todo;
todo    => doing;
doing   => done;
done    => final;

rendition

Choice - ^

smcat treats states starting with ^ as UML pseudo state choice. Strictly speaking 'choice' is a superfluous element of the UML state machine specification, but it is there and sometimes it makes diagrams easier to read.

^fraud?: transaction fraudulent?;

initial -> reserved;
reserved -> quoted:
    quote
    requested;
quoted -> ^fraud?: payment;
^fraud? -> ticketed: [no];
^fraud? -> removed: [yes];
ticketed -> final;
removed -> final;

rendition

Forks and joins - ]

In UML you can fork state transitions into multiple or join them into one with the fork and join pseudo states. Both of them are represented by a black bar. To make a join or fork pseudo state, start its name with a ]. Here's an example of a join:

a => ]join;
b => ]join;
]join => c;

rendition

Gotchas

  • when you need ;, ,, { or spaces as part of a state - place em in quotes "a state"
  • Activities have the same restriction, except they allow spaces.
  • Labels have the same restriction as activities, except they allow for , too.
  • State declaration precedence is: deep wins from shallow; explicit wins from implicit
  • It's possible to declare the same state multiple times on the same level, buts smcat will take the last declaration into account only. For example:

This

# first declaration of "cool state"
"cool state",
"other state",
# second declaration of "cool state"
"cool state": cool down;

results in (/ is equivalent to):

# second declaration of "cool state"
"cool state": cool down,
"other state";

nested state machines

It's possible to have state machines within states. the states stopped, playing and pause can only occur when the tape player is on:

initial,
"tape player off",
"tape player on" {
  stopped => playing : play;
  playing => stopped : stop;
  playing => paused  : pause;
  paused  => playing : pause;
  paused  => stopped : stop;
};

initial           => "tape player off";
"tape player off" => stopped           : power;
"tape player on"  => "tape player off" : power;

rendition

grammar

I made the parser with pegjs - you can find it at src/parse/peg/smcat-parser.pegjs

Status

  • Thoroughly tested and good enough for public use.
  • Despite this you might bump into the occasional issue - don't hesitate to report it, either on GitLab or on GitHub.
  • It's also an 1.x.x version - so I might change some things around (always respectful of the semantic versioning guidelines).

doc/pic/smcat-full-small.png

About

turns text into state charts

Resources

License

Unknown, GPL-3.0 licenses found

Licenses found

Unknown
LICENSE.md
GPL-3.0
COPYING

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 90.8%
  • Makefile 4.9%
  • HTML 3.6%
  • Shell 0.7%