fooling around with options - not working currently...
diff --git a/doc/markdown/todo.md b/doc/markdown/todo.md
index 1a73049..f680006 100644
--- a/doc/markdown/todo.md
+++ b/doc/markdown/todo.md
@@ -2,10 +2,7 @@
 

 - colors in output

 

-OMFG stringify overloading not working for gcc! std::string example failing!

-

 - fix command line

-- [unsure] improve command line - passing "-dt-no-run=1 -dt-no-run=0" should result in running the tests (AND SHORT VERSIONS!!!)

 

 

 add _CONFIG_ in config macros

diff --git a/doctest/doctest.h b/doctest/doctest.h
index ed00695..46a9dc2 100644
--- a/doctest/doctest.h
+++ b/doctest/doctest.h
@@ -302,14 +302,14 @@
     {

         detail::Vector<detail::Vector<String> > filters;

 

-        bool count;            // if only the count of matching tests is to be retreived

-        bool case_sensitive;   // if filtering should be case sensitive

-        bool allow_overrides;  // all but this can be overriden

-        bool exit_after_tests; // calls exit() after the tests are ran/counted

-        bool no_exitcode;      // if the framework should return 0 as the exitcode

-        bool no_run;           // to not run the tests at all (can be done with an "*" exclude)

-        bool no_colors;        // if output to the console should be colorized

-        bool no_breaks;        // to not break into the debugger

+        bool count;          // if only the count of matching tests is to be retreived

+        bool case_sensitive; // if filtering should be case sensitive

+        bool no_overrides;   // to disable overrides from code

+        bool exit;           // calls exit() after the tests are ran/counted/whatever

+        bool no_exitcode;    // if the framework should return 0 as the exitcode

+        bool no_run;         // to not run the tests at all (can be done with an "*" exclude)

+        bool no_colors;      // if output to the console should be colorized

+        bool no_breaks;      // to not break into the debugger

 

         bool hash_table_histogram; // if the hash table should be printed as a histogram

         bool no_path_in_filenames; // if the path to files should be removed from the output

@@ -331,10 +331,13 @@
 {

 #if !defined(DOCTEST_DISABLE)

     detail::ContextParams p;

+

+    void parseArgs(int argc, const char* const* argv, bool withDefaults = false);

+

 #endif // DOCTEST_DISABLE

 

 public:

-    Context(int argc, char** argv);

+    Context(int argc, const char* const* argv);

 

     void addFilter(const char* filter, const char* value);

     void setOption(const char* option, int value);

@@ -564,7 +567,7 @@
 inline int     String::compare(const char*, bool) const { return 0; }

 inline int     String::compare(const String&, bool) const { return 0; }

 

-inline Context::Context(int, char**) {}

+inline Context::Context(int, const char* const*) {}

 inline void Context::addFilter(const char*, const char*) {}

 inline void Context::setOption(const char*, int) {}

 inline int  Context::runTests() { return 0; }

@@ -1150,68 +1153,6 @@
         return res;

     }

 

-    // parses a comma separated list of words after a pattern in one of the arguments in argv

-    void parseFilter(int argc, char** argv, const char* pattern, Vector<String>& filters) {

-        String filtersString;

-        for(int i = 0; i < argc; ++i) {

-            const char* temp = strstr(argv[i], pattern);

-            if(temp) {

-                temp += my_strlen(pattern);

-                size_t len = my_strlen(temp);

-                if(len) {

-                    filtersString = temp;

-                    break;

-                }

-            }

-        }

-

-        // if we have found the filter string

-        if(filtersString.c_str()) {

-            // tokenize with "," as a separator

-            char* pch = strtok(filtersString.c_str(), ","); // modifies the string

-            while(pch != 0) {

-                if(my_strlen(pch))

-                    filters.push_back(pch);

-                pch = strtok(0, ","); // uses the strtok() internal state to go to the next token

-            }

-        }

-    }

-

-    // parses an option from the command line (bool: type == 0, int: type == 1)

-    int parseOption(int argc, char** argv, const char* option, int type, int defaultVal) {

-        int outVal = defaultVal;

-

-        Vector<String> parsedValues;

-        parseFilter(argc, argv, option, parsedValues);

-

-        // if the option has been found (and there is only 1 value in the "comma separated list")

-        if(parsedValues.size() == 1) {

-            if(type == 0) {

-                // boolean

-                const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1

-                const char negative[][6] = {"0", "false", "off", "no"};

-

-                // if the value matches any of the positive/negative possibilities

-                for(size_t i = 0; i < 4; i++) {

-                    if(parsedValues[0].compare(positive[i], true) == 0) {

-                        outVal = 1;

-                        break;

-                    }

-                    if(parsedValues[0].compare(negative[i], true) == 0) {

-                        outVal = 0;

-                        break;

-                    }

-                }

-            } else {

-                // integer

-                int res = atoi(parsedValues[0].c_str());

-                if(res != 0)

-                    outVal = res;

-            }

-        }

-        return outVal;

-    }

-

     struct Color

     {

         enum Code

@@ -1302,7 +1243,7 @@
             case Color::BrightGreen: set(FOREGROUND_INTENSITY | FOREGROUND_GREEN);             break;

             case Color::BrightWhite: set(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;

             case Color::None:

-            case Color::Bright:

+            case Color::Bright: // invalid

             default:                 set(originalForegroundAttributes);

         }

 // clang-format on

@@ -1456,6 +1397,79 @@
         }

         return false;

     }

