Skip to content

Commit 1be57ed

Browse files
authored
Merge branch 'main' into stub-generator-patch
2 parents c78b6be + 29afef9 commit 1be57ed

File tree

6 files changed

+53
-1
lines changed

6 files changed

+53
-1
lines changed

bin/add_practice_exercise

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#!/usr/bin/env bash
22

3+
34
# shellcheck source=./generator-utils/utils.sh
45
# shellcheck source=./generator-utils/prompts.sh
56
# shellcheck source=./generator-utils/templates.sh
7+
68
source ./bin/generator-utils/utils.sh
79
source ./bin/generator-utils/prompts.sh
810
source ./bin/generator-utils/templates.sh
@@ -37,20 +39,23 @@ check_exercise_existence "$1"
3739

3840
# ==================================================
3941

42+
4043
slug="$1"
4144
# Fetch canonical data
4245
canonical_json=$(bin/fetch_canonical_data "$slug")
4346

4447
has_canonical_data=true
4548
if [ "${canonical_json}" == "404: Not Found" ]; then
4649
has_canonical_data=false
50+
4751
message "warning" "This exercise doesn't have canonical data"
4852

4953
else
5054
echo "$canonical_json" >canonical_data.json
5155
message "success" "Fetched canonical data successfully!"
5256
fi
5357

58+
5459
underscored_slug=$(dash_to_underscore "$slug")
5560
exercise_dir="exercises/practice/${slug}"
5661
exercise_name=$(format_exercise_name "$slug")
@@ -67,15 +72,18 @@ create_rust_files "$exercise_dir" "$slug" "$has_canonical_data"
6772
# ==================================================
6873

6974
# Build configlet
75+
7076
./bin/fetch-configlet
7177
message "success" "Fetched configlet successfully!"
7278

7379
# Preparing config.json
7480
message "info" "Adding instructions and configuration files..."
81+
7582
uuid=$(bin/configlet uuid)
7683

7784
# Add exercise-data to global config.json
7885
jq --arg slug "$slug" --arg uuid "$uuid" --arg name "$exercise_name" --arg difficulty "$exercise_difficulty" \
86+
7987
'.exercises.practice += [{slug: $slug, name: $name, uuid: $uuid, practices: [], prerequisites: [], difficulty: $difficulty}]' \
8088
config.json >config.json.tmp
8189
# jq always rounds whole numbers, but average_run_time needs to be a float
@@ -85,6 +93,7 @@ message "success" "Added instructions and configuration files"
8593

8694
# Create instructions and config files
8795
echo "Creating instructions and config files"
96+
8897
./bin/configlet sync --update --yes --docs --metadata --exercise "$slug"
8998
./bin/configlet sync --update --yes --filepaths --exercise "$slug"
9099
./bin/configlet sync --update --tests include --exercise "$slug"
@@ -97,7 +106,10 @@ message "success" "You've been added as the author of this exercise."
97106

98107
sed -i "s/name = \".*\"/name = \"$underscored_slug\"/" "$exercise_dir"/Cargo.toml
99108

109+
100110
message "done" "All stub files were created."
101111

102112
message "info" "After implementing the solution, tests and configuration, please run:"
113+
103114
echo "./bin/configlet fmt --update --yes --exercise ${slug}"
115+

bin/fetch_canonical_data

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#!/usr/bin/env bash
22
# This script fetches the canonical data of the exercise.
33

4+
45
# Exit if anything fails.
56
set -euo pipefail
67

8+
79
if [ $# -ne 1 ]; then
810
echo "Usage: bin/fetch_canonical_data <exercise-slug>"
911
exit 1

bin/generate_tests

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env bash
22

3+
34
# Exit if anything fails.
45
set -euo pipefail
56

@@ -11,11 +12,13 @@ digest_template() {
1112
local template
1213
template=$(cat bin/test_template)
1314
# Turn every token into a jq command
15+
1416
echo "$template" | sed 's/${\([^}]*\)\}\$/$(echo $case | jq -r '\''.\1'\'')/g'
1517
}
1618

