diff options
author | Richard Burke <rich.g.burke@gmail.com> | 2018-12-29 15:25:05 +0000 |
---|---|---|
committer | Richard Burke <rich.g.burke@gmail.com> | 2018-12-29 15:25:05 +0000 |
commit | eb2b83c00de7510d128f1a6d44deb7c802ec686e (patch) | |
tree | 3d6bb5dc93c3f28d2a0b4fdf06afc92bf6c89b37 | |
parent | 9d1119dfdddcbbc18d69056ceba787e61bd269e6 (diff) |
Can now execute user defined commands
-rw-r--r-- | cmd/grv/config.go | 35 | ||||
-rw-r--r-- | cmd/grv/config_parse.go | 48 |
2 files changed, 80 insertions, 3 deletions
diff --git a/cmd/grv/config.go b/cmd/grv/config.go index c5df0ff..1712966 100644 --- a/cmd/grv/config.go +++ b/cmd/grv/config.go @@ -315,14 +315,16 @@ type Configuration struct { grvConfigDir string channels Channels variables GRVVariableGetter + customCommands map[string]string } // NewConfiguration creates a Configuration instance with default values func NewConfiguration(keyBindings KeyBindings, channels Channels, variables GRVVariableGetter) *Configuration { config := &Configuration{ - keyBindings: keyBindings, - channels: channels, - variables: variables, + keyBindings: keyBindings, + channels: channels, + variables: variables, + customCommands: map[string]string{}, themes: map[string]MutableTheme{ cfClassicThemeName: NewClassicTheme(), cfColdThemeName: NewColdTheme(), @@ -515,6 +517,10 @@ func (config *Configuration) processCommand(command ConfigCommand, inputSource s config.processHelpCommand() case *ShellCommand: err = config.processShellCommand(command, inputSource) + case *DefCommand: + err = config.processDefCommand(command) + case *CustomCommand: + err = config.processCustomCommand(command) default: log.Errorf("Unknown command type %T", command) } @@ -833,6 +839,29 @@ func (config *Configuration) processShellCommand(shellCommand *ShellCommand, inp return } +func (config *Configuration) processDefCommand(defCommand *DefCommand) (err error) { + if err = DefineCustomCommand(defCommand.commandName); err != nil { + return + } + + config.customCommands[defCommand.commandName] = defCommand.functionBody + return +} + +func (config *Configuration) processCustomCommand(customCommand *CustomCommand) (err error) { + commandBody, ok := config.customCommands[customCommand.commandName] + if !ok { + return fmt.Errorf("No command with name %v exists", customCommand.commandName) + } + + if errs := config.Evaluate(commandBody); len(errs) > 0 { + config.channels.ReportErrors(errs) + err = fmt.Errorf("Command %v generated errors", customCommand.commandName) + } + + return +} + func (config *Configuration) runCommand(command string, outputType ShellCommandOutputType) { NewShellCommandProcessor(config.channels, config.variables, command, outputType).Execute() } diff --git a/cmd/grv/config_parse.go b/cmd/grv/config_parse.go index f71e1aa..1aec5d8 100644 --- a/cmd/grv/config_parse.go +++ b/cmd/grv/config_parse.go @@ -141,6 +141,14 @@ type DefCommand struct { func (defCommand *DefCommand) configCommand() {} +// CustomCommand represents an invocation of a user defined command +type CustomCommand struct { + commandName string + args []string +} + +func (customCommand *CustomCommand) configCommand() {} + type commandHelpGenerator func(config Config) []*HelpSection type commandCustomParser func(parser *ConfigParser) (tokens []*ConfigToken, err error) @@ -149,6 +157,33 @@ type commandDescriptor struct { constructor commandConstructor commandHelpGenerator commandHelpGenerator customParser commandCustomParser + userDefined bool +} + +// DefineCustomCommand allows a custom command to be parsed +func DefineCustomCommand(commandName string) (err error) { + if existingDescriptor, ok := commandDescriptors[commandName]; ok && !existingDescriptor.userDefined { + return fmt.Errorf("Cannot override built in command %v", commandName) + } + + commandDescriptors[commandName] = &commandDescriptor{ + customParser: parseVarArgsCommand, + constructor: customCommandConstructor, + userDefined: true, + } + + return +} + +// UndefineCustomCommand invalidates a custom command +func UndefineCustomCommand(commandName string) (err error) { + if existingDescriptor, ok := commandDescriptors[commandName]; ok && !existingDescriptor.userDefined { + return fmt.Errorf("Cannot undefine built in command %v", commandName) + } + + delete(commandDescriptors, commandName) + + return } var commandDescriptors = map[string]*commandDescriptor{ @@ -633,3 +668,16 @@ func defCommandConstructor(parser *ConfigParser, commandToken *ConfigToken, toke return } + +func customCommandConstructor(parser *ConfigParser, commandToken *ConfigToken, tokens []*ConfigToken) (configCommand ConfigCommand, err error) { + var args []string + + for _, token := range tokens { + args = append(args, token.value) + } + + return &CustomCommand{ + commandName: commandToken.value, + args: args, + }, nil +} |