Skip to content

Commit

Permalink
Switch to explicit args
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikSchierboom committed Jan 11, 2024
1 parent 900b500 commit d4d6b10
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 52 deletions.
54 changes: 27 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,45 +65,45 @@ 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
-p, --practice Create a concept exercise
-c, --concept Create a practice 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
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
31 changes: 19 additions & 12 deletions src/cli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ 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
practice*: bool
`concept`*: 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 @@ -85,8 +85,8 @@ type
# Options for `create`
optCreateApproach = "approach"
optCreateArticle = "article"
optCreateConcept = "concept"
optCreatePractice = "practice"
optCreateConceptExercise = "concept-exercise"
optCreatePracticeExercise = "practice-exercise"

# Options for `completion`
optCompletionShell = "shell"
Expand Down Expand Up @@ -114,7 +114,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 @@ -124,7 +125,7 @@ const
short = genShortKeys()
optsNoVal = {optHelp, optVersion, optFmtSyncUpdate, optFmtSyncYes,
optInfoSyncOffline, optSyncDocs, optSyncFilepaths, optSyncMetadata,
optCreatePractice, optCreateConcept}
optCreatePracticeExercise, optCreateConceptExercise}

func generateNoVals: tuple[shortNoVal: set[char], longNoVal: seq[string]] =
## Returns the short and long keys for the options in `optsNoVal`.
Expand Down Expand Up @@ -184,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 @@ -239,8 +242,8 @@ func genHelpText: string =
&"{paddingOpt}{allowedValues(Verbosity)} (default: normal)",
optCreateApproach: "The slug of the approach",
optCreateArticle: "The slug of the article",
optCreateConcept: "Create a practice exercise",
optCreatePractice: "Create a concept exercise",
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",
Expand Down Expand Up @@ -298,6 +301,10 @@ func genHelpText: string =
optCreateApproach
of "articleSlug":
optCreateArticle
of "conceptExerciseSlug":
optCreateConceptExercise
of "practiceExerciseSlug":
optCreatePracticeExercise
of "exerciseCreate":
optFmtSyncCreateExercise
of "exerciseFmt":
Expand Down Expand Up @@ -537,10 +544,10 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
setActionOpt(articleSlug, val)
of optFmtSyncCreateExercise:
setActionOpt(exerciseCreate, val)
of optCreateConcept:
setActionOpt(`concept`, true)
of optCreatePractice:
setActionOpt(practice, true)
of optCreateConceptExercise:
setActionOpt(conceptExerciseSlug, val)
of optCreatePracticeExercise:
setActionOpt(practiceExerciseSlug, val)
else:
discard
of actFmt:
Expand Down
18 changes: 11 additions & 7 deletions src/create/create.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ 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 1
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 1
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 1
let trackConfigPath = conf.trackDir / "config.json"
let trackConfig = parseFile(trackConfigPath, TrackConfig)
let trackExerciseSlugs = getSlugs(trackConfig.exercises, conf, trackConfigPath)
Expand All @@ -50,12 +54,12 @@ proc create*(conf: Conf) =
quit 1

createArticle(Slug(conf.action.articleSlug), userExercise, exerciseDir)
elif conf.action.`concept`:
elif conf.action.conceptExerciseSlug.len > 0:
createConceptExercise(conf)
elif conf.action.practice:
elif conf.action.practiceExerciseSlug.len > 0:
createPracticeExercise(conf)
else:
let msg = "Please specify `--article <slug>`, `--approach <slug>`, `--concept` or `--practice`"
let msg = "Please specify `--article <slug>`, `--approach <slug>`, `--concept-exercise <slug>` or `--practice-exercise <slug>`"
stderr.writeLine msg
quit 1
else:
Expand Down
8 changes: 4 additions & 4 deletions src/create/exercises.nim
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import std/[sets, os, strformat]
import ".."/[cli, helpers, fmt/track_config, sync/probspecs, sync/sync, sync/sync_filepaths, sync/sync_metadata, types_exercise_config, types_track_config, uuid/uuid]

proc verifyExerciseDoesNotExist(conf: Conf): tuple[trackConfig: TrackConfig, trackConfigPath: string, exercise: Slug] =
proc verifyExerciseDoesNotExist(conf: Conf, slug: string): tuple[trackConfig: TrackConfig, trackConfigPath: string, exercise: Slug] =
let trackConfigPath = conf.trackDir / "config.json"
let trackConfig = parseFile(trackConfigPath, TrackConfig)
let trackExerciseSlugs = getSlugs(trackConfig.exercises, conf, trackConfigPath)
let userExercise = Slug(conf.action.exerciseCreate)
let userExercise = Slug(slug)

if userExercise in trackExerciseSlugs.`concept`:
let msg = &"There already is a concept exercise with `{userExercise}` as the slug " &
Expand Down Expand Up @@ -50,7 +50,7 @@ proc syncExercise(conf: Conf, scope: set[SyncKind]) =
discard syncImpl(syncConf, log = false)

proc createConceptExercise*(conf: Conf) =
var (trackConfig, trackConfigPath, userExercise) = verifyExerciseDoesNotExist(conf)
var (trackConfig, trackConfigPath, userExercise) = verifyExerciseDoesNotExist(conf, conf.action.conceptExerciseSlug)

let probSpecsDir = ProbSpecsDir.init(conf)
if dirExists(probSpecsDir / "exercises" / $userExercise):
Expand Down Expand Up @@ -83,7 +83,7 @@ proc createConceptExercise*(conf: Conf) =
syncFiles(trackConfig, conf.trackDir, userExercise, ekConcept)

proc createPracticeExercise*(conf: Conf) =
var (trackConfig, trackConfigPath, userExercise) = verifyExerciseDoesNotExist(conf)
var (trackConfig, trackConfigPath, userExercise) = verifyExerciseDoesNotExist(conf, conf.action.practiceExerciseSlug)

let probSpecsDir = ProbSpecsDir.init(conf)
let metadata = parseMetadataToml(probSpecsDir / "exercises" / $userExercise / "metadata.toml")
Expand Down
4 changes: 2 additions & 2 deletions tests/test_binary_create.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ proc main =
There already is a concept exercise with `lasagna` as the slug in the track config:
{trackDir / "config.json"}
""".unindent()
execAndCheck(1, &"{createBase} -e lasagna --concept", expectedOutput)
execAndCheck(1, &"{createBase} --concept-exercise lasagna ", expectedOutput)

test "practice exercise that already has been implemented (prints the expected output, and exits with 1)":
const expectedOutput = fmt"""
There already is a practice exercise with `leap` as the slug in the track config:
{trackDir / "config.json"}
""".unindent()
execAndCheck(1, &"{createBase} -e leap --practice", expectedOutput)
execAndCheck(1, &"{createBase} --practice-exercise leap", expectedOutput)

main()
{.used.}

0 comments on commit d4d6b10

Please sign in to comment.