mirror of
https://github.com/sametersoylu/argument-parser.git
synced 2026-05-28 20:08:10 +00:00
Compare commits
14 Commits
v3
...
feat/accum
| Author | SHA1 | Date | |
|---|---|---|---|
| 1015b66d80 | |||
| 3f63bf958f | |||
| 8a57dca32e | |||
| 566b9128db | |||
| d1267c892f | |||
| 85e52a1dcd | |||
| b8e9f5c98c | |||
| 21ca1f638b | |||
|
|
2b2a0df933 | ||
| c067bbca38 | |||
| 54415f9527 | |||
| 96fdbb5f00 | |||
|
|
7fa218b7f3 | ||
| fc847c4cd1 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ build
|
||||
.vscode
|
||||
.vs
|
||||
.cache
|
||||
.idea
|
||||
|
||||
7
.idea/argument-parser.iml
generated
7
.idea/argument-parser.iml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
344
.idea/editor.xml
generated
344
.idea/editor.xml
generated
@@ -1,344 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="BackendCodeEditorSettings">
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppModulePartitionWithSeveralPartitionUnits/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||
</component>
|
||||
</project>
|
||||
365
.idea/workspace.xml
generated
365
.idea/workspace.xml
generated
@@ -1,365 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="BackendCodeEditorMiscSettings">
|
||||
<option name="/Default/Housekeeping/FeatureSuggestion/FeatureSuggestionManager/DisabledSuggesters/=SwitchToGoToActionSuggester/@EntryIndexedValue" value="true" type="bool" />
|
||||
</component>
|
||||
<component name="CMakePresetLoader">{
|
||||
"useNewFormat": true
|
||||
}</component>
|
||||
<component name="CMakeProjectFlavorService">
|
||||
<option name="flavorId" value="CMakePlainProjectFlavor" />
|
||||
</component>
|
||||
<component name="CMakeReloadState">
|
||||
<option name="reloaded" value="true" />
|
||||
</component>
|
||||
<component name="CMakeRunConfigurationManager">
|
||||
<generated>
|
||||
<config projectName="argument_parser" targetName="test" />
|
||||
</generated>
|
||||
</component>
|
||||
<component name="CMakeSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-G Ninja -DCMAKE_BUILD_TYPE=Debug" />
|
||||
<configuration PROFILE_NAME="Release" ENABLED="true" CONFIG_NAME="Release" GENERATION_OPTIONS="-G Ninja -DCMAKE_BUILD_TYPE=Release" />
|
||||
</configurations>
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="7ddada81-7b11-42b9-8fbe-5e1e6cce3b05" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/include/argparse" beforeDir="false" afterPath="$PROJECT_DIR$/include/argparse" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/include/parser/platform_headers/macos_parser.hpp" beforeDir="false" afterPath="$PROJECT_DIR$/include/parser/platform_headers/macos_parser.hpp" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ClangdSettings">
|
||||
<option name="formatViaClangd" value="false" />
|
||||
</component>
|
||||
<component name="ExecutionTargetManager" SELECTED_TARGET="CMakeBuildProfile:Debug" />
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
<option name="RESET_MODE" value="HARD" />
|
||||
</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="mock:///Users/killua/Projects/argument-parser/include/argparse" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///Users/killua/Projects/argument-parser/include/parser/argument_parser.hpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///Users/killua/Projects/argument-parser/include/parser/platform_headers/macos_parser.hpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///Users/killua/Projects/argument-parser/src/main.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="mock:///dummy.cpp" root0="SKIP_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="ProjectApplicationVersion">
|
||||
<option name="ide" value="CLion" />
|
||||
<option name="majorVersion" value="2025" />
|
||||
<option name="minorVersion" value="2.3" />
|
||||
<option name="productBranch" value="Classic" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 5
|
||||
}</component>
|
||||
<component name="ProjectId" id="33gk58BoSkVT3osKJJ81IgwdTvK" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"CMake Application.test.executor": "Debug",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"RunOnceActivity.RadMigrateCodeStyle": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.cidr.known.project.marker": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
||||
"RunOnceActivity.west.config.association.type.startup.service": "true",
|
||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"cf.first.check.clang-format": "false",
|
||||
"cidr.known.project.marker": "true",
|
||||
"git-widget-placeholder": "main",
|
||||
"last_opened_file_path": "/Users/killua/Projects/argument-parser",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "CMakeSettings",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager">
|
||||
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true">
|
||||
<method v="2">
|
||||
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="test" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="-h " REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="argument_parser" TARGET_NAME="test" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="argument_parser" RUN_TARGET_NAME="test">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="7ddada81-7b11-42b9-8fbe-5e1e6cce3b05" name="Changes" comment="" />
|
||||
<created>1759745916574</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1759745916574</updated>
|
||||
<workItem from="1759745917880" duration="2252000" />
|
||||
<workItem from="1759749176613" duration="2694000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="VCPKGProject">
|
||||
<isAutomaticCheckingOnLaunch value="false" />
|
||||
<isAutomaticFoundErrors value="true" />
|
||||
<isAutomaticReloadCMake value="true" />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
<breakpoints>
|
||||
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||
<url>file://$PROJECT_DIR$/include/parser/argument_parser.hpp</url>
|
||||
<line>145</line>
|
||||
<option name="timeStamp" value="4" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||
<url>file://$PROJECT_DIR$/include/parser/argument_parser.hpp</url>
|
||||
<line>277</line>
|
||||
<option name="timeStamp" value="6" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||
<url>file://$PROJECT_DIR$/include/parser/argument_parser.hpp</url>
|
||||
<line>276</line>
|
||||
<option name="timeStamp" value="7" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||
<url>file://$PROJECT_DIR$/include/parser/argument_parser.hpp</url>
|
||||
<line>219</line>
|
||||
<option name="timeStamp" value="9" />
|
||||
</line-breakpoint>
|
||||
</breakpoints>
|
||||
</breakpoint-manager>
|
||||
</component>
|
||||
</project>
|
||||
936
DOCS.MD
Normal file
936
DOCS.MD
Normal file
@@ -0,0 +1,936 @@
|
||||
# Argument Parser API Documentation
|
||||
|
||||
This document covers the public API exposed by:
|
||||
|
||||
- `src/headers/parser/argument_parser.hpp`: the original v1 parser surface.
|
||||
- `src/headers/parser/parser_v2.hpp`: the v2 map/initializer-list facade.
|
||||
- `src/headers/parser/argument_builder.hpp`: the staged fluent builder for v2.
|
||||
|
||||
The lower-level v1 API still powers the platform parsers and v2. New code will
|
||||
usually be clearest with `argument_parser::v2` and
|
||||
`argument_parser::builder::new_argument()`, but the v1 types remain public and
|
||||
useful when you need direct control over actions, stored values, or positional
|
||||
registration.
|
||||
|
||||
## Common Concepts
|
||||
|
||||
Argument names are registered without command-line prefixes. Use `"v"` and
|
||||
`"verbose"`, not `"-v"` or `"--verbose"`. The active convention objects decide
|
||||
which concrete syntaxes are accepted during parsing and how help text is
|
||||
rendered.
|
||||
|
||||
Typed values are parsed through
|
||||
`argument_parser::parsing_traits::parser_trait<T>::parse(std::string const&)`.
|
||||
The built-in traits cover common scalar types such as `std::string`, `bool`,
|
||||
`int`, `float`, and `double`; custom value types need a trait specialization.
|
||||
Trait `format_hint` and `purpose_hint` members are used in help text and parse
|
||||
error messages when available.
|
||||
|
||||
Stored values are type-erased internally. Retrieve them with the same type used
|
||||
when the argument was registered.
|
||||
|
||||
## v1 API: `argument_parser.hpp`
|
||||
|
||||
The public v1 types live in the `argument_parser` namespace unless otherwise
|
||||
noted.
|
||||
|
||||
### `action_base`
|
||||
|
||||
```cpp
|
||||
class action_base {
|
||||
public:
|
||||
virtual ~action_base() = default;
|
||||
[[nodiscard]] virtual bool expects_parameter() const = 0;
|
||||
virtual void invoke() const = 0;
|
||||
virtual void invoke_with_parameter(std::string const& param) const = 0;
|
||||
[[nodiscard]] virtual std::pair<std::string, std::string> get_trait_hints() const = 0;
|
||||
[[nodiscard]] virtual std::unique_ptr<action_base> clone() const = 0;
|
||||
};
|
||||
```
|
||||
|
||||
`action_base` is the polymorphic interface stored by registered arguments.
|
||||
Application code normally uses `action_with_param<T>`, `action_no_param`, or
|
||||
the overloaded `helpers::make_action(...)` factories instead of implementing
|
||||
this interface directly.
|
||||
|
||||
- `expects_parameter()` reports whether the action consumes a value token.
|
||||
- `invoke()` runs a no-value action. On `action_with_param<T>`, it throws
|
||||
`std::runtime_error`.
|
||||
- `invoke_with_parameter(param)` runs a value action. On
|
||||
`action_no_param`, the parameter is ignored.
|
||||
- `get_trait_hints()` returns `{format_hint, purpose_hint}` for typed actions
|
||||
when the parser trait exposes those members.
|
||||
- `clone()` returns a heap-allocated copy used by `argument`.
|
||||
|
||||
### `action_with_param<T>`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
class action_with_param : public action_base {
|
||||
public:
|
||||
using parameter_type = T;
|
||||
|
||||
explicit action_with_param(std::function<void(T const&)> const& handler);
|
||||
void invoke(T const& arg) const;
|
||||
[[nodiscard]] bool expects_parameter() const override;
|
||||
void invoke() const override;
|
||||
void invoke_with_parameter(std::string const& param) const override;
|
||||
[[nodiscard]] std::pair<std::string, std::string> get_trait_hints() const override;
|
||||
[[nodiscard]] std::unique_ptr<action_base> clone() const override;
|
||||
};
|
||||
```
|
||||
|
||||
Adapts a `std::function<void(T const&)>` into a parser action. During
|
||||
`invoke_with_parameter`, the raw string is converted with
|
||||
`parser_trait<T>::parse(param)` and the parsed value is passed to the handler.
|
||||
Parse failures are reported as `std::runtime_error` with trait-derived hints
|
||||
when available.
|
||||
|
||||
### `action_no_param`
|
||||
|
||||
```cpp
|
||||
class action_no_param : public action_base {
|
||||
public:
|
||||
explicit action_no_param(std::function<void()> const& handler);
|
||||
|
||||
void invoke() const override;
|
||||
[[nodiscard]] bool expects_parameter() const override;
|
||||
void invoke_with_parameter(std::string const& param) const override;
|
||||
[[nodiscard]] std::pair<std::string, std::string> get_trait_hints() const override;
|
||||
[[nodiscard]] std::unique_ptr<action_base> clone() const override;
|
||||
};
|
||||
```
|
||||
|
||||
Adapts a `std::function<void()>` into a flag-style action.
|
||||
`expects_parameter()` returns `false`; `invoke_with_parameter(...)` ignores the
|
||||
parameter and runs the no-value handler.
|
||||
|
||||
### `argument_parser::helpers`
|
||||
|
||||
```cpp
|
||||
namespace argument_parser::helpers {
|
||||
template <typename T>
|
||||
action_with_param<T>
|
||||
make_action(std::function<void(T const&)> const& function);
|
||||
|
||||
action_no_param
|
||||
make_action(std::function<void()> const& function);
|
||||
}
|
||||
```
|
||||
|
||||
Factory helpers for creating action objects used by `base_parser` and v2.
|
||||
|
||||
### `parser_settings`
|
||||
|
||||
```cpp
|
||||
struct parser_settings {
|
||||
bool should_exit_on_error = true;
|
||||
bool should_exit_on_missing_required = true;
|
||||
bool should_exit_on_unknown_argument = true;
|
||||
bool should_exit_on_help = true;
|
||||
|
||||
bool ignore_unknown_arguments = false;
|
||||
bool ignore_errors = false;
|
||||
};
|
||||
|
||||
constexpr static inline parser_settings no_exit{
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
```
|
||||
|
||||
`parser_settings` configures how the parser reacts to help, parse errors,
|
||||
unknown arguments, and missing required arguments. The default settings preserve
|
||||
CLI-style behavior: help exits after printing, unknown arguments and parse
|
||||
errors exit with status `1`, and missing required arguments print diagnostics
|
||||
and help before exiting.
|
||||
|
||||
Use `argument_parser::no_exit` when embedding the parser in tests, tools, or
|
||||
larger applications that should receive exceptions instead of process exits:
|
||||
|
||||
```cpp
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit);
|
||||
```
|
||||
|
||||
For targeted behavior, pass an explicit settings object to the v2 platform
|
||||
parser constructor:
|
||||
|
||||
```cpp
|
||||
argument_parser::parser_settings settings;
|
||||
settings.should_exit_on_help = false;
|
||||
settings.should_exit_on_error = false;
|
||||
settings.should_exit_on_unknown_argument = false;
|
||||
settings.should_exit_on_missing_required = false;
|
||||
settings.ignore_unknown_arguments = true;
|
||||
|
||||
argument_parser::v2::parser parser(settings);
|
||||
```
|
||||
|
||||
The fields have these effects:
|
||||
|
||||
- `should_exit_on_help`: controls whether the automatically registered v2
|
||||
`-h` / `--help` action calls `std::exit(0)` after printing help.
|
||||
- `should_exit_on_error`: when `true`, non-unknown parse errors caught by
|
||||
`handle_arguments(...)` call `std::exit(1)`; when `false`, the exception is
|
||||
rethrown.
|
||||
- `should_exit_on_unknown_argument`: when `true`, unknown arguments caught by
|
||||
`handle_arguments(...)` call `std::exit(1)`; when `false`, the unknown
|
||||
argument exception is rethrown.
|
||||
- `should_exit_on_missing_required`: when `true`, missing required arguments
|
||||
print diagnostics/help and call `std::exit(1)`; when `false`, they throw
|
||||
`std::runtime_error`.
|
||||
- `ignore_unknown_arguments`: when `true`, tokens that match no convention and
|
||||
cannot be consumed as positionals are skipped.
|
||||
- `ignore_errors`: reserved in the public settings struct in the current
|
||||
worktree; no runtime branch currently reads it.
|
||||
|
||||
### `argument`
|
||||
|
||||
```cpp
|
||||
class argument {
|
||||
public:
|
||||
argument();
|
||||
|
||||
template <typename ActionType>
|
||||
argument(int id, std::string name, ActionType const& action);
|
||||
|
||||
argument(argument const& other);
|
||||
argument& operator=(argument const& other);
|
||||
argument(argument&& other) noexcept = default;
|
||||
argument& operator=(argument&& other) noexcept = default;
|
||||
|
||||
[[nodiscard]] bool is_required() const;
|
||||
[[nodiscard]] std::string get_name() const;
|
||||
[[nodiscard]] bool is_invoked() const;
|
||||
[[nodiscard]] bool expects_parameter() const;
|
||||
[[nodiscard]] std::string get_help_text() const;
|
||||
[[nodiscard]] bool is_positional() const;
|
||||
[[nodiscard]] bool is_positional_accumulator() const;
|
||||
[[nodiscard]] std::optional<int> get_position_index() const;
|
||||
};
|
||||
```
|
||||
|
||||
`argument` is the public descriptor returned by parser lookup operations. It is
|
||||
copyable; copies clone their stored action.
|
||||
|
||||
- `is_required()` reports whether parsing must see this argument.
|
||||
- `get_name()` returns the registered display name. Named options are stored as
|
||||
`"<short>|<long>"`; positional arguments use their positional name.
|
||||
- `is_invoked()` reports whether the action ran during `handle_arguments(...)`.
|
||||
- `expects_parameter()` mirrors the stored action.
|
||||
- `get_help_text()` returns the registration help text.
|
||||
- `is_positional()` identifies positional arguments.
|
||||
- `is_positional_accumulator()` is true for positional accumulators.
|
||||
- `get_position_index()` returns the explicit requested position, or
|
||||
`std::nullopt`.
|
||||
|
||||
### `base_parser`
|
||||
|
||||
```cpp
|
||||
class base_parser {
|
||||
public:
|
||||
template <typename T>
|
||||
void add_argument(
|
||||
std::string const& short_arg,
|
||||
std::string const& long_arg,
|
||||
std::string const& help_text,
|
||||
action_with_param<T> const& action,
|
||||
bool required);
|
||||
|
||||
template <typename T>
|
||||
void add_argument(
|
||||
std::string const& short_arg,
|
||||
std::string const& long_arg,
|
||||
std::string const& help_text,
|
||||
bool required);
|
||||
|
||||
void add_argument(
|
||||
std::string const& short_arg,
|
||||
std::string const& long_arg,
|
||||
std::string const& help_text,
|
||||
action_no_param const& action,
|
||||
bool required);
|
||||
|
||||
void add_argument(
|
||||
std::string const& short_arg,
|
||||
std::string const& long_arg,
|
||||
std::string const& help_text,
|
||||
bool required);
|
||||
|
||||
template <typename T>
|
||||
void add_positional_argument(
|
||||
std::string const& name,
|
||||
std::string const& help_text,
|
||||
action_with_param<T> const& action,
|
||||
bool required,
|
||||
std::optional<int> position = std::nullopt);
|
||||
|
||||
template <typename T>
|
||||
void add_positional_argument(
|
||||
std::string const& name,
|
||||
std::string const& help_text,
|
||||
bool required,
|
||||
std::optional<int> position = std::nullopt);
|
||||
|
||||
template <typename T>
|
||||
void add_positional_accumulator(
|
||||
std::string const& name,
|
||||
std::string const& help_text,
|
||||
action_with_param<T> const& action,
|
||||
bool required,
|
||||
std::optional<int> position = std::nullopt);
|
||||
|
||||
void on_complete(std::function<void(base_parser const&)> const& action);
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> get_optional(std::string const& arg) const;
|
||||
|
||||
[[nodiscard]] std::string build_help_text(
|
||||
std::initializer_list<conventions::convention const* const> convention_types) const;
|
||||
|
||||
argument& get_argument(conventions::parsed_argument const& arg);
|
||||
[[nodiscard]] std::optional<int> find_argument_id(std::string const& arg) const;
|
||||
void handle_arguments(
|
||||
std::initializer_list<conventions::convention const* const> convention_types);
|
||||
void display_help(
|
||||
std::initializer_list<conventions::convention const* const> convention_types) const;
|
||||
|
||||
protected:
|
||||
base_parser() = default;
|
||||
};
|
||||
```
|
||||
|
||||
`base_parser` owns registrations, parsed command-line tokens, stored values,
|
||||
required-argument checks, and completion hooks. Its constructor is protected;
|
||||
users normally instantiate a concrete parser from `<argparse>` or a platform
|
||||
header. Platform parser constructors populate `program_name` and
|
||||
`parsed_arguments` from the native process arguments.
|
||||
|
||||
`base_parser` is not thread-safe. `handle_arguments(...)` must be called on the
|
||||
same thread that created the parser or it throws `std::runtime_error`.
|
||||
|
||||
#### Named Arguments
|
||||
|
||||
Use `add_argument(...)` for short and/or long options. The v1 API uses `"-"` as
|
||||
the sentinel for an omitted short or long name.
|
||||
|
||||
```cpp
|
||||
argument_parser::parser parser;
|
||||
|
||||
parser.add_argument<std::string>(
|
||||
"o",
|
||||
"output",
|
||||
"Output file.",
|
||||
argument_parser::helpers::make_action<std::string>(
|
||||
[](std::string const& value) {
|
||||
// use value
|
||||
}),
|
||||
true);
|
||||
|
||||
parser.add_argument(
|
||||
"v",
|
||||
"verbose",
|
||||
"Enable verbose output.",
|
||||
false);
|
||||
```
|
||||
|
||||
Registration fails with `std::runtime_error("The key already exists!")` if the
|
||||
short or long key is already registered. Because duplicate checks also see the
|
||||
`"-"` sentinel, avoid registering multiple v1 arguments that pass `"-"` for the
|
||||
same side unless you have verified that behavior.
|
||||
|
||||
The overloads behave as follows:
|
||||
|
||||
- `add_argument<T>(..., action_with_param<T> const& action, bool required)`
|
||||
parses a value and invokes the supplied typed action.
|
||||
- `add_argument<T>(..., bool required)` parses a value and stores it internally
|
||||
for `get_optional<T>(...)`.
|
||||
- `add_argument(..., action_no_param const& action, bool required)`
|
||||
invokes a no-value action.
|
||||
- `add_argument(..., bool required)` stores `true` internally when the option is
|
||||
present.
|
||||
|
||||
#### Positional Arguments
|
||||
|
||||
```cpp
|
||||
parser.add_positional_argument<std::string>(
|
||||
"input",
|
||||
"Input path.",
|
||||
true,
|
||||
0);
|
||||
|
||||
parser.add_positional_argument<int>(
|
||||
"count",
|
||||
"Number of iterations.",
|
||||
argument_parser::helpers::make_action<int>(
|
||||
[](int value) {
|
||||
// use value
|
||||
}),
|
||||
false);
|
||||
```
|
||||
|
||||
Positional arguments are matched against tokens that do not match any supplied
|
||||
convention. You can provide an explicit zero-based `position`, or omit it to use
|
||||
the next available positional slot.
|
||||
|
||||
`add_positional_argument<T>(..., bool required, ...)` stores the parsed value
|
||||
internally under the positional name. The action overload invokes the supplied
|
||||
typed action.
|
||||
|
||||
`add_positional_accumulator<T>(...)` registers a typed positional action that can
|
||||
consume repeated positional tokens at its slot. Only one positional accumulator
|
||||
is allowed, and it must be the last positional argument. Duplicate names,
|
||||
negative explicit positions, or invalid accumulator placement throw
|
||||
`std::runtime_error`.
|
||||
|
||||
#### Parsing
|
||||
|
||||
```cpp
|
||||
parser.handle_arguments({
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
&argument_parser::conventions::gnu_equal_argument_convention,
|
||||
&argument_parser::conventions::windows_argument_convention,
|
||||
&argument_parser::conventions::windows_equal_argument_convention,
|
||||
});
|
||||
```
|
||||
|
||||
`handle_arguments(...)` invokes matching actions, records stored values, checks
|
||||
required arguments, then runs completion hooks. For each token, conventions are
|
||||
tried in order. If no convention matches, the token is consumed as the next
|
||||
positional value when one is available. `--` forces all following tokens to be
|
||||
treated as positional values.
|
||||
|
||||
Unknown options, missing values, parse failures, unexpected positional values,
|
||||
and action errors are reported with `std::runtime_error`. Missing required
|
||||
arguments print diagnostics and help text, then call `std::exit(1)`.
|
||||
|
||||
If a registered argument named `h` or `help` is found, the parser invokes that
|
||||
help argument and returns from argument invocation early. Required checks and
|
||||
completion hooks still run after invocation returns.
|
||||
|
||||
#### Lookup And Help
|
||||
|
||||
```cpp
|
||||
if (auto output = parser.get_optional<std::string>("output")) {
|
||||
// *output is the stored value
|
||||
}
|
||||
|
||||
auto id = parser.find_argument_id("output");
|
||||
std::string help = parser.build_help_text({
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
});
|
||||
parser.display_help({
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
});
|
||||
```
|
||||
|
||||
`get_optional<T>(arg)` returns a stored value for a registered short name, long
|
||||
name, or positional name. It returns `std::nullopt` when no argument by that name
|
||||
exists or when no value was stored. If a value exists but `T` does not match the
|
||||
stored type, `std::any_cast<T>` throws `std::bad_any_cast`.
|
||||
|
||||
`find_argument_id(arg)` returns the internal integer id for a registered short
|
||||
name, long name, or positional name. `get_argument(parsed_argument)` resolves a
|
||||
parsed convention result to an `argument&` and throws when no match exists.
|
||||
|
||||
`build_help_text(...)` returns formatted usage text. `display_help(...)` writes
|
||||
that text to `std::cout`.
|
||||
|
||||
#### Completion Hooks
|
||||
|
||||
```cpp
|
||||
parser.on_complete([](argument_parser::base_parser const& state) {
|
||||
// inspect state.get_optional<T>(...)
|
||||
});
|
||||
```
|
||||
|
||||
`on_complete(...)` appends a callback that runs after successful argument
|
||||
invocation and required-argument checks.
|
||||
|
||||
## v2 API: `parser_v2.hpp`
|
||||
|
||||
The v2 API is declared under `argument_parser::v2`. It provides a
|
||||
map/initializer-list facade over the v1 `base_parser`, while still accepting the
|
||||
same convention objects and action helpers.
|
||||
|
||||
Typical use is through the platform alias from `<argparse>`:
|
||||
|
||||
```cpp
|
||||
#include <argparse>
|
||||
|
||||
using namespace argument_parser::v2::flags;
|
||||
|
||||
int main() {
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit);
|
||||
|
||||
parser.add_argument<int>({
|
||||
{LongArgument, "count"},
|
||||
{HelpText, "Number of items to process."},
|
||||
{Required, true},
|
||||
});
|
||||
|
||||
parser.handle_arguments({
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
&argument_parser::conventions::windows_argument_convention,
|
||||
});
|
||||
|
||||
auto count = parser.get_optional<int>("count");
|
||||
}
|
||||
```
|
||||
|
||||
### `enum class add_argument_flags`
|
||||
|
||||
These keys describe an argument passed to `v2::base_parser::add_argument`.
|
||||
|
||||
| Flag | Value type | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `ShortArgument` | `std::string` | Short option name, such as `"v"`. |
|
||||
| `LongArgument` | `std::string` | Long option name, such as `"verbose"`. |
|
||||
| `Positional` | `std::string` | Registers a positional argument. When present, the positional registration path is used. |
|
||||
| `Position` | `int` | Optional zero-based position for a positional argument. |
|
||||
| `HelpText` | `std::string` | Help text shown in generated help output. |
|
||||
| `Action` | `action_with_param<T>` or `action_no_param` | Callback invoked when the argument is found. |
|
||||
| `Required` | `bool` | Marks the argument required when `true`. |
|
||||
| `Reference` | `T*` | Stores a parsed typed value into an external object. Cannot be combined with `Action`. |
|
||||
| `Accumulate` | `bool` or `T*` | Repeated-value mode. For `std::vector<U>`, each parsed `U` is appended. For `int`, each occurrence increments the count. |
|
||||
|
||||
The `argument_parser::v2::flags` namespace exposes inline constants with the
|
||||
same names for concise initializer-list calls.
|
||||
|
||||
```cpp
|
||||
using namespace argument_parser::v2::flags;
|
||||
|
||||
parser.add_argument({
|
||||
{ShortArgument, "q"},
|
||||
{HelpText, "Quiet mode."},
|
||||
});
|
||||
```
|
||||
|
||||
### `argument_parser::v2::deducers`
|
||||
|
||||
```cpp
|
||||
template <typename, typename = void>
|
||||
struct has_value_type;
|
||||
|
||||
template <typename T>
|
||||
struct is_vector;
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_vector_v = is_vector<T>::test();
|
||||
```
|
||||
|
||||
These public type traits are used by v2 accumulator logic. `has_value_type`
|
||||
detects `T::value_type`. `is_vector<T>::test()` and `is_vector_v<T>` are true
|
||||
only when `T` is exactly a `std::vector` specialization.
|
||||
|
||||
### `argument_parser::v2::base_parser`
|
||||
|
||||
`v2::base_parser` is the v2 facade. Concrete platform parsers such as
|
||||
`argument_parser::v2::linux_parser`, `macos_parser`, `windows_parser`, and the
|
||||
portable `<argparse>` alias `argument_parser::v2::parser` derive from it. The
|
||||
v2 platform parser constructors accept `parser_settings const& settings = {}`.
|
||||
Use the default constructor for normal command-line tools, or pass
|
||||
`argument_parser::no_exit` / a custom `parser_settings` object when the caller
|
||||
should handle errors without automatic process exits.
|
||||
|
||||
The class privately inherits from the v1 `argument_parser::base_parser` and
|
||||
re-exposes selected operations.
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
using typed_flag_value =
|
||||
std::variant<std::string, action_with_param<T>, bool, int, T*>;
|
||||
|
||||
using non_typed_flag_value =
|
||||
std::variant<std::string, action_no_param, bool, int>;
|
||||
|
||||
template <typename T>
|
||||
using typed_argument_pair =
|
||||
std::pair<add_argument_flags, typed_flag_value<T>>;
|
||||
|
||||
using non_typed_argument_pair =
|
||||
std::pair<add_argument_flags, non_typed_flag_value>;
|
||||
```
|
||||
|
||||
Use typed aliases for arguments that parse a value of `T`, run an
|
||||
`action_with_param<T>`, store into a `T`, or accumulate values. Use non-typed
|
||||
aliases for boolean flags and no-parameter actions.
|
||||
|
||||
#### Typed `add_argument`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
void add_argument(
|
||||
std::unordered_map<add_argument_flags, typed_flag_value<T>> const& argument_pairs);
|
||||
|
||||
template <typename T>
|
||||
void add_argument(std::initializer_list<typed_argument_pair<T>> const& pairs);
|
||||
```
|
||||
|
||||
Registers a typed option or positional argument. For non-positional options,
|
||||
provide at least one of `ShortArgument` or `LongArgument`. If only one name is
|
||||
supplied, the other is internally set to `"-"` and not registered.
|
||||
|
||||
Without `Action`, `Reference`, or `Accumulate`, the parsed `T` is stored
|
||||
internally and can be read with `get_optional<T>()`. For positional arguments,
|
||||
include `Positional`; `Position` can place the argument at a specific zero-based
|
||||
slot.
|
||||
|
||||
```cpp
|
||||
int threshold = 0;
|
||||
|
||||
parser.add_argument<int>({
|
||||
{LongArgument, "threshold"},
|
||||
{Reference, &threshold},
|
||||
{HelpText, "Store the parsed threshold."},
|
||||
});
|
||||
```
|
||||
|
||||
#### Non-Typed `add_argument`
|
||||
|
||||
```cpp
|
||||
void add_argument(
|
||||
std::unordered_map<add_argument_flags, non_typed_flag_value> const& argument_pairs);
|
||||
|
||||
void add_argument(std::initializer_list<non_typed_argument_pair> const& pairs);
|
||||
```
|
||||
|
||||
Registers a non-typed option or positional argument. For options, provide at
|
||||
least one of `ShortArgument` or `LongArgument`. Without `Action`, the argument
|
||||
behaves as a boolean flag: when present, it stores `true` for
|
||||
`get_optional<bool>()`.
|
||||
|
||||
With `Action`, provide an `action_no_param`. Non-typed arguments cannot use
|
||||
`Reference` or `Accumulate`. A non-typed positional argument is stored as
|
||||
`std::string`.
|
||||
|
||||
```cpp
|
||||
parser.add_argument({
|
||||
{ShortArgument, "v"},
|
||||
{LongArgument, "verbose"},
|
||||
{HelpText, "Enable verbose output."},
|
||||
});
|
||||
```
|
||||
|
||||
#### Other Public Operations
|
||||
|
||||
```cpp
|
||||
argument_parser::base_parser& to_v1();
|
||||
|
||||
void handle_arguments(
|
||||
std::initializer_list<conventions::convention const* const> convention_types);
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> get_optional(std::string const& arg);
|
||||
|
||||
using argument_parser::base_parser::display_help;
|
||||
using argument_parser::base_parser::on_complete;
|
||||
```
|
||||
|
||||
`to_v1()` returns a mutable reference to the underlying v1 parser interface.
|
||||
`handle_arguments(...)`, `get_optional<T>(...)`, `display_help(...)`, and
|
||||
`on_complete(...)` follow the v1 behavior described above.
|
||||
|
||||
### Accumulation
|
||||
|
||||
`Accumulate` has special typed behavior:
|
||||
|
||||
- `T = std::vector<U>` registers an argument that accepts repeated `U` values.
|
||||
- `T = int` registers a counter-style option; each occurrence increments the
|
||||
count.
|
||||
- `Accumulate` set to `true` stores the accumulated result internally and makes
|
||||
it available through `get_optional<T>()`.
|
||||
- `Accumulate` set to `T*`, or `Accumulate` combined with `Reference`, writes
|
||||
directly to an external object.
|
||||
|
||||
For vector accumulators, the public argument type is `std::vector<U>`, but each
|
||||
individual command-line occurrence is parsed as `U`.
|
||||
|
||||
```cpp
|
||||
parser.add_argument<std::vector<int>>({
|
||||
{LongArgument, "include-id"},
|
||||
{Accumulate, true},
|
||||
{HelpText, "May be repeated."},
|
||||
});
|
||||
|
||||
auto ids = parser.get_optional<std::vector<int>>("include-id");
|
||||
```
|
||||
|
||||
## Builder API: `argument_builder.hpp`
|
||||
|
||||
The public builder API lives under `argument_parser::builder`. It provides a
|
||||
staged fluent interface for registering arguments with
|
||||
`argument_parser::v2::base_parser`.
|
||||
|
||||
```cpp
|
||||
#include <argument_builder.hpp>
|
||||
// or
|
||||
#include <argparse>
|
||||
|
||||
using argument_parser::builder::new_argument;
|
||||
```
|
||||
|
||||
### Public Types
|
||||
|
||||
`non_type` is a marker type used before a value-producing mode has been
|
||||
selected. Application code normally does not need to name it.
|
||||
|
||||
`builder_mask` is a public namespace containing the compile-time machinery used
|
||||
by `argument<mask, store_type>`. It exposes `mask_type`, `value_mode`,
|
||||
`extra_capability`, capability constants such as `short_argument`,
|
||||
`long_argument`, `positional`, `help_text`, `required`, `reference`,
|
||||
`accumulate`, `count`, `store`, and `flag`, plus constexpr helpers such as
|
||||
`bit`, `has`, `remove`, `replace`, `is_buildable`, and
|
||||
`is_build_and_gettable`. These are mainly useful for type-level tests or
|
||||
advanced wrappers.
|
||||
|
||||
### `container<store_type>`
|
||||
|
||||
```cpp
|
||||
template <typename store_type>
|
||||
class container;
|
||||
```
|
||||
|
||||
Returned by `build_and_get(parser)`. It is populated after
|
||||
`parser.handle_arguments(...)` completes.
|
||||
|
||||
- `store_type get() const` returns the stored value. Call only after the
|
||||
container is populated.
|
||||
- `store_type& operator*()` dereferences the stored value.
|
||||
- `store_type* operator->()` accesses members of the stored value.
|
||||
- `operator bool()` reports whether a value is available.
|
||||
|
||||
For builder-managed storage, `build_and_get()` registers an `on_complete`
|
||||
callback that reads the parsed value by lookup key. For
|
||||
`accumulate(existing_vector)`, the container references the provided vector
|
||||
directly.
|
||||
|
||||
### `argument<mask, store_type>`
|
||||
|
||||
```cpp
|
||||
template <
|
||||
argument_parser::builder::builder_mask::mask_type mask =
|
||||
argument_parser::builder::builder_mask::initial,
|
||||
typename store_type = argument_parser::builder::non_type>
|
||||
class argument;
|
||||
```
|
||||
|
||||
The staged fluent builder. `mask` enables only valid next methods at compile
|
||||
time. `store_type` is the type produced by the selected value mode. Most users
|
||||
should create builders with `new_argument()`.
|
||||
|
||||
### Entry Points
|
||||
|
||||
```cpp
|
||||
static auto argument<>::start() -> argument<builder_mask::initial>;
|
||||
static inline auto new_argument();
|
||||
```
|
||||
|
||||
`new_argument()` is equivalent to `argument<>::start()`.
|
||||
|
||||
```cpp
|
||||
new_argument()
|
||||
.long_argument("output")
|
||||
.store<std::string>()
|
||||
.required()
|
||||
.build(parser);
|
||||
```
|
||||
|
||||
### Identifier Methods
|
||||
|
||||
At least one identifier method must be used before `build(parser)` or
|
||||
`build_and_get(parser)`.
|
||||
|
||||
```cpp
|
||||
auto short_argument(std::string short_name) const -> argument<..., store_type>;
|
||||
auto long_argument(std::string long_name) const -> argument<..., store_type>;
|
||||
auto positional(std::string positional_name) const -> argument<..., store_type>;
|
||||
auto position(int index) const -> argument<..., store_type>;
|
||||
```
|
||||
|
||||
`short_argument(...)` and `long_argument(...)` set named option identifiers and
|
||||
can be combined with each other. `positional(...)` registers a positional
|
||||
argument and is mutually exclusive with named identifiers. `position(...)` is
|
||||
available only after `positional(...)` and only once. If no value mode is
|
||||
selected for a positional argument, `build(parser)` registers a `std::string`
|
||||
positional value.
|
||||
|
||||
### Metadata Methods
|
||||
|
||||
```cpp
|
||||
auto help_text(std::string help) const -> argument<..., store_type>;
|
||||
auto required(bool value = true) const -> argument<..., store_type>;
|
||||
```
|
||||
|
||||
`help_text(...)` sets generated help text and is single-use. If omitted, v2
|
||||
generates default text, often using parser trait hints for typed value modes.
|
||||
|
||||
`required(...)` marks the argument required when `value` is `true`. There is no
|
||||
public `setRequired(...)` method in `argument_builder.hpp`; the public fluent API
|
||||
is `required(...)`.
|
||||
|
||||
### Terminal Value Modes
|
||||
|
||||
Exactly one terminal value mode can be selected. Once selected, the other modes
|
||||
are removed from the builder type.
|
||||
|
||||
```cpp
|
||||
template <typename T = std::string>
|
||||
auto store() const -> argument<..., T>;
|
||||
|
||||
template <typename T>
|
||||
auto reference(T& value) const -> argument<..., T>;
|
||||
|
||||
auto flag() const -> argument<..., bool>;
|
||||
|
||||
template <typename T = std::string>
|
||||
auto accumulate() const -> argument<..., std::vector<T>>;
|
||||
|
||||
template <typename T>
|
||||
auto accumulate(T& value) const -> argument<..., T>;
|
||||
|
||||
auto count() const -> argument<..., int>;
|
||||
auto count(int& value) const -> argument<..., int>;
|
||||
|
||||
template <typename Callable>
|
||||
auto action(Callable&& handler) const -> argument<..., non_type>;
|
||||
|
||||
template <typename T = std::string, typename Callable>
|
||||
auto action(Callable&& handler) const -> argument<..., T>;
|
||||
```
|
||||
|
||||
`store<T>()` parses a value and stores it in the parser for later lookup.
|
||||
`store<void>()` is rejected at compile time.
|
||||
|
||||
`reference(T&)` parses a value and assigns it directly to an object that must
|
||||
outlive parsing.
|
||||
|
||||
`flag()` registers a boolean presence flag. It is not available for positional
|
||||
arguments. Named arguments also default to flag behavior when no terminal mode
|
||||
is selected.
|
||||
|
||||
`accumulate<T>()` accepts repeated values and stores them as `std::vector<T>`.
|
||||
`accumulate(existing)` appends repeated values into an existing vector. The
|
||||
existing object must be a `std::vector` and must outlive parsing.
|
||||
|
||||
`count()` counts how many times a named argument appears. `count(int&)` writes
|
||||
the count into an existing integer. `count()` is not available for positional
|
||||
arguments.
|
||||
|
||||
`action(handler)` registers a no-value action when `handler` is invocable as
|
||||
`void()`. For positional arguments, the builder adapts it through a
|
||||
`std::string` positional action and ignores the parsed positional text.
|
||||
|
||||
`action<T>(handler)` registers a typed action when `handler` is invocable as
|
||||
`void(T const&)`. `action<void>(...)` is rejected at compile time.
|
||||
|
||||
### Build Methods
|
||||
|
||||
```cpp
|
||||
auto build(argument_parser::v2::base_parser& parser) const -> void;
|
||||
|
||||
auto build_and_get(argument_parser::v2::base_parser& parser) const
|
||||
-> container<store_type>;
|
||||
```
|
||||
|
||||
`build(parser)` registers the configured argument with the parser. It requires
|
||||
an identifier, dispatches to the selected terminal mode, and defaults to a named
|
||||
boolean flag or `std::string` positional value when no terminal mode was
|
||||
selected. It may propagate validation errors from `v2::base_parser`.
|
||||
|
||||
`build_and_get(parser)` registers the argument and returns a
|
||||
`container<store_type>` for storable modes such as `store<T>()`, `flag()`,
|
||||
default named flags, `accumulate<T>()`, `accumulate(vector&)`, `count()`, and
|
||||
`count(int&)`. It throws `std::logic_error` for unsupported terminal modes such
|
||||
as actions. The returned container is normally empty until
|
||||
`parser.handle_arguments(...)` completes.
|
||||
|
||||
### Compile-Time Builder Rules
|
||||
|
||||
Invalid fluent chains fail to compile rather than failing at runtime.
|
||||
|
||||
- `build(...)` requires `short_argument(...)`, `long_argument(...)`, or
|
||||
`positional(...)`.
|
||||
- `short_argument(...)` and `long_argument(...)` can be combined.
|
||||
- `positional(...)` is mutually exclusive with named identifiers.
|
||||
- `position(...)` is available only after `positional(...)` and only once.
|
||||
- `help_text(...)` and `required(...)` are single-use.
|
||||
- Terminal value modes are mutually exclusive.
|
||||
- `flag()` and `count()` are not available for positional arguments.
|
||||
- `store<void>()` and `action<void>(...)` are rejected with `static_assert`.
|
||||
- `accumulate(existing)` requires `existing` to be a `std::vector`.
|
||||
|
||||
The header also exposes `argument_parser::builder::assertions`, a namespace of
|
||||
small compile-time detection helpers and `static_assert` checks used to verify
|
||||
these staged-builder rules. They are not needed for normal parser
|
||||
configuration.
|
||||
|
||||
### Complete Builder Example
|
||||
|
||||
```cpp
|
||||
#include <argparse>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using argument_parser::builder::new_argument;
|
||||
|
||||
int main() {
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit);
|
||||
|
||||
int threshold = 0;
|
||||
std::vector<int> ids;
|
||||
|
||||
new_argument()
|
||||
.long_argument("file")
|
||||
.store<std::string>()
|
||||
.required()
|
||||
.help_text("Input file.")
|
||||
.build(parser);
|
||||
|
||||
new_argument()
|
||||
.long_argument("threshold")
|
||||
.reference(threshold)
|
||||
.build(parser);
|
||||
|
||||
new_argument()
|
||||
.long_argument("id")
|
||||
.accumulate(ids)
|
||||
.help_text("Repeatable numeric id.")
|
||||
.build(parser);
|
||||
|
||||
auto verbose = new_argument()
|
||||
.short_argument("v")
|
||||
.count()
|
||||
.build_and_get(parser);
|
||||
|
||||
parser.handle_arguments({
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
&argument_parser::conventions::windows_argument_convention,
|
||||
});
|
||||
|
||||
if (auto file = parser.get_optional<std::string>("file")) {
|
||||
std::cout << "file: " << *file << '\n';
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "verbosity: " << *verbose << '\n';
|
||||
}
|
||||
|
||||
std::cout << "threshold: " << threshold << '\n';
|
||||
std::cout << "ids: " << ids.size() << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
## Caveats
|
||||
|
||||
- The v1 API is retained as public compatibility surface, but the newer v2 and
|
||||
builder APIs are generally more ergonomic.
|
||||
- Parser registration and parsing are single-threaded; `handle_arguments(...)`
|
||||
enforces the parser creation thread.
|
||||
- `handle_arguments(...)` resets the current convention list after it returns
|
||||
or throws.
|
||||
- Namespaces named `argument_parser::internal::*` are implementation details
|
||||
despite being present in public headers.
|
||||
157
README.md
157
README.md
@@ -1,6 +1,6 @@
|
||||
# argument-parser
|
||||
|
||||
A lightweight, modern, and highly customizable C++17 argument parser with native platform argument collection, trait-driven typed parsing, pluggable option conventions, and a fluent `v2` builder API.
|
||||
A lightweight, modern, and highly customizable C++17 argument parser with native platform argument collection, trait-driven typed parsing, repeatable argument accumulation, pluggable option conventions, and a fluent `v2` builder API.
|
||||
|
||||
> `v1` is deprecated and mainly kept as implementation history. For new projects, use `argument_parser::v2` together with `argument_parser::builder`.
|
||||
|
||||
@@ -8,11 +8,14 @@ A lightweight, modern, and highly customizable C++17 argument parser with native
|
||||
|
||||
- Native platform parser alias: `argument_parser::v2::parser` resolves to the current platform parser and reads arguments directly from OS APIs.
|
||||
- Fluent builder API with compile-time builder constraints that prevent invalid combinations after a terminal/mutually exclusive mode has been selected.
|
||||
- Type-safe parsing and extraction. Just extend `parser_trait<T>` for your types and if just want to store use `get_optional<T>()`!
|
||||
- Type-safe parsing and extraction. Extend `parser_trait<T>` for your own types and retrieve stored values with `get_optional<T>()`.
|
||||
- Repeatable value accumulation with `accumulate<T>()`, `accumulate(vector&)`, `count()`, and `count(int&)`.
|
||||
- `build_and_get(parser)` for storable builder modes, returning a small container that is populated after parsing completes.
|
||||
- Positional arguments with optional explicit ordering and support for `--` as a positional separator.
|
||||
- Trait-driven `format_hint` and `purpose_hint` metadata used in generated help text and parse errors.
|
||||
- Automatic help flag on `argument_parser::v2::parser` (`-h`, `--help`) with configurable exit behavior.
|
||||
- Auto-formatted help output..
|
||||
- Automatic help flag on `argument_parser::v2::parser` (`-h`, `--help`) with configurable exit behavior through `parser_settings`.
|
||||
- `parser_settings` for choosing whether help, unknown arguments, parse errors, and missing required arguments exit or throw.
|
||||
- Auto-formatted help output.
|
||||
- Completion hooks via `parser.on_complete(...)`.
|
||||
- Pluggable conventions for GNU next-token, GNU equal-style, Windows next-token, and Windows inline `=` / `:` parsing, or bring your own!
|
||||
- Testing helper + pseudo command handler `argument_parser::v2::fake_parser`.
|
||||
@@ -28,15 +31,17 @@ A lightweight, modern, and highly customizable C++17 argument parser with native
|
||||
#include <argparse>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using argument = argument_parser::builder::argument<>;
|
||||
using argument_parser::builder::new_argument;
|
||||
|
||||
int main() {
|
||||
argument_parser::v2::parser parser(false); // --help prints without exiting immediately
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit); // throw instead of exiting
|
||||
|
||||
int threshold = 0;
|
||||
std::vector<int> ids;
|
||||
|
||||
argument::start()
|
||||
new_argument()
|
||||
.short_argument("e")
|
||||
.long_argument("echo")
|
||||
.action<std::string>([](std::string const& text) {
|
||||
@@ -44,26 +49,32 @@ int main() {
|
||||
})
|
||||
.build(parser);
|
||||
|
||||
argument::start()
|
||||
new_argument()
|
||||
.long_argument("file")
|
||||
.store<std::string>()
|
||||
.required()
|
||||
.help_text("Input file to process.")
|
||||
.build(parser);
|
||||
|
||||
argument::start()
|
||||
new_argument()
|
||||
.long_argument("threshold")
|
||||
.reference(threshold)
|
||||
.help_text("Numeric threshold.")
|
||||
.build(parser);
|
||||
|
||||
argument::start()
|
||||
auto verbose = new_argument()
|
||||
.short_argument("v")
|
||||
.long_argument("verbose")
|
||||
.flag()
|
||||
.help_text("Enable verbose output.")
|
||||
.help_text("Increase verbosity. Repeat for a higher level.")
|
||||
.count()
|
||||
.build_and_get(parser);
|
||||
|
||||
new_argument()
|
||||
.long_argument("id")
|
||||
.help_text("Collect an id. May be repeated.")
|
||||
.accumulate(ids)
|
||||
.build(parser);
|
||||
|
||||
argument::start()
|
||||
new_argument()
|
||||
.positional("output")
|
||||
.position(0)
|
||||
.help_text("Output file.")
|
||||
@@ -89,6 +100,11 @@ int main() {
|
||||
}
|
||||
|
||||
std::cout << "threshold: " << threshold << '\n';
|
||||
std::cout << "ids: " << ids.size() << '\n';
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "verbosity: " << *verbose << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -129,7 +145,7 @@ struct argument_parser::parsing_traits::parser_trait<Point> {
|
||||
Then use the type directly from the builder:
|
||||
|
||||
```cpp
|
||||
argument::start()
|
||||
new_argument()
|
||||
.long_argument("point")
|
||||
.store<Point>()
|
||||
.build(parser);
|
||||
@@ -142,8 +158,8 @@ If you omit `help_text()`, `v2` uses the trait hints to generate help such as `A
|
||||
`argument_parser::v2::parser` automatically registers `-h` and `--help`.
|
||||
|
||||
```cpp
|
||||
argument_parser::v2::parser parser; // help prints and exits
|
||||
argument_parser::v2::parser parser(false); // help prints without immediate exit
|
||||
argument_parser::v2::parser parser; // help prints and exits
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit); // help prints without exiting
|
||||
```
|
||||
|
||||
You can also display help manually:
|
||||
@@ -152,6 +168,39 @@ You can also display help manually:
|
||||
parser.display_help(conventions);
|
||||
```
|
||||
|
||||
## Parser Settings
|
||||
|
||||
Use `argument_parser::parser_settings` when the parser is embedded in a larger
|
||||
application, test, or REPL-like tool where parse failures should be handled by
|
||||
the caller instead of ending the process.
|
||||
|
||||
```cpp
|
||||
argument_parser::parser_settings settings;
|
||||
settings.should_exit_on_help = false;
|
||||
settings.should_exit_on_error = false;
|
||||
settings.should_exit_on_unknown_argument = false;
|
||||
settings.should_exit_on_missing_required = false;
|
||||
settings.ignore_unknown_arguments = true;
|
||||
|
||||
argument_parser::v2::parser parser(settings);
|
||||
```
|
||||
|
||||
The convenience constant `argument_parser::no_exit` disables the four automatic
|
||||
exit paths while leaving unknown-argument handling enabled:
|
||||
|
||||
```cpp
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit);
|
||||
```
|
||||
|
||||
Settings fields:
|
||||
|
||||
- `should_exit_on_help`: exit with status `0` after automatic `-h` / `--help`.
|
||||
- `should_exit_on_error`: exit with status `1` for non-unknown parse errors; otherwise rethrow.
|
||||
- `should_exit_on_unknown_argument`: exit with status `1` for unknown arguments; otherwise rethrow.
|
||||
- `should_exit_on_missing_required`: exit with status `1` after reporting missing required arguments; otherwise throw.
|
||||
- `ignore_unknown_arguments`: skip unknown arguments that cannot be consumed as positionals.
|
||||
- `ignore_errors`: present in the public settings struct, but not currently read by the parser runtime.
|
||||
|
||||
## Supported Conventions
|
||||
|
||||
- GNU next-token: `-o value`, `--output value`
|
||||
@@ -161,9 +210,15 @@ parser.display_help(conventions);
|
||||
|
||||
Mix any of them in the same parser by passing the conventions you want to `handle_arguments()`.
|
||||
|
||||
## Builder Modes
|
||||
## Builder API
|
||||
|
||||
`argument_parser::builder::argument<>` is a staged builder. `build(parser)` is the terminal call.
|
||||
`argument_parser::builder::argument<>` is a staged builder. Prefer `argument_parser::builder::new_argument()` as the entry point:
|
||||
|
||||
```cpp
|
||||
using argument_parser::builder::new_argument;
|
||||
```
|
||||
|
||||
`build(parser)` registers the argument and returns `void`. `build_and_get(parser)` is available for storable modes and returns a lightweight `builder::container<T>`. The container is filled by an internal completion hook after `handle_arguments(...)` runs.
|
||||
|
||||
Before `build(...)`, you compose an argument from three kinds of steps:
|
||||
|
||||
@@ -173,13 +228,75 @@ Before `build(...)`, you compose an argument from three kinds of steps:
|
||||
- `store<T>()` to parse and retain a value for later `get_optional<T>()`
|
||||
- `flag()` to store a boolean presence flag
|
||||
- `reference(value)` to write the parsed result directly into an existing variable
|
||||
- `accumulate<T>()` to collect repeated values into a stored `std::vector<T>`
|
||||
- `accumulate(vector)` to collect repeated values into an existing `std::vector<T>`
|
||||
- `count()` to store how many times an option appears
|
||||
- `count(value)` to write the occurrence count into an existing `int`
|
||||
- `action([] { ... })` for no-value callbacks
|
||||
- `action<T>([](T const&) { ... })` for typed value callbacks
|
||||
|
||||
Once you select one value behavior, the other value behavior methods are disabled at compile time, so combinations like `store<T>().action(...)` or `flag().reference(value)` are rejected by the type system. Also you cannot use the same method repeatedly as it is also disabled at compile time by the type system.
|
||||
Once you select one value behavior, the other value behavior methods are disabled at compile time, so combinations like `store<T>().action(...)` or `flag().reference(value)` are rejected by the type system. The same staged typing also prevents repeating one-shot methods such as `help_text(...)`, `position(...)`, or `store<T>()` on the same builder chain.
|
||||
|
||||
If you do not select a value behavior explicitly, `build(parser)` uses the default for the argument kind: named arguments become boolean flags, while positional arguments store a `std::string`.
|
||||
|
||||
## Accumulators and Counts
|
||||
|
||||
Use `accumulate<T>()` when the parser should accept the same value-bearing argument multiple times and store all parsed values:
|
||||
|
||||
```cpp
|
||||
auto values = new_argument()
|
||||
.short_argument("n")
|
||||
.long_argument("number")
|
||||
.accumulate<int>()
|
||||
.build_and_get(parser);
|
||||
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
if (values) {
|
||||
for (int value : *values) {
|
||||
std::cout << value << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use `accumulate(target)` to append into a vector you own:
|
||||
|
||||
```cpp
|
||||
std::vector<int> ids;
|
||||
|
||||
new_argument()
|
||||
.long_argument("id")
|
||||
.accumulate(ids)
|
||||
.build(parser);
|
||||
```
|
||||
|
||||
Use `count()` for repeatable flags such as `-v -v -v`:
|
||||
|
||||
```cpp
|
||||
auto verbosity = new_argument()
|
||||
.short_argument("v")
|
||||
.count()
|
||||
.build_and_get(parser);
|
||||
```
|
||||
|
||||
The lower-level `v2::base_parser::add_argument` API exposes the same accumulator behavior through the `Accumulate` flag:
|
||||
|
||||
```cpp
|
||||
using namespace argument_parser::v2::flags;
|
||||
|
||||
parser.add_argument<std::vector<int>>({
|
||||
{LongArgument, "id"},
|
||||
{HelpText, "Collect an id. May be repeated."},
|
||||
{Accumulate, true},
|
||||
});
|
||||
|
||||
std::vector<int> captured_ids;
|
||||
parser.add_argument<std::vector<int>>({
|
||||
{LongArgument, "captured-id"},
|
||||
{Accumulate, &captured_ids},
|
||||
});
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
For unit tests or synthetic argument lists, use `argument_parser::v2::fake_parser` instead of the native platform parser:
|
||||
|
||||
7
TODO.md
7
TODO.md
@@ -19,8 +19,6 @@ After handle_parse(...) ends, we can call the on_parse_done callbacks. But this
|
||||
1. Storable arguments. Those would be not actions, but stored values. So you could get them later on in the callback or somewhere else.
|
||||
2. The on_parse_done callbacks should be called after all actions are invoked. But we should make this a toggle, so the callback only gets executed if the user explicitly wants it to be called. By default we would enable it.
|
||||
|
||||
## Self reminder, implement this feature. It'd be helpful.
|
||||
|
||||
### Update: 29 March. 2026
|
||||
Help text is clear, supports multi convention print, also provides hints for types that provides the hints in the traits.
|
||||
Positional argument support is here. Also we now have some tests to ensure the library works as intended.
|
||||
@@ -39,9 +37,8 @@ Configure CMAKE to ensure the library can be built as a library and can be insta
|
||||
# TODO 5: Display help | DONE
|
||||
Display help doesn't reflect the conventions right now. Also it should come automatically, and should be allowed to overriden by user.
|
||||
|
||||
# TODO 6: Accumulate repeated calls
|
||||
Add support to letting users accumulate repeated calls to a flag. If the flag is called x times, the result should be x items stored in a vector,
|
||||
instead of an action doing it.
|
||||
# TODO 6: Accumulate repeated calls | DONE
|
||||
Add support to let users accumulate repeated calls to a flag. If the flag is called x times, the result should be x items stored in a vector, instead of an action doing it.
|
||||
|
||||
# TODO 7: Defaults/Implicits
|
||||
If given, an arguments default store value could be changed. If nothing was given use that value instead.
|
||||
|
||||
@@ -1,110 +1,167 @@
|
||||
|
||||
#include <argparse>
|
||||
#include <argument_parser.hpp>
|
||||
#include <gnu_argument_convention.hpp>
|
||||
#include <macros.h>
|
||||
#include <iostream>
|
||||
#include <macros.h>
|
||||
#include <parser_v2.hpp>
|
||||
#include <string>
|
||||
#include <traits.hpp>
|
||||
#include <vector>
|
||||
#include <windows_argument_convention.hpp>
|
||||
|
||||
using argument = argument_parser::builder::argument<>;
|
||||
using argument_parser::builder::new_argument;
|
||||
|
||||
using argument_parser::parsing_traits::hint_type;
|
||||
|
||||
auto echo(std::string const& s) -> void {
|
||||
std::cout << s << '\n';
|
||||
auto echo(std::string const &s) -> void {
|
||||
std::cout << s << '\n';
|
||||
}
|
||||
|
||||
using namespace argument_parser::parsing_traits;
|
||||
|
||||
constexpr hint_type vector_purpose_hint = "vector of ";
|
||||
template <typename T> struct parser_trait<std::vector<T>> {
|
||||
static std::vector<T> parse(std::string const &s) {
|
||||
std::vector<T> result;
|
||||
std::stringstream ss(s);
|
||||
|
||||
template<typename T>
|
||||
class parser_trait<std::vector<T>> {
|
||||
public:
|
||||
static std::vector<T> parse(std::string const& s) {
|
||||
std::vector<T> result;
|
||||
std::stringstream ss(s);
|
||||
for (std::string line; std::getline(ss, line, ',');) {
|
||||
T item = parser_trait<T>::parse(line);
|
||||
result.push_back(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
for (std::string line; std::getline(ss, line, ',');) {
|
||||
T item = parser_trait<T>::parse(line);
|
||||
result.push_back(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
ARGPARSE_TRAIT_FORMAT_HINT = concat<hint_provider<&parser_trait<T>::format_hint>, hint_provider<&comma>,
|
||||
hint_provider<&parser_trait<T>::format_hint>>;
|
||||
|
||||
ARGPARSE_TRAIT_FORMAT_HINT = concat<
|
||||
hint_provider<&parser_trait<T>::format_hint>,
|
||||
hint_provider<&comma>,
|
||||
hint_provider<&parser_trait<T>::format_hint>
|
||||
>;
|
||||
|
||||
ARGPARSE_TRAIT_PURPOSE_HINT = concat<
|
||||
hint_provider<&vector_purpose_hint>,
|
||||
hint_provider<&parser_trait<T>::purpose_hint>
|
||||
>;
|
||||
ARGPARSE_TRAIT_PURPOSE_HINT =
|
||||
concat<hint_provider<&vector_purpose_hint>, hint_provider<&parser_trait<T>::purpose_hint>>;
|
||||
};
|
||||
|
||||
using namespace argument_parser::v2::flags;
|
||||
|
||||
auto main() -> int {
|
||||
argument_parser::v2::parser parser(false);
|
||||
argument_parser::v2::parser parser(argument_parser::no_exit);
|
||||
|
||||
argument::start()
|
||||
.positional("count")
|
||||
.position(0)
|
||||
.help_text("How many times to repeat the action.")
|
||||
.action<int>([](int const& count) {
|
||||
std::cout << "count action configured for " << count << '\n';
|
||||
})
|
||||
.build(parser);
|
||||
new_argument()
|
||||
.positional("count")
|
||||
.position(1)
|
||||
.help_text("How many times to repeat the action.")
|
||||
.action<int>([](int const &count) { std::cout << "count action configured for " << count << '\n'; })
|
||||
.build(parser);
|
||||
|
||||
int captured_value = 0;
|
||||
argument::start()
|
||||
.long_argument("threshold")
|
||||
.help_text("Store the parsed value through a reference.")
|
||||
.reference(captured_value)
|
||||
.build(parser);
|
||||
int captured_value = 0;
|
||||
new_argument()
|
||||
.long_argument("threshold")
|
||||
.help_text("Store the parsed value through a reference.")
|
||||
.reference(captured_value)
|
||||
.build(parser);
|
||||
|
||||
// parser.add_argument<int>({
|
||||
// {ShortArgument, "c"},
|
||||
// {HelpText, "capture count"},
|
||||
// {Reference, &captured_value},
|
||||
// });
|
||||
new_argument()
|
||||
.positional("captured")
|
||||
.position(0)
|
||||
.help_text("Store the parsed value through a reference.")
|
||||
.reference(captured_value)
|
||||
.build(parser);
|
||||
|
||||
argument::start()
|
||||
.short_argument("q")
|
||||
.help_text("Store a boolean flag.")
|
||||
.build(parser);
|
||||
// parser.add_argument<int>({
|
||||
// {ShortArgument, "c"},
|
||||
// {HelpText, "capture count"},
|
||||
// {Reference, &captured_value},
|
||||
// });
|
||||
|
||||
// argument::start()
|
||||
// .long_argument("regex")
|
||||
// .help_text("Store a regex value.")
|
||||
// .store<std::optional<std::regex>>()
|
||||
// .build(parser);
|
||||
new_argument().short_argument("q").help_text("Store a boolean flag.").build(parser);
|
||||
|
||||
argument::start()
|
||||
.short_argument("e")
|
||||
.long_argument("echo")
|
||||
.help_text("Echo the parsed value.")
|
||||
.action(echo)
|
||||
.build(parser);
|
||||
// argument::start()
|
||||
// .long_argument("regex")
|
||||
// .help_text("Store a regex value.")
|
||||
// .store<std::optional<std::regex>>()
|
||||
// .build(parser);
|
||||
|
||||
argument::start()
|
||||
.long_argument("vecstr")
|
||||
.short_argument("vs")
|
||||
.action<std::vector<int>>([](std::vector<int> const& vecstr) {
|
||||
for (auto const& str : vecstr) {
|
||||
std::cout << str << '\n';
|
||||
}
|
||||
})
|
||||
.build(parser);
|
||||
new_argument()
|
||||
.short_argument("e")
|
||||
.long_argument("echo")
|
||||
.help_text("Echo the parsed value.")
|
||||
.action(echo)
|
||||
.build(parser);
|
||||
|
||||
parser.handle_arguments({
|
||||
&argument_parser::conventions::gnu_argument_convention
|
||||
});
|
||||
new_argument()
|
||||
.long_argument("vecstr")
|
||||
.short_argument("vs")
|
||||
.action<std::vector<int>>([](std::vector<int> const &vecstr) {
|
||||
for (auto const &str : vecstr) {
|
||||
std::cout << str << '\n';
|
||||
}
|
||||
})
|
||||
.build(parser);
|
||||
|
||||
std::cout << "captured value: " << captured_value << '\n';
|
||||
auto accumulated_pos = new_argument()
|
||||
.short_argument("v")
|
||||
.help_text("turns on verbose execution. up to three levels of verbosity.")
|
||||
.count()
|
||||
.build_and_get(parser);
|
||||
|
||||
return 0;
|
||||
auto accumulate_vec =
|
||||
new_argument().long_argument("vecstr1").short_argument("vs1").accumulate<int>().build_and_get(parser);
|
||||
|
||||
parser.add_argument<std::vector<int>>({
|
||||
{LongArgument, "accumulate"},
|
||||
{HelpText, "accumulates given ints into the vector (flag ver)"},
|
||||
{Accumulate, true},
|
||||
});
|
||||
|
||||
std::vector<int> captured_vec;
|
||||
parser.add_argument<std::vector<int>>({
|
||||
{LongArgument, "accumulate2"},
|
||||
{HelpText, "accumulates given ints into the vector (ref ver)"},
|
||||
{Accumulate, &captured_vec},
|
||||
});
|
||||
|
||||
std::vector<int> captured_vec2;
|
||||
parser.add_argument<std::vector<int>>({
|
||||
{LongArgument, "accumulate3"},
|
||||
{HelpText, "accumulates given ints into the vector (ref ver)"},
|
||||
{Accumulate, true},
|
||||
{Reference, &captured_vec2},
|
||||
});
|
||||
|
||||
parser.on_complete([](argument_parser::base_parser const &p) {
|
||||
if (const auto value = p.get_optional<std::vector<int>>("accumulate"); value.has_value()) {
|
||||
std::cout << "accumulate: ";
|
||||
for (auto const &str : *value) {
|
||||
std::cout << str << '\n';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
parser.handle_arguments({&argument_parser::conventions::gnu_argument_convention,
|
||||
&argument_parser::conventions::windows_argument_convention});
|
||||
if (!captured_vec.empty()) {
|
||||
std::cout << "accumulate2: ";
|
||||
for (auto const &str : captured_vec) {
|
||||
std::cout << str << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (!captured_vec2.empty()) {
|
||||
std::cout << "accumulate3: ";
|
||||
for (auto const &str : captured_vec2) {
|
||||
std::cout << str << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulate_vec) {
|
||||
std::cout << "accumulate_vec: ";
|
||||
for (auto const &str : *accumulate_vec) {
|
||||
std::cout << str << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulated_pos) {
|
||||
std::cout << "accumulated_pos: " << *accumulated_pos << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#ifndef ARGPARSE_HPP
|
||||
#define ARGPARSE_HPP
|
||||
#include "macros.h"
|
||||
#include <argument_builder.hpp>
|
||||
#include <argument_parser.hpp>
|
||||
#include <parser_v2.hpp>
|
||||
#include <argument_builder.hpp>
|
||||
#include "macros.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux_parser.hpp>
|
||||
|
||||
@@ -14,15 +14,15 @@ namespace argument_parser::conventions {
|
||||
|
||||
class base_convention {
|
||||
public:
|
||||
virtual std::string extract_value(std::string const &) const = 0;
|
||||
virtual parsed_argument get_argument(std::string const &) const = 0;
|
||||
virtual bool requires_next_token() const = 0;
|
||||
virtual std::string name() const = 0;
|
||||
virtual std::string short_prec() const = 0;
|
||||
virtual std::string long_prec() const = 0;
|
||||
virtual std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const = 0;
|
||||
virtual std::vector<convention_features> get_features() const = 0;
|
||||
[[nodiscard]] virtual std::string extract_value(std::string const &) const = 0;
|
||||
[[nodiscard]] virtual parsed_argument get_argument(std::string const &) const = 0;
|
||||
[[nodiscard]] virtual bool requires_next_token() const = 0;
|
||||
[[nodiscard]] virtual std::string name() const = 0;
|
||||
[[nodiscard]] virtual std::string short_prec() const = 0;
|
||||
[[nodiscard]] virtual std::string long_prec() const = 0;
|
||||
[[nodiscard]] virtual std::pair<std::string, std::string>
|
||||
make_help_text(std::string const &short_arg, std::string const &long_arg, bool requires_value) const = 0;
|
||||
[[nodiscard]] virtual std::vector<convention_features> get_features() const = 0;
|
||||
|
||||
protected:
|
||||
base_convention() = default;
|
||||
|
||||
@@ -8,15 +8,16 @@ namespace argument_parser::conventions::implementations {
|
||||
|
||||
class gnu_argument_convention : public base_convention {
|
||||
public:
|
||||
parsed_argument get_argument(std::string const &raw) const override;
|
||||
std::string extract_value(std::string const & /*raw*/) const override;
|
||||
bool requires_next_token() const override;
|
||||
std::string name() const override;
|
||||
std::string short_prec() const override;
|
||||
std::string long_prec() const override;
|
||||
std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
std::vector<convention_features> get_features() const override;
|
||||
virtual ~gnu_argument_convention() = default;
|
||||
[[nodiscard]] parsed_argument get_argument(std::string const &raw) const override;
|
||||
[[nodiscard]] std::string extract_value(std::string const & /*raw*/) const override;
|
||||
[[nodiscard]] bool requires_next_token() const override;
|
||||
[[nodiscard]] std::string name() const override;
|
||||
[[nodiscard]] std::string short_prec() const override;
|
||||
[[nodiscard]] std::string long_prec() const override;
|
||||
[[nodiscard]] std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
[[nodiscard]] std::vector<convention_features> get_features() const override;
|
||||
|
||||
static gnu_argument_convention instance;
|
||||
|
||||
@@ -26,15 +27,16 @@ namespace argument_parser::conventions::implementations {
|
||||
|
||||
class gnu_equal_argument_convention : public base_convention {
|
||||
public:
|
||||
parsed_argument get_argument(std::string const &raw) const override;
|
||||
std::string extract_value(std::string const &raw) const override;
|
||||
bool requires_next_token() const override;
|
||||
std::string name() const override;
|
||||
std::string short_prec() const override;
|
||||
std::string long_prec() const override;
|
||||
std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
std::vector<convention_features> get_features() const override;
|
||||
virtual ~gnu_equal_argument_convention() = default;
|
||||
[[nodiscard]] parsed_argument get_argument(std::string const &raw) const override;
|
||||
[[nodiscard]] std::string extract_value(std::string const &raw) const override;
|
||||
[[nodiscard]] bool requires_next_token() const override;
|
||||
[[nodiscard]] std::string name() const override;
|
||||
[[nodiscard]] std::string short_prec() const override;
|
||||
[[nodiscard]] std::string long_prec() const override;
|
||||
[[nodiscard]] std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
[[nodiscard]] std::vector<convention_features> get_features() const override;
|
||||
|
||||
static gnu_equal_argument_convention instance;
|
||||
|
||||
|
||||
@@ -5,22 +5,23 @@
|
||||
#define WINDOWS_ARGUMENT_CONVENTION_HPP
|
||||
|
||||
#ifndef ALLOW_DASH_FOR_WINDOWS
|
||||
#define ALLOW_DASH_FOR_WINDOWS 1
|
||||
#define ALLOW_DASH_FOR_WINDOWS true
|
||||
#endif
|
||||
|
||||
namespace argument_parser::conventions::implementations {
|
||||
class windows_argument_convention : public base_convention {
|
||||
public:
|
||||
virtual ~windows_argument_convention() = default;
|
||||
explicit windows_argument_convention(bool accept_dash = true);
|
||||
parsed_argument get_argument(std::string const &raw) const override;
|
||||
std::string extract_value(std::string const & /*raw*/) const override;
|
||||
bool requires_next_token() const override;
|
||||
std::string name() const override;
|
||||
std::string short_prec() const override;
|
||||
std::string long_prec() const override;
|
||||
std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
std::vector<convention_features> get_features() const override;
|
||||
[[nodiscard]] parsed_argument get_argument(std::string const &raw) const override;
|
||||
[[nodiscard]] std::string extract_value(std::string const & /*raw*/) const override;
|
||||
[[nodiscard]] bool requires_next_token() const override;
|
||||
[[nodiscard]] std::string name() const override;
|
||||
[[nodiscard]] std::string short_prec() const override;
|
||||
[[nodiscard]] std::string long_prec() const override;
|
||||
[[nodiscard]] std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
[[nodiscard]] std::vector<convention_features> get_features() const override;
|
||||
|
||||
static windows_argument_convention instance;
|
||||
|
||||
@@ -30,16 +31,17 @@ namespace argument_parser::conventions::implementations {
|
||||
|
||||
class windows_kv_argument_convention : public base_convention {
|
||||
public:
|
||||
virtual ~windows_kv_argument_convention() = default;
|
||||
explicit windows_kv_argument_convention(bool accept_dash = true);
|
||||
parsed_argument get_argument(std::string const &raw) const override;
|
||||
std::string extract_value(std::string const &raw) const override;
|
||||
bool requires_next_token() const override;
|
||||
std::string name() const override;
|
||||
std::string short_prec() const override;
|
||||
std::string long_prec() const override;
|
||||
std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
std::vector<convention_features> get_features() const override;
|
||||
[[nodiscard]] parsed_argument get_argument(std::string const &raw) const override;
|
||||
[[nodiscard]] std::string extract_value(std::string const &raw) const override;
|
||||
[[nodiscard]] bool requires_next_token() const override;
|
||||
[[nodiscard]] std::string name() const override;
|
||||
[[nodiscard]] std::string short_prec() const override;
|
||||
[[nodiscard]] std::string long_prec() const override;
|
||||
[[nodiscard]] std::pair<std::string, std::string> make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const override;
|
||||
[[nodiscard]] std::vector<convention_features> get_features() const override;
|
||||
|
||||
static windows_kv_argument_convention instance;
|
||||
|
||||
@@ -48,9 +50,9 @@ namespace argument_parser::conventions::implementations {
|
||||
};
|
||||
|
||||
inline windows_argument_convention windows_argument_convention::instance =
|
||||
windows_argument_convention(bool(ALLOW_DASH_FOR_WINDOWS));
|
||||
windows_argument_convention(ALLOW_DASH_FOR_WINDOWS);
|
||||
inline windows_kv_argument_convention windows_kv_argument_convention::instance =
|
||||
windows_kv_argument_convention(bool(ALLOW_DASH_FOR_WINDOWS));
|
||||
windows_kv_argument_convention(ALLOW_DASH_FOR_WINDOWS);
|
||||
} // namespace argument_parser::conventions::implementations
|
||||
|
||||
namespace argument_parser::conventions {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
// ReSharper disable CppFunctionIsNotImplemented
|
||||
// ReSharper disable All
|
||||
#pragma once
|
||||
#ifndef ARGUMENT_PARSER_HPP
|
||||
#define ARGUMENT_PARSER_HPP
|
||||
@@ -64,9 +66,9 @@ namespace argument_parser {
|
||||
copyable_atomic &operator=(copyable_atomic &&other) noexcept = default;
|
||||
~copyable_atomic() = default;
|
||||
|
||||
T operator=(T desired) noexcept {
|
||||
copyable_atomic &operator=(T desired) noexcept {
|
||||
store(desired);
|
||||
return desired;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T() const noexcept {
|
||||
@@ -79,7 +81,7 @@ namespace argument_parser {
|
||||
}
|
||||
}
|
||||
|
||||
T load(std::memory_order order = std::memory_order_seq_cst) const noexcept {
|
||||
[[nodiscard]] T load(std::memory_order order = std::memory_order_seq_cst) const noexcept {
|
||||
return value ? value->load(order) : T{};
|
||||
}
|
||||
|
||||
@@ -102,9 +104,9 @@ namespace argument_parser {
|
||||
[[nodiscard]] virtual std::unique_ptr<action_base> clone() const = 0;
|
||||
};
|
||||
|
||||
template <typename T> class parametered_action : public action_base {
|
||||
template <typename T> class action_with_param : public action_base {
|
||||
public:
|
||||
explicit parametered_action(std::function<void(const T &)> const &handler) : handler(handler) {}
|
||||
explicit action_with_param(std::function<void(const T &)> const &handler) : handler(handler) {}
|
||||
using parameter_type = T;
|
||||
void invoke(const T &arg) const {
|
||||
handler(arg);
|
||||
@@ -124,7 +126,7 @@ namespace argument_parser {
|
||||
T parsed_value = parsing_traits::parser_trait<T>::parse(param);
|
||||
parse_success = true;
|
||||
invoke(parsed_value);
|
||||
} catch (const std::runtime_error &e) {
|
||||
} catch (const std::runtime_error &_) {
|
||||
if (!parse_success) {
|
||||
auto [format_hint, purpose_hint] = get_trait_hints();
|
||||
if (purpose_hint.empty())
|
||||
@@ -147,16 +149,16 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<action_base> clone() const override {
|
||||
return std::make_unique<parametered_action<T>>(handler);
|
||||
return std::make_unique<action_with_param<T>>(handler);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(const T &)> handler;
|
||||
};
|
||||
|
||||
class non_parametered_action : public action_base {
|
||||
class action_no_param : public action_base {
|
||||
public:
|
||||
explicit non_parametered_action(std::function<void()> const &handler) : handler(handler) {}
|
||||
explicit action_no_param(std::function<void()> const &handler) : handler(handler) {}
|
||||
|
||||
void invoke() const override {
|
||||
handler();
|
||||
@@ -175,7 +177,7 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<action_base> clone() const override {
|
||||
return std::make_unique<non_parametered_action>(handler);
|
||||
return std::make_unique<action_no_param>(handler);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -203,6 +205,7 @@ namespace argument_parser {
|
||||
[[nodiscard]] bool expects_parameter() const;
|
||||
[[nodiscard]] std::string get_help_text() const;
|
||||
[[nodiscard]] bool is_positional() const;
|
||||
[[nodiscard]] bool is_positional_accumulator() const;
|
||||
[[nodiscard]] std::optional<int> get_position_index() const;
|
||||
|
||||
private:
|
||||
@@ -210,6 +213,7 @@ namespace argument_parser {
|
||||
void set_invoked(bool val);
|
||||
void set_help_text(std::string const &text);
|
||||
void set_positional(bool val);
|
||||
void set_positional_accumulator(bool val);
|
||||
void set_position_index(std::optional<int> idx);
|
||||
|
||||
friend class base_parser;
|
||||
@@ -221,20 +225,40 @@ namespace argument_parser {
|
||||
bool invoked;
|
||||
std::string help_text;
|
||||
bool positional = false;
|
||||
bool positional_accumulator = false;
|
||||
std::optional<int> position_index = std::nullopt;
|
||||
};
|
||||
|
||||
namespace helpers {
|
||||
template <typename T>
|
||||
static parametered_action<T> make_parametered_action(std::function<void(const T &)> const &function) {
|
||||
return parametered_action<T>(function);
|
||||
template <typename T> static action_with_param<T> make_action(std::function<void(const T &)> const &function) {
|
||||
return action_with_param<T>(function);
|
||||
}
|
||||
|
||||
static non_parametered_action make_non_parametered_action(std::function<void()> const &function) {
|
||||
return non_parametered_action(function);
|
||||
static action_no_param make_action(std::function<void()> const &function) {
|
||||
return action_no_param(function);
|
||||
}
|
||||
} // namespace helpers
|
||||
|
||||
struct parser_settings {
|
||||
bool should_exit_on_error = true;
|
||||
bool should_exit_on_missing_required = true;
|
||||
bool should_exit_on_unknown_argument = true;
|
||||
bool should_exit_on_help = true;
|
||||
|
||||
bool ignore_unknown_arguments = false;
|
||||
bool ignore_errors = false;
|
||||
};
|
||||
|
||||
constexpr static inline parser_settings no_exit{
|
||||
.should_exit_on_error = false,
|
||||
.should_exit_on_missing_required = false,
|
||||
.should_exit_on_unknown_argument = false,
|
||||
.should_exit_on_help = false,
|
||||
|
||||
.ignore_unknown_arguments = false,
|
||||
.ignore_errors = false,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Base class for parsing arguments from the command line.
|
||||
*
|
||||
@@ -246,7 +270,7 @@ namespace argument_parser {
|
||||
public:
|
||||
template <typename T>
|
||||
void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text,
|
||||
parametered_action<T> const &action, bool required) {
|
||||
action_with_param<T> const &action, bool required) {
|
||||
base_add_argument(short_arg, long_arg, help_text, action, required);
|
||||
}
|
||||
|
||||
@@ -257,7 +281,7 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text,
|
||||
non_parametered_action const &action, bool required) {
|
||||
action_no_param const &action, bool required) {
|
||||
base_add_argument(short_arg, long_arg, help_text, action, required);
|
||||
}
|
||||
|
||||
@@ -268,7 +292,7 @@ namespace argument_parser {
|
||||
|
||||
template <typename T>
|
||||
void add_positional_argument(std::string const &name, std::string const &help_text,
|
||||
parametered_action<T> const &action, bool required,
|
||||
action_with_param<T> const &action, bool required,
|
||||
std::optional<int> position = std::nullopt) {
|
||||
base_add_positional_argument(name, help_text, action, required, position);
|
||||
}
|
||||
@@ -279,6 +303,13 @@ namespace argument_parser {
|
||||
base_add_positional_argument<T>(name, help_text, required, position);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void add_positional_accumulator(std::string const &name, std::string const &help_text,
|
||||
action_with_param<T> const &action, bool required,
|
||||
std::optional<int> position = std::nullopt) {
|
||||
base_add_positional_argument(name, help_text, action, required, position, true);
|
||||
}
|
||||
|
||||
void on_complete(std::function<void(base_parser const &)> const &action);
|
||||
|
||||
template <typename T> std::optional<T> get_optional(std::string const &arg) const {
|
||||
@@ -317,28 +348,41 @@ namespace argument_parser {
|
||||
return _current_conventions;
|
||||
}
|
||||
|
||||
private:
|
||||
bool test_conventions(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::unordered_map<std::string, std::string> &values_for_arguments,
|
||||
std::vector<std::pair<std::string, argument>> &found_arguments,
|
||||
std::optional<argument> &found_help, std::vector<std::string>::iterator &it,
|
||||
std::stringstream &error_stream);
|
||||
void extract_arguments(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::unordered_map<std::string, std::string> &values_for_arguments,
|
||||
std::vector<std::pair<std::string, argument>> &found_arguments,
|
||||
std::optional<argument> &found_help);
|
||||
std::unordered_map<int, std::any> &ref_stored_arguments() {
|
||||
return stored_arguments;
|
||||
}
|
||||
|
||||
void invoke_arguments(std::unordered_map<std::string, std::string> const &values_for_arguments,
|
||||
std::vector<std::pair<std::string, argument>> &found_arguments,
|
||||
std::optional<argument> const &found_help);
|
||||
void enforce_creation_thread();
|
||||
void on_complete(std::function<void(base_parser const &)> const &handler, bool to_start);
|
||||
|
||||
void set_settings(parser_settings const &settings) {
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
private:
|
||||
parser_settings m_settings;
|
||||
struct found_argument {
|
||||
std::string key;
|
||||
argument arg;
|
||||
std::optional<std::string> value = std::nullopt;
|
||||
};
|
||||
|
||||
bool test_conventions(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::vector<found_argument> &found_arguments, std::optional<argument> &found_help,
|
||||
std::vector<std::string>::iterator &it, std::stringstream &error_stream);
|
||||
void extract_arguments(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::vector<found_argument> &found_arguments, std::optional<argument> &found_help);
|
||||
|
||||
void invoke_arguments(std::vector<found_argument> &found_arguments, std::optional<argument> const &found_help);
|
||||
void enforce_creation_thread() const;
|
||||
|
||||
void assert_argument_not_exist(std::string const &short_arg, std::string const &long_arg) const;
|
||||
void assert_positional_not_exist(std::string const &name) const;
|
||||
void assert_can_place_positional(int id, std::optional<int> position, bool accumulator) const;
|
||||
static void set_argument_status(bool is_required, std::string const &help_text, argument &arg);
|
||||
void place_argument(int id, argument const &arg, std::string const &short_arg, std::string const &long_arg);
|
||||
void place_positional_argument(int id, argument const &arg, std::string const &name,
|
||||
std::optional<int> position);
|
||||
std::optional<int> position, bool accumulator = false);
|
||||
[[nodiscard]] std::optional<size_t> next_positional_slot(size_t start) const;
|
||||
|
||||
template <typename ActionType>
|
||||
void base_add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text,
|
||||
@@ -356,13 +400,12 @@ namespace argument_parser {
|
||||
assert_argument_not_exist(short_arg, long_arg);
|
||||
int id = id_counter.fetch_add(1);
|
||||
if constexpr (std::is_same_v<StoreType, void>) {
|
||||
auto action =
|
||||
helpers::make_non_parametered_action([id, this] { stored_arguments[id] = std::any{true}; });
|
||||
auto action = helpers::make_action([id, this] { stored_arguments[id] = std::any{true}; });
|
||||
argument arg(id, short_arg + "|" + long_arg, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
place_argument(id, arg, short_arg, long_arg);
|
||||
} else {
|
||||
auto action = helpers::make_parametered_action<StoreType>(
|
||||
auto action = helpers::make_action<StoreType>(
|
||||
[id, this](StoreType const &value) { stored_arguments[id] = std::any{value}; });
|
||||
argument arg(id, short_arg + "|" + long_arg, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
@@ -373,14 +416,15 @@ namespace argument_parser {
|
||||
template <typename ActionType>
|
||||
void base_add_positional_argument(std::string const &name, std::string const &help_text,
|
||||
ActionType const &action, bool required,
|
||||
std::optional<int> position = std::nullopt) {
|
||||
std::optional<int> position = std::nullopt, bool accumulator = false) {
|
||||
assert_positional_not_exist(name);
|
||||
int id = id_counter.fetch_add(1);
|
||||
argument arg(id, name, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
arg.set_positional(true);
|
||||
arg.set_positional_accumulator(accumulator);
|
||||
arg.set_position_index(position);
|
||||
place_positional_argument(id, arg, name, position);
|
||||
place_positional_argument(id, arg, name, position, accumulator);
|
||||
}
|
||||
|
||||
template <typename StoreType>
|
||||
@@ -388,7 +432,7 @@ namespace argument_parser {
|
||||
std::optional<int> position = std::nullopt) {
|
||||
assert_positional_not_exist(name);
|
||||
int id = id_counter.fetch_add(1);
|
||||
auto action = helpers::make_parametered_action<StoreType>(
|
||||
auto action = helpers::make_action<StoreType>(
|
||||
[id, this](StoreType const &value) { stored_arguments[id] = std::any{value}; });
|
||||
argument arg(id, name, action);
|
||||
set_argument_status(required, help_text, arg);
|
||||
|
||||
18
src/headers/parser/exceptions.hpp
Normal file
18
src/headers/parser/exceptions.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef ARGUMENT_PARSER_EXCEPTIONS_HPP
|
||||
#define ARGUMENT_PARSER_EXCEPTIONS_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace argument_parser {
|
||||
namespace parser {
|
||||
class unknown_argument_exception : public std::runtime_error {
|
||||
public:
|
||||
unknown_argument_exception(const std::string &message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
} // namespace parser
|
||||
} // namespace argument_parser
|
||||
|
||||
#endif // ARGUMENT_PARSER_EXCEPTIONS_HPP
|
||||
@@ -25,13 +25,13 @@ namespace argument_parser {
|
||||
public:
|
||||
fake_parser() = default;
|
||||
fake_parser(std::string program_name, std::vector<std::string> const &arguments);
|
||||
fake_parser(std::string const &program_name, std::vector<std::string> &&arguments);
|
||||
fake_parser(std::string const &program_name, std::initializer_list<std::string> const &arguments);
|
||||
fake_parser(std::string program_name, std::vector<std::string> &&arguments);
|
||||
fake_parser(std::string program_name, std::initializer_list<std::string> const &arguments);
|
||||
|
||||
void set_program_name(std::string const &program_name);
|
||||
void set_parsed_arguments(std::vector<std::string> const &parsed_arguments);
|
||||
};
|
||||
}
|
||||
} // namespace v2
|
||||
} // namespace argument_parser
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "traits.hpp"
|
||||
#include <argument_parser.hpp>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -15,7 +14,17 @@
|
||||
#include <vector>
|
||||
|
||||
namespace argument_parser::v2 {
|
||||
enum class add_argument_flags { ShortArgument, LongArgument, Positional, Position, HelpText, Action, Required, Reference };
|
||||
enum class add_argument_flags {
|
||||
ShortArgument,
|
||||
LongArgument,
|
||||
Positional,
|
||||
Position,
|
||||
HelpText,
|
||||
Action,
|
||||
Required,
|
||||
Reference,
|
||||
Accumulate
|
||||
};
|
||||
|
||||
namespace flags {
|
||||
constexpr static inline add_argument_flags ShortArgument = add_argument_flags::ShortArgument;
|
||||
@@ -26,19 +35,37 @@ namespace argument_parser::v2 {
|
||||
constexpr static inline add_argument_flags Positional = add_argument_flags::Positional;
|
||||
constexpr static inline add_argument_flags Position = add_argument_flags::Position;
|
||||
constexpr static inline add_argument_flags Reference = add_argument_flags::Reference;
|
||||
constexpr static inline add_argument_flags Accumulate = add_argument_flags::Accumulate;
|
||||
} // namespace flags
|
||||
|
||||
class base_parser : private argument_parser::base_parser {
|
||||
namespace deducers {
|
||||
template <typename, typename = void> struct has_value_type : std::false_type {};
|
||||
template <typename T> struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};
|
||||
|
||||
template <typename T> struct is_vector {
|
||||
static constexpr bool test() {
|
||||
if constexpr (has_value_type<T>::value) {
|
||||
return std::is_same_v<T, std::vector<typename T::value_type, typename T::allocator_type>>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> constexpr bool is_vector_v = is_vector<T>::test();
|
||||
} // namespace deducers
|
||||
|
||||
class base_parser : argument_parser::base_parser {
|
||||
public:
|
||||
template <typename T> using typed_flag_value = std::variant<std::string, parametered_action<T>, bool, int, T*>;
|
||||
using non_typed_flag_value = std::variant<std::string, non_parametered_action, bool, int>;
|
||||
template <typename T> using typed_flag_value = std::variant<std::string, action_with_param<T>, bool, int, T *>;
|
||||
using non_typed_flag_value = std::variant<std::string, action_no_param, bool, int>;
|
||||
|
||||
template <typename T> using typed_argument_pair = std::pair<add_argument_flags, typed_flag_value<T>>;
|
||||
using non_typed_argument_pair = std::pair<add_argument_flags, non_typed_flag_value>;
|
||||
|
||||
template <typename T>
|
||||
void add_argument(std::unordered_map<add_argument_flags, typed_flag_value<T>> const &argument_pairs) {
|
||||
add_argument_impl<true, parametered_action<T>, T>(argument_pairs);
|
||||
add_argument_impl<true, action_with_param<T>, T>(argument_pairs);
|
||||
}
|
||||
|
||||
template <typename T> void add_argument(std::initializer_list<typed_argument_pair<T>> const &pairs) {
|
||||
@@ -62,7 +89,7 @@ namespace argument_parser::v2 {
|
||||
}
|
||||
|
||||
void add_argument(std::unordered_map<add_argument_flags, non_typed_flag_value> const &argument_pairs) {
|
||||
add_argument_impl<false, non_parametered_action, void>(argument_pairs);
|
||||
add_argument_impl<false, action_no_param, void>(argument_pairs);
|
||||
}
|
||||
|
||||
argument_parser::base_parser &to_v1() {
|
||||
@@ -95,7 +122,7 @@ namespace argument_parser::v2 {
|
||||
void prepare_help_flag(bool should_exit = true) {
|
||||
add_argument({{flags::ShortArgument, "h"},
|
||||
{flags::LongArgument, "help"},
|
||||
{flags::Action, helpers::make_non_parametered_action([this, should_exit]() {
|
||||
{flags::Action, helpers::make_action([this, should_exit] {
|
||||
this->display_help(this->current_conventions());
|
||||
if (should_exit) {
|
||||
std::exit(0);
|
||||
@@ -104,6 +131,10 @@ namespace argument_parser::v2 {
|
||||
{flags::HelpText, "Prints this help text."}});
|
||||
}
|
||||
|
||||
void set_settings(parser_settings const &settings) {
|
||||
base::set_settings(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
template <bool IsTyped, typename ActionType, typename T, typename ArgsMap>
|
||||
void add_argument_impl(ArgsMap const &argument_pairs) {
|
||||
@@ -118,12 +149,13 @@ namespace argument_parser::v2 {
|
||||
std::string short_arg, long_arg, help_text;
|
||||
std::unique_ptr<action_base> action;
|
||||
bool required = false;
|
||||
bool accumulates = false;
|
||||
|
||||
if (argument_pairs.find(add_argument_flags::ShortArgument) != argument_pairs.end()) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::ShortArgument)) {
|
||||
found_params[extended_add_argument_flags::ShortArgument] = true;
|
||||
short_arg = get_or_throw<std::string>(argument_pairs.at(add_argument_flags::ShortArgument), "short");
|
||||
}
|
||||
if (argument_pairs.find(add_argument_flags::LongArgument) != argument_pairs.end()) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::LongArgument)) {
|
||||
found_params[extended_add_argument_flags::LongArgument] = true;
|
||||
long_arg = get_or_throw<std::string>(argument_pairs.at(add_argument_flags::LongArgument), "long");
|
||||
if (short_arg.empty())
|
||||
@@ -133,32 +165,71 @@ namespace argument_parser::v2 {
|
||||
long_arg = "-";
|
||||
}
|
||||
|
||||
if (argument_pairs.find(add_argument_flags::Action) != argument_pairs.end()) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::Action)) {
|
||||
found_params[extended_add_argument_flags::Action] = true;
|
||||
action = get_or_throw<ActionType>(argument_pairs.at(add_argument_flags::Action), "action").clone();
|
||||
}
|
||||
if (argument_pairs.find(add_argument_flags::HelpText) != argument_pairs.end()) {
|
||||
help_text = get_or_throw<std::string>(argument_pairs.at(add_argument_flags::HelpText), "help");
|
||||
}
|
||||
help_text = read_help_text(argument_pairs);
|
||||
required = read_required(argument_pairs);
|
||||
|
||||
if (argument_pairs.find(add_argument_flags::Required) != argument_pairs.end() &&
|
||||
get_or_throw<bool>(argument_pairs.at(add_argument_flags::Required), "required")) {
|
||||
required = true;
|
||||
}
|
||||
bool ref_mode = false;
|
||||
|
||||
if (argument_pairs.find(add_argument_flags::Reference) != argument_pairs.end()) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::Reference)) {
|
||||
ref_mode = true;
|
||||
if (!IsTyped) {
|
||||
throw std::logic_error("Reference argument must be typed");
|
||||
throw std::logic_error("Reference argument must be typed");
|
||||
}
|
||||
|
||||
found_params[extended_add_argument_flags::Action] = true;
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
auto ref = get_or_throw<T*>(argument_pairs.at(add_argument_flags::Reference), "reference");
|
||||
action = helpers::make_parametered_action<T>([ref](T const& t) {
|
||||
*ref = t;
|
||||
}).clone();
|
||||
auto ref = get_or_throw<T *>(argument_pairs.at(add_argument_flags::Reference), "reference");
|
||||
if (action) {
|
||||
throw std::logic_error("Cannot use both action and reference for the same argument");
|
||||
}
|
||||
action = make_reference_action(ref);
|
||||
} else {
|
||||
throw std::logic_error("Reference argument must not be void");
|
||||
throw std::logic_error("Reference argument must not be void");
|
||||
}
|
||||
}
|
||||
|
||||
if (has_flag(argument_pairs, add_argument_flags::Accumulate)) {
|
||||
if (!IsTyped)
|
||||
throw std::logic_error("Accumulate argument must be typed");
|
||||
|
||||
found_params[extended_add_argument_flags::Action] = true;
|
||||
accumulates = true;
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
if constexpr (std::is_same_v<T, int>) {
|
||||
action = make_accumulate_action<T>(argument_pairs, ref_mode, short_arg, long_arg);
|
||||
} else if constexpr (!deducers::is_vector_v<T>) {
|
||||
throw std::logic_error("Expected vector or integer type");
|
||||
} else {
|
||||
if (action && !ref_mode) {
|
||||
throw std::logic_error("Cannot use both action and accumulate for the same argument");
|
||||
}
|
||||
|
||||
action = make_accumulate_action<T>(argument_pairs, ref_mode, short_arg, long_arg);
|
||||
}
|
||||
} else {
|
||||
throw std::logic_error("Accumulate argument must not be void");
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulates) {
|
||||
if constexpr (!std::is_same_v<T, void> && deducers::is_vector_v<T>) {
|
||||
if (suggest_candidate(found_params) == candidate_type::unknown) {
|
||||
throw std::runtime_error(
|
||||
"Could not match any add argument overload to given parameters. Are you "
|
||||
"missing some required parameter?");
|
||||
}
|
||||
if (help_text.empty()) {
|
||||
help_text = "Accepts repeated values.";
|
||||
}
|
||||
|
||||
base::add_argument<typename T::value_type>(
|
||||
short_arg, long_arg, help_text,
|
||||
*static_cast<action_with_param<typename T::value_type> *>(&(*action)), required);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +254,8 @@ namespace argument_parser::v2 {
|
||||
}
|
||||
}
|
||||
|
||||
base::add_argument(short_arg, long_arg, help_text, *static_cast<ActionType *>(&(*action)), required);
|
||||
base::add_argument(short_arg, long_arg, help_text, *static_cast<ActionType *>(&(*action)),
|
||||
required);
|
||||
break;
|
||||
case candidate_type::store_other:
|
||||
if (help_text.empty()) {
|
||||
@@ -226,33 +298,65 @@ namespace argument_parser::v2 {
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"Could not match the arguments against any overload. The suggested candidate was: " +
|
||||
std::to_string((int(suggested_add))));
|
||||
std::to_string(static_cast<int>(suggested_add)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <bool IsTyped, typename ActionType, typename T, typename ArgsMap>
|
||||
void add_positional_argument_impl(ArgsMap const &argument_pairs) {
|
||||
std::string positional_name =
|
||||
auto positional_name =
|
||||
get_or_throw<std::string>(argument_pairs.at(add_argument_flags::Positional), "positional");
|
||||
|
||||
std::string help_text;
|
||||
std::unique_ptr<action_base> action;
|
||||
bool required = false;
|
||||
std::optional<int> position = std::nullopt;
|
||||
bool ref_mode = false;
|
||||
bool accumulates = false;
|
||||
|
||||
if (argument_pairs.find(add_argument_flags::Action) != argument_pairs.end()) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::Action)) {
|
||||
action = get_or_throw<ActionType>(argument_pairs.at(add_argument_flags::Action), "action").clone();
|
||||
}
|
||||
if (argument_pairs.find(add_argument_flags::HelpText) != argument_pairs.end()) {
|
||||
help_text = get_or_throw<std::string>(argument_pairs.at(add_argument_flags::HelpText), "help");
|
||||
std::string help_text = read_help_text(argument_pairs);
|
||||
required = read_required(argument_pairs);
|
||||
std::optional<int> position = read_position(argument_pairs);
|
||||
|
||||
if (has_flag(argument_pairs, add_argument_flags::Reference)) {
|
||||
ref_mode = true;
|
||||
if (!IsTyped) {
|
||||
throw std::logic_error("Reference argument must be typed");
|
||||
}
|
||||
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
if (!has_flag(argument_pairs, add_argument_flags::Accumulate)) {
|
||||
auto ref = get_or_throw<T *>(argument_pairs.at(add_argument_flags::Reference), "reference");
|
||||
if (action) {
|
||||
throw std::logic_error("Cannot use both action and reference for the same argument");
|
||||
}
|
||||
|
||||
action = make_reference_action(ref);
|
||||
}
|
||||
} else {
|
||||
throw std::logic_error("Reference argument must not be void");
|
||||
}
|
||||
}
|
||||
if (argument_pairs.find(add_argument_flags::Required) != argument_pairs.end() &&
|
||||
get_or_throw<bool>(argument_pairs.at(add_argument_flags::Required), "required")) {
|
||||
required = true;
|
||||
}
|
||||
if (argument_pairs.find(add_argument_flags::Position) != argument_pairs.end()) {
|
||||
position = get_or_throw<int>(argument_pairs.at(add_argument_flags::Position), "position");
|
||||
|
||||
if (has_flag(argument_pairs, add_argument_flags::Accumulate)) {
|
||||
if (!IsTyped)
|
||||
throw std::logic_error("Accumulate positional argument must be typed");
|
||||
|
||||
accumulates = true;
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
if constexpr (!deducers::is_vector_v<T>) {
|
||||
throw std::logic_error("Expected vector (type does not have value_type member)");
|
||||
} else {
|
||||
if (action && !ref_mode) {
|
||||
throw std::logic_error("Cannot use both action and accumulate for the same argument");
|
||||
}
|
||||
action = make_accumulate_action<T>(argument_pairs, ref_mode, positional_name);
|
||||
}
|
||||
} else {
|
||||
throw std::logic_error("Accumulate argument must not be void");
|
||||
}
|
||||
}
|
||||
|
||||
if (help_text.empty()) {
|
||||
@@ -271,15 +375,24 @@ namespace argument_parser::v2 {
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulates) {
|
||||
if constexpr (!std::is_same_v<T, void> && deducers::is_vector_v<T>) {
|
||||
base::add_positional_accumulator<typename T::value_type>(
|
||||
positional_name, help_text,
|
||||
*static_cast<action_with_param<typename T::value_type> *>(&(*action)), required, position);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (IsTyped) {
|
||||
if (action) {
|
||||
base::add_positional_argument<T>(positional_name, help_text,
|
||||
*static_cast<ActionType *>(&(*action)), required, position);
|
||||
base::add_positional_argument<T>(positional_name, help_text, *static_cast<ActionType *>(&(*action)),
|
||||
required, position);
|
||||
} else {
|
||||
base::template add_positional_argument<T>(positional_name, help_text, required, position);
|
||||
base::add_positional_argument<T>(positional_name, help_text, required, position);
|
||||
}
|
||||
} else {
|
||||
base::template add_positional_argument<std::string>(positional_name, help_text, required, position);
|
||||
base::add_positional_argument<std::string>(positional_name, help_text, required, position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,11 +403,7 @@ namespace argument_parser::v2 {
|
||||
|
||||
template <typename T, size_t S>
|
||||
bool satisfies_at_least_one(std::array<T, S> const &arr, std::unordered_map<T, bool> const &map) {
|
||||
for (const auto &req : arr) {
|
||||
if (map.find(req) != map.end())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return std::any_of(arr.begin(), arr.end(), [&map](T const &entry) { return map.find(entry) != map.end(); });
|
||||
}
|
||||
|
||||
candidate_type suggest_candidate(std::unordered_map<extended_add_argument_flags, bool> const &available_vars) {
|
||||
@@ -306,8 +415,7 @@ namespace argument_parser::v2 {
|
||||
if (available_vars.find(extended_add_argument_flags::Action) != available_vars.end()) {
|
||||
if (available_vars.at(extended_add_argument_flags::IsTyped))
|
||||
return candidate_type::typed_action;
|
||||
else
|
||||
return candidate_type::non_typed_action;
|
||||
return candidate_type::non_typed_action;
|
||||
}
|
||||
|
||||
if (available_vars.at(extended_add_argument_flags::IsTyped))
|
||||
@@ -315,6 +423,158 @@ namespace argument_parser::v2 {
|
||||
return candidate_type::store_boolean;
|
||||
}
|
||||
|
||||
template <typename ArgsMap> static bool has_flag(ArgsMap const &argument_pairs, add_argument_flags flag) {
|
||||
return argument_pairs.find(flag) != argument_pairs.end();
|
||||
}
|
||||
|
||||
template <typename ArgsMap> std::string read_help_text(ArgsMap const &argument_pairs) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::HelpText)) {
|
||||
return get_or_throw<std::string>(argument_pairs.at(add_argument_flags::HelpText), "help");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
template <typename ArgsMap> bool read_required(ArgsMap const &argument_pairs) {
|
||||
return has_flag(argument_pairs, add_argument_flags::Required) &&
|
||||
get_or_throw<bool>(argument_pairs.at(add_argument_flags::Required), "required");
|
||||
}
|
||||
|
||||
template <typename ArgsMap> std::optional<int> read_position(ArgsMap const &argument_pairs) {
|
||||
if (has_flag(argument_pairs, add_argument_flags::Position)) {
|
||||
return get_or_throw<int>(argument_pairs.at(add_argument_flags::Position), "position");
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T, typename T2, typename I>
|
||||
std::variant<T, T2> get_either_or_throw(typed_flag_value<I> const &v, std::string_view key) {
|
||||
if (auto p = std::get_if<T>(&v))
|
||||
return *p;
|
||||
if (auto p = std::get_if<T2>(&v))
|
||||
return *p;
|
||||
throw std::invalid_argument(std::string("variant type mismatch for key: ") + std::string(key));
|
||||
}
|
||||
|
||||
template <typename T> std::unique_ptr<action_base> make_reference_action(T *target) {
|
||||
return helpers::make_action<T>([target](T const &value) { *target = value; }).clone();
|
||||
}
|
||||
|
||||
template <typename Vector> std::unique_ptr<action_base> make_accumulate_ref_action(Vector *target) {
|
||||
if constexpr (std::is_same_v<Vector, int>) {
|
||||
return helpers::make_action([target]() { *target += 1; }).clone();
|
||||
} else {
|
||||
using Value = typename Vector::value_type;
|
||||
return helpers::make_action<Value>([target](Value const &value) { target->emplace_back(value); })
|
||||
.clone();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Vector>
|
||||
void store_accumulated_on_complete(std::string short_arg, std::string long_arg,
|
||||
std::shared_ptr<Vector> accumulation_target) {
|
||||
on_complete(
|
||||
[this, short_arg = std::move(short_arg), long_arg = std::move(long_arg),
|
||||
accumulation_target](auto const &) {
|
||||
if constexpr (std::is_same_v<int, Vector>) {
|
||||
if (*accumulation_target == 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (accumulation_target->empty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const auto sid = this->find_argument_id(short_arg);
|
||||
const auto lid = this->find_argument_id(long_arg);
|
||||
|
||||
if (const auto id = sid ? *sid : (lid ? *lid : -1); id != -1) {
|
||||
this->ref_stored_arguments()[id] = *accumulation_target;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
template <typename Vector>
|
||||
void store_accumulated_on_complete(std::string positional_name, std::shared_ptr<Vector> accumulation_target) {
|
||||
on_complete(
|
||||
[this, positional_name = std::move(positional_name), accumulation_target](auto const &) {
|
||||
if constexpr (std::is_same_v<int, Vector>) {
|
||||
if (*accumulation_target == 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (accumulation_target->empty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto id = this->find_argument_id(positional_name);
|
||||
if (id.has_value()) {
|
||||
this->ref_stored_arguments()[*id] = *accumulation_target;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
template <typename Vector, typename ArgsMap>
|
||||
std::unique_ptr<action_base> make_accumulate_action(ArgsMap const &argument_pairs, bool ref_mode,
|
||||
std::string const &short_arg, std::string const &long_arg) {
|
||||
if (ref_mode) {
|
||||
auto ref = get_or_throw<Vector *>(argument_pairs.at(add_argument_flags::Reference), "reference");
|
||||
return make_accumulate_ref_action(ref);
|
||||
}
|
||||
|
||||
auto accumulate =
|
||||
get_either_or_throw<Vector *, bool>(argument_pairs.at(add_argument_flags::Accumulate), "accumulate");
|
||||
|
||||
return std::visit(
|
||||
[this, short_arg, long_arg](auto &&acc) -> std::unique_ptr<action_base> {
|
||||
using V = std::decay_t<decltype(acc)>;
|
||||
if constexpr (std::is_same_v<V, bool>) {
|
||||
if (!acc) {
|
||||
throw std::logic_error("Accumulate flag must be true when used as a bool");
|
||||
}
|
||||
|
||||
auto accumulation_target = std::make_shared<Vector>();
|
||||
store_accumulated_on_complete(short_arg, long_arg, accumulation_target);
|
||||
return make_accumulate_ref_action(accumulation_target.get());
|
||||
} else {
|
||||
return make_accumulate_ref_action(acc);
|
||||
}
|
||||
},
|
||||
accumulate);
|
||||
}
|
||||
|
||||
template <typename Vector, typename ArgsMap>
|
||||
std::unique_ptr<action_base> make_accumulate_action(ArgsMap const &argument_pairs, bool ref_mode,
|
||||
std::string const &positional_name) {
|
||||
if (ref_mode) {
|
||||
auto ref = get_or_throw<Vector *>(argument_pairs.at(add_argument_flags::Reference), "reference");
|
||||
return make_accumulate_ref_action(ref);
|
||||
}
|
||||
|
||||
auto accumulate =
|
||||
get_either_or_throw<Vector *, bool>(argument_pairs.at(add_argument_flags::Accumulate), "accumulate");
|
||||
|
||||
return std::visit(
|
||||
[this, positional_name](auto &&acc) -> std::unique_ptr<action_base> {
|
||||
using V = std::decay_t<decltype(acc)>;
|
||||
if constexpr (std::is_same_v<V, bool>) {
|
||||
if (!acc) {
|
||||
throw std::logic_error("Accumulate flag must be true when used as a bool");
|
||||
}
|
||||
|
||||
auto accumulation_target = std::make_shared<Vector>();
|
||||
store_accumulated_on_complete(positional_name, accumulation_target);
|
||||
return make_accumulate_ref_action(accumulation_target.get());
|
||||
} else {
|
||||
return make_accumulate_ref_action(acc);
|
||||
}
|
||||
},
|
||||
accumulate);
|
||||
}
|
||||
|
||||
template <typename T, typename I> T get_or_throw(typed_flag_value<I> const &v, std::string_view key) {
|
||||
if (auto p = std::get_if<T>(&v))
|
||||
return *p;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// ReSharper disable CppFunctionIsNotImplemented
|
||||
#pragma once
|
||||
#ifndef PARSING_TRAITS_HPP
|
||||
#define PARSING_TRAITS_HPP
|
||||
@@ -5,12 +6,12 @@
|
||||
#include <string>
|
||||
|
||||
namespace argument_parser::parsing_traits {
|
||||
using hint_type = const char*;
|
||||
using hint_type = const char *;
|
||||
|
||||
template <typename T_> struct parser_trait {
|
||||
using type = T_;
|
||||
static T_ parse(const std::string &input);
|
||||
static bool validate(T_ const&);
|
||||
static bool validate(T_ const &);
|
||||
|
||||
static constexpr hint_type format_hint = "value";
|
||||
static constexpr hint_type purpose_hint = "value";
|
||||
@@ -51,40 +52,36 @@ namespace argument_parser::parsing_traits {
|
||||
static constexpr hint_type purpose_hint = "double precision floating point number";
|
||||
};
|
||||
|
||||
|
||||
|
||||
constexpr hint_type comma = ",";
|
||||
template <const hint_type* PtrAddr>
|
||||
struct hint_provider {
|
||||
static constexpr hint_type value = *PtrAddr;
|
||||
};
|
||||
template <const hint_type *PtrAddr> struct hint_provider {
|
||||
static constexpr hint_type value = *PtrAddr;
|
||||
};
|
||||
|
||||
template<typename... Providers>
|
||||
struct joiner {
|
||||
static constexpr auto get_combined() {
|
||||
constexpr size_t total_len = (std::string_view{Providers::value}.length() + ... + 0);
|
||||
template <typename... Providers> struct joiner {
|
||||
static constexpr auto get_combined() {
|
||||
constexpr size_t total_len = (std::string_view{Providers::value}.length() + ... + 0);
|
||||
|
||||
std::array<char, total_len + 1> arr{};
|
||||
size_t offset = 0;
|
||||
std::array<char, total_len + 1> arr{};
|
||||
// ReSharper disable once CppDFAUnreadVariable
|
||||
size_t offset = 0;
|
||||
auto append = [&](const hint_type s) {
|
||||
const std::string_view sv{s};
|
||||
for (char c : sv)
|
||||
arr[offset++] = c;
|
||||
return 0;
|
||||
};
|
||||
|
||||
auto append = [&](hint_type s) {
|
||||
std::string_view sv{s};
|
||||
for (char c : sv) arr[offset++] = c;
|
||||
return 0;
|
||||
};
|
||||
(append(Providers::value), ...);
|
||||
|
||||
(append(Providers::value), ...);
|
||||
arr[total_len] = '\0';
|
||||
return arr;
|
||||
}
|
||||
|
||||
arr[total_len] = '\0';
|
||||
return arr;
|
||||
}
|
||||
static constexpr auto storage = get_combined();
|
||||
static constexpr hint_type value = storage.data();
|
||||
};
|
||||
|
||||
static constexpr auto storage = get_combined();
|
||||
static constexpr hint_type value = storage.data();
|
||||
};
|
||||
|
||||
template<typename... Providers>
|
||||
constexpr hint_type concat = joiner<Providers...>::value;
|
||||
template <typename... Providers> constexpr hint_type concat = joiner<Providers...>::value;
|
||||
|
||||
} // namespace argument_parser::parsing_traits
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace argument_parser {
|
||||
namespace v2 {
|
||||
class linux_parser : public v2::base_parser {
|
||||
public:
|
||||
linux_parser(bool should_exit = true);
|
||||
linux_parser(parser_settings const &settings = {});
|
||||
using base_parser::display_help;
|
||||
};
|
||||
} // namespace v2
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace argument_parser {
|
||||
namespace v2 {
|
||||
class macos_parser : public v2::base_parser {
|
||||
public:
|
||||
macos_parser(bool should_exit = true);
|
||||
explicit macos_parser(parser_settings const &settings = {});
|
||||
using base_parser::display_help;
|
||||
};
|
||||
} // namespace v2
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace argument_parser {
|
||||
namespace v2 {
|
||||
class windows_parser : public v2::base_parser {
|
||||
public:
|
||||
windows_parser(bool should_exit = true);
|
||||
windows_parser(parser_settings const &settings = {});
|
||||
using base_parser::display_help;
|
||||
};
|
||||
} // namespace v2
|
||||
|
||||
254
src/main.cpp
254
src/main.cpp
@@ -1,254 +0,0 @@
|
||||
#include "macros.h"
|
||||
#include "traits.hpp"
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <argparse>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
struct Point {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
template <> struct argument_parser::parsing_traits::parser_trait<Point> {
|
||||
static Point parse(const std::string &input) {
|
||||
auto comma_pos = input.find(',');
|
||||
if (comma_pos == std::string::npos) {
|
||||
throw std::runtime_error("Invalid Point format. Expected 'x,y'.");
|
||||
}
|
||||
int x = std::stoi(input.substr(0, comma_pos));
|
||||
int y = std::stoi(input.substr(comma_pos + 1));
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
static bool validate(Point const& p) {
|
||||
return p.x >= 0 && p.y >= 0;
|
||||
}
|
||||
|
||||
ARGPARSE_TRAIT_FORMAT_HINT = "x,y";
|
||||
ARGPARSE_TRAIT_PURPOSE_HINT = "coordinates";
|
||||
};
|
||||
|
||||
template <> struct argument_parser::parsing_traits::parser_trait<std::regex> {
|
||||
static std::regex parse(const std::string &input) {
|
||||
return std::regex(input);
|
||||
}
|
||||
ARGPARSE_TRAIT_FORMAT_HINT = "regex";
|
||||
ARGPARSE_TRAIT_PURPOSE_HINT = "regular expression";
|
||||
};
|
||||
|
||||
|
||||
template <> struct argument_parser::parsing_traits::parser_trait<std::vector<std::string>> {
|
||||
static std::vector<std::string> parse(const std::string &input) {
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss{input};
|
||||
std::string item;
|
||||
while (std::getline(ss, item, ',')) {
|
||||
result.push_back(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ARGPARSE_TRAIT_FORMAT_HINT = "string,string,string";
|
||||
ARGPARSE_TRAIT_PURPOSE_HINT = "list of strings";
|
||||
};
|
||||
|
||||
template <typename VT> struct argument_parser::parsing_traits::parser_trait<std::vector<VT>> {
|
||||
static std::vector<VT> parse(const std::string &input) {
|
||||
std::vector<VT> result;
|
||||
std::stringstream ss{input};
|
||||
std::string item;
|
||||
|
||||
while (std::getline(ss, item, ',')) {
|
||||
result.push_back(argument_parser::parsing_traits::parser_trait<VT>::parse(item));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
ARGPARSE_TRAIT_FORMAT_HINT = "VT,VT,VT";
|
||||
ARGPARSE_TRAIT_PURPOSE_HINT = "list of VT";
|
||||
};
|
||||
|
||||
const std::initializer_list<argument_parser::conventions::convention const *const> conventions = {
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
&argument_parser::conventions::gnu_equal_argument_convention,
|
||||
// &argument_parser::conventions::windows_argument_convention,
|
||||
// &argument_parser::conventions::windows_equal_argument_convention
|
||||
};
|
||||
|
||||
const auto echo = argument_parser::helpers::make_parametered_action<std::string>(
|
||||
[](std::string const &text) { std::cout << text << std::endl; });
|
||||
|
||||
const auto echo_point = argument_parser::helpers::make_parametered_action<Point>(
|
||||
[](Point const &point) { std::cout << "Point(" << point.x << ", " << point.y << ")" << std::endl; });
|
||||
|
||||
const auto cat = argument_parser::helpers::make_parametered_action<std::string>([](std::string const &file_name) {
|
||||
std::ifstream file(file_name);
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Could not open file");
|
||||
}
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
|
||||
file.close();
|
||||
});
|
||||
|
||||
|
||||
auto grep(argument_parser::base_parser const &parser, std::string const &filename, std::regex const &pattern) {
|
||||
if (filename.empty()) {
|
||||
std::cerr << "Missing filename" << std::endl;
|
||||
parser.display_help(conventions);
|
||||
exit(-1);
|
||||
}
|
||||
std::ifstream file(filename);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Could not open file: \"" << filename << '"' << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (std::string line; std::getline(file, line);) {
|
||||
if (std::regex_search(line, pattern)) {
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void run_grep(argument_parser::base_parser const &parser) {
|
||||
auto filename = parser.get_optional<std::string>("file");
|
||||
auto pattern = parser.get_optional<std::regex>("grep");
|
||||
|
||||
if (filename && pattern) {
|
||||
grep(parser, filename.value(), pattern.value());
|
||||
} else if (filename) {
|
||||
std::cerr << "Missing grep pattern" << std::endl;
|
||||
parser.display_help(conventions);
|
||||
exit(-1);
|
||||
} else if (pattern) {
|
||||
std::cerr << "Missing filename" << std::endl;
|
||||
parser.display_help(conventions);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void run_store_point(argument_parser::base_parser const &parser) {
|
||||
auto point = parser.get_optional<Point>("store-point");
|
||||
if (point) {
|
||||
std::cout << "Point(" << point->x << ", " << point->y << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int v2Examples() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
argument_parser::v2::parser parser{ false };
|
||||
|
||||
parser.add_argument<std::string>(
|
||||
{{ShortArgument, "e"}, {LongArgument, "echo"}, {Action, echo}, {HelpText, "echoes given variable"}});
|
||||
|
||||
parser.add_argument<Point>({{ShortArgument, "ep"}, {LongArgument, "echo-point"}, {Action, echo_point}});
|
||||
|
||||
parser.add_argument<std::string>({
|
||||
// stores string for f/file flag
|
||||
{ShortArgument, "f"},
|
||||
{LongArgument, "file"},
|
||||
{HelpText, "File to grep, required only if using grep"},
|
||||
// if no action, falls to store operation with given type.
|
||||
});
|
||||
|
||||
parser.add_argument<std::regex>({
|
||||
// stores string for g/grep flag
|
||||
{ShortArgument, "g"},
|
||||
{LongArgument, "grep"},
|
||||
{HelpText, "Grep pattern, required only if using file"},
|
||||
// same as 'file' flag
|
||||
});
|
||||
|
||||
parser.add_argument<std::string>(
|
||||
{{ShortArgument, "c"}, {LongArgument, "cat"}, {Action, cat}, {HelpText, "Prints the content of the file"}}
|
||||
);
|
||||
|
||||
parser.add_argument<Point>({
|
||||
// { ShortArgument, "sp" }, // now if ShortArgument or LongArgument is missing, it will use it for the other.
|
||||
{LongArgument, "store-point"},
|
||||
{Required, true} // makes this flag required
|
||||
});
|
||||
|
||||
parser.add_argument({{ShortArgument, "v"}, {LongArgument, "verbose"}});
|
||||
|
||||
parser.add_argument<std::string>({
|
||||
{Positional, "input"},
|
||||
{HelpText, "Input file to process"},
|
||||
{Required, true},
|
||||
});
|
||||
|
||||
parser.add_argument<std::string>({
|
||||
{Positional, "output"},
|
||||
{HelpText, "Output file path"},
|
||||
});
|
||||
|
||||
parser.add_argument<std::vector<Point>>({{LongArgument, "points"}, {HelpText, "List of points to store"}});
|
||||
|
||||
parser.on_complete(::run_grep);
|
||||
parser.on_complete(::run_store_point);
|
||||
parser.on_complete([](argument_parser::base_parser const &p) {
|
||||
auto input = p.get_optional<std::string>("input");
|
||||
auto output = p.get_optional<std::string>("output");
|
||||
if (input) {
|
||||
std::cout << "Input: " << input.value() << std::endl;
|
||||
}
|
||||
if (output) {
|
||||
std::cout << "Output: " << output.value() << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
parser.handle_arguments(conventions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto unique_copy(std::unique_ptr<std::string> ptr) {
|
||||
std::cout << *ptr << std::endl;
|
||||
}
|
||||
|
||||
auto unique_reference(std::unique_ptr<std::string> const& ptr) {
|
||||
std::cout << *ptr << std::endl;
|
||||
}
|
||||
|
||||
auto unique_move(std::unique_ptr<std::string>&& ptr) {
|
||||
std::cout << *ptr << std::endl;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T return_example(std::function<T()> func) {
|
||||
if constexpr (std::is_same_v<void, T>) {
|
||||
return func();
|
||||
} else {
|
||||
return func();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void log_result(std::function<T()> func) {
|
||||
if constexpr (std::is_same_v<void, T>) {
|
||||
func();
|
||||
} else {
|
||||
std::cout << "result: " << func() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
try {
|
||||
return_example<void>([]{});
|
||||
|
||||
return v2Examples();
|
||||
} catch (std::exception const &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
namespace argument_parser::conventions::helpers {
|
||||
std::string to_lower(std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](const unsigned char c) { return std::tolower(c); });
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string to_upper(std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::toupper(c); });
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](const unsigned char c) { return std::toupper(c); });
|
||||
return s;
|
||||
}
|
||||
} // namespace argument_parser::conventions::helpers
|
||||
@@ -10,10 +10,9 @@ namespace argument_parser::conventions::implementations {
|
||||
parsed_argument gnu_argument_convention::get_argument(std::string const &raw) const {
|
||||
if (starts_with(raw, long_prec()))
|
||||
return {argument_type::LONG, raw.substr(2)};
|
||||
else if (starts_with(raw, short_prec()))
|
||||
if (starts_with(raw, short_prec()))
|
||||
return {argument_type::SHORT, raw.substr(1)};
|
||||
else
|
||||
return {argument_type::ERROR, "GNU standard convention does not allow arguments without a preceding dash."};
|
||||
return {argument_type::ERROR, "GNU standard convention does not allow arguments without a preceding dash."};
|
||||
}
|
||||
|
||||
std::string gnu_argument_convention::extract_value(std::string const & /*raw*/) const {
|
||||
@@ -42,17 +41,17 @@ namespace argument_parser::conventions::implementations {
|
||||
|
||||
std::pair<std::string, std::string> gnu_argument_convention::make_help_text(std::string const &short_arg,
|
||||
std::string const &long_arg,
|
||||
bool requires_value) const {
|
||||
std::string s_part = "";
|
||||
if (short_arg != "-" && short_arg != "") {
|
||||
bool const requires_value) const {
|
||||
std::string s_part;
|
||||
if (short_arg != "-" && !short_arg.empty()) {
|
||||
s_part += short_prec() + short_arg;
|
||||
if (requires_value) {
|
||||
s_part += " <value>";
|
||||
}
|
||||
}
|
||||
|
||||
std::string l_part = "";
|
||||
if (long_arg != "-" && long_arg != "") {
|
||||
std::string l_part;
|
||||
if (long_arg != "-" && !long_arg.empty()) {
|
||||
l_part += long_prec() + long_arg;
|
||||
if (requires_value) {
|
||||
l_part += " <value>";
|
||||
@@ -65,18 +64,17 @@ namespace argument_parser::conventions::implementations {
|
||||
|
||||
namespace argument_parser::conventions::implementations {
|
||||
parsed_argument gnu_equal_argument_convention::get_argument(std::string const &raw) const {
|
||||
auto pos = raw.find('=');
|
||||
auto arg = pos != std::string::npos ? raw.substr(0, pos) : raw;
|
||||
const auto pos = raw.find('=');
|
||||
const auto arg = pos != std::string::npos ? raw.substr(0, pos) : raw;
|
||||
if (starts_with(arg, long_prec()))
|
||||
return {argument_type::LONG, arg.substr(2)};
|
||||
else if (starts_with(arg, short_prec()))
|
||||
if (starts_with(arg, short_prec()))
|
||||
return {argument_type::SHORT, arg.substr(1)};
|
||||
else
|
||||
return {argument_type::ERROR, "GNU standard convention does not allow arguments without a preceding dash."};
|
||||
return {argument_type::ERROR, "GNU standard convention does not allow arguments without a preceding dash."};
|
||||
}
|
||||
|
||||
std::string gnu_equal_argument_convention::extract_value(std::string const &raw) const {
|
||||
auto pos = raw.find('=');
|
||||
const auto pos = raw.find('=');
|
||||
if (pos == std::string::npos || pos + 1 >= raw.size())
|
||||
throw std::runtime_error("Expected value after '='.");
|
||||
return raw.substr(pos + 1);
|
||||
@@ -100,17 +98,17 @@ namespace argument_parser::conventions::implementations {
|
||||
|
||||
std::pair<std::string, std::string> gnu_equal_argument_convention::make_help_text(std::string const &short_arg,
|
||||
std::string const &long_arg,
|
||||
bool requires_value) const {
|
||||
std::string s_part = "";
|
||||
if (short_arg != "-" && short_arg != "") {
|
||||
bool const requires_value) const {
|
||||
std::string s_part;
|
||||
if (short_arg != "-" && !short_arg.empty()) {
|
||||
s_part += short_prec() + short_arg;
|
||||
if (requires_value) {
|
||||
s_part += "=<value>";
|
||||
}
|
||||
}
|
||||
|
||||
std::string l_part = "";
|
||||
if (long_arg != "-" && long_arg != "") {
|
||||
std::string l_part;
|
||||
if (long_arg != "-" && !long_arg.empty()) {
|
||||
l_part += long_prec() + long_arg;
|
||||
if (requires_value) {
|
||||
l_part += "=<value>";
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace argument_parser::conventions::implementations {
|
||||
windows_argument_convention::windows_argument_convention(bool accept_dash) : accept_dash_(accept_dash) {}
|
||||
windows_argument_convention::windows_argument_convention(bool const accept_dash) : accept_dash_(accept_dash) {}
|
||||
|
||||
parsed_argument windows_argument_convention::get_argument(std::string const &raw) const {
|
||||
if (raw.empty()) {
|
||||
return {argument_type::ERROR, "Empty argument token."};
|
||||
}
|
||||
const char c0 = raw[0];
|
||||
const bool ok_prefix = (c0 == '/') || (accept_dash_ && c0 == '-');
|
||||
if (!ok_prefix) {
|
||||
if (const bool ok_prefix = (c0 == '/') || (accept_dash_ && c0 == '-'); !ok_prefix) {
|
||||
return {argument_type::ERROR,
|
||||
accept_dash_ ? "Windows-style expects options to start with '/' (or '-' in compat mode)."
|
||||
: "Windows-style expects options to start with '/'."};
|
||||
@@ -50,18 +49,19 @@ namespace argument_parser::conventions::implementations {
|
||||
return "/";
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> windows_argument_convention::make_help_text(std::string const &short_arg, std::string const &long_arg,
|
||||
bool requires_value) const {
|
||||
std::string s_part = "";
|
||||
if (short_arg != "-" && short_arg != "") {
|
||||
std::pair<std::string, std::string> windows_argument_convention::make_help_text(std::string const &short_arg,
|
||||
std::string const &long_arg,
|
||||
bool const requires_value) const {
|
||||
std::string s_part;
|
||||
if (short_arg != "-" && !short_arg.empty()) {
|
||||
s_part += short_prec() + short_arg;
|
||||
if (requires_value) {
|
||||
s_part += " <value>";
|
||||
}
|
||||
}
|
||||
|
||||
std::string l_part = "";
|
||||
if (long_arg != "-" && long_arg != "") {
|
||||
std::string l_part;
|
||||
if (long_arg != "-" && !long_arg.empty()) {
|
||||
l_part += long_prec() + long_arg;
|
||||
if (requires_value) {
|
||||
l_part += " <value>";
|
||||
@@ -78,15 +78,14 @@ namespace argument_parser::conventions::implementations {
|
||||
} // namespace argument_parser::conventions::implementations
|
||||
|
||||
namespace argument_parser::conventions::implementations {
|
||||
windows_kv_argument_convention::windows_kv_argument_convention(bool accept_dash) : accept_dash_(accept_dash) {}
|
||||
windows_kv_argument_convention::windows_kv_argument_convention(bool const accept_dash) : accept_dash_(accept_dash) {}
|
||||
|
||||
parsed_argument windows_kv_argument_convention::get_argument(std::string const &raw) const {
|
||||
if (raw.empty()) {
|
||||
return {argument_type::ERROR, "Empty argument token."};
|
||||
}
|
||||
const char c0 = raw[0];
|
||||
const bool ok_prefix = (c0 == '/') || (accept_dash_ && c0 == '-');
|
||||
if (!ok_prefix) {
|
||||
if (const bool ok_prefix = (c0 == '/') || (accept_dash_ && c0 == '-'); !ok_prefix) {
|
||||
return {argument_type::ERROR,
|
||||
accept_dash_ ? "Windows-style expects options to start with '/' (or '-' in compat mode)."
|
||||
: "Windows-style expects options to start with '/'."};
|
||||
@@ -129,17 +128,18 @@ namespace argument_parser::conventions::implementations {
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> windows_kv_argument_convention::make_help_text(std::string const &short_arg,
|
||||
std::string const &long_arg, bool requires_value) const {
|
||||
std::string s_part = "";
|
||||
if (short_arg != "-" && short_arg != "") {
|
||||
std::string const &long_arg,
|
||||
bool const requires_value) const {
|
||||
std::string s_part;
|
||||
if (short_arg != "-" && !short_arg.empty()) {
|
||||
s_part += short_prec() + short_arg;
|
||||
if (requires_value) {
|
||||
s_part += "=<value>, " + short_prec() + short_arg + ":<value>";
|
||||
}
|
||||
}
|
||||
|
||||
std::string l_part = "";
|
||||
if (long_arg != "-" && long_arg != "") {
|
||||
std::string l_part;
|
||||
if (long_arg != "-" && !long_arg.empty()) {
|
||||
l_part += long_prec() + long_arg;
|
||||
if (requires_value) {
|
||||
l_part += "=<value>, " + long_prec() + long_arg + ":<value>";
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#include "argument_parser.hpp"
|
||||
#include "exceptions.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
@@ -13,7 +16,7 @@
|
||||
|
||||
class deferred_exec {
|
||||
public:
|
||||
deferred_exec(std::function<void()> const &func) : func(func) {}
|
||||
explicit deferred_exec(std::function<void()> const &func) : func(func) {}
|
||||
~deferred_exec() {
|
||||
func();
|
||||
}
|
||||
@@ -27,13 +30,12 @@ bool contains(std::unordered_map<std::string, int> const &map, std::string const
|
||||
}
|
||||
|
||||
namespace argument_parser {
|
||||
argument::argument()
|
||||
: id(0), name(), action(std::make_unique<non_parametered_action>([]() {})), required(false), invoked(false) {}
|
||||
argument::argument() : id(0), action(std::make_unique<action_no_param>([] {})), required(false), invoked(false) {}
|
||||
|
||||
argument::argument(const argument &other)
|
||||
: id(other.id), name(other.name), action(other.action->clone()), required(other.required),
|
||||
invoked(other.invoked), help_text(other.help_text), positional(other.positional),
|
||||
position_index(other.position_index) {}
|
||||
positional_accumulator(other.positional_accumulator), position_index(other.position_index) {}
|
||||
|
||||
argument &argument::operator=(const argument &other) {
|
||||
if (this != &other) {
|
||||
@@ -44,6 +46,7 @@ namespace argument_parser {
|
||||
invoked = other.invoked;
|
||||
help_text = other.help_text;
|
||||
positional = other.positional;
|
||||
positional_accumulator = other.positional_accumulator;
|
||||
position_index = other.position_index;
|
||||
}
|
||||
return *this;
|
||||
@@ -69,11 +72,11 @@ namespace argument_parser {
|
||||
return help_text;
|
||||
}
|
||||
|
||||
void argument::set_required(bool val) {
|
||||
void argument::set_required(const bool val) {
|
||||
required = val;
|
||||
}
|
||||
|
||||
void argument::set_invoked(bool val) {
|
||||
void argument::set_invoked(const bool val) {
|
||||
invoked = val;
|
||||
}
|
||||
|
||||
@@ -85,20 +88,36 @@ namespace argument_parser {
|
||||
return positional;
|
||||
}
|
||||
|
||||
bool argument::is_positional_accumulator() const {
|
||||
return positional_accumulator;
|
||||
}
|
||||
|
||||
std::optional<int> argument::get_position_index() const {
|
||||
return position_index;
|
||||
}
|
||||
|
||||
void argument::set_positional(bool val) {
|
||||
void argument::set_positional(const bool val) {
|
||||
positional = val;
|
||||
}
|
||||
|
||||
void argument::set_position_index(std::optional<int> idx) {
|
||||
void argument::set_positional_accumulator(const bool val) {
|
||||
positional_accumulator = val;
|
||||
}
|
||||
|
||||
void argument::set_position_index(const std::optional<int> idx) {
|
||||
position_index = idx;
|
||||
}
|
||||
|
||||
void base_parser::on_complete(std::function<void(base_parser const &)> const &handler) {
|
||||
on_complete_events.emplace_back(handler);
|
||||
void base_parser::on_complete(std::function<void(base_parser const &)> const &action) {
|
||||
on_complete_events.emplace_back(action);
|
||||
}
|
||||
|
||||
void base_parser::on_complete(std::function<void(base_parser const &)> const &handler, const bool to_start) {
|
||||
if (to_start) {
|
||||
on_complete_events.emplace_front(handler);
|
||||
} else {
|
||||
on_complete_events.emplace_back(handler);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -112,12 +131,17 @@ namespace argument_parser {
|
||||
auto name_it = reverse_positional_names.find(pos_id);
|
||||
if (name_it == reverse_positional_names.end())
|
||||
continue;
|
||||
|
||||
auto const &arg = argument_map.at(pos_id);
|
||||
if (arg.is_required()) {
|
||||
ss << " <" << name_it->second << ">";
|
||||
} else {
|
||||
ss << " [" << name_it->second << "]";
|
||||
}
|
||||
|
||||
if (arg.is_positional_accumulator()) {
|
||||
ss << "...";
|
||||
}
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
@@ -143,8 +167,8 @@ namespace argument_parser {
|
||||
std::unordered_set<std::string> hasOnce;
|
||||
for (auto const &convention : convention_types) {
|
||||
auto generatedParts = convention->make_help_text(short_arg, long_arg, arg.expects_parameter());
|
||||
std::string combined = generatedParts.first + "|" + generatedParts.second;
|
||||
if (hasOnce.find(combined) == hasOnce.end()) {
|
||||
if (std::string combined = generatedParts.first + "|" + generatedParts.second;
|
||||
hasOnce.find(combined) == hasOnce.end()) {
|
||||
parts.push_back(generatedParts);
|
||||
hasOnce.insert(combined);
|
||||
|
||||
@@ -155,24 +179,24 @@ namespace argument_parser {
|
||||
max_long_len = generatedParts.second.length();
|
||||
}
|
||||
} else {
|
||||
parts.push_back({"", ""}); // trigger empty space in the help text
|
||||
parts.emplace_back("", ""); // trigger empty space in the help text
|
||||
}
|
||||
}
|
||||
help_lines.push_back({parts, arg.help_text});
|
||||
}
|
||||
|
||||
if (!help_lines.empty()) {
|
||||
for (auto const &line : help_lines) {
|
||||
for (const auto &[convention_parts, desc] : help_lines) {
|
||||
ss << "\t";
|
||||
for (size_t i = 0; i < line.convention_parts.size(); ++i) {
|
||||
auto const &parts = line.convention_parts[i];
|
||||
for (size_t i = 0; i < convention_parts.size(); ++i) {
|
||||
const auto &[fst, snd] = convention_parts[i];
|
||||
if (i > 0) {
|
||||
ss << " ";
|
||||
}
|
||||
ss << std::left << std::setw(static_cast<int>(max_short_len)) << parts.first << " "
|
||||
<< std::setw(static_cast<int>(max_long_len)) << parts.second;
|
||||
ss << std::left << std::setw(static_cast<int>(max_short_len)) << fst << " "
|
||||
<< std::setw(static_cast<int>(max_long_len)) << snd;
|
||||
}
|
||||
ss << "\t" << line.desc << "\n";
|
||||
ss << "\t" << desc << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,10 +206,8 @@ namespace argument_parser {
|
||||
for (auto const &pos_id : positional_arguments) {
|
||||
if (pos_id == -1)
|
||||
continue;
|
||||
auto name_it = reverse_positional_names.find(pos_id);
|
||||
if (name_it != reverse_positional_names.end()) {
|
||||
size_t display_len = name_it->second.length() + 2; // for < >
|
||||
if (display_len > max_pos_name_len)
|
||||
if (auto name_it = reverse_positional_names.find(pos_id); name_it != reverse_positional_names.end()) {
|
||||
if (size_t display_len = name_it->second.length() + 2; display_len > max_pos_name_len)
|
||||
max_pos_name_len = display_len;
|
||||
}
|
||||
}
|
||||
@@ -208,37 +230,32 @@ namespace argument_parser {
|
||||
|
||||
argument &base_parser::get_argument(conventions::parsed_argument const &arg) {
|
||||
if (arg.first == conventions::argument_type::LONG) {
|
||||
auto long_pos = long_arguments.find(arg.second);
|
||||
if (long_pos != long_arguments.end())
|
||||
if (const auto long_pos = long_arguments.find(arg.second); long_pos != long_arguments.end())
|
||||
return argument_map.at(long_pos->second);
|
||||
} else if (arg.first == conventions::argument_type::SHORT) {
|
||||
auto short_pos = short_arguments.find(arg.second);
|
||||
if (short_pos != short_arguments.end())
|
||||
if (const auto short_pos = short_arguments.find(arg.second); short_pos != short_arguments.end())
|
||||
return argument_map.at(short_pos->second);
|
||||
} else if (arg.first == conventions::argument_type::INTERCHANGABLE) {
|
||||
auto long_pos = long_arguments.find(arg.second);
|
||||
if (long_pos != long_arguments.end())
|
||||
if (const auto long_pos = long_arguments.find(arg.second); long_pos != long_arguments.end())
|
||||
return argument_map.at(long_pos->second);
|
||||
auto short_pos = short_arguments.find(arg.second);
|
||||
if (short_pos != short_arguments.end())
|
||||
if (const auto short_pos = short_arguments.find(arg.second); short_pos != short_arguments.end())
|
||||
return argument_map.at(short_pos->second);
|
||||
}
|
||||
throw std::runtime_error("Unknown argument: " + arg.second);
|
||||
}
|
||||
|
||||
void base_parser::enforce_creation_thread() {
|
||||
void base_parser::enforce_creation_thread() const {
|
||||
if (std::this_thread::get_id() != this->creation_thread_id.load()) {
|
||||
throw std::runtime_error("handle_arguments must be called from the main thread");
|
||||
}
|
||||
}
|
||||
|
||||
bool base_parser::test_conventions(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::unordered_map<std::string, std::string> &values_for_arguments,
|
||||
std::vector<std::pair<std::string, argument>> &found_arguments,
|
||||
std::optional<argument> &found_help, std::vector<std::string>::iterator &it,
|
||||
std::stringstream &error_stream) {
|
||||
bool
|
||||
base_parser::test_conventions(const std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::vector<found_argument> &found_arguments, std::optional<argument> &found_help,
|
||||
std::vector<std::string>::iterator &it, std::stringstream &error_stream) {
|
||||
|
||||
std::string current_argument = *it;
|
||||
const std::string current_argument = *it;
|
||||
|
||||
for (auto const &convention_type : convention_types) {
|
||||
auto extracted = convention_type->get_argument(current_argument);
|
||||
@@ -256,16 +273,17 @@ namespace argument_parser {
|
||||
return true;
|
||||
}
|
||||
|
||||
found_arguments.emplace_back(extracted.second, corresponding_argument);
|
||||
found_argument found{extracted.second, corresponding_argument};
|
||||
|
||||
if (corresponding_argument.expects_parameter()) {
|
||||
if (convention_type->requires_next_token() && (it + 1) == parsed_arguments.end()) {
|
||||
if (convention_type->requires_next_token() && it + 1 == parsed_arguments.end()) {
|
||||
throw std::runtime_error("Expected value for argument " + extracted.second);
|
||||
}
|
||||
values_for_arguments[extracted.second] =
|
||||
found.value =
|
||||
convention_type->requires_next_token() ? *(++it) : convention_type->extract_value(*it);
|
||||
}
|
||||
|
||||
found_arguments.emplace_back(std::move(found));
|
||||
return true;
|
||||
} catch (const std::runtime_error &e) {
|
||||
error_stream << "Convention \"" << convention_type->name() << "\" failed with: " << e.what() << "\n";
|
||||
@@ -275,10 +293,9 @@ namespace argument_parser {
|
||||
return false;
|
||||
}
|
||||
|
||||
void base_parser::extract_arguments(std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::unordered_map<std::string, std::string> &values_for_arguments,
|
||||
std::vector<std::pair<std::string, argument>> &found_arguments,
|
||||
std::optional<argument> &found_help) {
|
||||
void
|
||||
base_parser::extract_arguments(const std::initializer_list<conventions::convention const *const> convention_types,
|
||||
std::vector<found_argument> &found_arguments, std::optional<argument> &found_help) {
|
||||
|
||||
size_t next_positional_index = 0;
|
||||
bool force_positional = false;
|
||||
@@ -290,39 +307,43 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
if (force_positional) {
|
||||
if (next_positional_index >= positional_arguments.size()) {
|
||||
auto slot = next_positional_slot(next_positional_index);
|
||||
if (!slot.has_value()) {
|
||||
throw std::runtime_error("Unexpected positional argument: \"" + *it + "\"");
|
||||
}
|
||||
int arg_id = positional_arguments[next_positional_index];
|
||||
int arg_id = positional_arguments[*slot];
|
||||
argument &pos_arg = argument_map.at(arg_id);
|
||||
std::string const &pos_name = reverse_positional_names.at(arg_id);
|
||||
found_arguments.emplace_back(pos_name, pos_arg);
|
||||
values_for_arguments[pos_name] = *it;
|
||||
next_positional_index++;
|
||||
found_arguments.push_back({pos_name, pos_arg, *it});
|
||||
if (!pos_arg.is_positional_accumulator()) {
|
||||
next_positional_index = *slot + 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream error_stream;
|
||||
|
||||
if (!test_conventions(convention_types, values_for_arguments, found_arguments, found_help, it,
|
||||
error_stream)) {
|
||||
if (next_positional_index < positional_arguments.size()) {
|
||||
int arg_id = positional_arguments[next_positional_index];
|
||||
if (std::stringstream error_stream;
|
||||
!test_conventions(convention_types, found_arguments, found_help, it, error_stream)) {
|
||||
if (auto slot = next_positional_slot(next_positional_index); slot.has_value()) {
|
||||
int arg_id = positional_arguments[*slot];
|
||||
argument &pos_arg = argument_map.at(arg_id);
|
||||
std::string const &pos_name = reverse_positional_names.at(arg_id);
|
||||
found_arguments.emplace_back(pos_name, pos_arg);
|
||||
values_for_arguments[pos_name] = *it;
|
||||
next_positional_index++;
|
||||
found_arguments.push_back({pos_name, pos_arg, *it});
|
||||
if (!pos_arg.is_positional_accumulator()) {
|
||||
next_positional_index = *slot + 1;
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("All trials for argument: \n\t\"" + *it + "\"\n failed with: \n" +
|
||||
error_stream.str());
|
||||
if (m_settings.ignore_unknown_arguments) {
|
||||
continue;
|
||||
}
|
||||
throw parser::unknown_argument_exception("All trials for argument: \n\t\"" + *it +
|
||||
"\"\n failed with: \n" + error_stream.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string replace_var(std::string text, const std::string &var_name, const std::string &value) {
|
||||
std::string placeholder = "${" + var_name + "}";
|
||||
const std::string placeholder = "${" + var_name + "}";
|
||||
size_t pos = text.find(placeholder);
|
||||
|
||||
while (pos != std::string::npos) {
|
||||
@@ -332,8 +353,7 @@ namespace argument_parser {
|
||||
return text;
|
||||
}
|
||||
|
||||
void base_parser::invoke_arguments(std::unordered_map<std::string, std::string> const &values_for_arguments,
|
||||
std::vector<std::pair<std::string, argument>> &found_arguments,
|
||||
void base_parser::invoke_arguments(std::vector<found_argument> &found_arguments,
|
||||
std::optional<argument> const &found_help) {
|
||||
|
||||
if (found_help) {
|
||||
@@ -342,15 +362,15 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
std::stringstream error_stream;
|
||||
for (auto &[key, value] : found_arguments) {
|
||||
for (auto &[key, arg, value] : found_arguments) {
|
||||
try {
|
||||
if (value.expects_parameter()) {
|
||||
value.action->invoke_with_parameter(values_for_arguments.at(key));
|
||||
if (arg.expects_parameter()) {
|
||||
arg.action->invoke_with_parameter(value.value());
|
||||
} else {
|
||||
value.action->invoke();
|
||||
arg.action->invoke();
|
||||
}
|
||||
value.set_invoked(true);
|
||||
argument_map.at(value.id).set_invoked(true);
|
||||
arg.set_invoked(true);
|
||||
argument_map.at(arg.id).set_invoked(true);
|
||||
} catch (const std::runtime_error &e) {
|
||||
std::string err{e.what()};
|
||||
err = replace_var(err, "KEY", "for " + key);
|
||||
@@ -358,43 +378,55 @@ namespace argument_parser {
|
||||
}
|
||||
}
|
||||
|
||||
std::string error_message = error_stream.str();
|
||||
if (!error_message.empty()) {
|
||||
if (const std::string error_message = error_stream.str(); !error_message.empty()) {
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
}
|
||||
|
||||
void base_parser::handle_arguments(std::initializer_list<conventions::convention const *const> convention_types) {
|
||||
void
|
||||
base_parser::handle_arguments(const std::initializer_list<conventions::convention const *const> convention_types) {
|
||||
enforce_creation_thread();
|
||||
|
||||
deferred_exec reset_current_conventions([this]() { this->reset_current_conventions(); });
|
||||
deferred_exec reset_current_conventions([this] { this->reset_current_conventions(); });
|
||||
this->current_conventions(convention_types);
|
||||
|
||||
std::unordered_map<std::string, std::string> values_for_arguments;
|
||||
std::vector<std::pair<std::string, argument>> found_arguments;
|
||||
std::vector<found_argument> found_arguments;
|
||||
std::optional<argument> found_help = std::nullopt;
|
||||
|
||||
extract_arguments(convention_types, values_for_arguments, found_arguments, found_help);
|
||||
invoke_arguments(values_for_arguments, found_arguments, found_help);
|
||||
try {
|
||||
extract_arguments(convention_types, found_arguments, found_help);
|
||||
invoke_arguments(found_arguments, found_help);
|
||||
} catch (parser::unknown_argument_exception const &e) {
|
||||
if (m_settings.should_exit_on_unknown_argument) {
|
||||
std::exit(1);
|
||||
}
|
||||
throw e;
|
||||
} catch (std::exception const &e) {
|
||||
if (m_settings.should_exit_on_error) {
|
||||
std::exit(1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
check_for_required_arguments(convention_types);
|
||||
fire_on_complete_events();
|
||||
}
|
||||
|
||||
void base_parser::display_help(std::initializer_list<conventions::convention const *const> convention_types) const {
|
||||
void base_parser::display_help(
|
||||
const std::initializer_list<conventions::convention const *const> convention_types) const {
|
||||
std::cout << build_help_text(convention_types);
|
||||
}
|
||||
|
||||
std::optional<int> base_parser::find_argument_id(std::string const &arg) const {
|
||||
auto long_pos = long_arguments.find(arg);
|
||||
auto short_post = short_arguments.find(arg);
|
||||
const auto long_pos = long_arguments.find(arg);
|
||||
const auto short_post = short_arguments.find(arg);
|
||||
|
||||
if (long_pos != long_arguments.end())
|
||||
return long_pos->second;
|
||||
if (short_post != short_arguments.end())
|
||||
return short_post->second;
|
||||
|
||||
auto pos_it = positional_name_map.find(arg);
|
||||
if (pos_it != positional_name_map.end())
|
||||
if (const auto pos_it = positional_name_map.find(arg); pos_it != positional_name_map.end())
|
||||
return pos_it->second;
|
||||
|
||||
return std::nullopt;
|
||||
@@ -406,12 +438,12 @@ namespace argument_parser {
|
||||
}
|
||||
}
|
||||
|
||||
void base_parser::set_argument_status(bool is_required, std::string const &help_text, argument &arg) {
|
||||
void base_parser::set_argument_status(const bool is_required, std::string const &help_text, argument &arg) {
|
||||
arg.set_required(is_required);
|
||||
arg.set_help_text(help_text);
|
||||
}
|
||||
|
||||
void base_parser::place_argument(int id, argument const &arg, std::string const &short_arg,
|
||||
void base_parser::place_argument(int const id, argument const &arg, std::string const &short_arg,
|
||||
std::string const &long_arg) {
|
||||
argument_map[id] = arg;
|
||||
if (short_arg != "-") {
|
||||
@@ -430,19 +462,57 @@ namespace argument_parser {
|
||||
}
|
||||
}
|
||||
|
||||
void base_parser::place_positional_argument(int id, argument const &arg, std::string const &name,
|
||||
std::optional<int> position) {
|
||||
void base_parser::assert_can_place_positional(const int id, const std::optional<int> position,
|
||||
const bool accumulator) const {
|
||||
const auto existing_accumulator =
|
||||
std::find_if(positional_arguments.begin(), positional_arguments.end(), [this](int const arg_id) {
|
||||
if (arg_id == -1) {
|
||||
return false;
|
||||
}
|
||||
return argument_map.at(arg_id).is_positional_accumulator();
|
||||
});
|
||||
|
||||
if (accumulator && existing_accumulator != positional_arguments.end()) {
|
||||
throw std::runtime_error("Only one positional accumulator is allowed.");
|
||||
}
|
||||
|
||||
if (!accumulator && existing_accumulator != positional_arguments.end()) {
|
||||
const auto accumulator_slot =
|
||||
static_cast<size_t>(std::distance(positional_arguments.begin(), existing_accumulator));
|
||||
if (!position.has_value() || static_cast<size_t>(position.value()) >= accumulator_slot) {
|
||||
throw std::runtime_error("Positional accumulator must be the last positional argument.");
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulator && position.has_value()) {
|
||||
const auto idx = static_cast<size_t>(position.value());
|
||||
for (size_t i = idx + 1; i < positional_arguments.size(); ++i) {
|
||||
if (positional_arguments[i] != -1 && positional_arguments[i] != id) {
|
||||
throw std::runtime_error("Positional accumulator must be the last positional argument.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void base_parser::place_positional_argument(int const id, argument const &arg, std::string const &name,
|
||||
const std::optional<int> position, const bool accumulator) {
|
||||
if (position.has_value() && position.value() < 0) {
|
||||
throw std::runtime_error("Positional argument position cannot be negative.");
|
||||
}
|
||||
assert_can_place_positional(id, position, accumulator);
|
||||
|
||||
argument_map[id] = arg;
|
||||
positional_name_map[name] = id;
|
||||
reverse_positional_names[id] = name;
|
||||
|
||||
if (position.has_value()) {
|
||||
auto idx = static_cast<size_t>(position.value());
|
||||
const auto idx = static_cast<size_t>(position.value());
|
||||
if (idx > positional_arguments.size()) {
|
||||
positional_arguments.resize(idx + 1, -1);
|
||||
}
|
||||
if (idx < positional_arguments.size() && positional_arguments[idx] != -1) {
|
||||
throw std::runtime_error("Position " + std::to_string(idx) + " is already occupied!");
|
||||
positional_arguments.insert(positional_arguments.begin() + static_cast<std::ptrdiff_t>(idx), id);
|
||||
return;
|
||||
}
|
||||
if (idx == positional_arguments.size()) {
|
||||
positional_arguments.push_back(id);
|
||||
@@ -450,10 +520,24 @@ namespace argument_parser {
|
||||
positional_arguments[idx] = id;
|
||||
}
|
||||
} else {
|
||||
positional_arguments.push_back(id);
|
||||
if (const auto empty_slot = std::find(positional_arguments.begin(), positional_arguments.end(), -1);
|
||||
empty_slot != positional_arguments.end()) {
|
||||
*empty_slot = id;
|
||||
} else {
|
||||
positional_arguments.push_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<size_t> base_parser::next_positional_slot(size_t const start) const {
|
||||
for (size_t i = start; i < positional_arguments.size(); ++i) {
|
||||
if (positional_arguments[i] != -1) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string get_one_name(std::string const &short_name, std::string const &long_name) {
|
||||
std::string res{};
|
||||
if (short_name != "-") {
|
||||
@@ -500,15 +584,15 @@ namespace argument_parser {
|
||||
} else {
|
||||
std::cerr << "\t" << get_one_name(s, l) << ": must be provided as one of [";
|
||||
for (auto it = convention_types.begin(); it != convention_types.end(); ++it) {
|
||||
auto generatedParts = (*it)->make_help_text(s, l, p);
|
||||
std::string help_str = generatedParts.first;
|
||||
if (!generatedParts.first.empty() && !generatedParts.second.empty()) {
|
||||
auto [short_part, long_part] = (*it)->make_help_text(s, l, p);
|
||||
std::string help_str = short_part;
|
||||
if (!short_part.empty() && !long_part.empty()) {
|
||||
help_str += " ";
|
||||
}
|
||||
help_str += generatedParts.second;
|
||||
help_str += long_part;
|
||||
|
||||
size_t last_not_space = help_str.find_last_not_of(" \t");
|
||||
if (last_not_space != std::string::npos) {
|
||||
if (size_t last_not_space = help_str.find_last_not_of(" \t");
|
||||
last_not_space != std::string::npos) {
|
||||
help_str.erase(last_not_space + 1);
|
||||
}
|
||||
std::cerr << help_str;
|
||||
@@ -521,7 +605,10 @@ namespace argument_parser {
|
||||
}
|
||||
std::cerr << "\n";
|
||||
display_help(convention_types);
|
||||
std::exit(1);
|
||||
if (m_settings.should_exit_on_missing_required) {
|
||||
std::exit(1);
|
||||
}
|
||||
throw std::runtime_error("required arguments not provided");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
fake_parser::fake_parser(std::string const &program_name, std::initializer_list<std::string> const &arguments)
|
||||
: fake_parser(program_name, std::vector<std::string>(arguments)) {}
|
||||
: fake_parser(program_name, std::vector(arguments)) {}
|
||||
|
||||
void fake_parser::set_program_name(std::string const &program_name) {
|
||||
this->program_name = program_name;
|
||||
@@ -23,28 +23,27 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
namespace v2 {
|
||||
fake_parser::fake_parser(std::string program_name, std::vector<std::string> const &arguments) {
|
||||
set_program_name(program_name);
|
||||
ref_parsed_args() = arguments;
|
||||
prepare_help_flag(false);
|
||||
}
|
||||
fake_parser::fake_parser(std::string program_name, std::vector<std::string> const &arguments) {
|
||||
base_parser::set_program_name(std::move(program_name));
|
||||
ref_parsed_args() = arguments;
|
||||
prepare_help_flag(false);
|
||||
}
|
||||
|
||||
fake_parser::fake_parser(std::string const &program_name, std::vector<std::string> &&arguments) {
|
||||
set_program_name(program_name);
|
||||
ref_parsed_args() = std::move(arguments);
|
||||
prepare_help_flag(false);
|
||||
}
|
||||
fake_parser::fake_parser(std::string program_name, std::vector<std::string> &&arguments) {
|
||||
base_parser::set_program_name(std::move(program_name));
|
||||
ref_parsed_args() = std::move(arguments);
|
||||
prepare_help_flag(false);
|
||||
}
|
||||
|
||||
fake_parser::fake_parser(std::string const &program_name, std::initializer_list<std::string> const &arguments)
|
||||
: fake_parser(program_name, std::vector<std::string>(arguments)) {
|
||||
}
|
||||
fake_parser::fake_parser(std::string program_name, std::initializer_list<std::string> const &arguments)
|
||||
: fake_parser(std::move(program_name), std::vector(arguments)) {}
|
||||
|
||||
void fake_parser::set_program_name(std::string const &program_name) {
|
||||
set_program_name(program_name);
|
||||
}
|
||||
void fake_parser::set_program_name(std::string const &program_name) {
|
||||
base_parser::set_program_name(program_name);
|
||||
}
|
||||
|
||||
void fake_parser::set_parsed_arguments(std::vector<std::string> const &parsed_arguments) {
|
||||
ref_parsed_args() = parsed_arguments;
|
||||
}
|
||||
}
|
||||
void fake_parser::set_parsed_arguments(std::vector<std::string> const &parsed_arguments) {
|
||||
ref_parsed_args() = parsed_arguments;
|
||||
}
|
||||
} // namespace v2
|
||||
} // namespace argument_parser
|
||||
|
||||
@@ -15,17 +15,17 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
namespace v2 {
|
||||
linux_parser::linux_parser(bool should_exit) {
|
||||
linux_parser::linux_parser(parser_settings const &settings) {
|
||||
std::ifstream command_line_file{"/proc/self/cmdline"};
|
||||
std::string program_name;
|
||||
std::getline(command_line_file, program_name, '\0');
|
||||
set_program_name(program_name);
|
||||
|
||||
for (std::string line; std::getline(command_line_file, line, '\0');) {
|
||||
parsed_arguments.emplace_back(line);
|
||||
ref_parsed_args().emplace_back(line);
|
||||
}
|
||||
|
||||
prepare_help_flag(should_exit);
|
||||
prepare_help_flag(settings.should_exit_on_help);
|
||||
}
|
||||
} // namespace v2
|
||||
} // namespace argument_parser
|
||||
|
||||
@@ -4,15 +4,20 @@
|
||||
|
||||
#include <crt_externs.h>
|
||||
|
||||
#define MACOS_GETARGS_LOOP(argc_name, argv_name, before_for, for_body) \
|
||||
do { \
|
||||
const int argc_name = *_NSGetArgc(); \
|
||||
if (char **argv_name = *_NSGetArgv(); argc_name > 0 && argv_name != nullptr && argv_name[0] != nullptr) { \
|
||||
do { before_for; } while(false); \
|
||||
for (int i = 1; i < argc_name; ++i) { \
|
||||
for_body \
|
||||
} \
|
||||
} \
|
||||
#define MACOS_GETARGS_LOOP(argc_name, argv_name, before_for, for_body) \
|
||||
do { \
|
||||
const int(argc_name) = *_NSGetArgc(); \
|
||||
if (char **(argv_name) = *_NSGetArgv(); \
|
||||
(argc_name) > 0 && (argv_name) != nullptr && (argv_name)[0] != nullptr) { \
|
||||
do { \
|
||||
(before_for); \
|
||||
} while (false); \
|
||||
for (int i = 1; i < (argc_name); ++i) { \
|
||||
{ \
|
||||
for_body \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
namespace argument_parser {
|
||||
@@ -24,12 +29,13 @@ namespace argument_parser {
|
||||
}
|
||||
|
||||
namespace v2 {
|
||||
macos_parser::macos_parser(bool should_exit) {
|
||||
MACOS_GETARGS_LOOP(argc, argv, set_program_name(argv[0]), {
|
||||
if (argv[i] != nullptr)
|
||||
macos_parser::macos_parser(parser_settings const &settings) {
|
||||
MACOS_GETARGS_LOOP(argc, argv, set_program_name(argv[0]), {
|
||||
if (argv[i] != nullptr)
|
||||
ref_parsed_args().emplace_back(argv[i]);
|
||||
});
|
||||
prepare_help_flag(should_exit);
|
||||
});
|
||||
prepare_help_flag(settings.should_exit_on_help);
|
||||
set_settings(settings);
|
||||
}
|
||||
} // namespace v2
|
||||
} // namespace argument_parser
|
||||
|
||||
@@ -95,11 +95,11 @@ namespace argument_parser {
|
||||
} // namespace argument_parser
|
||||
|
||||
namespace argument_parser::v2 {
|
||||
windows_parser::windows_parser(bool should_exit) {
|
||||
windows_parser::windows_parser(parser_settings const &settings) {
|
||||
parse_windows_arguments(ref_parsed_args(),
|
||||
[this](std::string const &program_name) { this->set_program_name(program_name); });
|
||||
|
||||
prepare_help_flag(should_exit);
|
||||
prepare_help_flag(settings.should_exit_on_help);
|
||||
}
|
||||
} // namespace argument_parser::v2
|
||||
|
||||
|
||||
420
src/test.cpp
420
src/test.cpp
@@ -1,420 +0,0 @@
|
||||
#include <argparse>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
const std::initializer_list<argument_parser::conventions::convention const *const> conventions = {
|
||||
&argument_parser::conventions::gnu_argument_convention,
|
||||
&argument_parser::conventions::gnu_equal_argument_convention,
|
||||
};
|
||||
|
||||
namespace v2_test {
|
||||
class fake_parser : public argument_parser::v2::base_parser {
|
||||
public:
|
||||
fake_parser(std::string const &program_name, std::initializer_list<std::string> const &arguments) {
|
||||
set_program_name(program_name);
|
||||
ref_parsed_args() = std::vector<std::string>(arguments);
|
||||
prepare_help_flag();
|
||||
}
|
||||
};
|
||||
} // namespace v2_test
|
||||
|
||||
int tests_run = 0;
|
||||
int tests_passed = 0;
|
||||
|
||||
void test_result(const char *name, bool passed) {
|
||||
tests_run++;
|
||||
if (passed) {
|
||||
tests_passed++;
|
||||
std::cout << " [PASS] " << name << std::endl;
|
||||
} else {
|
||||
std::cout << " [FAIL] " << name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// V1 Tests (using argument_parser::fake_parser)
|
||||
// ============================================================
|
||||
|
||||
void test_v1_single_positional_store() {
|
||||
argument_parser::fake_parser parser("test", {"hello"});
|
||||
parser.add_positional_argument<std::string>("greeting", "A greeting", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<std::string>("greeting");
|
||||
test_result("v1: single positional store", val.has_value() && val.value() == "hello");
|
||||
}
|
||||
|
||||
void test_v1_multiple_positionals_ordered() {
|
||||
argument_parser::fake_parser parser("test", {"alpha", "beta", "gamma"});
|
||||
parser.add_positional_argument<std::string>("first", "First arg", false);
|
||||
parser.add_positional_argument<std::string>("second", "Second arg", false);
|
||||
parser.add_positional_argument<std::string>("third", "Third arg", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto first = parser.get_optional<std::string>("first");
|
||||
auto second = parser.get_optional<std::string>("second");
|
||||
auto third = parser.get_optional<std::string>("third");
|
||||
|
||||
bool ok = first.has_value() && first.value() == "alpha" && second.has_value() && second.value() == "beta" &&
|
||||
third.has_value() && third.value() == "gamma";
|
||||
test_result("v1: multiple positionals preserve order", ok);
|
||||
}
|
||||
|
||||
void test_v1_positional_with_explicit_position() {
|
||||
argument_parser::fake_parser parser("test", {"first_val", "second_val"});
|
||||
parser.add_positional_argument<std::string>("second", "Second", false, 1);
|
||||
parser.add_positional_argument<std::string>("first", "First", false, 0);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto first = parser.get_optional<std::string>("first");
|
||||
auto second = parser.get_optional<std::string>("second");
|
||||
|
||||
bool ok = first.has_value() && first.value() == "first_val" && second.has_value() && second.value() == "second_val";
|
||||
test_result("v1: explicit position index", ok);
|
||||
}
|
||||
|
||||
void test_v1_positional_typed_int() {
|
||||
argument_parser::fake_parser parser("test", {"42"});
|
||||
parser.add_positional_argument<int>("count", "A count", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<int>("count");
|
||||
test_result("v1: positional with int type", val.has_value() && val.value() == 42);
|
||||
}
|
||||
|
||||
void test_v1_positional_with_action() {
|
||||
std::string captured;
|
||||
argument_parser::fake_parser parser("test", {"world"});
|
||||
|
||||
auto action =
|
||||
argument_parser::helpers::make_parametered_action<std::string>([&](std::string const &v) { captured = v; });
|
||||
parser.add_positional_argument<std::string>("name", "A name", action, false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
test_result("v1: positional with action", captured == "world");
|
||||
}
|
||||
|
||||
void test_v1_mixed_named_and_positional() {
|
||||
argument_parser::fake_parser parser("test", {"--verbose", "true", "myfile.txt"});
|
||||
parser.add_argument<bool>("v", "verbose", "Verbose mode", false);
|
||||
parser.add_positional_argument<std::string>("file", "Input file", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto verbose = parser.get_optional<bool>("verbose");
|
||||
auto file = parser.get_optional<std::string>("file");
|
||||
|
||||
bool ok = verbose.has_value() && verbose.value() == true && file.has_value() && file.value() == "myfile.txt";
|
||||
test_result("v1: mixed named and positional args", ok);
|
||||
}
|
||||
|
||||
void test_v1_positional_after_named() {
|
||||
argument_parser::fake_parser parser("test", {"-n", "5", "output.txt"});
|
||||
parser.add_argument<int>("n", "number", "A number", false);
|
||||
parser.add_positional_argument<std::string>("output", "Output file", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto number = parser.get_optional<int>("number");
|
||||
auto output = parser.get_optional<std::string>("output");
|
||||
|
||||
bool ok = number.has_value() && number.value() == 5 && output.has_value() && output.value() == "output.txt";
|
||||
test_result("v1: positional after named args", ok);
|
||||
}
|
||||
|
||||
void test_v1_positional_between_named() {
|
||||
argument_parser::fake_parser parser("test", {"-a", "1", "positional_val", "--beta", "2"});
|
||||
parser.add_argument<int>("a", "alpha", "Alpha", false);
|
||||
parser.add_argument<int>("b", "beta", "Beta", false);
|
||||
parser.add_positional_argument<std::string>("middle", "Middle arg", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto alpha = parser.get_optional<int>("alpha");
|
||||
auto beta = parser.get_optional<int>("beta");
|
||||
auto middle = parser.get_optional<std::string>("middle");
|
||||
|
||||
bool ok = alpha.has_value() && alpha.value() == 1 && beta.has_value() && beta.value() == 2 && middle.has_value() &&
|
||||
middle.value() == "positional_val";
|
||||
test_result("v1: positional between named args", ok);
|
||||
}
|
||||
|
||||
void test_v1_double_dash_separator() {
|
||||
argument_parser::fake_parser parser("test", {"--", "-not-a-flag"});
|
||||
parser.add_positional_argument<std::string>("item", "An item", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<std::string>("item");
|
||||
test_result("v1: -- separator treats next as positional", val.has_value() && val.value() == "-not-a-flag");
|
||||
}
|
||||
|
||||
void test_v1_double_dash_multiple() {
|
||||
argument_parser::fake_parser parser("test", {"--name", "hello", "--", "--weird", "-x"});
|
||||
parser.add_argument<std::string>("n", "name", "A name", false);
|
||||
parser.add_positional_argument<std::string>("first", "First", false);
|
||||
parser.add_positional_argument<std::string>("second", "Second", false);
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto name = parser.get_optional<std::string>("name");
|
||||
auto first = parser.get_optional<std::string>("first");
|
||||
auto second = parser.get_optional<std::string>("second");
|
||||
|
||||
bool ok = name.has_value() && name.value() == "hello" && first.has_value() && first.value() == "--weird" &&
|
||||
second.has_value() && second.value() == "-x";
|
||||
test_result("v1: -- separator with multiple positionals", ok);
|
||||
}
|
||||
|
||||
void test_v1_required_positional_missing() {
|
||||
argument_parser::fake_parser parser("test", {});
|
||||
parser.add_positional_argument<std::string>("file", "A file", true);
|
||||
|
||||
bool threw = false;
|
||||
try {
|
||||
// check_for_required_arguments calls std::exit(1) so we can't easily test it
|
||||
// instead, test that handle_arguments doesn't crash when positionals are provided
|
||||
parser.handle_arguments(conventions);
|
||||
} catch (...) {
|
||||
threw = true;
|
||||
}
|
||||
// Note: required check calls std::exit(1), so if we get here the arg wasn't required-checked
|
||||
// This test just verifies setup doesn't crash. The exit behavior is tested manually.
|
||||
test_result("v1: required positional setup (no crash)", true);
|
||||
}
|
||||
|
||||
void test_v1_unexpected_positional_throws() {
|
||||
argument_parser::fake_parser parser("test", {"unexpected"});
|
||||
// no positional args defined, but a bare token is provided
|
||||
|
||||
bool threw = false;
|
||||
try {
|
||||
parser.handle_arguments(conventions);
|
||||
} catch (const std::runtime_error &) {
|
||||
threw = true;
|
||||
}
|
||||
test_result("v1: unexpected positional throws", threw);
|
||||
}
|
||||
|
||||
void test_v1_duplicate_positional_name_throws() {
|
||||
argument_parser::fake_parser parser("test", {"a", "b"});
|
||||
parser.add_positional_argument<std::string>("file", "A file", false);
|
||||
|
||||
bool threw = false;
|
||||
try {
|
||||
parser.add_positional_argument<std::string>("file", "Duplicate", false);
|
||||
} catch (const std::runtime_error &) {
|
||||
threw = true;
|
||||
}
|
||||
test_result("v1: duplicate positional name throws", threw);
|
||||
}
|
||||
|
||||
void test_v1_positional_on_complete() {
|
||||
std::string captured_file;
|
||||
argument_parser::fake_parser parser("test", {"data.csv"});
|
||||
parser.add_positional_argument<std::string>("file", "Input file", false);
|
||||
parser.on_complete([&](argument_parser::base_parser const &p) {
|
||||
auto val = p.get_optional<std::string>("file");
|
||||
if (val)
|
||||
captured_file = val.value();
|
||||
});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
test_result("v1: positional accessible in on_complete", captured_file == "data.csv");
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// V2 Tests (using v2_test::fake_parser)
|
||||
// ============================================================
|
||||
|
||||
void test_v2_single_positional() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"hello"});
|
||||
|
||||
parser.add_argument<std::string>({{Positional, "greeting"}, {HelpText, "A greeting"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<std::string>("greeting");
|
||||
test_result("v2: single positional store", val.has_value() && val.value() == "hello");
|
||||
}
|
||||
|
||||
void test_v2_positional_required() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"value"});
|
||||
|
||||
parser.add_argument<std::string>({{Positional, "arg"}, {Required, true}, {HelpText, "Required arg"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<std::string>("arg");
|
||||
test_result("v2: required positional", val.has_value() && val.value() == "value");
|
||||
}
|
||||
|
||||
void test_v2_positional_with_position() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"first_val", "second_val"});
|
||||
|
||||
parser.add_argument<std::string>({{Positional, "second"}, {Position, 1}, {HelpText, "Second"}});
|
||||
parser.add_argument<std::string>({{Positional, "first"}, {Position, 0}, {HelpText, "First"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto first = parser.get_optional<std::string>("first");
|
||||
auto second = parser.get_optional<std::string>("second");
|
||||
|
||||
bool ok = first.has_value() && first.value() == "first_val" && second.has_value() && second.value() == "second_val";
|
||||
test_result("v2: positional with explicit Position", ok);
|
||||
}
|
||||
|
||||
void test_v2_positional_typed_int() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"99"});
|
||||
|
||||
parser.add_argument<int>({{Positional, "count"}, {HelpText, "A count"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<int>("count");
|
||||
test_result("v2: positional with int type", val.has_value() && val.value() == 99);
|
||||
}
|
||||
|
||||
void test_v2_mixed_named_and_positional() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"--output", "out.txt", "input.txt"});
|
||||
|
||||
parser.add_argument<std::string>({{ShortArgument, "o"}, {LongArgument, "output"}, {HelpText, "Output file"}});
|
||||
parser.add_argument<std::string>({{Positional, "input"}, {HelpText, "Input file"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto output = parser.get_optional<std::string>("output");
|
||||
auto input = parser.get_optional<std::string>("input");
|
||||
|
||||
bool ok = output.has_value() && output.value() == "out.txt" && input.has_value() && input.value() == "input.txt";
|
||||
test_result("v2: mixed named and positional", ok);
|
||||
}
|
||||
|
||||
void test_v2_positional_with_action() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
std::string captured;
|
||||
v2_test::fake_parser parser("test", {"world"});
|
||||
|
||||
parser.add_argument<std::string>({{Positional, "name"},
|
||||
{Action, argument_parser::helpers::make_parametered_action<std::string>(
|
||||
[&](std::string const &v) { captured = v; })},
|
||||
{HelpText, "A name"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
test_result("v2: positional with action", captured == "world");
|
||||
}
|
||||
|
||||
void test_v2_double_dash_separator() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"--", "--not-a-flag"});
|
||||
|
||||
parser.add_argument<std::string>({{Positional, "item"}, {HelpText, "An item"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<std::string>("item");
|
||||
test_result("v2: -- separator", val.has_value() && val.value() == "--not-a-flag");
|
||||
}
|
||||
|
||||
void test_v2_positional_auto_help_text() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"42"});
|
||||
|
||||
// no HelpText provided — should auto-generate from traits
|
||||
parser.add_argument<int>({{Positional, "count"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto val = parser.get_optional<int>("count");
|
||||
test_result("v2: positional auto help text (no crash)", val.has_value() && val.value() == 42);
|
||||
}
|
||||
|
||||
void test_v2_multiple_positionals_and_named() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
v2_test::fake_parser parser("test", {"-v", "src.txt", "dst.txt"});
|
||||
|
||||
parser.add_argument({{ShortArgument, "v"}, {LongArgument, "verbose"}});
|
||||
parser.add_argument<std::string>({{Positional, "source"}, {HelpText, "Source"}});
|
||||
parser.add_argument<std::string>({{Positional, "destination"}, {HelpText, "Destination"}});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
auto verbose = parser.get_optional<bool>("verbose");
|
||||
auto source = parser.get_optional<std::string>("source");
|
||||
auto dest = parser.get_optional<std::string>("destination");
|
||||
|
||||
bool ok = verbose.has_value() && source.has_value() && source.value() == "src.txt" && dest.has_value() &&
|
||||
dest.value() == "dst.txt";
|
||||
test_result("v2: multiple positionals with named flag", ok);
|
||||
}
|
||||
|
||||
void test_v2_on_complete_with_positional() {
|
||||
using namespace argument_parser::v2::flags;
|
||||
std::string captured;
|
||||
v2_test::fake_parser parser("test", {"payload"});
|
||||
|
||||
parser.add_argument<std::string>({{Positional, "data"}, {HelpText, "Data"}});
|
||||
parser.on_complete([&](argument_parser::base_parser const &p) {
|
||||
auto val = p.get_optional<std::string>("data");
|
||||
if (val)
|
||||
captured = val.value();
|
||||
});
|
||||
parser.handle_arguments(conventions);
|
||||
|
||||
test_result("v2: positional accessible in on_complete", captured == "payload");
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Main
|
||||
// ============================================================
|
||||
|
||||
int main() {
|
||||
std::cout << "=== V1 Positional Argument Tests ===" << std::endl;
|
||||
|
||||
std::array<std::function<void()>, 13> v1Tests {
|
||||
test_v1_single_positional_store,
|
||||
test_v1_multiple_positionals_ordered,
|
||||
test_v1_positional_with_explicit_position,
|
||||
test_v1_positional_typed_int,
|
||||
test_v1_positional_with_action,
|
||||
test_v1_mixed_named_and_positional,
|
||||
test_v1_positional_after_named,
|
||||
test_v1_positional_between_named,
|
||||
test_v1_double_dash_separator,
|
||||
test_v1_double_dash_multiple,
|
||||
test_v1_unexpected_positional_throws,
|
||||
test_v1_duplicate_positional_name_throws,
|
||||
test_v1_positional_on_complete
|
||||
};
|
||||
|
||||
for (auto const& test : v1Tests) {
|
||||
try {
|
||||
test();
|
||||
} catch(std::exception const& e) {
|
||||
std::cout << "test failed: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n=== V2 Positional Argument Tests ===" << std::endl;
|
||||
std::array<std::function<void()>, 10> v2Tests{
|
||||
test_v2_single_positional,
|
||||
test_v2_positional_required,
|
||||
test_v2_positional_with_position,
|
||||
test_v2_positional_typed_int,
|
||||
test_v2_mixed_named_and_positional,
|
||||
test_v2_positional_with_action,
|
||||
test_v2_double_dash_separator,
|
||||
test_v2_positional_auto_help_text,
|
||||
test_v2_multiple_positionals_and_named,
|
||||
test_v2_on_complete_with_positional
|
||||
};
|
||||
|
||||
|
||||
for (auto const& test : v2Tests) {
|
||||
try {
|
||||
test();
|
||||
} catch(std::exception const& e) {
|
||||
std::cout << "test failed: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n=== Results: " << tests_passed << "/" << tests_run << " passed ===" << std::endl;
|
||||
return (tests_passed == tests_run) ? 0 : 1;
|
||||
}
|
||||
Reference in New Issue
Block a user