From d4d6b10692abe831ec6e7d685246ea8ec697bf77 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 11 Jan 2024 09:07:17 +0100 Subject: [PATCH] Switch to explicit args --- README.md | 54 ++++++++++++++++++------------------ completions/configlet.bash | 6 ++++ src/cli.nim | 31 +++++++++++++-------- src/create/create.nim | 18 +++++++----- src/create/exercises.nim | 8 +++--- tests/test_binary_create.nim | 4 +-- 6 files changed, 69 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index b43dda17..ef07dd8b 100644 --- a/README.md +++ b/README.md @@ -65,45 +65,45 @@ Commands: uuid Output new (version 4) UUIDs, suitable for the value of a 'uuid' key Options for completion: - -s, --shell Choose the shell type (required) - Allowed values: b[ash], f[ish], z[sh] + -s, --shell Choose the shell type (required) + Allowed values: b[ash], f[ish], z[sh] Options for create: - --approach The slug of the approach - --article The slug of the article - -e, --exercise Only operate on this exercise - -p, --practice Create a concept exercise - -c, --concept Create a practice exercise + --approach The slug of the approach + --article The slug of the article + --practice-exercise The slug of the concept exercise + --concept-exercise The slug of the practice exercise + -e, --exercise Only operate on this exercise Options for fmt: - -e, --exercise Only operate on this exercise - -u, --update Prompt to write formatted files - -y, --yes Auto-confirm the prompt from --update + -e, --exercise 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 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 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 Number of UUIDs to output + -n, --num 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 Specify a track directory to use instead of the current directory - -v, --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 Specify a track directory to use instead of the current directory + -v, --verbosity The verbosity of output. + Allowed values: q[uiet], n[ormal], d[etailed] (default: normal) ``` ## `configlet lint` diff --git a/completions/configlet.bash b/completions/configlet.bash index 72110590..314aab03 100644 --- a/completions/configlet.bash +++ b/completions/configlet.bash @@ -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" ;; diff --git a/src/cli.nim b/src/cli.nim index 288fbc7a..703edaad 100644 --- a/src/cli.nim +++ b/src/cli.nim @@ -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 @@ -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" @@ -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] @@ -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`. @@ -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: "" @@ -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", @@ -298,6 +301,10 @@ func genHelpText: string = optCreateApproach of "articleSlug": optCreateArticle + of "conceptExerciseSlug": + optCreateConceptExercise + of "practiceExerciseSlug": + optCreatePracticeExercise of "exerciseCreate": optFmtSyncCreateExercise of "exerciseFmt": @@ -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: diff --git a/src/create/create.nim b/src/create/create.nim index 53a6c8a9..73442f44 100644 --- a/src/create/create.nim +++ b/src/create/create.nim @@ -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 " - 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 " + 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 @@ -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 " + stderr.writeLine msg + quit 1 let trackConfigPath = conf.trackDir / "config.json" let trackConfig = parseFile(trackConfigPath, TrackConfig) let trackExerciseSlugs = getSlugs(trackConfig.exercises, conf, trackConfigPath) @@ -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 `, `--approach `, `--concept` or `--practice`" + let msg = "Please specify `--article `, `--approach `, `--concept-exercise ` or `--practice-exercise `" stderr.writeLine msg quit 1 else: diff --git a/src/create/exercises.nim b/src/create/exercises.nim index d5df3878..5962f527 100644 --- a/src/create/exercises.nim +++ b/src/create/exercises.nim @@ -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 " & @@ -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): @@ -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") diff --git a/tests/test_binary_create.nim b/tests/test_binary_create.nim index ddda2c12..03f12132 100644 --- a/tests/test_binary_create.nim +++ b/tests/test_binary_create.nim @@ -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.}