90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
|
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
|
||
|
}
|