2022-01-13 14:15:05 +00:00
|
|
|
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
|
|
|
|
|
2022-01-13 18:57:39 +00:00
|
|
|
// Desc is the command description
|
|
|
|
Desc string
|
|
|
|
|
2022-01-13 14:15:05 +00:00
|
|
|
// StateF is the command handler function
|
|
|
|
F interface{}
|
|
|
|
|
|
|
|
stateID int
|
|
|
|
states map[State]State
|
|
|
|
statesFunc map[State]interface{}
|
|
|
|
initState, lastState State
|
|
|
|
}
|
|
|
|
|
2022-01-13 18:57:39 +00:00
|
|
|
func NewCommand(name, desc string, f interface{}) *Command {
|
2022-01-13 14:15:05 +00:00
|
|
|
c := &Command{
|
|
|
|
Name: name,
|
2022-01-13 18:57:39 +00:00
|
|
|
Desc: desc,
|
2022-01-13 14:15:05 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-01-13 16:17:41 +00:00
|
|
|
func (c *Command) NamedNext(n State, f interface{}) *Command {
|
2022-01-13 14:15:05 +00:00
|
|
|
var curState State
|
|
|
|
if c.lastState == "" {
|
|
|
|
curState = State(c.Name + "_" + strconv.Itoa(c.stateID))
|
|
|
|
} else {
|
|
|
|
curState = c.lastState
|
|
|
|
}
|
|
|
|
|
2022-01-13 16:17:41 +00:00
|
|
|
nextState := n
|
2022-01-13 14:15:05 +00:00
|
|
|
c.states[curState] = nextState
|
|
|
|
c.statesFunc[curState] = f
|
|
|
|
c.lastState = nextState
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2022-01-14 19:06:36 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-01-13 14:15:05 +00:00
|
|
|
// 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
|
|
|
|
}
|