Initial commit for ArgParser
This commit is contained in:
+334
@@ -0,0 +1,334 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignArrayOfStructures: None
|
||||||
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: true
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveShortCaseStatements:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCaseArrows: false
|
||||||
|
AlignCaseColons: false
|
||||||
|
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveTableGenCondOperatorColons:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignConsecutiveTableGenDefinitionColons:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
AlignFunctionDeclarations: false
|
||||||
|
AlignFunctionPointers: false
|
||||||
|
PadOperators: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments:
|
||||||
|
Kind: Always
|
||||||
|
OverEmptyLines: 0
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowBreakBeforeNoexceptSpecifier: Never
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortCaseExpressionOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortCompoundRequirementOnASingleLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AllowShortNamespacesOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AttributeMacros:
|
||||||
|
- __capability
|
||||||
|
- absl_nonnull
|
||||||
|
- absl_nullable
|
||||||
|
- absl_nullability_unknown
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackLongBracedList: true
|
||||||
|
BinPackParameters: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BracedInitializerIndentWidth: -1
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakAdjacentStringLiterals: true
|
||||||
|
BreakAfterAttributes: Leave
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakAfterReturnType: None
|
||||||
|
BreakArrays: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeConceptDeclarations: Always
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
BreakBeforeInlineASMColon: OnlyMultiline
|
||||||
|
BreakBeforeTemplateCloser: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakBinaryOperations: Never
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakFunctionDefinitionParameters: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakStringLiterals: true
|
||||||
|
BreakTemplateDeclarations: Yes
|
||||||
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerIndentWidth: 2
|
||||||
|
ContinuationIndentWidth: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
EmptyLineAfterAccessModifier: Never
|
||||||
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
|
EnumTrailingComma: Leave
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: false
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IfMacros:
|
||||||
|
- KJ_IF_MAYBE
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<ext/.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentExportBlock: true
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
|
IndentGotoLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentRequiresClause: true
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertBraces: false
|
||||||
|
InsertNewlineAtEOF: false
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
IntegerLiteralSeparator:
|
||||||
|
Binary: 0
|
||||||
|
BinaryMinDigits: 0
|
||||||
|
Decimal: 0
|
||||||
|
DecimalMinDigits: 0
|
||||||
|
Hex: 0
|
||||||
|
HexMinDigits: 0
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLines:
|
||||||
|
AtEndOfFile: false
|
||||||
|
AtStartOfBlock: false
|
||||||
|
AtStartOfFile: true
|
||||||
|
KeepFormFeed: false
|
||||||
|
LambdaBodyIndentation: Signature
|
||||||
|
LineEnding: DeriveLF
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MainIncludeChar: Quote
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: All
|
||||||
|
ObjCBinPackProtocolList: Never
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
OneLineFormatOffRegex: ''
|
||||||
|
PackConstructorInitializers: Never
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakBeforeMemberAccess: 150
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakOpenParenthesis: 0
|
||||||
|
PenaltyBreakScopeResolution: 500
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Left
|
||||||
|
PPIndentWidth: -1
|
||||||
|
QualifierAlignment: Leave
|
||||||
|
RawStringFormats:
|
||||||
|
- Language: Cpp
|
||||||
|
Delimiters:
|
||||||
|
- cc
|
||||||
|
- CC
|
||||||
|
- cpp
|
||||||
|
- Cpp
|
||||||
|
- CPP
|
||||||
|
- 'c++'
|
||||||
|
- 'C++'
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
- Language: TextProto
|
||||||
|
Delimiters:
|
||||||
|
- pb
|
||||||
|
- PB
|
||||||
|
- proto
|
||||||
|
- PROTO
|
||||||
|
EnclosingFunctions:
|
||||||
|
- EqualsProto
|
||||||
|
- EquivToProto
|
||||||
|
- PARSE_PARTIAL_TEXT_PROTO
|
||||||
|
- PARSE_TEST_PROTO
|
||||||
|
- PARSE_TEXT_PROTO
|
||||||
|
- ParseTextOrDie
|
||||||
|
- ParseTextProtoOrDie
|
||||||
|
- ParseTestProto
|
||||||
|
- ParsePartialTestProto
|
||||||
|
CanonicalDelimiter: pb
|
||||||
|
BasedOnStyle: google
|
||||||
|
ReferenceAlignment: Pointer
|
||||||
|
ReflowComments: Always
|
||||||
|
RemoveBracesLLVM: false
|
||||||
|
RemoveEmptyLinesInUnwrappedLines: false
|
||||||
|
RemoveParentheses: Leave
|
||||||
|
RemoveSemicolon: false
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
|
RequiresExpressionIndentation: OuterScope
|
||||||
|
SeparateDefinitionBlocks: Always
|
||||||
|
ShortNamespaceLines: 1
|
||||||
|
SkipMacroDefinitionBody: false
|
||||||
|
SortIncludes:
|
||||||
|
Enabled: true
|
||||||
|
IgnoreCase: false
|
||||||
|
SortJavaStaticImport: Before
|
||||||
|
SortUsingDeclarations: LexicographicNumeric
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterOperatorKeyword: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeJsonColon: false
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterForeachMacros: true
|
||||||
|
AfterFunctionDefinitionName: false
|
||||||
|
AfterFunctionDeclarationName: false
|
||||||
|
AfterIfMacros: true
|
||||||
|
AfterNot: false
|
||||||
|
AfterOverloadedOperator: false
|
||||||
|
AfterPlacementOperator: true
|
||||||
|
AfterRequiresInClause: false
|
||||||
|
AfterRequiresInExpression: false
|
||||||
|
BeforeNonEmptyParentheses: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: Never
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInLineCommentPrefix:
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParens: Never
|
||||||
|
SpacesInParensOptions:
|
||||||
|
ExceptDoubleParentheses: false
|
||||||
|
InCStyleCasts: false
|
||||||
|
InConditionalStatements: false
|
||||||
|
InEmptyParentheses: false
|
||||||
|
Other: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
StatementAttributeLikeMacros:
|
||||||
|
- Q_EMIT
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TableGenBreakInsideDAGArg: DontBreak
|
||||||
|
TabWidth: 2
|
||||||
|
UseTab: Never
|
||||||
|
VerilogBreakBetweenInstancePorts: true
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
- CF_SWIFT_NAME
|
||||||
|
- NS_SWIFT_NAME
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- STRINGIZE
|
||||||
|
WrapNamespaceBodyWithEmptyLines: Leave
|
||||||
|
...
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
bin/
|
||||||
|
compile_flags.txt
|
||||||
|
Makefile
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Tim Håkansson
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
<makegen>
|
||||||
|
<configuration name="Test">
|
||||||
|
<generatehfile>false</generatehfile>
|
||||||
|
<outputdir>bin/Test/</outputdir>
|
||||||
|
<outputname>arg_parser</outputname>
|
||||||
|
<outputtype>executable</outputtype>
|
||||||
|
<projectname>ArgParser</projectname>
|
||||||
|
<srcdir>src/</srcdir>
|
||||||
|
</configuration>
|
||||||
|
<configuration name="Release">
|
||||||
|
<generatehfile>false</generatehfile>
|
||||||
|
<outputdir>bin/Release</outputdir>
|
||||||
|
<outputname>libarg_parser.so</outputname>
|
||||||
|
<outputtype>sharedlibrary</outputtype>
|
||||||
|
<sourceexclude>main.cpp</sourceexclude>
|
||||||
|
<projectname>ArgParser</projectname>
|
||||||
|
<srcdir>src/</srcdir>
|
||||||
|
</configuration>
|
||||||
|
<configuration name="Debug">
|
||||||
|
<cflag>-g3</cflag>
|
||||||
|
<cflag>-w</cflag>
|
||||||
|
<define>_DEBUG</define>
|
||||||
|
<generatehfile>false</generatehfile>
|
||||||
|
<outputdir>bin/Debug/</outputdir>
|
||||||
|
<outputname>arg_parser</outputname>
|
||||||
|
<outputtype>executable</outputtype>
|
||||||
|
<projectname>ArgParser</projectname>
|
||||||
|
<srcdir>src/</srcdir>
|
||||||
|
</configuration>
|
||||||
|
<target>Release</target>
|
||||||
|
<version>v1.3.8</version>
|
||||||
|
</makegen>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#include "ActionArg.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
ActionArg::ActionArg(const std::string& argument, const std::string& helpText, std::function<void()> action)
|
||||||
|
: Arg{argument, helpText, false, true},
|
||||||
|
action{action}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ActionArg::PartialMatch(const std::string& arg) const
|
||||||
|
{
|
||||||
|
for (const auto& argument : arguments)
|
||||||
|
{
|
||||||
|
if (argument == arg)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ActionArg::Parse(const std::vector<std::string>& arguments, size_t& index)
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ActionArg::GetHelpArgument(bool onlyFirst) const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
if (onlyFirst)
|
||||||
|
{
|
||||||
|
if (required)
|
||||||
|
{
|
||||||
|
ss << arguments.front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << "[" << arguments.front() << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << arguments.front();
|
||||||
|
for (int i = 1; i < arguments.size(); i++)
|
||||||
|
{
|
||||||
|
ss << ", " << arguments[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "Arg.h"
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
struct ActionArg : public Arg
|
||||||
|
{
|
||||||
|
std::function<void()> action;
|
||||||
|
|
||||||
|
ActionArg(const std::string& argument, const std::string& helpText, std::function<void()> action);
|
||||||
|
|
||||||
|
bool PartialMatch(const std::string& arg) const override;
|
||||||
|
bool Parse(const std::vector<std::string>& arguments, size_t& index) override;
|
||||||
|
std::string GetHelpArgument(bool onlyFirst) const override;
|
||||||
|
};
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
#include "Arg.h"
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
Arg::Arg(const std::string& argument, const std::string& helpText, bool required, bool overridesMandatory)
|
||||||
|
: helpText{helpText},
|
||||||
|
required{required},
|
||||||
|
overridesMandatory{overridesMandatory}
|
||||||
|
{
|
||||||
|
size_t lastPos = 0;
|
||||||
|
size_t pos = argument.find(',');
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
arguments.emplace_back(argument.substr(lastPos, (pos - lastPos)));
|
||||||
|
lastPos = pos + 1;
|
||||||
|
pos = argument.find(',', lastPos);
|
||||||
|
}
|
||||||
|
arguments.emplace_back(argument.substr(lastPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Arg::Match(const std::string& arg) const
|
||||||
|
{
|
||||||
|
for (const auto& argument : arguments)
|
||||||
|
{
|
||||||
|
if (argument == arg)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MatchAdditional(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Arg::PartialMatch(const std::string& arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Arg::MatchAdditional(const std::string& arg) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
struct Arg
|
||||||
|
{
|
||||||
|
std::vector<std::string> arguments;
|
||||||
|
std::string helpText;
|
||||||
|
bool required;
|
||||||
|
bool overridesMandatory;
|
||||||
|
bool wasSpecified{false};
|
||||||
|
|
||||||
|
Arg(const std::string& argument, const std::string& helpText, bool required, bool overridesMandatory);
|
||||||
|
|
||||||
|
bool Match(const std::string& arg) const;
|
||||||
|
virtual bool PartialMatch(const std::string& arg) const;
|
||||||
|
|
||||||
|
virtual bool MatchAdditional(const std::string& arg) const;
|
||||||
|
|
||||||
|
virtual bool Parse(const std::vector<std::string>& arguments, size_t& index) = 0;
|
||||||
|
virtual std::string GetHelpArgument(bool onlyFirst) const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
#include "ArgParser.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "ActionArg.h"
|
||||||
|
#include "FlagArg.h"
|
||||||
|
|
||||||
|
const int HELP_WIDTH = 25;
|
||||||
|
const int MAX_WIDTH = 80;
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
ArgParser::ArgParser(const std::string& commandName,
|
||||||
|
const std::string& description,
|
||||||
|
const std::string& additionalHelp,
|
||||||
|
const std::vector<std::string>& arguments)
|
||||||
|
: commandName{commandName},
|
||||||
|
description{description},
|
||||||
|
additionalHelp{additionalHelp},
|
||||||
|
argumentStrings{arguments}
|
||||||
|
{
|
||||||
|
AddAction("--help,-h", "Displays this information", [&]() { PrintHelp(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgParser::ArgParser(const std::string& commandName,
|
||||||
|
const std::string& description,
|
||||||
|
const std::string& additionalHelp,
|
||||||
|
int argc,
|
||||||
|
char** argv)
|
||||||
|
: commandName{commandName},
|
||||||
|
description{description},
|
||||||
|
additionalHelp{additionalHelp}
|
||||||
|
{
|
||||||
|
AddAction("--help,-h", "Displays this information", [&]() { PrintHelp(); });
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
argumentStrings.emplace_back(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::AddAction(const std::string& arg, const std::string& helpText, std::function<void()> action)
|
||||||
|
{
|
||||||
|
args.emplace_back(std::make_shared<ActionArg>(arg, helpText, action));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::AddFlag(const std::string& arg, bool& flag, const std::string& helpText)
|
||||||
|
{
|
||||||
|
args.emplace_back(std::make_shared<FlagArg>(flag, arg, helpText));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::PrintHelp() const
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
size_t offset = 0;
|
||||||
|
Utils::PrintMaxWidthSplit(description, pos, offset, MAX_WIDTH, " ");
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Usage: " << std::endl;
|
||||||
|
PrintCommandHelp(false);
|
||||||
|
PrintCommandHelp(true);
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Options: " << std::endl;
|
||||||
|
|
||||||
|
size_t width = 0;
|
||||||
|
for (auto& arg : args)
|
||||||
|
{
|
||||||
|
std::string helpArg = arg->GetHelpArgument(false);
|
||||||
|
if (helpArg.size() + 4 < HELP_WIDTH)
|
||||||
|
width = std::max(width, helpArg.size());
|
||||||
|
}
|
||||||
|
width = std::min(size_t(HELP_WIDTH), width + 4);
|
||||||
|
|
||||||
|
for (const auto& arg : args)
|
||||||
|
{
|
||||||
|
PrintArgHelp(*arg, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
pos = 0;
|
||||||
|
offset = 0;
|
||||||
|
Utils::PrintMaxWidthSplit(additionalHelp, pos, offset, MAX_WIDTH, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::PrintError() const
|
||||||
|
{
|
||||||
|
std::cout << "Use --help for more info" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArgParser::Parse()
|
||||||
|
{
|
||||||
|
bool anyOverridesMandatory = false;
|
||||||
|
for (size_t i = 0; i < argumentStrings.size(); i++)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(args.begin(),
|
||||||
|
args.end(),
|
||||||
|
[&](const std::shared_ptr<Arg>& arg)
|
||||||
|
{ return arg->overridesMandatory && arg->Match(argumentStrings[i]); });
|
||||||
|
if (it != args.end())
|
||||||
|
{
|
||||||
|
(*it)->Parse(argumentStrings, i);
|
||||||
|
anyOverridesMandatory = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyOverridesMandatory)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < argumentStrings.size(); i++)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(
|
||||||
|
args.begin(), args.end(), [&](const std::shared_ptr<Arg>& arg) { return arg->Match(argumentStrings[i]); });
|
||||||
|
if (it != args.end())
|
||||||
|
{
|
||||||
|
if (!(*it)->Parse(argumentStrings, i))
|
||||||
|
{
|
||||||
|
PrintError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utils::IsMultiFlag(argumentStrings[i]))
|
||||||
|
{
|
||||||
|
std::vector<std::vector<std::shared_ptr<Arg>>::iterator> iterators;
|
||||||
|
for (size_t j = 1; j < argumentStrings[i].size(); j++)
|
||||||
|
{
|
||||||
|
std::string flag = std::string("-") + argumentStrings[i][j];
|
||||||
|
auto it =
|
||||||
|
std::find_if(args.begin(), args.end(), [&](const std::shared_ptr<Arg>& arg) { return arg->Match(flag); });
|
||||||
|
if (it == args.end())
|
||||||
|
{
|
||||||
|
std::cout << "Unknown flag: \"" << flag << "\" in \"" << argumentStrings[i] << "\"" << std::endl
|
||||||
|
<< std::endl
|
||||||
|
<< std::endl;
|
||||||
|
PrintError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iterators.emplace_back(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it : iterators)
|
||||||
|
{
|
||||||
|
if (!(*it)->Parse(argumentStrings, i))
|
||||||
|
{
|
||||||
|
PrintError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((*it)->overridesMandatory)
|
||||||
|
{
|
||||||
|
anyOverridesMandatory = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Unknown argment: \"" << argumentStrings[i] << "\"" << std::endl << std::endl;
|
||||||
|
PrintError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyOverridesMandatory)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& arg : args)
|
||||||
|
{
|
||||||
|
if (arg->required && !arg->wasSpecified)
|
||||||
|
{
|
||||||
|
std::cout << "Mandatory argument not specified: " << arg->arguments.front() << std::endl << std::endl;
|
||||||
|
PrintError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::PrintCommandHelp(bool actions) const
|
||||||
|
{
|
||||||
|
std::cout << " " << commandName;
|
||||||
|
size_t offset = 4;
|
||||||
|
if (commandName.size() - 3 > HELP_WIDTH)
|
||||||
|
std::cout << std::endl << " ";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " ";
|
||||||
|
offset = commandName.size() + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pos = offset;
|
||||||
|
PrintCommandArgsHelp(pos, offset, actions, true);
|
||||||
|
PrintCommandArgsHelp(pos, offset, actions, false);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::PrintCommandArgsHelp(size_t& pos, size_t offset, bool actions, bool required) const
|
||||||
|
{
|
||||||
|
for (auto& arg : args)
|
||||||
|
{
|
||||||
|
if (arg->overridesMandatory == actions && arg->required == required)
|
||||||
|
{
|
||||||
|
Utils::PrintMaxWidth(arg->GetHelpArgument(true), pos, offset, MAX_WIDTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgParser::PrintArgHelp(const Arg& arg, size_t offset) const
|
||||||
|
{
|
||||||
|
std::string helpArg = arg.GetHelpArgument(false);
|
||||||
|
if (helpArg.size() + 4 >= HELP_WIDTH)
|
||||||
|
{
|
||||||
|
std::cout << " " << helpArg << std::endl;
|
||||||
|
std::cout << std::setw(offset) << "";
|
||||||
|
size_t pos = offset;
|
||||||
|
Utils::PrintMaxWidthSplit(arg.helpText, pos, offset, MAX_WIDTH, " ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " " << std::setw(offset - 2) << std::left << helpArg;
|
||||||
|
size_t pos = offset;
|
||||||
|
Utils::PrintMaxWidthSplit(arg.helpText, pos, offset, MAX_WIDTH, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Arg.h"
|
||||||
|
#include "ValueArg.h"
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
struct ArgParser
|
||||||
|
{
|
||||||
|
std::string commandName;
|
||||||
|
std::string description;
|
||||||
|
std::string additionalHelp;
|
||||||
|
std::vector<std::string> argumentStrings;
|
||||||
|
std::vector<std::shared_ptr<Arg>> args;
|
||||||
|
|
||||||
|
ArgParser(const std::string& commandName,
|
||||||
|
const std::string& description,
|
||||||
|
const std::string& additionalHelp,
|
||||||
|
const std::vector<std::string>& arguments);
|
||||||
|
|
||||||
|
ArgParser(const std::string& commandName,
|
||||||
|
const std::string& description,
|
||||||
|
const std::string& additionalHelp,
|
||||||
|
int argc,
|
||||||
|
char** argv);
|
||||||
|
|
||||||
|
void AddAction(const std::string& arg, const std::string& helpText, std::function<void()> action);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Add(const std::string& arg, T& value, const std::string& helpText)
|
||||||
|
{
|
||||||
|
args.emplace_back(std::make_shared<ValueArg<T>>(value, arg, helpText, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Add(const std::string& arg, T& value, const std::string& helpText, const T& defaultValue)
|
||||||
|
{
|
||||||
|
value = defaultValue;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << helpText << " (default=" << defaultValue << ")";
|
||||||
|
args.emplace_back(std::make_shared<ValueArg<T>>(value, arg, ss.str(), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void AddOptional(const std::string& arg, std::optional<T>& value, const std::string& helpText)
|
||||||
|
{
|
||||||
|
value = std::nullopt;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << helpText << " (default=null)";
|
||||||
|
args.emplace_back(std::make_shared<ValueArg<std::optional<T>>>(value, arg, ss.str(), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddFlag(const std::string& arg, bool& flag, const std::string& helpText);
|
||||||
|
|
||||||
|
bool Parse();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PrintCommandHelp(bool actions) const;
|
||||||
|
void PrintCommandArgsHelp(size_t& pos, size_t offset, bool actions, bool required) const;
|
||||||
|
void PrintArgHelp(const Arg& arg, size_t offset) const;
|
||||||
|
void PrintHelp() const;
|
||||||
|
void PrintError() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include "FlagArg.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
FlagArg::FlagArg(bool& flag, const std::string& argument, const std::string& helpText)
|
||||||
|
: Arg{argument, helpText, false, false},
|
||||||
|
flag{flag}
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlagArg::PartialMatch(const std::string& arg) const
|
||||||
|
{
|
||||||
|
for (const auto& argument : arguments)
|
||||||
|
{
|
||||||
|
if (argument == arg)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlagArg::Parse(const std::vector<std::string>& arguments, size_t& index)
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FlagArg::GetHelpArgument(bool onlyFirst) const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
if (onlyFirst)
|
||||||
|
{
|
||||||
|
if (required)
|
||||||
|
{
|
||||||
|
ss << arguments.front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << "[" << arguments.front() << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << arguments.front();
|
||||||
|
for (int i = 1; i < arguments.size(); i++)
|
||||||
|
{
|
||||||
|
ss << ", " << arguments[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Arg.h"
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
struct FlagArg : public Arg
|
||||||
|
{
|
||||||
|
bool& flag;
|
||||||
|
|
||||||
|
FlagArg(bool& flag, const std::string& argument, const std::string& helpText);
|
||||||
|
|
||||||
|
bool PartialMatch(const std::string& arg) const override;
|
||||||
|
bool Parse(const std::vector<std::string>& arguments, size_t& index) override;
|
||||||
|
std::string GetHelpArgument(bool onlyFirst) const override;
|
||||||
|
};
|
||||||
|
}
|
||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
std::pair<bool, int> ParseValue<int>(const std::string_view& str)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
size_t index = 0;
|
||||||
|
int i = std::stoi(std::string(str), &index);
|
||||||
|
|
||||||
|
if (index != str.size())
|
||||||
|
return {false, 0};
|
||||||
|
|
||||||
|
return {true, i};
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {false, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, float> ParseValue<float>(const std::string_view& str)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
size_t index = 0;
|
||||||
|
float f = std::stof(std::string(str), &index);
|
||||||
|
|
||||||
|
if (index != str.size())
|
||||||
|
return {false, 0};
|
||||||
|
|
||||||
|
return {true, f};
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {false, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, std::string> ParseValue<std::string>(const std::string_view& str)
|
||||||
|
{
|
||||||
|
return {true, std::string(str)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, bool> ParseValue<bool>(const std::string_view& str)
|
||||||
|
{
|
||||||
|
if (Utils::CaseInsensitiveEqual(str, "true") || Utils::CaseInsensitiveEqual(str, "yes") || str == "y" || str == "Y")
|
||||||
|
{
|
||||||
|
return {true, true};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utils::CaseInsensitiveEqual(str, "false") || Utils::CaseInsensitiveEqual(str, "no") || str == "n" || str == "N")
|
||||||
|
{
|
||||||
|
return {true, false};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {false, false};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<bool>()
|
||||||
|
{
|
||||||
|
return "<boolean>";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<int>()
|
||||||
|
{
|
||||||
|
return "<int>";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<float>()
|
||||||
|
{
|
||||||
|
return "<float>";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<std::string>()
|
||||||
|
{
|
||||||
|
return "<string>";
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
bool CaseInsensitiveEqual(const std::string_view& sv, const std::string& str)
|
||||||
|
{
|
||||||
|
if (sv.size() != str.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sv.size(); i++)
|
||||||
|
{
|
||||||
|
if (std::tolower(sv[i]) != str[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintMaxWidth(
|
||||||
|
const std::vector<std::string>& strings, size_t pos, size_t offset, size_t maxWidth, const std::string& delim)
|
||||||
|
{
|
||||||
|
if (strings.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto& string : strings)
|
||||||
|
{
|
||||||
|
PrintMaxWidth(strings.front(), pos, offset, maxWidth);
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintMaxWidthSplit(
|
||||||
|
const std::string& str, size_t pos, size_t offset, size_t maxWidth, const std::string& delim)
|
||||||
|
{
|
||||||
|
size_t lastPos = 0;
|
||||||
|
size_t strPos = str.find(delim);
|
||||||
|
while (strPos != std::string::npos)
|
||||||
|
{
|
||||||
|
PrintMaxWidth(std::string_view(str.c_str() + lastPos, strPos - lastPos), pos, offset, maxWidth);
|
||||||
|
lastPos = strPos + 1;
|
||||||
|
strPos = str.find(' ', lastPos);
|
||||||
|
}
|
||||||
|
PrintMaxWidth(std::string_view(str.c_str() + lastPos, str.size() - lastPos), pos, offset, maxWidth);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintMaxWidth(const std::string_view& view, size_t& pos, size_t offset, size_t maxWidth)
|
||||||
|
{
|
||||||
|
if (pos + view.size() > maxWidth && pos != offset)
|
||||||
|
{
|
||||||
|
std::cout << std::endl << std::setw(offset) << "";
|
||||||
|
pos = offset;
|
||||||
|
}
|
||||||
|
size_t lastPos = 0;
|
||||||
|
size_t newline = view.find('\n');
|
||||||
|
while (newline != std::string::npos)
|
||||||
|
{
|
||||||
|
std::cout << view.substr(lastPos, newline - lastPos) << std::endl << std::setw(offset) << "";
|
||||||
|
pos = offset;
|
||||||
|
lastPos = newline + 1;
|
||||||
|
newline = view.find('\n', lastPos);
|
||||||
|
}
|
||||||
|
std::cout << view.substr(lastPos);
|
||||||
|
if (pos + view.size() != maxWidth)
|
||||||
|
std::cout << " ";
|
||||||
|
pos += view.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsMultiFlag(const std::string& arg)
|
||||||
|
{
|
||||||
|
if (arg[0] != '-')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto i = 1; i < arg.size(); i++)
|
||||||
|
{
|
||||||
|
if (!(arg[i] >= 'a' && arg[i] <= 'z') && !(arg[i] >= 'A' && arg[i] <= 'Z') && !(arg[i] >= '0' && arg[i] <= '9'))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
struct dependent_false
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
value = false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_optional : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_optional<std::optional<T>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::string GetTypeHelpName()
|
||||||
|
{
|
||||||
|
static_assert(dependent_false<T>::value, "No GetTypeHelpName function created for type T");
|
||||||
|
return {false, T{}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::pair<bool, T> ParseValue(const std::string_view& str)
|
||||||
|
{
|
||||||
|
static_assert(dependent_false<T>::value, "No ParseValue function created for type T");
|
||||||
|
return {false, T{}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, int> ParseValue<int>(const std::string_view& str);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, float> ParseValue<float>(const std::string_view& str);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, std::string> ParseValue<std::string>(const std::string_view& str);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<bool, bool> ParseValue<bool>(const std::string_view& str);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<bool>();
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<int>();
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<float>();
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::string GetTypeHelpName<std::string>();
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
bool CaseInsensitiveEqual(const std::string_view& sv, const std::string& str);
|
||||||
|
void PrintMaxWidth(
|
||||||
|
const std::vector<std::string>& strings, size_t pos, size_t offset, size_t maxWidth, const std::string& delim);
|
||||||
|
void PrintMaxWidthSplit(
|
||||||
|
const std::string& view, size_t pos, size_t offset, size_t maxWidth, const std::string& delim);
|
||||||
|
void PrintMaxWidth(const std::string_view& view, size_t& pos, size_t offset, size_t maxWidth);
|
||||||
|
|
||||||
|
bool IsMultiFlag(const std::string& arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Arg.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
namespace ap
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
struct ValueArg : public Arg
|
||||||
|
{
|
||||||
|
T& value;
|
||||||
|
|
||||||
|
ValueArg(T& value, const std::string& argument, const std::string& helpText, bool required)
|
||||||
|
: Arg{argument, helpText, required, false},
|
||||||
|
value{value}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchAdditional(const std::string& arg) const override
|
||||||
|
{
|
||||||
|
size_t pos = arg.find('=');
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const auto& argument : arguments)
|
||||||
|
{
|
||||||
|
if (std::string_view(arg.c_str(), pos) == argument)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parse(const std::vector<std::string>& arguments, size_t& index) override
|
||||||
|
{
|
||||||
|
wasSpecified = true;
|
||||||
|
|
||||||
|
size_t pos = arguments[index].find('=');
|
||||||
|
std::string valStr;
|
||||||
|
std::string argStr;
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
argStr = arguments[index];
|
||||||
|
if (arguments.size() <= index + 1)
|
||||||
|
{
|
||||||
|
std::cout << "No argument specified for " << arguments[index] << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
|
||||||
|
valStr = arguments[index];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argStr = arguments[index].substr(0, pos);
|
||||||
|
valStr = arguments[index].substr(pos + 1, arguments[index].size() - pos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, T> res;
|
||||||
|
if constexpr (is_optional<T>::value)
|
||||||
|
{
|
||||||
|
res = ParseValue<typename T::value_type>(valStr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = ParseValue<T>(valStr);
|
||||||
|
}
|
||||||
|
const auto& [result, val] = res;
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
std::cout << "Could not parse value for argument=\"" << argStr << "\"" << " value=\"" << valStr << "\""
|
||||||
|
<< std::endl
|
||||||
|
<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = val;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetHelpArgument(bool onlyFirst) const override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
if (!onlyFirst)
|
||||||
|
{
|
||||||
|
ss << arguments.front();
|
||||||
|
for (int i = 1; i < arguments.size(); i++)
|
||||||
|
{
|
||||||
|
ss << ", " << arguments[i];
|
||||||
|
}
|
||||||
|
OutputTypeHelpName(ss);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!required)
|
||||||
|
ss << "[";
|
||||||
|
|
||||||
|
ss << arguments.front();
|
||||||
|
OutputTypeHelpName(ss);
|
||||||
|
|
||||||
|
if (!required)
|
||||||
|
ss << "]";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OutputTypeHelpName(std::ostream& os) const
|
||||||
|
{
|
||||||
|
if constexpr (is_optional<T>::value)
|
||||||
|
{
|
||||||
|
os << " " << GetTypeHelpName<typename T::value_type>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << " " << GetTypeHelpName<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "ArgParser.h"
|
||||||
|
|
||||||
|
void PrintVersion()
|
||||||
|
{
|
||||||
|
std::cout << "command v1.2.3" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
ap::ArgParser parser(
|
||||||
|
"makegen",
|
||||||
|
"MakeGen is a utility tool to generate and run Makefiles in a simple manner. By default it "
|
||||||
|
"always compiles code with parallel jobs",
|
||||||
|
"If no option is given it will run \"make all\"\n\nIf multiple make options are given it will "
|
||||||
|
"run in the following order:\nclean all install run, rebuild will be translated to \"clean all\"",
|
||||||
|
argc - 1,
|
||||||
|
argv + 1);
|
||||||
|
|
||||||
|
struct Args
|
||||||
|
{
|
||||||
|
bool make;
|
||||||
|
bool install;
|
||||||
|
bool clean;
|
||||||
|
bool rebuild;
|
||||||
|
bool run;
|
||||||
|
bool single;
|
||||||
|
bool simple;
|
||||||
|
bool conf;
|
||||||
|
std::optional<std::string> target;
|
||||||
|
int test;
|
||||||
|
};
|
||||||
|
|
||||||
|
Args args;
|
||||||
|
parser.AddAction("--version,-v", "Displays the version of this program", PrintVersion);
|
||||||
|
parser.AddFlag("make,all,-m,-a", args.make, "Generates a Makefile and runs \"make all\"");
|
||||||
|
parser.AddFlag("install,-i", args.install, "Generates a Makefile and runs \"make all && make install\"");
|
||||||
|
parser.AddFlag("clean,-c", args.clean, "Generates a Makefile and runs \"make clean\"");
|
||||||
|
parser.AddFlag("rebuld,-r", args.rebuild, "Generates a Makefile and runs \"make clean && make all\"");
|
||||||
|
parser.AddFlag("run,execute,-e", args.run, "Generates a Makefile and runs \"make all && make run\"");
|
||||||
|
parser.AddFlag("single,-s", args.single, "Runs additional makegen options as single thread\n(no --jobs=X flag)");
|
||||||
|
parser.AddFlag("--simple", args.simple, "Creates a simple Makefile without include dependencies");
|
||||||
|
parser.AddOptional("--target,-t", args.target, "Run the makegen.xml file with the specified target");
|
||||||
|
if (parser.Parse())
|
||||||
|
{
|
||||||
|
if (args.target)
|
||||||
|
std::cout << args.target.value() << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "null" << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#if 0
|
||||||
|
ap::ArgParser parser("command",
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
|
||||||
|
"labore et dolore magna aliqua",
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
|
||||||
|
"labore et dolore magna aliqua",
|
||||||
|
argc - 1,
|
||||||
|
argv + 1);
|
||||||
|
|
||||||
|
// ArgParser parser("command",
|
||||||
|
// "This text explains what the command does",
|
||||||
|
// "Additional help information",
|
||||||
|
// {{"--test", "10", "--test2=20", "--test4=tesssda", "--test5", "--test6=Y"}});
|
||||||
|
int test;
|
||||||
|
int test2;
|
||||||
|
float test3;
|
||||||
|
std::string test4;
|
||||||
|
bool flag;
|
||||||
|
bool b;
|
||||||
|
bool version;
|
||||||
|
parser.AddInfo("--version", version, "Displays the version of the program");
|
||||||
|
parser.Add<int>(
|
||||||
|
"--test",
|
||||||
|
test,
|
||||||
|
"some1 help2 text3 some4 help5 text6 some7 help8 text9 some10 "
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||||
|
parser.Add<int>("--test2,-t", test2, "some help text 2");
|
||||||
|
parser.Add<float>("--test3", test3, "some help text", 0.1f);
|
||||||
|
parser.Add<std::string>("--test4", test4, "some help text");
|
||||||
|
parser.Add<bool>("--test6", b, "some help text");
|
||||||
|
parser.Add<bool>("--test7", b, "some help text");
|
||||||
|
parser.AddFlag("--test5", flag, "some help text");
|
||||||
|
parser.AddFlag("--very_very_very_very_long", flag, "some help text");
|
||||||
|
parser.AddFlag("--very_very_very_very_longxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
flag,
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore "
|
||||||
|
"et dolore magna aliqua");
|
||||||
|
parser.AddFlag("--very_very_very_very", flag, "some help text");
|
||||||
|
parser.AddFlag("--very_very_very_ver", flag, "some help text");
|
||||||
|
if (parser.Parse())
|
||||||
|
{
|
||||||
|
std::cout << test << std::endl;
|
||||||
|
std::cout << test2 << std::endl;
|
||||||
|
std::cout << test3 << std::endl;
|
||||||
|
std::cout << test4 << std::endl;
|
||||||
|
std::cout << b << std::endl;
|
||||||
|
std::cout << flag << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version)
|
||||||
|
{
|
||||||
|
std::cout << "Command 1.2.3" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user