// Fetch returns exercism problems. func Fetch(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } client := api.NewClient(c) problems, err := client.Fetch(ctx.Args()) if err != nil { log.Fatal(err) } submissionInfo, err := client.Submissions() if err != nil { log.Fatal(err) } if err := setSubmissionState(problems, submissionInfo); err != nil { log.Fatal(err) } hw := user.NewHomework(problems, c) if err := hw.Save(); err != nil { log.Fatal(err) } hw.Summarize(user.HWAll) }
// Tracks lists available tracks. func Tracks(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } client := api.NewClient(c) tracks, err := client.Tracks() if err != nil { log.Fatal(err) } curr := user.NewCurriculum(tracks) fmt.Println("\nActive language tracks:") curr.Report(user.TrackActive) fmt.Println("\nInactive language tracks:") curr.Report(user.TrackInactive) // TODO: implement `list` command to list problems in a track msg := ` Related commands: hootcode fetch (see 'hootcode help fetch') ` fmt.Println(msg) }
// Unsubmit deletes an iteration from the api. // If no iteration is specified, the most recent iteration // is deleted. func Unsubmit(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } if !c.IsAuthenticated() { log.Fatal(msgPleaseAuthenticate) } client := api.NewClient(c) if err := client.Unsubmit(); err != nil { log.Fatal(err) } fmt.Println("Your most recent submission was successfully deleted.") }
func Open(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } client := api.NewClient(c) args := ctx.Args() if len(args) != 2 { msg := "Usage: hootcode open LANGUAGE EXERCISE" log.Fatal(msg) } language := args[0] exercise := args[1] submission, err := client.Submission(language, exercise) if err != nil { log.Fatal(err) } url := submission.URL // Escape characters not allowed by cmd/bash switch runtime.GOOS { case "windows": url = strings.Replace(url, "&", `^&`, -1) default: url = strings.Replace(url, "&", `\&`, -1) } // setup command to open browser var cmd *exec.Cmd switch runtime.GOOS { case "darwin": cmd = exec.Command("open", url) case "freebsd", "linux", "netbsd", "openbsd": cmd = exec.Command("xdg-open", url) case "windows": cmd = exec.Command("cmd", "/c", "start", url) } if err := cmd.Run(); err != nil { log.Fatal(err) } }
// Restore returns a user's solved problems. func Restore(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } client := api.NewClient(c) problems, err := client.Restore() if err != nil { log.Fatal(err) } hw := user.NewHomework(problems, c) if err := hw.Save(); err != nil { log.Fatal(err) } hw.Summarize(user.HWNotSubmitted) }
// Debug provides information about the user's environment and configuration. func Debug(ctx *cli.Context) { defer fmt.Printf("\nIf you are having trouble and need to file a GitHub issue (https://github.com/exercism/exercism.io/issues) please include this information (except your API key. Keep that private).\n") fmt.Printf("\n**** Debug Information ****\n") fmt.Printf("Exercism CLI Version: %s\n", ctx.App.Version) fmt.Printf("OS/Architecture: %s/%s\n", runtime.GOOS, runtime.GOARCH) dir, err := config.Home() if err != nil { log.Fatal(err) } fmt.Printf("Home Dir: %s\n", dir) c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } configured := true if _, err = os.Stat(c.File); err != nil { if os.IsNotExist(err) { configured = false } else { log.Fatal(err) } } if configured { fmt.Printf("Config file: %s\n", c.File) fmt.Printf("API Key: %s\n", c.APIKey) } else { fmt.Println("Config file: <not configured>") fmt.Println("API Key: <not configured>") } client := http.Client{Timeout: 5 * time.Second} fmt.Printf("API: %s [%s]\n", c.API, pingUrl(client, c.API)) fmt.Printf("XAPI: %s [%s]\n", c.XAPI, pingUrl(client, c.XAPI)) fmt.Printf("Exercises Directory: %s\n", c.Dir) }
// Demo returns one problem for each active track. func Demo(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } client := api.NewClient(c) problems, err := client.Demo() if err != nil { log.Fatal(err) } hw := user.NewHomework(problems, c) if err := hw.Save(); err != nil { log.Fatal(err) } hw.Report(user.HWAll) fmt.Println("Next step: choose a language, read the README, and make the test suite pass.") }
// Download returns specified submissions and related problem. func Download(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } client := api.NewClient(c) args := ctx.Args() if len(args) != 1 { msg := "Usage: hootcode download SUBMISSION_ID" log.Fatal(msg) } submission, err := client.Download(args[0]) if err != nil { log.Fatal(err) } path := filepath.Join(c.Dir, "solutions", submission.Username, submission.Language, submission.Slug, args[0]) if err := os.MkdirAll(path, 0755); err != nil { log.Fatal(err) } for name, contents := range submission.ProblemFiles { if err := ioutil.WriteFile(fmt.Sprintf("%s/%s", path, name), []byte(contents), 0755); err != nil { log.Fatal(err) } } for name, contents := range submission.SolutionFiles { if err := ioutil.WriteFile(fmt.Sprintf("%s/%s", path, name), []byte(contents), 0755); err != nil { log.Fatal(err) } } fmt.Printf("Successfully downloaded submission.\n\nThe submission can be viewed at:\n %s\n\n", path) }
// Configure stores settings in a JSON file. // If a setting is not passed as an argument, default // values are used. func Configure(ctx *cli.Context) { c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } key := ctx.String("key") host := ctx.String("host") dir := ctx.String("dir") api := ctx.String("api") c.Update(key, host, dir, api) if err := os.MkdirAll(c.Dir, os.ModePerm); err != nil { log.Fatalf("Error creating hootcode directory %s\n", err) } if err := c.Write(); err != nil { log.Fatal(err) } fmt.Printf("The configuration has been written to %s\n", c.File) fmt.Printf("Your exercises directory can be found at %s\n", c.Dir) }
// Submit posts an iteration to the api func Submit(ctx *cli.Context) { if len(ctx.Args()) == 0 { log.Fatal("Please enter a file name") } c, err := config.New(ctx.GlobalString("config")) if err != nil { log.Fatal(err) } if ctx.GlobalBool("debug") { log.Printf("Exercises dir: %s", c.Dir) dir, err := os.Getwd() if err != nil { log.Printf("Unable to get current working directory - %s", err) } else { log.Printf("Current dir: %s", dir) } } if !c.IsAuthenticated() { log.Fatal(msgPleaseAuthenticate) } dir, err := filepath.EvalSymlinks(c.Dir) if err != nil { log.Fatal(err) } if ctx.GlobalBool("debug") { log.Printf("eval symlinks (dir): %s", dir) } files := []string{} for _, filename := range ctx.Args() { if ctx.GlobalBool("debug") { log.Printf("file name: %s", filename) } if isTest(filename) { log.Fatal("Please submit the solution, not the test file.") } file, err := filepath.Abs(filename) if err != nil { log.Fatal(err) } if ctx.GlobalBool("debug") { log.Printf("absolute path: %s", file) } file, err = filepath.EvalSymlinks(file) if err != nil { log.Fatal(err) } if ctx.GlobalBool("debug") { log.Printf("eval symlinks (file): %s", file) } files = append(files, file) } iteration, err := api.NewIteration(dir, files) if err != nil { log.Fatalf("Unable to submit - %s", err) } iteration.Key = c.APIKey client := api.NewClient(c) submission, err := client.Submit(iteration) if err != nil { log.Fatal(err) } msg := ` Submitted %s in %s. Your submission can be found online at %s To get the next exercise, run "hootcode fetch" again. ` fmt.Printf(msg, submission.Name, submission.Language, submission.URL) }