package interact import "strconv" // Command is a domain specific language syntax helper // It's used for helping developer define the state and transition function type Command struct { // Name is the command name Name string // Desc is the command description Desc string // StateF is the command handler function F interface{} stateID int states map[State]State statesFunc map[State]interface{} initState, lastState State } func NewCommand(name, desc string, f interface{}) *Command { c := &Command{ Name: name, Desc: desc, F: f, states: make(map[State]State), statesFunc: make(map[State]interface{}), initState: State(name + "_" + strconv.Itoa(0)), } return c.Next(f) } // Transit defines the state transition that is not related to the last defined state. func (c *Command) Transit(state1, state2 State, f interface{}) *Command { c.states[state1] = state2 c.statesFunc[state1] = f return c } func (c *Command) NamedNext(n State, f interface{}) *Command { var curState State if c.lastState == "" { curState = State(c.Name + "_" + strconv.Itoa(c.stateID)) } else { curState = c.lastState } nextState := n c.states[curState] = nextState c.statesFunc[curState] = f c.lastState = nextState return c } func (c *Command) Cycle(f interface{}) *Command { var curState State if c.lastState == "" { curState = State(c.Name + "_" + strconv.Itoa(c.stateID)) } else { curState = c.lastState } nextState := curState c.states[curState] = nextState c.statesFunc[curState] = f c.lastState = nextState return c } // Next defines the next state with the transition function from the last defined state. func (c *Command) Next(f interface{}) *Command { var curState State if c.lastState == "" { curState = State(c.Name + "_" + strconv.Itoa(c.stateID)) } else { curState = c.lastState } // generate the next state by the stateID c.stateID++ nextState := State(c.Name + "_" + strconv.Itoa(c.stateID)) c.states[curState] = nextState c.statesFunc[curState] = f c.lastState = nextState return c }