Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add list command #1113

Closed
wants to merge 1 commit into from
Closed

Add list command #1113

wants to merge 1 commit into from

Conversation

baduker
Copy link
Contributor

@baduker baduker commented Sep 19, 2023

List all Exercism tracks, exercises implementation, and download selected exercises.

What does this PR do?

The PR implements a feature in the exercism-cli for listing all the available Exercism tracks and exercises based on the given track and difficulty level. It also allows the users to download the list of exercises for a specific track and difficulty level.

Changes Made:

  • Added a new command, list, to the CLI. This command can take the following flags --track, --all, --level, and --download.
  • Implemented validation of the track names and difficulty levels using predefined maps and sets.
  • Added a new feature to download all the exercises for a given track and difficulty level, provided the user is eligible for given exercises
  • Implemented sorting of exercises based on difficulty.
  • Updated the CLI documentation to add the usage of the list command.
  • Refactored downlaod.go command for readability
  • Added new function MakeRequest to api.go

Related Issue:

How to test it?

  • Check out the feature branch (on my fork): add-list-command
  • Run go build exercism/main.go
  • Run ./main configure --token=YOUR_TOKEN_VALUE

Start testing the new command.

Note: the results will be different because the CLI shows tracks and exercises available to a given user.

List your tracks: Run ./main list

This should return:

+-----------------+--------+-----------+-----------+----------+--------------+---------------------------------------------+
| TRACK           | JOINED | EXERCISES | COMPLETED | PROGRESS | LAST TOUCHED | TRACK LINK                                  |
+-----------------+--------+-----------+-----------+----------+--------------+---------------------------------------------+
| AWK             | Yes    |        61 |         2 | 3%       | 2023-09-19   | https://exercism.org/tracks/awk             |
| Bash            | Yes    |        89 |         5 | 6%       | 2023-03-17   | https://exercism.org/tracks/bash            |
| C               | Yes    |        73 |         2 | 3%       | 2023-09-15   | https://exercism.org/tracks/c               |
| C#              | Yes    |       164 |         0 | 0%       | 2023-09-12   | https://exercism.org/tracks/csharp          |
| C++             | Yes    |        73 |         0 | 0%       | 2023-09-12   | https://exercism.org/tracks/cpp             |
| Erlang          | Yes    |        78 |         0 | 0%       | 2023-09-06   | https://exercism.org/tracks/erlang          |
| Go              | Yes    |       141 |        39 | 28%      | 2023-09-16   | https://exercism.org/tracks/go              |
| JavaScript      | Yes    |       141 |         3 | 2%       | 2023-07-28   | https://exercism.org/tracks/javascript      |
| Perl            | Yes    |        64 |         0 | 0%       | 2023-09-06   | https://exercism.org/tracks/perl5           |
| PL/SQL          | Yes    |        11 |         0 | 0%       | 2023-09-12   | https://exercism.org/tracks/plsql           |
| Python          | Yes    |       137 |        48 | 35%      | 2023-09-19   | https://exercism.org/tracks/python          |
| Rust            | Yes    |        97 |         7 | 7%       | 2023-09-14   | https://exercism.org/tracks/rust            |
| x86-64 Assembly | Yes    |        18 |         0 | 0%       | 2023-09-06   | https://exercism.org/tracks/x86-64-assembly |
+-----------------+--------+-----------+-----------+----------+--------------+---------------------------------------------+
| TOTAL TRACKS    | 13     |           |           |          |              |                                             |
+-----------------+--------+-----------+-----------+----------+--------------+---------------------------------------------+

Note: To see all tracks, run ./main list --all.

List all exercises for a given track: Run ./main --list --track=awk

This should return:

