package shell type State interface { Variable(string) string Command(string) CommandExecutor Env(string) string Pushd(string) error Popd() error Cwd() string SetVariable(string, string) SetCommand(string, CommandExecutor) SetEnv(string, string) Clone() State } func NewShellState() *ShellState { return &ShellState{ variables: map[string]string{}, commands: map[string]CommandExecutor{}, env: map[string]string{}, dirstack: []string{}, } } type ShellState struct { variables map[string]string commands map[string]CommandExecutor env map[string]string dirstack []string } func (s *ShellState) Variable(n string) string { if v, ok := s.variables[n]; ok { return v } return "" } func (s *ShellState) Command(n string) CommandExecutor { if v, ok := s.commands[n]; ok { return v } return nil } func (s *ShellState) Env(n string) string { if v, ok := s.env[n]; ok { return v } return "" } func (s *ShellState) SetVariable(n string, v string) { s.variables[n] = v } func (s *ShellState) SetCommand(n string, e CommandExecutor) { s.commands[n] = e } func (s *ShellState) SetEnv(n string, v string) { s.env[n] = v } func (s *ShellState) Pushd(dir string) error { s.dirstack = append([]string{dir}, s.dirstack...) return nil } func (s *ShellState) Popd() error { if len(s.dirstack) == 0 { return nil } s.dirstack = s.dirstack[1:] return nil } func (s *ShellState) Cwd() string { if len(s.dirstack) == 0 { return "" } return s.dirstack[0] } func (s *ShellState) Clone() State { state := NewShellState() for k, v := range s.commands { state.SetCommand(k, v) } for k, v := range s.variables { state.SetVariable(k, v) } for k, v := range s.env { state.SetEnv(k, v) } state.dirstack = make([]string, len(s.dirstack)) copy(s.dirstack, state.dirstack) return state }