1719
message "info" "Generating tests.."
1820
canonical_json=$(cat canonical_data.json)
21+
1922
slug=$(echo "$canonical_json" | jq '.exercise')
2023
# Remove double quotes
2124
slug=$(echo "$slug" | sed 's/"//g')
@@ -24,21 +27,25 @@ test_file="$exercise_dir/tests/$slug.rs"
2427

2528
cat <<EOT >"$test_file"
2629
use $(dash_to_underscore "$slug")::*;
30+
2731
// Add tests here
2832
2933
EOT
3034

3135
# Flattens canonical json, extracts only the objects with a uuid
3236
cases=$(echo "$canonical_json" | jq '[ .. | objects | with_entries(select(.key | IN("uuid", "description", "input", "expected", "property"))) | select(. != {}) | select(has("uuid")) ]')
3337

38+
3439
# Shellcheck doesn't recognize that `case` is not unused
40+
3541
# shellcheck disable=SC2034
3642
jq -c '.[]' <<<"$cases" | while read -r case; do
3743

3844
# Evaluate the bash parts and replace them with their return values
3945
eval_template="$(digest_template | sed -e "s/\$(\(.*\))/\$\(\1\)/g")"
4046
eval_template="$(eval "echo \"$eval_template\"")"
4147

48+
4249
# Turn function name into snake_case
4350
formatted_template=$(echo "$eval_template" | sed -e ':loop' -e 's/\(fn[^(]*\)[ -]/\1_/g' -e 't loop' | sed 's/fn_/fn /')
4451

@@ -51,3 +58,4 @@ done
5158
rustfmt "$test_file"
5259

5360
message "success" "Generated tests successfully! Check out ${test_file}"
61+

bin/generator-utils/prompts.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#!/usr/bin/env bash
22

3+
34
# shellcheck source=./colors.sh
45
source ./bin/generator-utils/colors.sh
56

67
get_exercise_difficulty() {
8+
79
read -rp "Difficulty of exercise (1-10): " exercise_difficulty
810
echo "$exercise_difficulty"
911
}
1012