+-----------------------------+------------+-----------------------------------------------------------------------+
| EXERCISE                    | DIFFICULTY | EXERCISE LINK                                                         |
+-----------------------------+------------+-----------------------------------------------------------------------+
| High Scores                 | easy       | https://exercism.org/tracks/awk/exercises/high-scores                 |
| Allergies                   | easy       | https://exercism.org/tracks/awk/exercises/allergies                   |
| RNA Transcription           | easy       | https://exercism.org/tracks/awk/exercises/rna-transcription           |
| Leap                        | easy       | https://exercism.org/tracks/awk/exercises/leap                        |
| Scrabble Score              | easy       | https://exercism.org/tracks/awk/exercises/scrabble-score              |
| Hamming                     | easy       | https://exercism.org/tracks/awk/exercises/hamming                     |
| Acronym                     | easy       | https://exercism.org/tracks/awk/exercises/acronym                     |
| Two Fer                     | easy       | https://exercism.org/tracks/awk/exercises/two-fer                     |
| Pangram                     | easy       | https://exercism.org/tracks/awk/exercises/pangram                     |
| Grains                      | easy       | https://exercism.org/tracks/awk/exercises/grains                      |
| Series                      | easy       | https://exercism.org/tracks/awk/exercises/series                      |
| Resistor Color Duo          | easy       | https://exercism.org/tracks/awk/exercises/resistor-color-duo          |
| Largest Series Product      | easy       | https://exercism.org/tracks/awk/exercises/largest-series-product      |
| ETL                         | easy       | https://exercism.org/tracks/awk/exercises/etl                         |
| Rotational Cipher           | easy       | https://exercism.org/tracks/awk/exercises/rotational-cipher           |
| Queen Attack                | easy       | https://exercism.org/tracks/awk/exercises/queen-attack                |
| Matching Brackets           | easy       | https://exercism.org/tracks/awk/exercises/matching-brackets           |
| Triangle                    | easy       | https://exercism.org/tracks/awk/exercises/triangle                    |
| Armstrong Numbers           | easy       | https://exercism.org/tracks/awk/exercises/armstrong-numbers           |
| Protein Translation         | easy       | https://exercism.org/tracks/awk/exercises/protein-translation         |
| Bob                         | easy       | https://exercism.org/tracks/awk/exercises/bob                         |
| Space Age                   | easy       | https://exercism.org/tracks/awk/exercises/space-age                   |
| Secret Handshake            | easy       | https://exercism.org/tracks/awk/exercises/secret-handshake            |
| Darts                       | easy       | https://exercism.org/tracks/awk/exercises/darts                       |
| Gigasecond                  | easy       | https://exercism.org/tracks/awk/exercises/gigasecond                  |
| Sum of Multiples            | easy       | https://exercism.org/tracks/awk/exercises/sum-of-multiples            |
| Prime Factors               | easy       | https://exercism.org/tracks/awk/exercises/prime-factors               |
| Beer Song                   | easy       | https://exercism.org/tracks/awk/exercises/beer-song                   |
| Grade School                | easy       | https://exercism.org/tracks/awk/exercises/grade-school                |
| Robot Simulator             | easy       | https://exercism.org/tracks/awk/exercises/robot-simulator             |
| Word Count                  | easy       | https://exercism.org/tracks/awk/exercises/word-count                  |
| Resistor Color Trio         | easy       | https://exercism.org/tracks/awk/exercises/resistor-color-trio         |
| Raindrops                   | easy       | https://exercism.org/tracks/awk/exercises/raindrops                   |
| Hello World                 | easy       | https://exercism.org/tracks/awk/exercises/hello-world                 |
| Reverse String              | easy       | https://exercism.org/tracks/awk/exercises/reverse-string              |
| Rectangles                  | medium     | https://exercism.org/tracks/awk/exercises/rectangles                  |
| Pig Latin                   | medium     | https://exercism.org/tracks/awk/exercises/pig-latin                   |
| Two Bucket                  | medium     | https://exercism.org/tracks/awk/exercises/two-bucket                  |
| Affine Cipher               | medium     | https://exercism.org/tracks/awk/exercises/affine-cipher               |
| Wordy                       | medium     | https://exercism.org/tracks/awk/exercises/wordy                       |
| Anagram                     | medium     | https://exercism.org/tracks/awk/exercises/anagram                     |
| Kindergarten Garden         | medium     | https://exercism.org/tracks/awk/exercises/kindergarten-garden         |
| Luhn                        | medium     | https://exercism.org/tracks/awk/exercises/luhn                        |
| Tournament                  | medium     | https://exercism.org/tracks/awk/exercises/tournament                  |
| Matrix                      | medium     | https://exercism.org/tracks/awk/exercises/matrix                      |
| Run-Length Encoding         | medium     | https://exercism.org/tracks/awk/exercises/run-length-encoding         |
| Diamond                     | medium     | https://exercism.org/tracks/awk/exercises/diamond                     |
| OCR Numbers                 | medium     | https://exercism.org/tracks/awk/exercises/ocr-numbers                 |
| Atbash Cipher               | medium     | https://exercism.org/tracks/awk/exercises/atbash-cipher               |
| Roman Numerals              | medium     | https://exercism.org/tracks/awk/exercises/roman-numerals              |
| Forth                       | medium     | https://exercism.org/tracks/awk/exercises/forth                       |
| Grep                        | medium     | https://exercism.org/tracks/awk/exercises/grep                        |
| Nth Prime                   | medium     | https://exercism.org/tracks/awk/exercises/nth-prime                   |
| All Your Base               | medium     | https://exercism.org/tracks/awk/exercises/all-your-base               |
| Variable Length Quantity    | medium     | https://exercism.org/tracks/awk/exercises/variable-length-quantity    |
| Say                         | medium     | https://exercism.org/tracks/awk/exercises/say                         |
| Automated readability index | medium     | https://exercism.org/tracks/awk/exercises/automated-readability-index |
| Knapsack                    | hard       | https://exercism.org/tracks/awk/exercises/knapsack                    |
| List Ops                    | hard       | https://exercism.org/tracks/awk/exercises/list-ops                    |
| Change                      | hard       | https://exercism.org/tracks/awk/exercises/change                      |
| Mazy Mice                   | hard       | https://exercism.org/tracks/awk/exercises/mazy-mice                   |
+-----------------------------+------------+-----------------------------------------------------------------------+
| TOTAL EXERCISES:            | 61         |                                                                       |
+-----------------------------+------------+-----------------------------------------------------------------------+

