Compare commits

..

3 Commits

Author SHA1 Message Date
085236fb62 Fix whitespace 2024-07-13 19:09:58 -06:00
1449f7e47c Abandon --help 2024-07-13 18:56:16 -06:00
ea017d1d54 Add install prefix to Makefile 2024-07-13 18:01:57 -06:00
5 changed files with 71 additions and 70 deletions

View File

@ -6,13 +6,15 @@ namespace Arguments
{ {
enum ERROR { enum ERROR {
NO_ERROR = 0, NO_ERROR = 0,
ERROR_UNKNOWN_ARGUMENT,
ERROR_UNKNOWN_POSITIONAL_ARGUMENT, ERROR_UNKNOWN_ARGUMENT,
ERROR_MISSING_VALUE, ERROR_UNKNOWN_POSITIONAL_ARGUMENT,
ERROR_MISSING_POSITIONAL_ARGUMENT,
ERROR_MISSING_VALUE,
ERROR_MISSING_POSITIONAL_ARGUMENT,
ERROR_INVALID_INT, ERROR_INVALID_INT,
SPECIAL_CASE_HELP,
}; };
class Parser class Parser
@ -38,8 +40,6 @@ public:
Argument(const char* name); Argument(const char* name);
Argument(char name); Argument(char name);
Argument& description(const char* desc);
Argument& alias(const char* alias); Argument& alias(const char* alias);
Argument& alias(char alias); Argument& alias(char alias);
@ -56,8 +56,6 @@ protected:
const char* m_Name; const char* m_Name;
char m_ShortName; char m_ShortName;
const char* m_Description;
private: private:
std::vector<const char*> m_Aliases; std::vector<const char*> m_Aliases;
std::vector<char> m_ShortAliases; std::vector<char> m_ShortAliases;
@ -112,16 +110,11 @@ class PositionalArgument
public: public:
PositionalArgument(bool required); PositionalArgument(bool required);
void description(const char* desc);
virtual ERROR parseValue(Parser& state) = 0; virtual ERROR parseValue(Parser& state) = 0;
public: public:
bool found; bool found;
bool required; bool required;
private:
const char* m_Description;
}; };

View File

