+++ /dev/null
-image: archlinux
-packages:
- - readline
- - cmake
- - gcc
-sources:
- - https://git.sr.ht/~armaan/gen-shell
-tasks:
- - cmake: |
- cd gen-shell
- cmake .
- make
-artifacts:
- - gen-shell/src/gen-shell
-*.d
-*.slo
-*.lo
-*.o
-*.obj
-*.gch
-*.pch
-*.so
-*.dylib
-*.dll
-*.a
-*.mod
-*.smod
-*.exe
-*.out
-*.app
gen-shell
-CMakeLists.txt.user
-CMakeCache.txt
-CMakeFiles
-CMakeScripts
-Testing
-Makefile
-cmake_install.cmake
-install_manifest.txt
-compile_commands.json
-CTestTestfile.cmake
-_deps
-CPackConfig.cmake
-CPackSourceConfig.cmake
-commit.h
-commit.h.in
-*-prefix/
-*~
-.fuse_hidden*
-.directory
-.Trash-*
-.nfs*
-cmake.h
+*.o
-[submodule "Sarge"]
- path = Sarge
- url = https://github.com/MayaPosch/Sarge
+++ /dev/null
-cmake_minimum_required (VERSION 2.8)
-set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
-set (HAVE_CMAKE true)
-
-project (gen-shell)
-include (CXXSniffer)
-
-include (CheckFunctionExists)
-include (CheckStructHasMember)
-include (CheckCXXCompilerFlag)
-
-# include the readline library finder module
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
-
-# find readline
-message ("-- Looking for GNU Readline")
-find_package (Readline REQUIRED)
-if (READLINE_FOUND)
- set (HAVE_READLINE true)
- set (GEN-SHELL_INCLUDE_DIRS ${GEN-SHELL_INCLUDE_DIRS} ${READLINE_INCLUDE_DIR})
- set (GEN-SHELL_LIBRARIES ${GEN-SHELL_LIBRARIES} ${READLINE_LIBRARIES})
-endif (READLINE_FOUND)
-
-message ("-- Configuring cmake.h")
-configure_file (
- ${CMAKE_SOURCE_DIR}/cmake.h.in
- ${CMAKE_SOURCE_DIR}/cmake.h)
-
-add_subdirectory (src)
--- /dev/null
+all:
+ ${CC} -o gen-shell src/*.cpp ${CFLAGS} -lstdc++ -lreadline ${LDFLAGS}
+
+install: all
+ cp gen-shell /usr/local/bin/gen-shell
+
+uninstall:
+ rm /usr/local/bin/gen-shell
+
+.PHONY: all
# gen-shell
-[![builds.sr.ht status](https://builds.sr.ht/~armaan/gen-shell/commits/.build.yml.svg)](https://builds.sr.ht/~armaan/gen-shell/commits/.build.yml?)
-
-A simple way to turn any command into a shell with arrow key/history support (if compiled with libreadline). Forked from [taskshell](https://github.com/GothenburgBitFactory/taskshell).
+A simple way to turn any command into a REPL with arrow key/history support.
## Usage
See `gen-shell --help`
## Installation
-### From a binary
-Binaries can be downloaded from [here](https://builds.sr.ht/~armaan/gen-shell/commits/.build.yml). NB: these binaries are compiled against libreadline version 8
-
-### From source
Dependencies:
- - cmake (2.8 or higher)
- - make
- - g++ (sometimes packaged as gcc-c++ or gcc-g++)
- - libreadline development files (7 or 8 is fine, 5 is untested) (optional, but highly recommended)
+ - POSIX make
+ - a c++ compiler and standard library
+ - libreadline development files (7 or 8 is fine, 5 is untested)
```bash
-git clone https://git.sr.ht/~armaan/gen-shell
-cd gen-shell
-cmake .
-sudo make install
+make
+make install
```
## License
Following suit from taskshell, gen-shell is MIT licensed by Armaan Bhojwani, 2021. Gen-shell is forked from taskshell, which was developed by [these people](https://github.com/GothenburgBitFactory/taskshell/blob/master/AUTHORS).
+++ /dev/null
-Subproject commit 5c0b2a714aca97de16bb0a1b2f723681f69f3307
+++ /dev/null
-/* cmake.h.in. Creates cmake.h during a cmake run */
-
-/* Product identification */
-#define PRODUCT_TASKSH 1
-
-/* Package information */
-#define PACKAGE "${PACKAGE}"
-#define VERSION "${VERSION}"
-#define PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}"
-#define PACKAGE_NAME "${PACKAGE_NAME}"
-#define PACKAGE_TARNAME "${PACKAGE_TARNAME}"
-#define PACKAGE_VERSION "${PACKAGE_VERSION}"
-#define PACKAGE_STRING "${PACKAGE_STRING}"
-
-#define CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}"
-
-/* Localization */
-#define PACKAGE_LANGUAGE ${PACKAGE_LANGUAGE}
-#define LANGUAGE_ENG_USA ${LANGUAGE_ENG_USA}
-
-/* git information */
-#cmakedefine HAVE_COMMIT
-
-/* cmake information */
-#cmakedefine HAVE_CMAKE
-#define CMAKE_VERSION "${CMAKE_VERSION}"
-
-/* Compiling platform */
-#cmakedefine LINUX
-#cmakedefine DARWIN
-#cmakedefine CYGWIN
-#cmakedefine FREEBSD
-#cmakedefine OPENBSD
-#cmakedefine NETBSD
-#cmakedefine HAIKU
-#cmakedefine SOLARIS
-#cmakedefine KFREEBSD
-#cmakedefine GNUHURD
-#cmakedefine UNKNOWN
-
-/* Found the Readline library */
-#cmakedefine HAVE_READLINE
-
-/* Found the pthread library */
-#cmakedefine HAVE_LIBPTHREAD
-
-/* Found wordexp.h */
-#cmakedefine HAVE_WORDEXP
-
-/* Found tm.tm_gmtoff struct member */
-#cmakedefine HAVE_TM_GMTOFF
-
-/* Found st.st_birthtime struct member */
-#cmakedefine HAVE_ST_BIRTHTIME
-
-/* Functions */
-#cmakedefine HAVE_GET_CURRENT_DIR_NAME
-#cmakedefine HAVE_TIMEGM
-#cmakedefine HAVE_UUID_UNPARSE_LOWER
-
+++ /dev/null
-message ("-- Configuring C++11")
-message ("-- System: ${CMAKE_SYSTEM_NAME}")
-
-include (CheckCXXCompilerFlag)
-
-# NOTE: Phase out -std=gnu++0x and --std=c++0x as soon as realistically possible.
-CHECK_CXX_COMPILER_FLAG("-std=c++11" _HAS_CXX11)
-CHECK_CXX_COMPILER_FLAG("-std=c++0x" _HAS_CXX0X)
-CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" _HAS_GNU0X)
-
-if (_HAS_CXX11)
- set (_CXX11_FLAGS "-std=c++11")
-elseif (_HAS_CXX0X)
- message (WARNING "Enabling -std=c++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.")
- set (_CXX11_FLAGS "-std=c++0x")
-elseif (_HAS_GNU0X)
- message (WARNING "Enabling -std=gnu++0x draft compile flag. Your compiler does not support the standard '-std=c++11' option. Consider upgrading.")
- set (_CXX11_FLAGS "-std=gnu++0x")
-else (_HAS_CXX11)
- message (FATAL_ERROR "C++11 support missing. Try upgrading your C++ compiler.")
-endif (_HAS_CXX11)
-
-if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- set (LINUX true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set (DARWIN true)
- set (_CXX11_FLAGS "${_CXX11_FLAGS} -stdlib=libc++")
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
- set (KFREEBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- set (FREEBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
- set (OPENBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
- set (NETBSD true)
-elseif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
- set (SOLARIS true)
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "GNU")
- set (GNUHURD true)
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN")
- set (CYGWIN true)
- # NOTE: Not setting -std=gnu++0x leads to compile errors even with
- # GCC 4.8.3, and debugging those leads to insanity. Adding this
- # workaround instead of fixing Cygwin.
- set (_CXX11_FLAGS "-std=gnu++0x")
-else (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- set (UNKNOWN true)
-endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-set (CMAKE_CXX_FLAGS "${_CXX11_FLAGS} ${CMAKE_CXX_FLAGS}")
-set (CMAKE_CXX_FLAGS "-Wall -Wextra -Wsign-compare -Wreturn-type ${CMAKE_CXX_FLAGS}")
+++ /dev/null
-# - Find the readline library
-# This module defines
-# READLINE_INCLUDE_DIR, path to readline/readline.h, etc.
-# READLINE_LIBRARIES, the libraries required to use READLINE.
-# READLINE_FOUND, If false, do not try to use READLINE.
-# also defined, but not for general use are
-# READLINE_readline_LIBRARY, where to find the READLINE library.
-# READLINE_ncurses_LIBRARY, where to find the ncurses library [might not be defined]
-
-# Apple readline does not support readline hooks
-# So we look for another one by default
-IF (APPLE OR FREEBSD)
- FIND_PATH (READLINE_INCLUDE_DIR NAMES readline/readline.h PATHS
- /usr/include/
- /sw/include
- /opt/local/include
- /opt/include
- /usr/local/include
- NO_DEFAULT_PATH
- )
-ENDIF (APPLE OR FREEBSD)
-FIND_PATH (READLINE_INCLUDE_DIR NAMES readline/readline.h)
-
-
-# Apple readline does not support readline hooks
-# So we look for another one by default
-IF (APPLE OR FREEBSD)
- FIND_LIBRARY (READLINE_readline_LIBRARY NAMES readline PATHS
- /usr/lib
- /sw/lib
- /opt/local/lib
- /opt/lib
- /usr/local/lib
- NO_DEFAULT_PATH
- )
-ENDIF (APPLE OR FREEBSD)
-FIND_LIBRARY (READLINE_readline_LIBRARY NAMES readline)
-
-# Sometimes readline really needs ncurses
-IF (APPLE OR FREEBSD)
- FIND_LIBRARY (READLINE_ncurses_LIBRARY NAMES ncurses PATHS
- /usr/lib
- /sw/lib
- /opt/local/lib
- /opt/lib
- /usr/local/lib
- /usr/lib
- NO_DEFAULT_PATH
- )
-ENDIF (APPLE OR FREEBSD)
-FIND_LIBRARY (READLINE_ncurses_LIBRARY NAMES ncurses)
-
-MARK_AS_ADVANCED (
- READLINE_INCLUDE_DIR
- READLINE_readline_LIBRARY
- READLINE_ncurses_LIBRARY
- )
-
-SET (READLINE_FOUND "NO" )
-IF (READLINE_INCLUDE_DIR)
- IF (READLINE_readline_LIBRARY)
- SET (READLINE_FOUND "YES" )
- SET (READLINE_LIBRARIES
- ${READLINE_readline_LIBRARY}
- )
-
- # some readline libraries depend on ncurses
- IF (READLINE_ncurses_LIBRARY)
- SET (READLINE_LIBRARIES ${READLINE_LIBRARIES} ${READLINE_ncurses_LIBRARY})
- ENDIF (READLINE_ncurses_LIBRARY)
-
- ENDIF (READLINE_readline_LIBRARY)
-ENDIF (READLINE_INCLUDE_DIR)
-
-IF (READLINE_FOUND)
- MESSAGE (STATUS "Found readline library")
-ELSE (READLINE_FOUND)
- IF (READLINE_FIND_REQUIRED)
- MESSAGE (FATAL_ERROR "Could not find readline -- please give some paths to CMake")
- ENDIF (READLINE_FIND_REQUIRED)
-ENDIF (READLINE_FOUND)
+++ /dev/null
-cmake_minimum_required (VERSION 2.8)
-include_directories (${CMAKE_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/src
- ${GEN-SHELL_INCLUDE_DIRS})
-
-set (gen-shell_SRCS ../Sarge/src/sarge.cpp)
-
-add_library (gen-shell STATIC ${gen-shell_SRCS})
-
-add_executable (gen-shell_executable main.cpp)
-
-target_link_libraries (gen-shell_executable gen-shell ${GEN-SHELL_LIBRARIES})
-
-set_property (TARGET gen-shell_executable PROPERTY OUTPUT_NAME "gen-shell")
-
-install (TARGETS gen-shell_executable DESTINATION /usr/bin/)
-// gen-shell - the generic shell
+// gen-shell - the generic REPL
// Copyright (c) 2021, Armaan Bhojwani <me@armaanb.net>
-#include <cmake.h>
#include <iostream>
-#include <../Sarge/src/sarge.h>
+#include "sarge.h"
+
#include <vector>
#include <string>
-#ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
-#endif
////////////////////////////////////////////////////////////////////////////////
using namespace std;
-const std::string getResponse(const std::string & prompt) {
+const std::string
+getResponse(const std::string & prompt) {
std::string response {
""
};
// Display prompt, get input
-#ifdef HAVE_READLINE
char * line_read = readline(prompt.c_str());
if (!line_read) {
std::cout << "\n";
response = "<EOF>";
} else {
- // Save history
- if ( * line_read)
+ if (*line_read) {
add_history(line_read);
+ }
response = std::string(line_read);
free(line_read);
}
-#else
- std::cout << prompt;
- std::getline(std::cin, response);
- if (std::cin.eof() == 1) {
- std::cout << "\n";
- response = "<EOF>";
- }
-#endif
return response;
}
////////////////////////////////////////////////////////////////////////////////
-int main(int argc, char** argv)
+int
+main(int argc, char** argv)
{
-
// Command line arguments
Sarge sarge;
- sarge.setArgument("a", "after",
- "Command to execute before leaving the shell", true);
- sarge.setArgument("b", "before",
- "Command to execute before entering the shell", true);
- sarge.setArgument("c", "command", "Command to convert to shell", true);
- sarge.setArgument("h", "help", "Get help.", false);
+ sarge.setArgument("c", "command", "Command to convert to REPL", true);
+ sarge.setArgument("h", "help", "Show this message.", false);
sarge.setArgument("p", "prompt", "Define a custom prompt", true);
- sarge.setArgument("", "no-space",
- "Dont automatically add spaces after custom prompt and command", true);
- sarge.setDescription("Make a shell from any executable");
+ sarge.setArgument("q", "quotes", "Treat whole input as argv[1]", false);
+ sarge.setDescription("Make a REPL from any executable");
sarge.setUsage("gen-shell <options>");
if (!sarge.parseArguments(argc, argv)) {
- std::cerr << "Couldn't parse arguments..." << std::endl;
+ std::cerr << "Could not parse command line arguments" << std::endl;
return 1;
}
return 0;
}
- bool space = true;
- if (sarge.exists("no-space")) {
- space = false;
- }
-
- // Define input command
string arg_cmd;
sarge.getFlag("command", arg_cmd);
- if ( space )
- arg_cmd += " ";
- // Define prompt
string prompt = "";
sarge.getFlag("prompt", prompt);
- if ( prompt == "" )
- {
+ if (prompt == "") {
prompt = "% ";
- } else if ( space ) {
- prompt += " ";
}
- // Execute before-command
- string before_command;
- sarge.getFlag("before", before_command);
- system (before_command.c_str ());
-
- // Execute after-command
- string after_command;
- sarge.getFlag("after", after_command);
-
// Do the stuffs!
while (true) {
auto command = getResponse(prompt);
- if (command == "<EOF>" || command == "exit" || command == "quit" )
- {
- system (after_command.c_str ());
+ if (command == "<EOF>" || command == "exit" || command == "quit" ) {
return 0;
} else {
- string whole_command = arg_cmd + command;
- system (whole_command.c_str ());
+ string whole_command = arg_cmd + " ";
+ if (sarge.exists("quotes")) {
+ whole_command = whole_command + "\"" + command + "\"";
+ } else {
+ whole_command += command;
+ }
+ system(whole_command.c_str());
}
}
}
--- /dev/null
+/*
+ sarge.cpp - Implementation file for the Sarge command line argument parser project.
+
+ Revision 0
+
+ Features:
+ -
+
+ Notes:
+ -
+
+ 2019/03/16, Maya Posch
+
+*/
+
+
+#include "sarge.h"
+
+#include <iostream>
+
+
+// --- SET ARGUMENT ---
+void Sarge::setArgument(std::string arg_short, std::string arg_long, std::string desc, bool hasVal) {
+ std::unique_ptr<Argument> arg(new Argument);
+ arg->arg_short = arg_short;
+ arg->arg_long = arg_long;
+ arg->description = desc;
+ arg->hasValue = hasVal;
+ args.push_back(std::move(arg));
+
+ // Set up links.
+ if (!arg_short.empty()) {
+ argNames.insert(std::pair<std::string, Argument*>(arg_short, args.back().get()));
+ }
+
+ if (!arg_long.empty()) {
+ argNames.insert(std::pair<std::string, Argument*>(arg_long, args.back().get()));
+ }
+}
+
+
+// --- SET ARGUMENTS ---
+void Sarge::setArguments(std::vector<Argument> args) {
+ for (Argument a : args) {
+ setArgument(a.arg_short, a.arg_long, a.description, a.hasValue);
+ }
+}
+
+
+// --- PARSE ARGUMENTS ---
+bool Sarge::parseArguments(int argc, char** argv) {
+ // The first argument is the name of the executable. After it we loop through the remaining
+ // arguments, linking flags and values.
+ execName = std::string(argv[0]);
+ bool expectValue = false;
+ std::map<std::string, Argument*>::const_iterator flag_it;
+ for (int i = 1; i < argc; ++i) {
+ // Each flag will start with a '-' character. Multiple flags can be joined together in the
+ // same string if they're the short form flag type (one character per flag).
+ std::string entry(argv[i]);
+
+ if (expectValue) {
+ // Copy value.
+ flag_it->second->value = entry;
+ expectValue = false;
+ }
+ else if (entry.compare(0, 1, "-") == 0) {
+ if (textArguments.size() > 0) {
+ std::cerr << "Flags not allowed after text arguments." << std::endl;
+ }
+
+ // Parse flag.
+ // First check for the long form.
+ if (entry.compare(0, 2, "--") == 0) {
+ // Long form of flag.
+ entry.erase(0, 2); // Erase the double dash since we no longer need it.
+
+ flag_it = argNames.find(entry);
+ if (flag_it == argNames.end()) {
+ // Flag wasn't found. Abort.
+ std::cerr << "Long flag " << entry << " wasn't found." << std::endl;
+ return false;
+ }
+
+ // Mark as found.
+ flag_it->second->parsed = true;
+ ++flagCounter;
+
+ if (flag_it->second->hasValue) {
+ expectValue = true; // Next argument has to be a value string.
+ }
+ }
+ else {
+ // Parse short form flag. Parse all of them sequentially. Only the last one
+ // is allowed to have an additional value following it.
+ entry.erase(0, 1); // Erase the dash.
+ for (int i = 0; i < entry.length(); ++i) {
+ std::string k(&(entry[i]), 1);
+ flag_it = argNames.find(k);
+ if (flag_it == argNames.end()) {
+ // Flag wasn't found. Abort.
+ std::cerr << "Short flag " << k << " wasn't found." << std::endl;
+ return false;
+ }
+
+ // Mark as found.
+ flag_it->second->parsed = true;
+ ++flagCounter;
+
+ if (flag_it->second->hasValue) {
+ if (i != (entry.length() - 1)) {
+ // Flag isn't at end, thus cannot have value.
+ std::cerr << "Flag " << k << " needs to be followed by a value string."
+ << std::endl;
+ return false;
+ } else {
+ expectValue = true; // Next argument has to be a value string.
+ }
+ }
+ }
+ }
+ }
+ else {
+ // Add to text argument vector.
+ textArguments.push_back(entry);
+ }
+ }
+
+ parsed = true;
+
+ return true;
+}
+
+
+// --- GET FLAG ---
+// Returns whether the flag was found, along with the value if relevant.
+bool Sarge::getFlag(std::string arg_flag, std::string &arg_value) {
+ if (!parsed) { return false; }
+
+ std::map<std::string, Argument*>::const_iterator it = argNames.find(arg_flag);
+ if (it == argNames.end()) { return false; }
+ if (!it->second->parsed) { return false; }
+
+ if (it->second->hasValue) { arg_value = it->second->value; }
+
+ return true;
+}
+
+
+// --- EXISTS ---
+// Returns whether the flag was found.
+bool Sarge::exists(std::string arg_flag) {
+ if (!parsed) { return false; }
+
+ std::map<std::string, Argument*>::const_iterator it = argNames.find(arg_flag);
+ if (it == argNames.end()) { return false; }
+ if (!it->second->parsed) { return false; }
+
+ return true;
+}
+
+
+// --- GET TEXT ARGUMENT ---
+// Updates the value parameter with the text argument (unbound value) if found.
+// Index starts at 0.
+// Returns true if found, else false.
+bool Sarge::getTextArgument(uint32_t index, std::string &value) {
+ if (index < textArguments.size()) { value = textArguments.at(index); return true; }
+
+ return false;
+}
+
+
+// --- PRINT HELP ---
+// Prints out the application description, usage and available options.
+void Sarge::printHelp() {
+ std::cout << std::endl << description << std::endl;
+ std::cout << std::endl << "Usage:" << std::endl;
+ std::cout << "\t" << usage << std::endl;
+ std::cout << std::endl;
+ std::cout << "Options: " << std::endl;
+
+ // Determine whitespace needed between arg_long and description.
+ int count = 1;
+ std::vector<std::unique_ptr<Argument> >::const_iterator it;
+ for (it = args.cbegin(); it != args.cend(); ++it) {
+ if ((*it)->arg_long.size() > count) {
+ count = (*it)->arg_long.size();
+ }
+ }
+
+ count += 3; // Number of actual spaces between the longest arg_long and description.
+
+ // Print out the options.
+ for (it = args.cbegin(); it != args.cend(); ++it) {
+ std::cout << ((*it)->arg_short.empty() ? " " : "-" + (*it)->arg_short + ", ")
+ << "--" << (*it)->arg_long;
+ std::cout << std::string(count - (*it)->arg_long.size(), ' ') << (*it)->description
+ << std::endl;
+ }
+}
--- /dev/null
+/*
+ sarge.h - Header file for the Sarge command line argument parser project.
+
+ Revision 0
+
+ Notes:
+ -
+
+ 2019/03/16, Maya Posch
+
+*/
+
+
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+
+struct Argument {
+ Argument() : hasValue(false), parsed(false) { /* */ }
+ std::string arg_short;
+ std::string arg_long;
+ std::string description;
+ bool hasValue;
+ std::string value;
+ bool parsed;
+};
+
+
+
+class Sarge {
+ std::vector<std::unique_ptr<Argument> > args;
+ std::map<std::string, Argument*> argNames;
+ bool parsed = false;
+ int flagCounter = 0;
+ std::string execName;
+ std::string description;
+ std::string usage;
+ std::vector<std::string> textArguments;
+
+public:
+ void setArgument(std::string arg_short, std::string arg_long, std::string desc, bool hasVal);
+ void setArguments(std::vector<Argument> args);
+ void setDescription(std::string desc) { this->description = desc; }
+ void setUsage(std::string use) { this->usage = use; }
+ bool parseArguments(int argc, char** argv);
+ bool getFlag(std::string arg_flag, std::string &arg_value);
+ bool exists(std::string arg_flag);
+ bool getTextArgument(uint32_t index, std::string &value);
+ void printHelp();
+ int flagCount() { return flagCounter; }
+ std::string executableName() { return execName; }
+};