From 14c21d6747bbcc5bbc46387f8732480a3512f869 Mon Sep 17 00:00:00 2001 From: lalizita Date: Mon, 9 Jan 2023 21:45:02 -0300 Subject: Add watch command and listener test --- Makefile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 020bc08..aa8bce3 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ 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 -- cgit v1.2.3-70-g09d2 From 1358ddbc59bd5706ff78888725e98c3868256a40 Mon Sep 17 00:00:00 2001 From: lalizita Date: Mon, 27 Feb 2023 21:06:06 -0300 Subject: Add list command and a channel for watch file events --- Makefile | 5 +- golings/cmd/root.go | 2 +- golings/cmd/run.go | 34 +++++++------ golings/cmd/watch.go | 140 ++++++++++++++++++++++++++++++++++----------------- 4 files changed, 119 insertions(+), 62 deletions(-) (limited to 'Makefile') 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{}) } -- cgit v1.2.3-70-g09d2