@ -6,8 +6,9 @@ SOURCE_DIR = Src
HEADER_DIR = Inc HEADER_DIR = Inc
BUILD_DIR = bin BUILD_DIR = bin
HEADER_INSTALL_DIR = /usr/local/include INSTALL_PREFIX ?= /usr/local
INSTALL_DIR = /usr/local/lib HEADER_INSTALL_DIR = $(INSTALL_PREFIX)/include
INSTALL_DIR = $(INSTALL_PREFIX)/lib
LIB_NAME = argParser LIB_NAME = argParser
ifeq ($(TYPE), $(SHARED_TYPE)) ifeq ($(TYPE), $(SHARED_TYPE))
@ -44,59 +45,59 @@ all: $(BUILD_DIR)/$(LIB_FILE_NAME)
ifneq ($(TYPE), $(SHARED_TYPE)) ifneq ($(TYPE), $(SHARED_TYPE))
shared: clean shared: clean
@sed -i -e "s/^TYPE = .*$$/TYPE = $(SHARED_TYPE)/" Makefile @sed -i -e "s/^TYPE = .*$$/TYPE = $(SHARED_TYPE)/" Makefile
.PHONY: shared .PHONY: shared
endif endif
ifneq ($(TYPE), $(STATIC_TYPE)) ifneq ($(TYPE), $(STATIC_TYPE))
static: clean static: clean
@sed -i -e "s/^TYPE = .*$$/TYPE = $(STATIC_TYPE)/" Makefile @sed -i -e "s/^TYPE = .*$$/TYPE = $(STATIC_TYPE)/" Makefile
.PHONY: static .PHONY: static
endif endif
$(BUILD_DIR)/$(LIB_FILE_NAME): $(OBJECTS) $(BUILD_DIR)/$(LIB_FILE_NAME): $(OBJECTS)
ifeq ($(TYPE), $(SHARED_TYPE)) ifeq ($(TYPE), $(SHARED_TYPE))
$(CXX) $^ $(CXXFLAGS) -shared -o $@ $(CXX) $^ $(CXXFLAGS) -shared -o $@
else else
$(AR) $(ARFLAGS) $@ $^ $(AR) $(ARFLAGS) $@ $^
endif endif
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c | $(BUILD_DIR) $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c | $(BUILD_DIR)
$(CC) -c $< $(CFLAGS) -o $@ $(CC) -c $< $(CFLAGS) -o $@
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp | $(BUILD_DIR) $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp | $(BUILD_DIR)
$(CXX) -c $< $(CXXFLAGS) -o $@ $(CXX) -c $< $(CXXFLAGS) -o $@
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
test: test.cpp all | $(BUILD_DIR) test: test.cpp all | $(BUILD_DIR)
$(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -L$(BUILD_DIR) $(TESTFLAGS) -o $(BUILD_DIR)/test $(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -L$(BUILD_DIR) $(TESTFLAGS) -o $(BUILD_DIR)/test
-$(BUILD_DIR)/test -$(BUILD_DIR)/test
test_installed: test.cpp | $(BUILD_DIR) test_installed: test.cpp | $(BUILD_DIR)
$(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -o $(BUILD_DIR)/test $(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -o $(BUILD_DIR)/test
-$(BUILD_DIR)/test -$(BUILD_DIR)/test
install: all install: all
cp $(BUILD_DIR)/$(LIB_FILE_NAME) $(INSTALL_DIR) cp $(BUILD_DIR)/$(LIB_FILE_NAME) $(INSTALL_DIR)
cp $(HEADERS) $(HEADER_INSTALL_DIR) cp $(HEADERS) $(HEADER_INSTALL_DIR)
@chmod 0755 $(INSTALL_DIR)/$(LIB_FILE_NAME) @chmod 0755 $(INSTALL_DIR)/$(LIB_FILE_NAME)
ifeq ($(TYPE), $(SHARED_TYPE)) ifeq ($(TYPE), $(SHARED_TYPE))
@ldconfig @ldconfig
endif endif
uninstall: uninstall:
$(RM) $(INSTALL_DIR)/$(LIB_FILE_NAME) $(RM) $(INSTALL_DIR)/$(LIB_FILE_NAME)
$(RM) $(addprefix $(HEADER_INSTALL_DIR)/, $(notdir $(HEADERS))) $(RM) $(addprefix $(HEADER_INSTALL_DIR)/, $(notdir $(HEADERS)))
ifeq ($(TYPE), $(SHARED_TYPE)) ifeq ($(TYPE), $(SHARED_TYPE))
@ldconfig @ldconfig
endif endif
clean: clean:
$(RM) -r $(BUILD_DIR) $(RM) -r $(BUILD_DIR)
.PHONY: all test install uninstall clean .PHONY: all test install uninstall clean

19
README.md Normal file
View File

@ -0,0 +1,19 @@
# 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

View File

@ -51,12 +51,6 @@ Argument::Argument(char name)
arguments.push_back(this); arguments.push_back(this);
}; };
Argument& Argument::description(const char* desc)
{
m_Description = desc;
return *this;
}
Argument& Argument::alias(const char* alias) Argument& Argument::alias(const char* alias)
{ {
m_Aliases.push_back(alias); m_Aliases.push_back(alias);
@ -223,7 +217,7 @@ ERROR Bool::parseValue(Parser& state)
PositionalArgument::PositionalArgument(bool required) PositionalArgument::PositionalArgument(bool required)
: found(false), required(required), m_Description(nullptr) : found(false), required(required)
{ {
if (required) { if (required) {
for (PositionalArgument* arg: positionalArguments) { for (PositionalArgument* arg: positionalArguments) {
@ -237,12 +231,6 @@ PositionalArgument::PositionalArgument(bool required)
positionalArguments.push_back(this); positionalArguments.push_back(this);
} }
void PositionalArgument::description(const char* desc)
{
m_Description = desc;
}
PositionalInt::PositionalInt(int64_t defaultValue, bool required) PositionalInt::PositionalInt(int64_t defaultValue, bool required)
: PositionalArgument(required), value(defaultValue) { } : PositionalArgument(required), value(defaultValue) { }

View File

@ -5,33 +5,33 @@
int main(int argc, char** argv) { int main(int argc, char** argv) {
Arguments::String first('f', "none"); Arguments::String first('f', "none");
first.description("First arg"); first.alias("first");
Arguments::Int second("second", 0); Arguments::Int second("second", 0);
second.description("Second arg").alias('s'); second.alias('s');
Arguments::Bool third("third"); Arguments::Bool third("third");
third.description("Third arg").alias("abc").alias('t'); third.alias("abc").alias('t');
Arguments::PositionalString name("", true); Arguments::PositionalString name("", true);
Arguments::PositionalInt age(0, false); Arguments::PositionalInt age(0, false);
if (Arguments::parse(argc, argv) != Arguments::NO_ERROR) { if (Arguments::parse(argc, argv) != Arguments::NO_ERROR) {
return 0; return 0;
} }
std::cout << "Found:" << std::endl; std::cout << "Found:" << std::endl;
std::cout << "\tFirst: " << first.found << std::endl; std::cout << "\tFirst: " << first.found << std::endl;
std::cout << "\tSecond: " << second.found << std::endl; std::cout << "\tSecond: " << second.found << std::endl;
std::cout << "\tThird: " << third.found << std::endl; std::cout << "\tThird: " << third.found << std::endl;
std::cout << "\tName: " << name.found << std::endl; std::cout << "\tName: " << name.found << std::endl;
std::cout << "\tAge: " << age.found << std::endl; std::cout << "\tAge: " << age.found << std::endl;
std::cout << std::endl << "Values:" << std::endl; std::cout << std::endl << "Values:" << std::endl;
std::cout << "\tFirst: " << first.value << std::endl; std::cout << "\tFirst: " << first.value << std::endl;
std::cout << "\tSecond: " << second.value << std::endl; std::cout << "\tSecond: " << second.value << std::endl;
std::cout << "\tName: " << name.value << std::endl; std::cout << "\tName: " << name.value << std::endl;
std::cout << "\tAge: " << age.value << std::endl; std::cout << "\tAge: " << age.value << std::endl;
return 0; return 0;
} }