+

+    // parses a comma separated list of words after a pattern in one of the arguments in argv

+    void parseCommaSepArg(int argc, const char* const* argv, const char* pattern,

+                          Vector<String>& res) {

+        String filtersString;

+        for(int i = argc - 1; i >= 0; --i) {

+            const char* temp = strstr(argv[i], pattern);

+            if(temp) {

+                temp += my_strlen(pattern);

+                size_t len = my_strlen(temp);

+                if(len) {

+                    filtersString = temp;

+                    break;

+                }

+            }

+        }

+

+        // if we have found the filter string

+        if(filtersString.c_str()) {

+            // tokenize with "," as a separator

+            char* pch = strtok(filtersString.c_str(), ","); // modifies the string

+            while(pch != 0) {

+                if(my_strlen(pch))

+                    res.push_back(pch);

+                pch = strtok(0, ","); // uses the strtok() internal state to go to the next token

+            }

+        }

+    }

+

+    enum paramType

+    {

+        param_bool,

+        param_int

+    };

+

+    // parses an option from the command line (bool: type == 0, int: type == 1)

+    bool parseOption(int argc, const char* const* argv, const char* option, paramType type, int def,

+                     int& res) {

+        res = def;

+

+        Vector<String> parsedValues;

+        parseCommaSepArg(argc, argv, option, parsedValues);

+

+        // if the option has been found (and there is only 1 value in the "comma separated list")

+        if(parsedValues.size() == 1) {

+            if(type == 0) {

+                // boolean

+                const char positive[][5] = {"1", "true", "on", "yes"};  // 5 - strlen("true") + 1

+                const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1

+

+                // if the value matches any of the positive/negative possibilities

+                for(size_t i = 0; i < 4; i++) {

+                    if(parsedValues[0].compare(positive[i], true) == 0) {

+                        res = 1;

+                        return true;

+                    }

+                    if(parsedValues[0].compare(negative[i], true) == 0) {

+                        res = 0;

+                        return true;

+                    }

+                }

+            } else {

+                // integer

+                int theInt = atoi(parsedValues[0].c_str());

+                if(theInt != 0) {

+                    res = theInt;

+                    return true;

+                }

+            }

+        }

+        return false;

+    }

+

 } // namespace detail

 

 String::String(const char* in)

@@ -1522,51 +1536,55 @@
     return strcmp(m_str, other.m_str);

 }

 

