summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Burke <rich.g.burke@gmail.com>2018-12-29 15:25:05 +0000
committerRichard Burke <rich.g.burke@gmail.com>2018-12-29 15:25:05 +0000
commiteb2b83c00de7510d128f1a6d44deb7c802ec686e (patch)
tree3d6bb5dc93c3f28d2a0b4fdf06afc92bf6c89b37
parent9d1119dfdddcbbc18d69056ceba787e61bd269e6 (diff)
Can now execute user defined commands
-rw-r--r--cmd/grv/config.go35
-rw-r--r--cmd/grv/config_parse.go48
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
+}