Filter exercises for a given track using difficulty: Run ./main list --track=awk --level=hard.

This should output:

+------------------+------------+-----------------------------------------------------+
| EXERCISE         | DIFFICULTY | EXERCISE LINK                                       |
+------------------+------------+-----------------------------------------------------+
| Knapsack         | hard       | https://exercism.org/tracks/awk/exercises/knapsack  |
| List Ops         | hard       | https://exercism.org/tracks/awk/exercises/list-ops  |
| Change           | hard       | https://exercism.org/tracks/awk/exercises/change    |
| Mazy Mice        | hard       | https://exercism.org/tracks/awk/exercises/mazy-mice |
+------------------+------------+-----------------------------------------------------+
| TOTAL EXERCISES: | 4          |                                                     |
+------------------+------------+-----------------------------------------------------+

Download selected exercises for a given track: Run ./main list --track=awk --level=hard --download.

This should output:

Do you want to download 4 exercises? (y/n) y
Collecting exercises...
Downloading 27 files:  100% |████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (27/27, 11 it/s)        

Successfully downloaded 27 files to the following directories:
/Users/baduker/Main/awk/knapsack
/Users/baduker/Main/awk/list-ops
/Users/baduker/Main/awk/change
/Users/baduker/Main/awk/mazy-mice
Happy coding!

@github-actions
Copy link

Hello. Thanks for opening a PR on Exercism. We are currently in a phase of our journey where we have paused community contributions to allow us to take a breather and redesign our community model. You can learn more in this blog post. As such, all issues and PRs in this repository are being automatically closed.

That doesn't mean we're not interested in your ideas, or that if you're stuck on something we don't want to help. The best place to discuss things is with our community on the Exercism Community Forum. You can use this link to copy this into a new topic there.


Note: If this PR has been pre-approved, please link back to this PR on the forum thread and a maintainer or staff member will reopen it.

Copy link
Member

@iHiD iHiD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work on this. I've reopened the PR :)

I have three general comments:

  1. I really like the list functionality. I'm 👍 on adding that.
  2. I don't love the download all functionality, as that has the downside of marking all those exercises in progress. I'd like to have a wider community discussion about that first, and also take time to consider it from a product perspective.
  3. There are quite a few other changes in this PR that make it hard to see exactly what's going on where. I've added questions to those for clarification.

Action suggestions:

  1. I think there are three seperate PRs here.
    a) The refactorings
    b) The addition of List
    c) The addition of Download

I'd like to see a PR just for (b) and potentially one for (a) to start with. Those will be more manageable to review. In its current state, there's so much happening in this PR, I think it will take a long time to get a proper review. I'd like to get the List stuff reviewed properly instead and be ale to deploy that, without waiting on the rest to get reviewesd.

The List functionality also needs a comprehensive test adding.

Thanks for your work on this. I hope that makes sense!

@@ -116,7 +124,7 @@ func runConfigure(configuration config.Config, flags *pflag.FlagSet) error {

// Verify that the token is valid.
if !skipVerification {
client, err := api.NewClient(token, baseURL)
client, err := api.NewClient("", baseURL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do?

assert.Regexp(t, "Welcome to Exercism", err.Error())
// It uses the default base API url to infer the host
assert.Regexp(t, "exercism.io/my/settings", err.Error())
assert.Regexp(t, "there is no token configured", err.Error())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change?

Copy link
Contributor Author

@baduker baduker Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and all the other changes you mention below is a poor attempt at "fixing" the broken tests on master. Additionally, I need to revert some of the changes that fix deprecated code, mostly from the io/ioutil to io and os packages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to CONTRIBUTING.MD you can run tests locally with go test ./... and this fails on a clean clone and master. I get this:

pwd && go test ./...
/Users/baduker/Downloads/cli
?   	github.com/exercism/cli/browser	[no test files]
?   	github.com/exercism/cli/exercism	[no test files]
ok  	github.com/exercism/cli/api	0.254s
ok  	github.com/exercism/cli/cli	0.315s
--- FAIL: TestSubmitFiles (0.01s)
        Error Trace:    submit_test.go:275
        Error:		Not equal: "This is file 2." (expected)
        	        != "" (actual)
        
--- FAIL: TestSubmitFilesForTeamExercise (0.00s)
        Error Trace:    submit_test.go:471
        Error:		Not equal: "This is file 2." (expected)
        	        != "" (actual)
        
FAIL
FAIL	github.com/exercism/cli/cmd	0.529s
ok  	github.com/exercism/cli/config	0.370s
ok  	github.com/exercism/cli/debug	0.424s
ok  	github.com/exercism/cli/workspace	(cached)
FAIL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean master or main? The primary branch on this repo is main.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I meant main, not master.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I don't know why that's not working on your machine when it is working on our CI. Maybe a different version of Go? CCing @junedev, @andrerfcsantos, @kytrinyx and @ErikSchierboom to see if they have any ideas :)

Copy link
Contributor

@nywilken nywilken Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iHiD @ErikSchierboom the failing tests happen when using a version of Go 1.17 and above. There was a change to the mime/multipart pkg that changes the file path information being returned for any files included in the mocked request. It looks like there's an open PR for this issue #1066 that can be merged in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've replied there. I'd appreciate eyes on that too pls :)

https://github.com/exercism/cli/pull/1066/files#r1331620696

@@ -40,7 +38,7 @@ func TestDownloadWithoutWorkspace(t *testing.T) {

err := runDownload(cfg, pflag.NewFlagSet("fake", pflag.PanicOnError), []string{})
if assert.Error(t, err) {
assert.Regexp(t, "re-run the configure", err.Error())
assert.Regexp(t, "need an --exercise name or a solution --uuid", err.Error())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change?

@@ -54,7 +52,7 @@ func TestDownloadWithoutBaseURL(t *testing.T) {

err := runDownload(cfg, pflag.NewFlagSet("fake", pflag.PanicOnError), []string{})
if assert.Error(t, err) {
assert.Regexp(t, "re-run the configure", err.Error())
assert.Regexp(t, "need an --exercise name or a solution --uuid", err.Error())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change?

path: tc.file,
baseURL: "http://www.example.com/",
path: tc.file,
sourceURL: "http://www.example.com/",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change?


if url != tc.expectedURL {
t.Fatalf("Expected URL '%s', got '%s'", tc.expectedURL, url)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this block?

@baduker
Copy link
Contributor Author

baduker commented Sep 28, 2023

I'm closing the PR as this is going to be broken down into two (or more) PRs, starting with this one here.

@baduker baduker closed this Sep 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feature request: list available exercises for download through cli Download all items for given track
3 participants