-Context::Context(int argc, char** argv) {

+Context::Context(int argc, const char* const* argv) { parseArgs(argc, argv, true); }

+

+// parses args

+void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {

     using namespace detail;

 

-    parseFilter(argc, argv, "-dt-file=", p.filters[0]);

-    parseFilter(argc, argv, "-dt-file-exclude=", p.filters[1]);

-    parseFilter(argc, argv, "-dt-suite=", p.filters[2]);

-    parseFilter(argc, argv, "-dt-suite-exclude=", p.filters[3]);

-    parseFilter(argc, argv, "-dt-name=", p.filters[4]);

-    parseFilter(argc, argv, "-dt-name-exclude=", p.filters[5]);

+    parseCommaSepArg(argc, argv, "dt-file=", p.filters[0]);

+    parseCommaSepArg(argc, argv, "dt-file-exclude=", p.filters[1]);

+    parseCommaSepArg(argc, argv, "dt-suite=", p.filters[2]);

+    parseCommaSepArg(argc, argv, "dt-suite-exclude=", p.filters[3]);

+    parseCommaSepArg(argc, argv, "dt-name=", p.filters[4]);

+    parseCommaSepArg(argc, argv, "dt-name-exclude=", p.filters[5]);

 

-    p.count                = !!parseOption(argc, argv, "-dt-count=", 0, 0);

-    p.case_sensitive       = !!parseOption(argc, argv, "-dt-case-sensitive=", 0, 0);

-    p.allow_overrides      = !!parseOption(argc, argv, "-dt-override=", 0, 1);

-    p.exit_after_tests     = !!parseOption(argc, argv, "-dt-exit=", 0, 0);

-    p.first                = parseOption(argc, argv, "-dt-first=", 1, 1);

-    p.last                 = parseOption(argc, argv, "-dt-last=", 1, 0);

-    p.no_exitcode          = !!parseOption(argc, argv, "-dt-no-exitcode=", 0, 0);

-    p.no_run               = !!parseOption(argc, argv, "-dt-no-run=", 0, 0);

-    p.no_colors            = !!parseOption(argc, argv, "-dt-no-colors=", 0, 0);

-    p.no_breaks            = !!parseOption(argc, argv, "-dt-no-breaks=", 0, 0);

-    p.hash_table_histogram = !!parseOption(argc, argv, "-dt-hash-table-histogram=", 0, 0);

-    p.no_path_in_filenames = !!parseOption(argc, argv, "-dt-no-path-in-filenames=", 0, 0);

+    int res = 0;

+

+    if(withDefaults || parseOption(argc, argv, "dt-count=", param_bool, 0, res))

+        p.count = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-case-sensitive=", param_bool, 0, res))

+        p.case_sensitive = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-no-overrides=", param_bool, 0, res))

+        p.no_overrides = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-exit=", param_bool, 0, res))

+        p.exit = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-first=", param_int, 0, res))

+        p.first = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-last=", param_int, 0, res))

+        p.last = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-no-exitcode=", param_bool, 0, res))

+        p.no_exitcode = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-no-run=", param_bool, 0, res))

+        p.no_run = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-no-colors=", param_bool, 0, res))

+        p.no_colors = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-no-breaks=", param_bool, 0, res))

+        p.no_breaks = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-hash-table-histogram=", param_bool, 0, res))

+        p.hash_table_histogram = !!res;

+    if(withDefaults || parseOption(argc, argv, "dt-no-path-in-filenames=", param_bool, 0, res))

+        p.no_path_in_filenames = !!res;

 }

 

 // allows the user to add procedurally to the filters from the command line

 void Context::addFilter(const char* filter, const char* value) {

     using namespace detail;

 

-    if(p.allow_overrides) {

-        size_t idx = 42;

-        if(strcmp(filter, "dt-file") == 0)

-            idx = 0;

-        if(strcmp(filter, "dt-file-exclude") == 0)

-            idx = 1;

-        if(strcmp(filter, "dt-suite") == 0)

-            idx = 2;

-        if(strcmp(filter, "dt-suite-exclude") == 0)

-            idx = 3;

-        if(strcmp(filter, "dt-name") == 0)

-            idx = 4;

-        if(strcmp(filter, "dt-name-exclude") == 0)

-            idx = 5;

-        // if the filter name is valid

-        if(idx != 42 && my_strlen(value))

-            p.filters[idx].push_back(value);

+    if(!p.no_overrides) {

+        String      argv   = String(filter) + "=" + value;

+        const char* lvalue = argv.c_str();

+        parseArgs(1, &lvalue);

     }

 }

 

@@ -1574,29 +1592,10 @@
 void Context::setOption(const char* option, int value) {

     using namespace detail;

 

-    if(p.allow_overrides) {

-        if(strcmp(option, "dt-count") == 0)

-            p.count = !!value;

-        if(strcmp(option, "dt-case-sensitive") == 0)

-            p.case_sensitive = !!value;

-        if(strcmp(option, "dt-exit") == 0)

-            p.exit_after_tests = !!value;

-        if(strcmp(option, "dt-first") == 0)

-            p.first = value;

-        if(strcmp(option, "dt-last") == 0)

-            p.last = value;

-        if(strcmp(option, "dt-no-exitcode") == 0)

-            p.no_exitcode = !!value;

-        if(strcmp(option, "dt-no-run") == 0)

-            p.no_run = !!value;

-        if(strcmp(option, "dt-no-colors") == 0)

-            p.no_colors = !!value;

-        if(strcmp(option, "dt-no-breaks") == 0)

-            p.no_breaks = !!value;

-        if(strcmp(option, "dt-hash-table-histogram") == 0)

-            p.hash_table_histogram = !!value;

-        if(strcmp(option, "dt-no-path-in-filenames") == 0)

-            p.no_path_in_filenames = !!value;

+    if(!p.no_overrides) {

+        String      argv   = String(option) + "=" + stringify(value);

+        const char* lvalue = argv.c_str();

+        parseArgs(1, &lvalue);

     }

 }

 

@@ -1608,7 +1607,7 @@
 

     // exit right now

     if(p.no_run) {

-        if(p.exit_after_tests)

+        if(p.exit)

             exit(EXIT_SUCCESS);

         return EXIT_SUCCESS;

     }

@@ -1721,7 +1720,7 @@
         }

     }

 

-    if(p.exit_after_tests)

+    if(p.exit)

         exit((numFailed && !p.no_exitcode) ? EXIT_FAILURE : EXIT_SUCCESS);

 

     if(numFailed && !p.no_exitcode)