mirror of
https://github.com/Cameron-Reed1/Cpp-Argument-Parser.git
synced 2025-01-11 08:16:48 +00:00
Compare commits
No commits in common. "085236fb6221d221ba5037dd54e90b3fbd391ff7" and "f8f5b4eafc2c83880a89b62b6ef6a25ae7e59f4a" have entirely different histories.
085236fb62
...
f8f5b4eafc
@ -6,15 +6,13 @@ namespace Arguments
|
||||
{
|
||||
|
||||
enum ERROR {
|
||||
NO_ERROR = 0,
|
||||
|
||||
ERROR_UNKNOWN_ARGUMENT,
|
||||
ERROR_UNKNOWN_POSITIONAL_ARGUMENT,
|
||||
|
||||
ERROR_MISSING_VALUE,
|
||||
ERROR_MISSING_POSITIONAL_ARGUMENT,
|
||||
|
||||
NO_ERROR = 0,
|
||||
ERROR_UNKNOWN_ARGUMENT,
|
||||
ERROR_UNKNOWN_POSITIONAL_ARGUMENT,
|
||||
ERROR_MISSING_VALUE,
|
||||
ERROR_MISSING_POSITIONAL_ARGUMENT,
|
||||
ERROR_INVALID_INT,
|
||||
SPECIAL_CASE_HELP,
|
||||
};
|
||||
|
||||
class Parser
|
||||
@ -40,6 +38,8 @@ public:
|
||||
Argument(const char* name);
|
||||
Argument(char name);
|
||||
|
||||
Argument& description(const char* desc);
|
||||
|
||||
Argument& alias(const char* alias);
|
||||
Argument& alias(char alias);
|
||||
|
||||
@ -56,6 +56,8 @@ protected:
|
||||
const char* m_Name;
|
||||
char m_ShortName;
|
||||
|
||||
const char* m_Description;
|
||||
|
||||
private:
|
||||
std::vector<const char*> m_Aliases;
|
||||
std::vector<char> m_ShortAliases;
|
||||
@ -110,11 +112,16 @@ class PositionalArgument
|
||||
public:
|
||||
PositionalArgument(bool required);
|
||||
|
||||
void description(const char* desc);
|
||||
|
||||
virtual ERROR parseValue(Parser& state) = 0;
|
||||
|
||||
public:
|
||||
bool found;
|
||||
bool required;
|
||||
|
||||
private:
|
||||
const char* m_Description;
|
||||
};
|
||||
|
||||
|
||||
|
43
Makefile
43
Makefile
@ -6,9 +6,8 @@ SOURCE_DIR = Src
|
||||
HEADER_DIR = Inc
|
||||
BUILD_DIR = bin
|
||||
|
||||
INSTALL_PREFIX ?= /usr/local
|
||||
HEADER_INSTALL_DIR = $(INSTALL_PREFIX)/include
|
||||
INSTALL_DIR = $(INSTALL_PREFIX)/lib
|
||||
HEADER_INSTALL_DIR = /usr/local/include
|
||||
INSTALL_DIR = /usr/local/lib
|
||||
|
||||
LIB_NAME = argParser
|
||||
ifeq ($(TYPE), $(SHARED_TYPE))
|
||||
@ -45,59 +44,59 @@ all: $(BUILD_DIR)/$(LIB_FILE_NAME)
|
||||
|
||||
ifneq ($(TYPE), $(SHARED_TYPE))
|
||||
shared: clean
|
||||
@sed -i -e "s/^TYPE = .*$$/TYPE = $(SHARED_TYPE)/" Makefile
|
||||
@sed -i -e "s/^TYPE = .*$$/TYPE = $(SHARED_TYPE)/" Makefile
|
||||
|
||||
.PHONY: shared
|
||||
endif
|
||||
|
||||
ifneq ($(TYPE), $(STATIC_TYPE))
|
||||
static: clean
|
||||
@sed -i -e "s/^TYPE = .*$$/TYPE = $(STATIC_TYPE)/" Makefile
|
||||
@sed -i -e "s/^TYPE = .*$$/TYPE = $(STATIC_TYPE)/" Makefile
|
||||
|
||||
.PHONY: static
|
||||
endif
|
||||
|
||||
$(BUILD_DIR)/$(LIB_FILE_NAME): $(OBJECTS)
|
||||
ifeq ($(TYPE), $(SHARED_TYPE))
|
||||
$(CXX) $^ $(CXXFLAGS) -shared -o $@
|
||||
$(CXX) $^ $(CXXFLAGS) -shared -o $@
|
||||
else
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
endif
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c | $(BUILD_DIR)
|
||||
$(CC) -c $< $(CFLAGS) -o $@
|
||||
$(CC) -c $< $(CFLAGS) -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp | $(BUILD_DIR)
|
||||
$(CXX) -c $< $(CXXFLAGS) -o $@
|
||||
$(CXX) -c $< $(CXXFLAGS) -o $@
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
mkdir -p $@
|
||||
|
||||
test: test.cpp all | $(BUILD_DIR)
|
||||
$(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -L$(BUILD_DIR) $(TESTFLAGS) -o $(BUILD_DIR)/test
|
||||
-$(BUILD_DIR)/test
|
||||
$(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -L$(BUILD_DIR) $(TESTFLAGS) -o $(BUILD_DIR)/test
|
||||
-$(BUILD_DIR)/test
|
||||
|
||||
test_installed: test.cpp | $(BUILD_DIR)
|
||||
$(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -o $(BUILD_DIR)/test
|
||||
-$(BUILD_DIR)/test
|
||||
$(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -o $(BUILD_DIR)/test
|
||||
-$(BUILD_DIR)/test
|
||||
|
||||
install: all
|
||||
cp $(BUILD_DIR)/$(LIB_FILE_NAME) $(INSTALL_DIR)
|
||||
cp $(HEADERS) $(HEADER_INSTALL_DIR)
|
||||
@chmod 0755 $(INSTALL_DIR)/$(LIB_FILE_NAME)
|
||||
cp $(BUILD_DIR)/$(LIB_FILE_NAME) $(INSTALL_DIR)
|
||||
cp $(HEADERS) $(HEADER_INSTALL_DIR)
|
||||
@chmod 0755 $(INSTALL_DIR)/$(LIB_FILE_NAME)
|
||||
ifeq ($(TYPE), $(SHARED_TYPE))
|
||||
@ldconfig
|
||||
@ldconfig
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
$(RM) $(INSTALL_DIR)/$(LIB_FILE_NAME)
|
||||
$(RM) $(addprefix $(HEADER_INSTALL_DIR)/, $(notdir $(HEADERS)))
|
||||
$(RM) $(INSTALL_DIR)/$(LIB_FILE_NAME)
|
||||
$(RM) $(addprefix $(HEADER_INSTALL_DIR)/, $(notdir $(HEADERS)))
|
||||
ifeq ($(TYPE), $(SHARED_TYPE))
|
||||
@ldconfig
|
||||
@ldconfig
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(RM) -r $(BUILD_DIR)
|
||||
$(RM) -r $(BUILD_DIR)
|
||||
|
||||
.PHONY: all test install uninstall clean
|
||||
|
||||
|
19
README.md
19
README.md
@ -1,19 +0,0 @@
|
||||
# v2
|
||||
|
||||
I never really liked the interface of v1, so after coming back to this project, I spent some time thinking about how it could be improved,
|
||||
took some inspiration from Golangs flag module, and made v2, which has a simpler, more flexible interface with better type safety
|
||||
|
||||
For example:
|
||||
- It doesn't cast char* to uint64_t and require you to cast it back
|
||||
- It doesn't require you to create a parser object, you just call parse
|
||||
- You don't have to add the arguments to that parser object, it's taken care of just by calling the constructor
|
||||
- You aren't required to provide descriptions for you program and every argument
|
||||
|
||||
That last one means that v2 will _not_ take care of --help and -h for you. If you want a help menu, you have to create it yourself.
|
||||
But help menus aren't always required and when you do want one, this gives you control over what it looks like
|
||||
|
||||
|
||||
# How do I use this
|
||||
|
||||
Check out [test.cpp](test.cpp). It demonstrates the full scope of this library
|
||||
|
@ -51,6 +51,12 @@ Argument::Argument(char name)
|
||||
arguments.push_back(this);
|
||||
};
|
||||
|
||||
Argument& Argument::description(const char* desc)
|
||||
{
|
||||
m_Description = desc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument& Argument::alias(const char* alias)
|
||||
{
|
||||
m_Aliases.push_back(alias);
|
||||
@ -217,7 +223,7 @@ ERROR Bool::parseValue(Parser& state)
|
||||
|
||||
|
||||
PositionalArgument::PositionalArgument(bool required)
|
||||
: found(false), required(required)
|
||||
: found(false), required(required), m_Description(nullptr)
|
||||
{
|
||||
if (required) {
|
||||
for (PositionalArgument* arg: positionalArguments) {
|
||||
@ -231,6 +237,12 @@ PositionalArgument::PositionalArgument(bool required)
|
||||
positionalArguments.push_back(this);
|
||||
}
|
||||
|
||||
void PositionalArgument::description(const char* desc)
|
||||
{
|
||||
m_Description = desc;
|
||||
}
|
||||
|
||||
|
||||
PositionalInt::PositionalInt(int64_t defaultValue, bool required)
|
||||
: PositionalArgument(required), value(defaultValue) { }
|
||||
|
||||
|
42
test.cpp
42
test.cpp
@ -5,33 +5,33 @@
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Arguments::String first('f', "none");
|
||||
first.alias("first");
|
||||
first.description("First arg");
|
||||
|
||||
Arguments::Int second("second", 0);
|
||||
second.alias('s');
|
||||
Arguments::Int second("second", 0);
|
||||
second.description("Second arg").alias('s');
|
||||
|
||||
Arguments::Bool third("third");
|
||||
third.alias("abc").alias('t');
|
||||
Arguments::Bool third("third");
|
||||
third.description("Third arg").alias("abc").alias('t');
|
||||
|
||||
Arguments::PositionalString name("", true);
|
||||
Arguments::PositionalInt age(0, false);
|
||||
Arguments::PositionalString name("", true);
|
||||
Arguments::PositionalInt age(0, false);
|
||||
|
||||
if (Arguments::parse(argc, argv) != Arguments::NO_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
if (Arguments::parse(argc, argv) != Arguments::NO_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "Found:" << std::endl;
|
||||
std::cout << "\tFirst: " << first.found << std::endl;
|
||||
std::cout << "\tSecond: " << second.found << std::endl;
|
||||
std::cout << "\tThird: " << third.found << std::endl;
|
||||
std::cout << "\tName: " << name.found << std::endl;
|
||||
std::cout << "\tAge: " << age.found << std::endl;
|
||||
std::cout << "Found:" << std::endl;
|
||||
std::cout << "\tFirst: " << first.found << std::endl;
|
||||
std::cout << "\tSecond: " << second.found << std::endl;
|
||||
std::cout << "\tThird: " << third.found << std::endl;
|
||||
std::cout << "\tName: " << name.found << std::endl;
|
||||
std::cout << "\tAge: " << age.found << std::endl;
|
||||
|
||||
std::cout << std::endl << "Values:" << std::endl;
|
||||
std::cout << "\tFirst: " << first.value << std::endl;
|
||||
std::cout << "\tSecond: " << second.value << std::endl;
|
||||
std::cout << "\tName: " << name.value << std::endl;
|
||||
std::cout << "\tAge: " << age.value << std::endl;
|
||||
std::cout << std::endl << "Values:" << std::endl;
|
||||
std::cout << "\tFirst: " << first.value << std::endl;
|
||||
std::cout << "\tSecond: " << second.value << std::endl;
|
||||
std::cout << "\tName: " << name.value << std::endl;
|
||||
std::cout << "\tAge: " << age.value << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user