aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--golings/cmd/root.go2
-rw-r--r--golings/cmd/run.go34
-rw-r--r--golings/cmd/watch.go140
4 files changed, 119 insertions, 62 deletions
diff --git a/Makefile b/Makefile
index aa8bce3..5202e86 100644
--- a/Makefile
+++ b/Makefile
@@ -2,4 +2,7 @@ test:
@cd golings && go test -coverprofile=coverage.out -v $$(go list ./... | grep -v fixtures/error1)
watch:
- @go run golings/golings.go watch \ No newline at end of file
+ @go run golings/golings.go watch
+
+run:
+ @go run golings/golings.go run \ No newline at end of file
diff --git a/golings/cmd/root.go b/golings/cmd/root.go
index 9869013..23b4583 100644
--- a/golings/cmd/root.go
+++ b/golings/cmd/root.go
@@ -19,7 +19,7 @@ func NewRootCmd(version string) *cobra.Command {
rootCmd.AddCommand(ListCmd("info.toml"))
rootCmd.AddCommand(RunCmd("info.toml"))
rootCmd.AddCommand(VerifyCmd("info.toml"))
- rootCmd.AddCommand(WatchCmd())
+ rootCmd.AddCommand(WatchCmd("info.toml"))
return rootCmd
}
diff --git a/golings/cmd/run.go b/golings/cmd/run.go
index 552c234..7d5fef8 100644
--- a/golings/cmd/run.go
+++ b/golings/cmd/run.go
@@ -27,20 +27,7 @@ func RunCmd(infoFile string) *cobra.Command {
exercise, err = exercises.Find(args[0], infoFile)
}
- spinner := progressbar.NewOptions(
- -1, // a negative number makes turns the progress bar into a spinner
- progressbar.OptionEnableColorCodes(true),
- progressbar.OptionSetDescription(color.WhiteString("Running exercise: %s", exercise.Name)),
- progressbar.OptionOnCompletion(func() {
- color.White("\nRunning complete!\n\n")
- }),
- )
- go func() {
- for x := 0; x < 100; x++ {
- spinner.Add(1) // nolint
- time.Sleep(250 * time.Millisecond)
- }
- }()
+ spinner := RunSpinner(exercise.Name)
if errors.Is(err, exercises.ErrExerciseNotFound) {
color.White("No exercise found for '%s'", args[0])
@@ -71,3 +58,22 @@ func RunCmd(infoFile string) *cobra.Command {
},
}
}
+
+func RunSpinner(exercise string) *progressbar.ProgressBar {
+ spinner := progressbar.NewOptions(
+ -1, // a negative number makes turns the progress bar into a spinner
+ progressbar.OptionEnableColorCodes(true),
+ progressbar.OptionSetDescription(color.WhiteString("Running exercise: %s", exercise)),
+ progressbar.OptionOnCompletion(func() {
+ color.White("\nRunning complete!\n\n")
+ }),
+ )
+ go func() {
+ for x := 0; x < 100; x++ {
+ spinner.Add(1) // nolint
+ time.Sleep(250 * time.Millisecond)
+ }
+ }()
+
+ return spinner
+}
diff --git a/golings/cmd/watch.go b/golings/cmd/watch.go
index 9e159dd..4d68060 100644
--- a/golings/cmd/watch.go
+++ b/golings/cmd/watch.go
@@ -1,78 +1,126 @@
package cmd
import (
+ "bufio"
"fmt"
"io/fs"
"log"
"os"
- "os/exec"
"path/filepath"
+ "strings"
+ "github.com/fatih/color"
"github.com/fsnotify/fsnotify"
+ "github.com/mauricioabreu/golings/golings/exercises"
+ "github.com/mauricioabreu/golings/golings/ui"
"github.com/spf13/cobra"
)
-func WatchCmd() *cobra.Command {
+func WatchCmd(infoFile string) *cobra.Command {
return &cobra.Command{
Use: "watch",
Short: "Run a single exercise",
- Run: func(cmd *cobra.Command, args []string) {
+ RunE: func(cmd *cobra.Command, args []string) error {
log.Println("Create watcher")
- watcher, err := fsnotify.NewWatcher()
- if err != nil {
- log.Fatal(err)
- }
- defer watcher.Close()
+ reader := bufio.NewReader(os.Stdin)
+ update := make(chan bool)
+
+ for {
+ go WatchEvents(update)
- path, _ := os.Getwd()
- file_path := fmt.Sprintf("%s/exercises", path)
+ for <-update {
+ exercise, err := exercises.NextPending(infoFile)
+ result, err := exercise.Run()
+
+ if err != nil {
+ color.Cyan("Failed to compile the exercise %s\n\n", result.Exercise.Path)
+ color.White("Check the output below: \n\n")
+ color.Red(result.Err)
+ color.Red(result.Out)
+ color.Yellow("If you feel stuck, ask a hint by executing `golings hint %s`", result.Exercise.Name)
+ } else {
+ color.Green("Congratulations!\n\n")
+ color.Green("Here is the output of your program:\n\n")
+ color.Cyan(result.Out)
+ if result.Exercise.State() == exercises.Pending {
+ color.White("Remove the 'I AM NOT DONE' from the file to keep going\n")
+ return fmt.Errorf("exercise is still pending")
+ }
+ }
+ }
+
+ color.Yellow("$")
+ cmdString, err := reader.ReadString('\n')
- err = filepath.WalkDir(file_path, func(path_dir string, d fs.DirEntry, err error) error {
if err != nil {
- log.Fatal(err)
- return err
+ fmt.Fprintln(os.Stderr, err)
}
- if d.IsDir() {
- err = watcher.Add(path_dir)
+ cmdStr := strings.TrimSuffix(cmdString, "\n")
+ log.Println("CMDr")
+ switch cmdStr {
+ case "list":
+ log.Println("List command", cmdString)
+ exs, err := exercises.List(infoFile)
if err != nil {
- log.Fatal(err)
+ color.Red(err.Error())
+ os.Exit(1)
}
+ ui.PrintList(os.Stdout, exs)
+ default:
+ fmt.Errorf("ERROR :/")
}
- return nil
- })
+ }
+ },
+ }
+}
+
+func WatchEvents(updateF chan<- bool) {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer watcher.Close()
+
+ path, _ := os.Getwd()
+ file_path := fmt.Sprintf("%s/exercises", path)
+
+ err = filepath.WalkDir(file_path, func(path_dir string, d fs.DirEntry, err error) error {
+ if err != nil {
+ log.Fatal(err)
+ return err
+ }
+ if d.IsDir() {
+ err = watcher.Add(path_dir)
if err != nil {
- log.Fatal("Error in file path:", err.Error())
+ log.Fatal(err)
}
+ }
+ return nil
+ })
- // Start listening for events.
- go func() {
- for {
- select {
- case event, ok := <-watcher.Events:
- if !ok {
- return
- }
- log.Println("event:", event)
- if event.Has(fsnotify.Write) {
- log.Println("modified file:", event.Name)
- cmd := exec.Command("golings run next")
- if err := cmd.Run(); err != nil {
- log.Fatal(err)
- }
- }
- case err, ok := <-watcher.Errors:
- if !ok {
- return
- }
- log.Println("error:", err)
- }
+ if err != nil {
+ log.Fatal("Error in file path:", err.Error())
+ }
+
+ // Start listening for events.
+ go func() {
+ for {
+ select {
+ case event, ok := <-watcher.Events:
+ if !ok {
+ return
+ }
+ // log.Println("event:", event)
+ if event.Has(fsnotify.Write) {
+ log.Println("modified file:", event.Name)
+ updateF <- true
}
- }()
+ }
+ }
+ }()
- // Block main goroutine forever.
- <-make(chan struct{})
- },
- }
+ // Block main goroutine forever.
+ <-make(chan struct{})
}