Skip to content

Refactor CLI parsing onto a single settings struct (CLI11 + nlohmann/json)#174

Open
drowaudio wants to merge 4 commits into
developfrom
claude/plan-magic-args-refactor-DvaCp
Open

Refactor CLI parsing onto a single settings struct (CLI11 + nlohmann/json)#174
drowaudio wants to merge 4 commits into
developfrom
claude/plan-magic-args-refactor-DvaCp

Conversation

@drowaudio
Copy link
Copy Markdown
Contributor

@drowaudio drowaudio commented Jun 6, 2026

Summary

Replaces the hand-rolled juce::ArgumentList CLI parser with one plain settings struct (PluginvalSettings) that CLI11 binds to directly, and adds a new --config <file.json> option. CLI + environment-variable behaviour is preserved; the flat flags are unchanged (subcommands are a planned follow-up).

Note: this PR started on magic_args (first two commits) and switched to CLI11 after review (3rd commit) to remove duplication and avoid the C++23 / macOS 13.3 costs. See history.

Design

CLI11 binds each option straight to a PluginvalSettings member, with the env var on the same line:

app.add_option("--strictness-level", s.strictnessLevel, "...")->envname("STRICTNESS_LEVEL");
app.add_option("--sample-rates",     s.sampleRates,     "...")->delimiter(',');           // comma lists
app.add_option("--rtcheck",          s.realtimeCheck,   "...")->transform(CheckedTransformer(...)); // enum
  • A --config <file.json> seeds the struct first; CLI11 only overwrites members whose flag/env was provided, so precedence is defaults < config < env < CLI (CLI wins) with no manual layering.
  • nlohmann/json provides --config load + the child-process handoff (an authoritative base64 JSON arg, --config-base64, avoiding command-line quoting hazards).
  • PluginvalSettings::toPluginTestOptions() converts to the existing PluginTests::Options at the JUCE boundary (unchanged downstream).

Adding an option is 3 edits: a struct member, a nlohmann macro entry, and one add_option(...) line. No parallel struct, no manual CLI→JSON or ENV→JSON code.

Key changes

  • New PluginvalSettings.h, SettingsParser.{h,cpp}, SettingsSerializer.{h,cpp}.
  • CommandLine.{h,cpp} reduced to a thin adapter (~395 lines of old parser removed); --run-tests/--strictness-help dispatched by token scan, --help/--version handled by CLI11 (auto usage + a footer with env-var/commands notes).
  • New --config <file.json>; precedence covered by tests.
  • CommandLineTests.cpp rewritten against the new pipeline (env tests use setenv/unsetenv since CLI11 reads the real environment).

Build / deps

  • CPM: CLI11 2.6.2 + nlohmann/json 3.12.0 (both header-only).
  • No language-standard or deployment-target change: stays cxx_std_20 and macOS 10.11. (CLI11 needs neither C++23 nor a newer macOS.)

Testing

  • --run-tests passes (all 21 CommandLineTests + existing suites).
  • Real --validate SUCCEEDs on multiple VST3s at strictness 5 and 10 (full build with embedded VST3 validator, macOS 10.11 target).
  • --config + CLI-override precedence verified by tests.

Follow-up (not in this PR)

Restructure the mode flags into subcommands (pluginval validate default / run-tests / strictness-help), keeping the old flat flags as deprecated aliases for one release. The settings struct + pipeline are designed to be reused unchanged.

drowaudio and others added 4 commits June 6, 2026 21:58
Prepares for the CLI parser refactor onto magic_args + a JSON-merge
settings pipeline.

- target_compile_features: cxx_std_20 -> cxx_std_23 (magic_args requires C++23)
- CPMAddPackage magic_args v0.2.1 (header-only INTERFACE: magic_args::magic_args)
- CPMAddPackage nlohmann/json 3.12.0 (nlohmann_json::nlohmann_json)
- link both into the pluginval target

