exercism / cli

A Go based command line tool for exercism.org.
https://exercism.org/docs/using/solving-exercises/working-locally
MIT License
1.32k stars 356 forks source link

Download all items for given track #718

Open Jarvvski opened 6 years ago

Jarvvski commented 6 years ago

Did some quick searching and I see that the ability to download all items for a given track isn't currently in the CLI.

I'd really find this item useful, as it's great to have access to items to work on during a long flight etc.

In the mean time (because I've been searching for it in the issues here) I made a tiny script to be able to download all items for a given track: https://github.com/Jarvvski/exercism-downloader

kytrinyx commented 6 years ago

I think this would be a nice addition.

A few notes:

We would need some design/implementation on the backend API in https://github.com/exercism/website before we can start addressing this

raymondchen625 commented 5 years ago

Before this task is completed, we can use this shell command to pull the list of go: curl -LS https://exercism.io/tracks/go/exercises | grep "/tracks/go/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1

Jarvvski commented 5 years ago

@raymondchen625 awesome 1 liner!

tsoernes commented 5 years ago
curl -LS https://exercism.io/tracks/rust/exercises | grep "/tracks/rust/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
while read in; do exercism download --exercise="$in" --track=rust; done < exercises.txt

Change track as needed

cocoonkid commented 5 years ago

I also would massively appreciate a way to download full tracks. EDIT: I just realized I have to have exercises unlocked. @tsoernes script works beautifully though.

agentofuser commented 4 years ago

If you're doing multiple tracks in parallel this might be helpful:

# "exercism download all" for specific tracks

function eda() {
  for trackname in "$@"; do
    echo https://exercism.io/tracks/$trackname/exercises
    curl -LS https://exercism.io/tracks/$trackname/exercises | grep "/tracks/$trackname/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
    while read in; do exercism download --exercise="$in" --track=$trackname; done < exercises.txt
    rm exercises.txt
  done
}

# example usage:
# ❯ eda typescript reasonml ocaml racket nim

Thank you @tsoernes for doing the hard part. This is just a for loop around his code.

farv commented 4 years ago

I'm having issues using that @tsoernes code from a computer using WSL2 and redid some part of it:

TRACK=<TRACK-TO-BE-DOWNLOADED> && curl -LS https://exercism.io/tracks/$TRACK/exercises | grep "/tracks/$TRACK/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
for word in `sed '/^$/d' exercises.txt`; do exercism download --exercise="$word" --track=$TRACK; done

Be careful when your home excercism workspace path has spaces.

Hope you all enjoy it! ;)

lcharles123 commented 3 years ago

If you're doing multiple tracks in parallel this might be helpful:

# "exercism download all" for specific tracks

function eda() {
  for trackname in "$@"; do
    echo https://exercism.io/tracks/$trackname/exercises
    curl -LS https://exercism.io/tracks/$trackname/exercises | grep "/tracks/$trackname/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
    while read in; do exercism download --exercise="$in" --track=$trackname; done < exercises.txt
    rm exercises.txt
  done
}

# example usage:
# ❯ eda typescript reasonml ocaml racket nim

Thank you @tsoernes for doing the hard part. This is just a for loop around his code.

Note that it will overwrite all already downloaded folders

she3o commented 2 years ago

The previous scripts don't work on the new website anymore.

This works for me:

#!/usr/bin/env bash 

# You have to have `pup` and `jq` in your $PATH.
# Does `mkfifo` work on MacOS?
# example usage:
# ❯ eda typescript reasonml ocaml racket nim

arrow="\e[31;1m=>\e[0m"
pipe="/tmp/pipe-$$"

for trackname in "$@"; do
    mkfifo "$pipe"
    echo -e "$arrow Downloading ${trackname^} track..."
    curl -LSs https://exercism.org/tracks/"$trackname"/exercises |
        pup -p 'section[class=exercises] div attr{data-react-data}' |
        jq -r '.request.options.initial_data.exercises | .[].slug' >"$pipe" &
    while read in; do
        exercism download --exercise="$in" --track="$trackname"
    done <"$pipe"
    rm "$pipe"
