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

create: allow creating of exercise #845

Merged
merged 33 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
992e2ea
Setup basic structure
ErikSchierboom Dec 19, 2023
9406ba2
initial work to update track config
ErikSchierboom Dec 19, 2023
322f2d1
Create exercise
ErikSchierboom Dec 19, 2023
4d6445f
Extract common logic
ErikSchierboom Dec 19, 2023
46e9b45
Use set literal
ErikSchierboom Dec 19, 2023
dd8c152
Create files
ErikSchierboom Dec 19, 2023
3abb434
Simplify code
ErikSchierboom Jan 2, 2024
f205ee7
Fix missing newlines
ErikSchierboom Jan 2, 2024
e127ad0
Fix unit tests
ErikSchierboom Jan 2, 2024
6b10b40
Add tests for trying to create exercise that already exists
ErikSchierboom Jan 2, 2024
00f3189
Rebased
ErikSchierboom Jan 18, 2024
11c73cd
Fix --practice-exercise and --concept-exercise args
ErikSchierboom Jan 11, 2024
dc8d3d0
Only update correct values
ErikSchierboom Jan 11, 2024
3813173
Couple of fixes
ErikSchierboom Jan 11, 2024
21998f0
Only sync once
ErikSchierboom Jan 11, 2024
b28d864
Use once:
ErikSchierboom Jan 11, 2024
182fc6d
Silence output
ErikSchierboom Jan 11, 2024
e4a0e53
Add logging output
ErikSchierboom Jan 11, 2024
bb15c83
Work on tests
ErikSchierboom Jan 12, 2024
e4afe61
Add tests to verify exercises being created
ErikSchierboom Jan 12, 2024
df22c84
Some cleanup
ErikSchierboom Jan 12, 2024
a5cbf57
Add comment
ErikSchierboom Jan 12, 2024
8846c98
Revert diff change
ErikSchierboom Jan 12, 2024
dbc65d8
Simplify
ErikSchierboom Jan 12, 2024
531c62d
Update src/exec.nim
ErikSchierboom Jan 12, 2024
7b7a835
Update src/exec.nim
ErikSchierboom Jan 12, 2024
1915ba5
More refactoring
ErikSchierboom Jan 12, 2024
5f53e64
Fix indentation
ErikSchierboom Jan 18, 2024
1035394
Hard wrap line
ErikSchierboom Jan 18, 2024
26bfed4
Allow offline create
ErikSchierboom Jan 18, 2024
77bb4a5
Output prob-specs updating
ErikSchierboom Jan 18, 2024
a564e73
Fix tests
ErikSchierboom Jan 18, 2024
bac7ac2
Fix readme test
ErikSchierboom Jan 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 29 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Usage:

Commands:
completion Output a completion script for a given shell
create Add a new approach or article
create Add a new exercise, approach or article
fmt Format the exercise 'config.json' files
generate Generate Concept Exercise 'introduction.md' files from 'introduction.md.tpl' files
info Print some information about the track
Expand All @@ -65,43 +65,46 @@ Commands:
uuid Output new (version 4) UUIDs, suitable for the value of a 'uuid' key

Options for completion:
-s, --shell <shell> Choose the shell type (required)
Allowed values: b[ash], f[ish], z[sh]
-s, --shell <shell> Choose the shell type (required)
Allowed values: b[ash], f[ish], z[sh]

Options for create:
--approach <slug> The slug of the approach
--article <slug> The slug of the article
-e, --exercise <slug> Only operate on this exercise
--approach <slug> The slug of the approach
--article <slug> The slug of the article
--practice-exercise <slug> The slug of the concept exercise
--concept-exercise <slug> The slug of the practice exercise
-e, --exercise <slug> Only operate on this exercise
Copy link
Member

Choose a reason for hiding this comment

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

I don't like the option description here. But unfortunately it's common to all of the --exercise descriptions, I think.

-o, --offline Do not update the cached 'problem-specifications' data

Options for fmt:
-e, --exercise <slug> Only operate on this exercise
-u, --update Prompt to write formatted files
-y, --yes Auto-confirm the prompt from --update
-e, --exercise <slug> Only operate on this exercise
-u, --update Prompt to write formatted files
-y, --yes Auto-confirm the prompt from --update

Options for info:
-o, --offline Do not update the cached 'problem-specifications' data
-o, --offline Do not update the cached 'problem-specifications' data

Options for sync:
-e, --exercise <slug> Only operate on this exercise
-o, --offline Do not update the cached 'problem-specifications' data
-u, --update Prompt to update the unsynced track data
-y, --yes Auto-confirm prompts from --update for updating docs, filepaths, and metadata
--docs Sync Practice Exercise '.docs/introduction.md' and '.docs/instructions.md' files
--filepaths Populate empty 'files' values in Concept/Practice exercise '.meta/config.json' files
--metadata Sync Practice Exercise '.meta/config.json' metadata values
--tests [mode] Sync Practice Exercise '.meta/tests.toml' files.
The mode value specifies how missing tests are handled when using --update.
Allowed values: c[hoose], i[nclude], e[xclude] (default: choose)
-e, --exercise <slug> Only operate on this exercise
-o, --offline Do not update the cached 'problem-specifications' data
-u, --update Prompt to update the unsynced track data
-y, --yes Auto-confirm prompts from --update for updating docs, filepaths, and metadata
--docs Sync Practice Exercise '.docs/introduction.md' and '.docs/instructions.md' files
--filepaths Populate empty 'files' values in Concept/Practice exercise '.meta/config.json' files
--metadata Sync Practice Exercise '.meta/config.json' metadata values
--tests [mode] Sync Practice Exercise '.meta/tests.toml' files.
The mode value specifies how missing tests are handled when using --update.
Allowed values: c[hoose], i[nclude], e[xclude] (default: choose)

Options for uuid:
-n, --num <int> Number of UUIDs to output
-n, --num <int> Number of UUIDs to output

Global options:
-h, --help Show this help message and exit
--version Show this tool's version information and exit
-t, --track-dir <dir> Specify a track directory to use instead of the current directory
-v, --verbosity <verbosity> The verbosity of output.
Allowed values: q[uiet], n[ormal], d[etailed] (default: normal)
-h, --help Show this help message and exit
--version Show this tool's version information and exit
-t, --track-dir <dir> Specify a track directory to use instead of the current directory
-v, --verbosity <verbosity> The verbosity of output.
Allowed values: q[uiet], n[ormal], d[etailed] (default: normal)
```

## `configlet lint`
Expand Down
6 changes: 6 additions & 0 deletions completions/configlet.bash
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ _configlet_complete_create_() {
'-e' | '--exercise')
_configlet_complete_slugs_ "practice" "concept"
;;
'--concept-exercise')
_configlet_complete_slugs_ "concept"
;;
'--practice-exercise')
_configlet_complete_slugs_ "practice"
;;
*)
_configlet_complete_options_ "--approach --article -e --exercise $global_opts"
;;
Expand Down
2 changes: 1 addition & 1 deletion completions/configlet.fish
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ complete -c configlet -n "__fish_use_subcommand" -a lint -d "Check the tra

# subcommands with options
complete -c configlet -n "__fish_use_subcommand" -a completion -d "Output a completion script for a given shell"
complete -c configlet -n "__fish_use_subcommand" -a create -d "Add a new approach or article"
complete -c configlet -n "__fish_use_subcommand" -a create -d "Add a new exercise, approach or article"
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not really familiar with how to configure this (the two new create options) for the fish shell. Would you mind taking a look?

complete -c configlet -n "__fish_use_subcommand" -a fmt -d "Format the exercise '.meta/config.json' files"
complete -c configlet -n "__fish_use_subcommand" -a info -d "Track info"
complete -c configlet -n "__fish_use_subcommand" -a sync -d "Check or update Practice Exercise docs, metadata, and tests"
Expand Down
2 changes: 1 addition & 1 deletion completions/configlet.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ _configlet_commands() {
"lint:Check the track configuration for correctness" \
# subcommands with options
"completion:Output a completion script for a given shell" \
"create:Add a new approach or article" \
"create:Add a new exercise, approach or article" \
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not really familiar with how to configure this (the two new create options) for the zsh shell. Would you mind taking a look?

"fmt:Format the exercise '.meta/config.json' files" \
"info:Print track information" \
"sync:Check or update Practice Exercise docs, metadata, and tests" \
Expand Down
40 changes: 31 additions & 9 deletions src/cli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,13 @@ type
of actCreate:
approachSlug*: string
articleSlug*: string
practiceExerciseSlug*: string
conceptExerciseSlug*: string
# We can't name this field `exercise` because we use that names
# in `actSync`, and Nim doesn't yet support duplicate field names
# in object variants.
exerciseCreate*: string
offlineCreate*: bool
of actFmt:
# We can't name these fields `exercise`, `update`, and `yes` because we
# use those names in `actSync`, and Nim doesn't yet support duplicate
Expand Down Expand Up @@ -83,6 +86,8 @@ type
# Options for `create`
optCreateApproach = "approach"
optCreateArticle = "article"
optCreateConceptExercise = "conceptExercise"
optCreatePracticeExercise = "practiceExercise"

# Options for `completion`
optCompletionShell = "shell"
Expand All @@ -94,8 +99,8 @@ type
optFmtSyncUpdate = "update"
optFmtSyncYes = "yes"

# Options for both `info` and `sync`
optInfoSyncOffline = "offline"
# Options for both `info`, `sync` and `create`
optInfoSyncCreateOffline = "offline"

# Scope to sync
optSyncDocs = "docs"
Expand All @@ -110,7 +115,8 @@ func genShortKeys: array[Opt, char] =
## Returns a lookup that gives the valid short option key for an `Opt`.
for opt in Opt:
if opt in {optVersion, optSyncDocs, optSyncFilepaths, optSyncMetadata,
optSyncTests, optCreateApproach, optCreateArticle}:
optSyncTests, optCreateApproach, optCreateArticle,
optCreateConceptExercise, optCreatePracticeExercise}:
result[opt] = '_' # No short option for these options.
else:
result[opt] = ($opt)[0]
Expand All @@ -119,7 +125,7 @@ const
configletVersion = staticRead("../configlet.version").strip()
short = genShortKeys()
optsNoVal = {optHelp, optVersion, optFmtSyncUpdate, optFmtSyncYes,
optInfoSyncOffline, optSyncDocs, optSyncFilepaths, optSyncMetadata}
optInfoSyncCreateOffline, optSyncDocs, optSyncFilepaths, optSyncMetadata}

func generateNoVals: tuple[shortNoVal: set[char], longNoVal: seq[string]] =
## Returns the short and long keys for the options in `optsNoVal`.
Expand Down Expand Up @@ -179,6 +185,8 @@ func genHelpText: string =
of optFmtSyncCreateExercise: "slug"
of optCreateApproach: "slug"
of optCreateArticle: "slug"
of optCreateConceptExercise: "slug"
of optCreatePracticeExercise: "slug"
of optSyncTests: "mode"
of optUuidNum: "int"
else: ""
Expand Down Expand Up @@ -206,7 +214,7 @@ func genHelpText: string =
const actionDescriptions: array[ActionKind, string] = [
actNil: "",
actCompletion: "Output a completion script for a given shell",
actCreate: "Add a new approach or article",
actCreate: "Add a new exercise, approach or article",
actFmt: "Format the exercise 'config.json' files",
actGenerate: "Generate Concept Exercise 'introduction.md' files from 'introduction.md.tpl' files",
actInfo: "Print some information about the track",
Expand Down Expand Up @@ -234,12 +242,14 @@ func genHelpText: string =
&"{paddingOpt}{allowedValues(Verbosity)} (default: normal)",
optCreateApproach: "The slug of the approach",
optCreateArticle: "The slug of the article",
optCreateConceptExercise: "The slug of the practice exercise",
optCreatePracticeExercise: "The slug of the concept exercise",
optCompletionShell: &"Choose the shell type (required)\n" &
&"{paddingOpt}{allowedValues(Shell)}",
optFmtSyncCreateExercise: "Only operate on this exercise",
optFmtSyncUpdate: "Prompt to update the unsynced track data",
optFmtSyncYes: &"Auto-confirm prompts from --{$optFmtSyncUpdate} for updating docs, filepaths, and metadata",
optInfoSyncOffline: "Do not update the cached 'problem-specifications' data",
optInfoSyncCreateOffline: "Do not update the cached 'problem-specifications' data",
optSyncDocs: "Sync Practice Exercise '.docs/introduction.md' and '.docs/instructions.md' files",
optSyncFilepaths: "Populate empty 'files' values in Concept/Practice exercise '.meta/config.json' files",
optSyncMetadata: "Sync Practice Exercise '.meta/config.json' metadata values",
Expand Down Expand Up @@ -291,6 +301,10 @@ func genHelpText: string =
optCreateApproach
of "articleSlug":
optCreateArticle
of "conceptExerciseSlug":
optCreateConceptExercise
of "practiceExerciseSlug":
optCreatePracticeExercise
of "exerciseCreate":
optFmtSyncCreateExercise
of "exerciseFmt":
Expand All @@ -300,7 +314,9 @@ func genHelpText: string =
of "yesFmt":
optFmtSyncYes
of "offlineInfo":
optInfoSyncOffline
optInfoSyncCreateOffline
of "offlineCreate":
optInfoSyncCreateOffline
else:
parseEnum[Opt](key)
# Set the description for `fmt` options.
Expand Down Expand Up @@ -530,6 +546,12 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
setActionOpt(articleSlug, val)
of optFmtSyncCreateExercise:
setActionOpt(exerciseCreate, val)
of optCreateConceptExercise:
setActionOpt(conceptExerciseSlug, val)
of optCreatePracticeExercise:
setActionOpt(practiceExerciseSlug, val)
of optInfoSyncCreateOffline:
setActionOpt(offlineCreate, true)
else:
discard
of actFmt:
Expand All @@ -544,7 +566,7 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
discard
of actInfo:
case opt
of optInfoSyncOffline:
of optInfoSyncCreateOffline:
setActionOpt(offlineInfo, true)
else:
discard
Expand All @@ -559,7 +581,7 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
of optSyncTests:
setActionOpt(tests, parseVal[TestsMode](kind, key, val))
conf.action.scope.incl skTests
of optInfoSyncOffline:
of optInfoSyncCreateOffline:
setActionOpt(offline, true)
of optSyncDocs, optSyncMetadata, optSyncFilepaths:
conf.action.scope.incl parseEnum[SyncKind]($opt)
Expand Down
21 changes: 15 additions & 6 deletions src/create/create.nim
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import std/[os, strformat]
import ".."/[cli, helpers, sync/sync, types_track_config]
import "."/[approaches, articles]
import "."/[approaches, articles, exercises]

proc create*(conf: Conf) =
if conf.action.kind == actCreate:
if conf.action.exerciseCreate.len == 0:
let msg = "Please specify an exercise, using --exercise <slug>"
stderr.writeLine msg
quit QuitFailure
if conf.action.approachSlug.len > 0:
if conf.action.exerciseCreate.len == 0:
let msg = "Please specify an exercise to create an approach for, using --exercise <slug>"
stderr.writeLine msg
quit QuitFailure
if conf.action.articleSlug.len > 0:
let msg = &"Both --approach and --article were provided. Please specify only one."
stderr.writeLine msg
Expand All @@ -32,6 +32,10 @@ proc create*(conf: Conf) =

createApproach(Slug(conf.action.approachSlug), userExercise, exerciseDir)
elif conf.action.articleSlug.len > 0:
if conf.action.exerciseCreate.len == 0:
let msg = "Please specify an exercise to create an article for, using --exercise <slug>"
stderr.writeLine msg
quit QuitFailure
let trackConfigPath = conf.trackDir / "config.json"
let trackConfig = parseFile(trackConfigPath, TrackConfig)
let trackExerciseSlugs = getSlugs(trackConfig.exercises, conf, trackConfigPath)
Expand All @@ -50,8 +54,13 @@ proc create*(conf: Conf) =
quit QuitFailure

createArticle(Slug(conf.action.articleSlug), userExercise, exerciseDir)
elif conf.action.conceptExerciseSlug.len > 0:
createConceptExercise(conf)
elif conf.action.practiceExerciseSlug.len > 0:
createPracticeExercise(conf)
else:
let msg = "Please specify `--article <slug>` or `--approach <slug>`"
let msg = "Please specify `--practice-exercise <slug>`, `--concept-exercise <slug>`, " &
"`--article <slug>` or `--approach <slug>`"
stderr.writeLine msg
quit QuitFailure
else:
Expand Down
Loading