fix: config reader/writer, formatter, and ExtrasError bugs#1369
Merged
Conversation
Config_inl.hpp:
- recognize section headers with a trailing comment ("[section] # ...")
- close one-line multiline comments ('''text''') instead of swallowing the file
- fix off-by-two in Join-policy embedded-delimiter detection (e>0 fallback)
- define detail::clean_name_string in namespace detail (was leaking into CLI::
and never satisfying its declaration); qualify call sites
- use consistent comment lead on the unnamed-subcommand group header
Formatter_inl.hpp:
- exclude hidden positionals (empty group) from the usage line so they no
longer render as "[]"
- wrap long subcommand names onto their own line like long option names
- drop the extra newline in the non-paragraph description path
Error.hpp:
- ExtrasError(name, args) now reports get_name()=="ExtrasError" like every
other error class, folding the app name into the message
Adds regression tests in ConfigFileTest, FormatterTest, and AppTest.
Assisted-by: ClaudeCode:claude-opus-4-8
The comparison `opt->count() < delim_count + 1` is semantically equivalent to `opt->count() <= delim_count` but the addend form triggers GCC's -Wstrict-overflow=5 (assumes no signed wrap), which is treated as an error in the Azure CI Docker jobs (gcc9, gcc13_17, gcc15_23). Rewrite as `<= delim_count` to suppress the warning without changing the logic. Assisted-by: ClaudeCode:claude-sonnet-4.6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 AI text below 🤖
Part of #1357
Fixes a batch of verified Config/Formatter/Error bugs. Each was reproduced before changing; regression tests accompany the behavioral fixes.
include/CLI/impl/Config_inl.hpp[section] # a comment(legal TOML) previously fell through thefront()=='[' && back()==']'check (becauseback()was't', not']'), producing a bogus flag item named[section]and mis-attributing following keys. The reader now strips a quote-aware trailing comment for lines that open with[but do not end with], before the section check. Value lines are untouched (they still handle their own trailing comments downstream).'''comment on one line'''followed by real config now parses correctly. After detecting the'''/"""opener the same line is checked for a closer, guarded by a length>= 6requirement so the opening quotes themselves are not counted as the closer.N-1+edelimiters; the array fallback should trigger whene > 0, i.e.opt->count() < delim_count + 1. The code tested< delim_count - 1, so embedded-delimiter cases slipped through and wrote a bare join (e.g.vals="c,[a,b]") instead of the array form (vals=['c', "[a,b]"]). Fixed the comparison (signedness preserved via the existing cast). A round-trip test exercises the array-fallback path via the[[ ]]vector escape, which is the reachable way an element retains an embedded delimiter (normal delimiter-splitting options never producee > 0).clean_name_stringnamespace/signature mismatch.Config.hppdeclaredvoid detail::clean_name_string(std::string&, const std::string&), but the definition lived in the publicCLI::namespace and returnedstd::string&, so thedetaildeclaration was never defined and the real function pollutedCLI::. The definition is moved intonamespace detail, the return type reconciled tovoid(matching the declaration; no caller used the return value), and the four call sites into_configqualified asdetail::clean_name_string.commentLead(# Group Options); it now matches the main option-group header stylecommentChar << commentLead(## Group Options).include/CLI/impl/Formatter_inl.hpp[]in the usage line.make_usagenow filters positionals with!opt->get_group().empty(), matchingmake_positionals.make_subcommandnow mirrorsmake_option's long-name branch: when the name fills the column it emits a newline and disables the skip-first-line-prefix, so the description starts on its own indented line.make_descriptionalready returnsdesc + "\n\n"; theenable_description_formatting(false)branch inmake_helpdropped its extra'\n'so toggling the flag no longer changes spacing. (Scope limited tomake_helpper the report;make_expandedleft as-is.)include/CLI/Error.hppExtrasError(name, args)reports the right error name. The two-argument constructor previously delegated to the protected 3-arg form, makingget_name()return the app/subcommand name instead of"ExtrasError"(every other error class returns its class name, andApp::exit/user code dispatch onget_name()). It now folds the app name into the message and constructs via the public single-arg path soget_name() == "ExtrasError", while preserving (and slightly enriching) the message content.Tests
tests/ConfigFileTest.cpp:TomlSectionTrailingComment(1),TomlDocStringCommentOneLine(2),IniJoinEmbeddedDelimiterRoundTrip(3, verified to fail on the pre-fix comparison).tests/FormatterTest.cpp:HiddenPositionalUsage(6),LongSubcommandName(7),DescriptionNoFormattingSpacing(8) — all verified to fail without their fix.tests/AppTest.cpp:ExtrasErrorName(9).No false positives were found; all nine issues reproduced.
Verification
ctestover the full suite: 24/24 passed. The five primary binaries (ConfigFileTest, HelpTest, FormatterTest, AppTest, SubcommandTest) all pass; no existing tests required changes.prek -a --quietis clean.🤖 Generated with Claude Code