13+
1114
validate_difficulty_input() {
1215

1316
local valid_input=false
@@ -17,13 +20,15 @@ validate_difficulty_input() {
1720
local valid_input=true
1821
else
1922
read -rp "${red}Invalid input. ${reset_color}Please enter an integer between 1 and 10. " exercise_difficulty
23+
2024
[[ "$exercise_difficulty" =~ ^[1-9]$|^10$ ]] && valid_input=true
2125

2226
fi
2327
done
2428
echo "$exercise_difficulty"
2529
}
2630

31+
2732
get_author_handle() {
2833
local default_author_handle
2934
default_author_handle="$(git config user.name)"
@@ -35,5 +40,4 @@ get_author_handle() {
3540

3641
fi
3742
echo "$author_handle"
38-
3943
}

bin/generator-utils/templates.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ create_fn_name() {
1010
if [ "$has_canonical_data" == false ]; then
1111
fn_name=$(dash_to_underscore "$slug")
1212
local fn_name
13+
1314
else
1415
fn_name=$(jq -r 'first(.. | .property? // empty)' canonical_data.json)
1516
fi
@@ -19,6 +20,7 @@ create_fn_name() {
1920
}
2021

2122
create_test_file_template() {
23+
2224
local exercise_dir=$1
2325
local slug=$2
2426
local has_canonical_data=$3
@@ -40,15 +42,19 @@ EOT
4042
message "info" "This exercise doesn't have canonical data."
4143
message "success" "Stub file for tests has been created!"
4244
else
45+
4346
local canonical_json
47+
4448
canonical_json=$(cat canonical_data.json)
4549

4650
# sometimes canonical data has multiple levels with multiple `cases` arrays.
4751
#(see kindergarten-garden https://github.com/exercism/problem-specifications/blob/main/exercises/kindergarten-garden/canonical-data.json)
4852
# so let's flatten it
53+
4954
local cases
5055
cases=$(echo "$canonical_json" | jq '[ .. | objects | with_entries(select(.key | IN("uuid", "description", "input", "expected"))) | select(. != {}) | select(has("uuid")) ]')
5156
local fn_name
57+
5258
fn_name=$(echo "$canonical_json" | jq -r 'first(.. | .property? // empty)')
5359

5460
first_iteration=true
@@ -83,6 +89,7 @@ create_lib_rs_template() {
8389
local slug=$2
8490
local has_canonical_data=$3
8591
local fn_name
92+
8693
fn_name=$(create_fn_name "$slug" "$has_canonical_data")
8794
cat <<EOT >"${exercise_dir}/src/lib.rs"
8895
pub fn ${fn_name}() {
@@ -93,6 +100,7 @@ EOT
93100
}
94101

95102
overwrite_gitignore() {
103+
96104
local exercise_dir=$1
97105
cat <<EOT >"$exercise_dir"/.gitignore
98106
# Generated by Cargo
@@ -107,12 +115,16 @@ EOT
107115
message "success" ".gitignore has been overwritten!"
108116
}
109117

118+
110119
create_example_rs_template() {
120+
111121
local exercise_dir=$1
112122
local slug=$2
113123
local has_canonical_data=$3
114124

125+
115126
local fn_name
127+
116128
fn_name=$(create_fn_name "$slug" "$has_canonical_data")
117129

118130
mkdir "${exercise_dir}/.meta"
@@ -126,7 +138,9 @@ EOT
126138
message "success" "Stub file for example.rs has been created!"
127139
}
128140

141+
129142
create_rust_files() {
143+
130144
local exercise_dir=$1
131145
local slug=$2
132146
local has_canonical_data=$3

bin/generator-utils/utils.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#!/usr/bin/env bash
22

3+
34
# shellcheck source=./colors.sh
45
source ./bin/generator-utils/colors.sh
56

67
message() {
8+
79
local flag=$1
810
local message=$2
911

1012
case "$flag" in
13+
1114
"success") printf "${green}%s${reset_color}\n" "[success]: $message" ;;
1215
"task") printf "${cyan}%s${reset_color}\n" "[task]: $message" ;;
1316
"info") printf "${blue}%s${reset_color}\n" "[info]: $message" ;;
@@ -21,33 +24,40 @@ message() {
2124
printf "%*s\n" "$cols" "" | tr " " "-"
2225
echo
2326
printf "${bold_green}%s${reset_color}\n" "[done]: $message"
27+
2428
;;
2529
*)
2630
echo "Invalid flag: $flag"
2731
;;
2832
esac
2933
}
3034

35+
3136
dash_to_underscore() {
37+
3238
echo "$1" | sed 's/-/_/g'
3339
}
3440

3541
# exercise_name -> Exercise Name
42+
3643
format_exercise_name() {
3744
echo "$1" | sed 's/-/ /g; s/\b\(.\)/\u\1/g'
3845
}
3946

4047
check_exercise_existence() {
4148
message "info" "Looking for exercise.."
4249
local slug="$1"
50+
4351
# Check if exercise is already in config.json
4452
if jq '.exercises.practice | map(.slug)' config.json | grep -q "$slug"; then
4553
echo "${1} has already been implemented."
4654
exit 1
4755
fi
4856

57+
4958
# Fetch configlet and crop out exercise list
5059
local unimplemented_exercises
60+
5161
unimplemented_exercises=$(bin/configlet info | sed -n '/With canonical data:/,/Track summary:/p' | sed -e '/\(With\(out\)\? canonical data:\|Track summary:\)/d' -e '/^$/d')
5262
if echo "$unimplemented_exercises" | grep -q "^$slug$"; then
5363
message "success" "Exercise has been found!"
@@ -57,6 +67,7 @@ check_exercise_existence() {
5767
${unimplemented_exercises}"
5868

5969
# Find closest match to typed-in not-found slug
70+
6071
# See util/ngram for source
6172
# First it builds a binary for the system of the contributor
6273
if [ -e bin/generator-utils/ngram ]; then
@@ -65,6 +76,7 @@ ${unimplemented_exercises}"
6576
message "info" "Building typo-checker binary for $(uname -m) system."
6677

6778
cd util/ngram && ./build && cd ../.. && echo "${yellow}$(bin/generator-utils/ngram "${unimplemented_exercises}" "$slug")${reset_color}"
79+
6880
fi
6981

7082
exit 1

0 commit comments

Comments
 (0)