summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Burke <rich.g.burke@gmail.com>2019-01-10 21:50:45 +0000
committerRichard Burke <rich.g.burke@gmail.com>2019-01-10 21:50:45 +0000
commitd75371247500183e4a1478292632abff60c0613b (patch)
treecfd027231cc75bb0dd7ef930dae5e9e65b56f3b1
parentf6990a7abff56d6b382833fc4caf70c793d1c120 (diff)
Added sleep command
-rw-r--r--cmd/grv/config.go11
-rw-r--r--cmd/grv/config_command_help.go21
-rw-r--r--cmd/grv/config_parse.go30
-rw-r--r--cmd/grv/config_parse_test.go27
-rw-r--r--cmd/grv/grv.go21
-rw-r--r--cmd/grv/key_bindings.go5
-rw-r--r--doc/documentation.md17
7 files changed, 131 insertions, 1 deletions
diff --git a/cmd/grv/config.go b/cmd/grv/config.go
index e54402e..fdb9275 100644
--- a/cmd/grv/config.go
+++ b/cmd/grv/config.go
@@ -538,6 +538,8 @@ func (config *Configuration) processCommand(command ConfigCommand, inputSource s
err = config.processCustomCommand(command)
case *EvalKeysCommand:
err = config.processEvalKeysCommand(command)
+ case *SleepCommand:
+ err = config.processSleepCommand(command)
default:
log.Errorf("Unknown command type %T", command)
}
@@ -958,6 +960,15 @@ func (config *Configuration) processEvalKeysCommand(evalKeysCommand *EvalKeysCom
return
}
+func (config *Configuration) processSleepCommand(sleepCommand *SleepCommand) (err error) {
+ config.channels.DoAction(Action{
+ ActionType: ActionSleep,
+ Args: []interface{}{sleepCommand.sleepSeconds},
+ })
+
+ return
+}
+
func (config *Configuration) runCommand(command string, outputType ShellCommandOutputType) {
NewShellCommandProcessor(config.channels, config.variables, command, outputType).Execute()
}
diff --git a/cmd/grv/config_command_help.go b/cmd/grv/config_command_help.go
index e5825b9..2f5e076 100644
--- a/cmd/grv/config_command_help.go
+++ b/cmd/grv/config_command_help.go
@@ -467,7 +467,28 @@ func GenerateEvalKeysCommandHelpSections(config Config) (helpSections []*HelpSec
{text: "For example, running the following will switch to the next tab:"},
{},
{text: "evalkeys <grv-next-tab>", themeComponentID: CmpHelpViewSectionCodeBlock},
+ }
+
+ return []*HelpSection{
+ {
+ description: description,
+ },
+ }
+}
+
+// GenerateSleepCommandHelpSections generates help documentation for the addtab command
+func GenerateSleepCommandHelpSections(config Config) (helpSections []*HelpSection) {
+ description := []HelpSectionText{
+ {text: "sleep", themeComponentID: CmpHelpViewSectionSubTitle},
+ {},
+ {text: "The sleep command causes grv to pause execution for the provided number of seconds."},
+ {text: "The format of the command is:"},
+ {},
+ {text: "sleep seconds", themeComponentID: CmpHelpViewSectionCodeBlock},
+ {},
+ {text: "For example, running the following will pause execution for 0.5 seconds:"},
{},
+ {text: "sleep 0.5", themeComponentID: CmpHelpViewSectionCodeBlock},
}
return []*HelpSection{
diff --git a/cmd/grv/config_parse.go b/cmd/grv/config_parse.go
index 8261640..5b5db19 100644
--- a/cmd/grv/config_parse.go
+++ b/cmd/grv/config_parse.go
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"regexp"
+ "strconv"
"strings"
"unicode"
@@ -30,6 +31,7 @@ const (
defCommand = "def"
undefCommand = "undef"
evalkeysCommand = "evalkeys"
+ sleepCommand = "sleep"
)
const (
@@ -179,6 +181,13 @@ type EvalKeysCommand struct {
func (evalKeysCommand *EvalKeysCommand) configCommand() {}
+// SleepCommand represents a command to sleep
+type SleepCommand struct {
+ sleepSeconds float64
+}
+
+func (sleepCommand *SleepCommand) configCommand() {}
+
type commandHelpGenerator func(config Config) []*HelpSection
type commandCustomParser func(parser *ConfigParser) (tokens []*ConfigToken, err error)
@@ -299,6 +308,11 @@ var commandDescriptors = map[string]*commandDescriptor{
constructor: evalKeysCommandConstructor,
commandHelpGenerator: GenerateEvalKeysCommandHelpSections,
},
+ sleepCommand: {
+ tokenTypes: []ConfigTokenType{CtkWord},
+ constructor: sleepCommandConstructor,
+ commandHelpGenerator: GenerateSleepCommandHelpSections,
+ },
}
// GenerateConfigCommandHelpSections generates help documentation for all configuration commands
@@ -769,3 +783,19 @@ func evalKeysCommandConstructor(parser *ConfigParser, commandToken *ConfigToken,
keys: keys,
}, nil
}
+
+func sleepCommandConstructor(parser *ConfigParser, commandToken *ConfigToken, tokens []*ConfigToken) (configCommand ConfigCommand, err error) {
+ if len(tokens) < 1 {
+ return nil, parser.generateParseError(commandToken, "No sleep time specified")
+ }
+
+ sleepToken := tokens[0]
+ sleepSeconds, err := strconv.ParseFloat(sleepToken.value, 64)
+ if err != nil || sleepSeconds <= 0.0 {
+ return nil, parser.generateParseError(sleepToken, "Invalid sleep time: %v. Must be a positive integer", sleepToken.value)
+ }
+
+ return &SleepCommand{
+ sleepSeconds: sleepSeconds,
+ }, nil
+}
diff --git a/cmd/grv/config_parse_test.go b/cmd/grv/config_parse_test.go
index a95deb5..6fb0dd4 100644
--- a/cmd/grv/config_parse_test.go
+++ b/cmd/grv/config_parse_test.go
@@ -309,6 +309,23 @@ func (evalKeysCommandValues *EvalKeysCommandValues) Equal(command ConfigCommand)
return evalKeysCommandValues.keys == other.keys
}
+type SleepCommandValues struct {
+ sleepSeconds float64
+}
+
+func (sleepCommandValues *SleepCommandValues) Equal(command ConfigCommand) bool {
+ if command == nil {
+ return false
+ }
+
+ other, ok := command.(*SleepCommand)
+ if !ok {
+ return false
+ }
+
+ return sleepCommandValues.sleepSeconds == other.sleepSeconds
+}
+
func TestParseSingleCommand(t *testing.T) {
var singleCommandTests = []struct {
input string
@@ -462,6 +479,12 @@ func TestParseSingleCommand(t *testing.T) {
keys: "<grv-next-tab><grv-search-prompt>Untracked files<Enter>",
},
},
+ {
+ input: "sleep 0.5",
+ expectedCommand: &SleepCommandValues{
+ sleepSeconds: 0.5,
+ },
+ },
}
for _, singleCommandTest := range singleCommandTests {
@@ -614,6 +637,10 @@ func TestErrorsAreReceivedForInvalidConfigTokenSequences(t *testing.T) {
input: "def myfunc { addview RefView ",
expectedErrorMessage: ConfigFile + ":1:29 Expected } but reached EOF",
},
+ {
+ input: "sleep -5",
+ expectedErrorMessage: ConfigFile + ":1:7 Invalid sleep time: -5. Must be a positive integer",
+ },
}
for _, errorTest := range errorTests {
diff --git a/cmd/grv/grv.go b/cmd/grv/grv.go
index 1b71a29..393e45b 100644
--- a/cmd/grv/grv.go
+++ b/cmd/grv/grv.go
@@ -485,6 +485,10 @@ func (grv *GRV) runHandlerLoop(waitGroup *sync.WaitGroup, exitCh <-chan bool, in
if err := grv.runCommand(action); err != nil {
errorCh <- err
}
+ case ActionSleep:
+ if err := grv.sleep(action); err != nil {
+ errorCh <- err
+ }
default:
if err := grv.view.HandleAction(action); err != nil {
errorCh <- err
@@ -585,6 +589,23 @@ func (grv *GRV) runCommand(action Action) (err error) {
return
}
+func (grv *GRV) sleep(action Action) (err error) {
+ if len(action.Args) == 0 {
+ return fmt.Errorf("Expected sleep seconds argument")
+ }
+
+ sleepSeconds, ok := action.Args[0].(float64)
+ if !ok {
+ return fmt.Errorf("Expected sleep seconds of type float64 but found type %T", action.Args[0])
+ }
+
+ log.Infof("Sleeping for %v seconds", sleepSeconds)
+ time.Sleep(time.Duration(sleepSeconds*1000) * time.Millisecond)
+ log.Infof("Finished sleeping")
+
+ return
+}
+
func (grv *GRV) runSignalHandlerLoop(waitGroup *sync.WaitGroup, exitCh <-chan bool) {
defer waitGroup.Done()
defer log.Info("Signal handler loop stopping")
diff --git a/cmd/grv/key_bindings.go b/cmd/grv/key_bindings.go
index dc839c4..8a9fdcb 100644
--- a/cmd/grv/key_bindings.go
+++ b/cmd/grv/key_bindings.go
@@ -30,6 +30,7 @@ const (
ActionExit
ActionSuspend
ActionRunCommand
+ ActionSleep
ActionPrompt
ActionSearchPrompt
ActionReverseSearchPrompt
@@ -148,6 +149,10 @@ var actionDescriptors = map[ActionType]ActionDescriptor{
actionCategory: ActionCategoryGeneral,
description: "Run a shell command",
},
+ ActionSleep: {
+ actionCategory: ActionCategoryGeneral,
+ description: "Sleep for a specified time",
+ },
ActionPrompt: {
actionKey: "<grv-prompt>",
actionCategory: ActionCategoryGeneral,
diff --git a/doc/documentation.md b/doc/documentation.md
index edcb981..3991721 100644
--- a/doc/documentation.md
+++ b/doc/documentation.md
@@ -37,6 +37,7 @@ The sections below provide an overview of the ways to configure and interact wit
* [q](#q)
* [rmtab](#rmtab)
* [set](#set)
+ * [sleep](#sleep)
* [split](#split)
* [theme](#theme)
* [undef](#undef)
@@ -350,7 +351,6 @@ For example, running the following will switch to the next tab:
evalkeys <grv-next-tab>
```
-
### git
The git command is an alias to the git cli command.
@@ -467,6 +467,21 @@ GRV currently has the following themes available:
The solarized theme is the default theme for GRV and does not respect the terminals colour palette.
The classic and cold themes do respect the terminals colour palette.
+### sleep
+
+The sleep command causes grv to pause execution for the provided number of seconds.
+The format of the command is:
+
+```
+sleep seconds
+```
+
+For example, running the following will pause execution for 0.5 seconds:
+
+```
+sleep 0.5
+```
+
### split
The split command is similar to the vsplit and hsplit commands.