done
robertpkoenig commented 2 years ago

This is a python script I just used.

import requests
import re
import os

# Replace this with your language
LANGUAGE = "java"

# Get the html from the exercism page
pageURL = 'https://exercism.org/tracks/' + LANGUAGE + '/exercises'
request = requests.get(pageURL)
pageHTML = request.content.decode('utf-8')

# Each exercise is in the form "/tracks/java/"exerciseName&
regexString = r'tracks/' + LANGUAGE + '/exercises/(.*?)&'
allMatches = re.findall(regexString, pageHTML)
numDownloads = 0
for exercise in allMatches:
    downloadCommand = 'exercism download --exercise=' + exercise + ' --track=' + LANGUAGE
    os.system(downloadCommand)
    numDownloads += 1

print("Total downloads: ", numDownloads)
gustafc commented 1 year ago

To add to this pageant of download scripts, here's a bash version of @robertpkoenig's Python script that doesn't need anything you don't already have (the exercism CLI, curl, and pretty standard *NIX/Posix stuff). Just change TRACK to whatever floats your boat.

(TRACK=rust; set -euo pipefail; trackdir="$(exercism workspace)/$TRACK"; mkdir -p "$trackdir"; curl --silent --fail "https://exercism.org/tracks/$TRACK/exercises" | grep -Eo 'tracks/'"$TRACK"'/exercises/[^&]+' | cut -d/ -f4 | tee "$trackdir/exercise-order.txt" | while read ex; do if test -d "$trackdir/$ex" ; then echo "$ex already downloaded"; else (set -x && exercism download --track "$TRACK" --exercise "$ex"); fi; done)

Works On My Machine™️

Edit: Now also works on other machines (Mac/bash and Alpine/ash at least)

AmjadHD commented 1 year ago

Here's a python script that asynchronously downloads a track from it's config.json:

import asyncio
import json
import requests

async def download_exercise(exercise: str, track: str, overwrite):
    cmd = f"exercism download --exercise={exercise} --track={track}"
    if overwrite:
        cmd += " --force"
    proc = await asyncio.create_subprocess_shell(
        cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    print(f'[{cmd!r} exited with {proc.returncode}]')
    if stdout:
        print(f'[stdout]\n{stdout.decode()}')
    if stderr:
        print(f'[stderr]\n{stderr.decode()}')

async def download_track(track: str, overwrite=false):
    url = f"https://github.com/exercism/{track}/raw/main/config.json"
    content = json.loads(requests.get(url).content)

    await asyncio.gather(*(download_exercise(exercise['slug'], track, overwrite) for exercise in content["exercises"]["practice"]))

asyncio.run(download_track("dart"))
nihilismus commented 1 year ago

Another Bash script, but using Exercism's API:

#!/usr/bin/env bash

set -e
set -u

export track="$1"

curl \
  --silent --fail \
  "https://exercism.org/api/v2/tracks/$track/exercises" \
  | sed 's/"slug":"/\n/g' \
  | sed 's/",.*$//' \
  | grep -v '"exercises":' \
  | while read -r slug; do
      exercism download --track="$track" --exercise="$slug"
    done
baduker commented 12 months ago

So, my PR got automatically closed because of the pause of community contributions, which I wasn't aware of, but that doesn't mean you can't use the feature I've developed to list, filter, and download exercises. Just read the PR, it has all the examples. Until the pause gets lifted, happy coding!

PR - https://github.com/exercism/cli/pull/1113

jonnylangefeld commented 9 months ago

A shorter command than what I have seen here before. Uses jq as dependency which is pretty common.

track=go; curl "https://exercism.org/api/v2/tracks/$track/exercises" | \
  jq -r '.exercises[].slug' | \
  xargs -I {} -n1 sh -c "exercism download --track=$track --exercise {} || true"
Giveback007 commented 1 month ago

In case somone wants an out of the box solution: exer-h

screen-1

It's a small wrapper for the official exercism cli. Hope it helps.