Verified: clean build + link under C++23 with juce_recommended_warning_flags
on JUCE 8.0.13 (macOS/AppleClang); binary runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduces a single parser-agnostic settings struct and a layered
JSON pipeline that replaces the bespoke juce::ArgumentList parser.

Pipeline: each input layer (--config file, environment, CLI) becomes a
sparse nlohmann::json object; layers are merged with merge_patch in
precedence order (defaults < config < env < CLI, CLI wins) and
deserialised in one step into PluginvalSettings, which converts to the
existing PluginTests::Options at the JUCE boundary.

- PluginvalSettings.h: unified std-typed struct + toPluginTestOptions()
  + fromPluginTestOptions(); NLOHMANN_DEFINE_TYPE..._WITH_DEFAULT so
  missing keys fall back to defaults; RealtimeCheck enum<->string mapping.
- SettingsSerializer.{h,cpp}: JSON load/save + the comma-list, hex-seed
  and disabled-tests(file-or-list) coercions shared by the CLI/env layers.
- SettingsParser.{h,cpp}: preprocess (deprecation rewrite, macOS flag
  strip, implicit --validate), magic_args parse of the flat options into
  the sparse CLI layer, env layer, merge, and the child-process handoff.
- Child process round-trip now uses an authoritative base64 JSON arg
  (--config-base64) instead of per-flag re-serialisation, avoiding
  quote/tokenisation hazards. Round-trip asserted in tests.
- CommandLine.{h,cpp}: thin adapter; old manual parsers/env-merge/help
  text deleted. magic_args drives --help (auto usage + env-var trailer).
- New --config <file.json> option; precedence covered by tests.
- CommandLineTests.cpp rewritten against the new pipeline (defaults,
  parser, hex seed, comma lists, rtcheck, path resolution, implicit
  validate, env precedence, config precedence, round-trip).
- CMake: macOS deployment target 10.11 -> 13.3 (std::format in magic_args
  requires libc++ floating-point to_chars, available on 13.3+); add new
  sources.

All --run-tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- docs/Command line options.md regenerated from magic_args --help output
- CLAUDE.md: document the JSON-merge settings pipeline, new source files,
  magic_args + nlohmann/json deps, C++23, and the macOS 13.3 deployment target

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses review feedback that the magic_args version duplicated the
settings into a parallel PluginvalCliArgs struct plus manual CLI->JSON
and ENV->JSON bridges (5-6 edit sites per new option), and forced
cxx_std_23 + a macOS 13.3 deployment target (std::format).

CLI11 binds each option directly to a PluginvalSettings member, with the
environment variable on the same line via ->envname(). Adding an option
is now three edits: a struct member, a nlohmann macro entry, and one
add_option(...) line. No parallel struct, no cliArgsToJson, no envLayer.

- SettingsParser: rewritten on CLI11; comma lists via ->delimiter(','),
  enum via CheckedTransformer, hex/int seed via a small callback. --config
  seeds the struct before parse so precedence stays defaults<config<env<CLI.
  --help/--version handled by CLI11 (auto usage + footer).
- SettingsSerializer: dropped the comma/JSON-array coercions; kept the hex
  seed + disabled-tests(file-or-list) helpers and JSON load/save.
- Child-process base64 JSON handoff (--config-base64) unchanged.
- CommandLineTests: env tests now use setenv/unsetenv (CLI11 reads the real
  environment); all other cases unchanged. All --run-tests pass.
- CMake: magic_args -> CLI11 2.6.2; revert cxx_std_23 -> cxx_std_20 and
  CMAKE_OSX_DEPLOYMENT_TARGET 13.3 -> 10.11.
- Docs/CLAUDE.md updated.

Verified: full build (validator ON, C++20, macOS 10.11), --run-tests pass,
real --validate SUCCESS, --config precedence covered by tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@drowaudio drowaudio changed the title Refactor CLI parsing onto a JSON-merge settings pipeline (magic_args + nlohmann/json) Refactor CLI parsing onto a single settings struct (CLI11 + nlohmann/json) Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant