Revert "Try moving goldens into cpp"

This reverts commit 2c64905ab571346574c9fe271b7824937e0c8867.
diff --git a/skia/goldens/build.sh b/skia/goldens/build.sh
deleted file mode 100755
index e0d0eb5..0000000
--- a/skia/goldens/build.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-
-# dir=$(pwd)
-
-# cd ../renderer
-# ./build.sh $@
-
-# cd $dir
-
-cd build
-
-OPTION=$1
-
-if [ "$OPTION" = 'help' ]; then
-    echo build.sh - build debug library
-    echo build.sh clean - clean the build
-    echo build.sh release - build release library
-elif [ "$OPTION" = "clean" ]; then
-    echo Cleaning project ...
-    # TODO: fix premake5 clean to bubble the clean command to dependent projects
-    premake5 gmake && make clean
-elif [ "$OPTION" = "release" ]; then
-    premake5 gmake && make config=release -j7
-else
-    premake5 gmake && make -j7
-fi
diff --git a/skia/goldens/build/premake5.lua b/skia/goldens/build/premake5.lua
deleted file mode 100644
index d6c3786..0000000
--- a/skia/goldens/build/premake5.lua
+++ /dev/null
@@ -1,110 +0,0 @@
-workspace "rive"
-configurations {"debug", "release"}
-
-BASE_DIR = path.getabsolute("../../../build")
-location("./")
-dofile(path.join(BASE_DIR, "premake5.lua"))
-
-BASE_DIR = path.getabsolute("../../renderer/build")
-location("./")
-dofile(path.join(BASE_DIR, "premake5.lua"))
-
-project "goldens"
-    kind "ConsoleApp"
-    language "C++"
-    cppdialect "C++17"
-    toolset "clang"
-    targetdir "%{cfg.system}/bin/%{cfg.buildcfg}"
-    objdir "obj/%{cfg.buildcfg}"
-    includedirs {
-        "../../../include",
-        "../../utils",
-        "../../renderer/include",
-        "../../dependencies/skia",
-        "../../dependencies/skia/include/core",
-        "../../dependencies/skia/include/effects",
-        "../../dependencies/skia/include/gpu",
-        "../../dependencies/skia/include/config",
-        "/usr/local/include",
-        "/usr/include",
-    }
-
-    if os.host() == 'macosx' then
-        links {
-            "Cocoa.framework",
-            "CoreFoundation.framework",
---            "CoreMedia.framework",
---            "CoreServices.framework",
---            "IOKit.framework",
---            "OpenGL.framework",
---            "Security.framework",
-            "bz2",
-            "iconv",
-            "lzma",
-            "rive_skia_renderer",
-            "rive",
-            "skia",
-        }
-    elseif os.host() == "windows" then
-        architecture "x64"
-        links {
-            "rive_skia_renderer",
-            "rive",
-            "skia.lib",
-            "opengl32.lib"
-        }
-        defines {"_USE_MATH_DEFINES"}
-        buildoptions {WINDOWS_CLANG_CL_SUPPRESSED_WARNINGS}
-        staticruntime "on"  -- Match Skia's /MT flag for link compatibility
-        runtime "Release"  -- Use /MT even in debug (/MTd is incompatible with Skia)
-    else
-        links {
-            "m",
-            "rive_skia_renderer",
-            "rive",
-            "skia",
-            "dl",
-            "pthread",
-        }
-    end
-
-    libdirs {
-        "../build/%{cfg.system}/bin/%{cfg.buildcfg}",
-        "../../dependencies/skia/out/static",
-        "../../renderer/build/%{cfg.system}/bin/%{cfg.buildcfg}",
-        "/usr/local/lib",
-        "/usr/lib",
-    }
-
-    files {
-        "../../utils/rive_mgr.cpp",
-        "../src/goldens.cpp",
-        "../src/goldens_grid.cpp"
-    }
-
-    buildoptions {"-Wall", "-fno-rtti"}
-
-    filter "configurations:debug"
-    defines {"DEBUG"}
-    symbols "On"
-
-    filter "configurations:release"
-    defines {"RELEASE"}
-    defines {"NDEBUG"}
-    optimize "On"
-
-
--- Clean Function --
-newaction {
-    trigger = "clean",
-    description = "clean the build",
-    execute = function()
-        print("clean the build...")
-        os.rmdir("./bin")
-        os.rmdir("./obj")
-        os.remove("Makefile")
-        -- no wildcards in os.remove, so use shell
-        os.execute("rm *.make")
-        print("build cleaned")
-    end
-}
diff --git a/skia/goldens/src/goldens.cpp b/skia/goldens/src/goldens.cpp
deleted file mode 100644
index 4656480..0000000
--- a/skia/goldens/src/goldens.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifdef TESTING
-#else
-
-#include "goldens_arguments.hpp"
-#include "goldens_grid.hpp"
-
-#include "rive_mgr.hpp"
-#include "rive/animation/animation.hpp"
-#include "rive/animation/linear_animation_instance.hpp"
-#include "rive/animation/linear_animation.hpp"
-#include "rive/artboard.hpp"
-#include "rive/file.hpp"
-
-#include "SkData.h"
-#include "skia_renderer.hpp"
-#include "SkImage.h"
-#include "SkPixmap.h"
-#include "SkStream.h"
-#include "SkSurface.h"
-
-#define DISTURB false
-
-int main(int argc, const char* argv[]) {
-    try {
-        GoldensArguments args(argc, argv);
-
-        const auto info = SkImageInfo::Make(SW, SH, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
-        auto surf = SkSurface::MakeRaster(info);
-        auto canvas = surf->getCanvas();
-
-        canvas->clear(SK_ColorWHITE);
-
-        rive::SkiaRenderer renderer(canvas);
-
-        RenderGoldensGrid(&renderer, args.source().c_str(), "", "");
-
-        if (DISTURB) {
-            SkPaint p;
-            p.setColor(0x80FF6622);
-            canvas->drawCircle(500, 500, 300, p);
-        }
-
-        auto img = surf->makeImageSnapshot();
-        auto data = img->encodeToData();
-        SkFILEWStream(args.destination().c_str()).write(data->data(), data->size());
-    } catch (const args::Completion& e) {
-        return 0;
-    } catch (const args::Help&) {
-        return 0;
-    } catch (const args::ParseError& e) {
-        return 1;
-    } catch (args::ValidationError e) {
-        return 1;
-    }
-
-    return 0;
-}
-
-#endif
diff --git a/skia/goldens/src/goldens_arguments.hpp b/skia/goldens/src/goldens_arguments.hpp
deleted file mode 100644
index e89e262..0000000
--- a/skia/goldens/src/goldens_arguments.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef GOLDENS_ARGUMENTS_HPP
-#define GOLDENS_ARGUMENTS_HPP
-
-#include <iostream>
-#include <memory>
-#include <string>
-
-#include "args.hxx"
-
-class GoldensArguments {
-
-public:
-    GoldensArguments(int argc, const char** argv) {
-        m_Parser = std::make_unique<args::ArgumentParser>(
-            "Reads a (source) .riv file, and optional artboard and animations names, "
-            "and generates the corresponding png grid image, "
-            "storing it in (destination).");
-
-        args::HelpFlag help(*m_Parser, "help", "Display this help menu", {'h', "help"});
-        args::Group required(*m_Parser, "required arguments:", args::Group::Validators::All);
-        args::Group optional(*m_Parser, "optional arguments:", args::Group::Validators::DontCare);
-
-        args::ValueFlag<std::string> source(
-            required, "path", "source riv filename", {'s', "source"});
-        args::ValueFlag<std::string> destination(
-            required, "path", "destination png filename", {'d', "destination"});
-
-        args::ValueFlag<std::string> artboard(
-            optional, "name", "artboard to draw from", {'t', "artboard"});
-        args::ValueFlag<std::string> animation(
-            optional, "name", "animation to be played, determines", {'a', "animation"});
-
-        args::CompletionFlag completion(*m_Parser, {"complete"});
-        try {
-            m_Parser->ParseCLI(argc, argv);
-        } catch (const std::invalid_argument e) {
-            std::cout << e.what();
-            throw;
-        } catch (const args::Completion& e) {
-            std::cout << e.what();
-            throw;
-        } catch (const args::Help&) {
-            std::cout << *m_Parser;
-            throw;
-        } catch (const args::ParseError& e) {
-            std::cerr << e.what() << std::endl;
-            std::cerr << *m_Parser;
-            throw;
-        } catch (args::ValidationError e) {
-            std::cerr << e.what() << std::endl;
-            std::cerr << *m_Parser;
-            throw;
-        }
-
-        m_Destination = args::get(destination);
-        m_Source = args::get(source);
-    }
-
-    const std::string& source() const { return m_Source; }
-    const std::string& destination() const { return m_Destination; }
-    const std::string& artboard() const { return m_Artboard; }
-    const std::string& animation() const { return m_Animation; }
-
-private:
-    std::unique_ptr<args::ArgumentParser> m_Parser;
-
-    std::string m_Source;
-    std::string m_Destination;
-    std::string m_Artboard;
-    std::string m_Animation;
-};
-#endif
diff --git a/skia/goldens/src/goldens_gpu.cpp b/skia/goldens/src/goldens_gpu.cpp
deleted file mode 100644
index 6de6425..0000000
--- a/skia/goldens/src/goldens_gpu.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifdef TESTING
-
-// Don't compile this file as part of the "tests" project.
-
-#else
-
-#include "goldens_grid.hpp"
-
-#include "GLFW/glfw3.h"
-#include "skia_renderer.hpp"
-#include "skia/include/core/SkSurface.h"
-#include "skia/include/gpu/GrDirectContext.h"
-#include "skia/include/gpu/gl/GrGLInterface.h"
-#include "skia/include/gpu/gl/GrGLAssembleInterface.h"
-#include "skia/third_party/externals/libpng/png.h"
-#include "tools/write_png_file.hpp"
-#include <iostream>
-#include <string>
-
-static GrGLFuncPtr get_proc_address(void* ctx, const char name[]) {
-    return glfwGetProcAddress(name);
-}
-
-static bool read_line(std::string& line) {
-    if (!std::getline(std::cin, line)) {
-        return false;
-    }
-    while (!line.empty() && (line.back() == '\n' || line.back() == '\r')) {
-        line.pop_back();
-    }
-    return true;
-}
-
-int main(int argc, const char* argv[]) {
-    if (!glfwInit()) {
-        fprintf(stderr, "Failed to initialize glfw.\n");
-        return -1;
-    }
-
-    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
-    GLFWwindow* window = glfwCreateWindow(SW, SH, "Rive Goldens", nullptr, nullptr);
-    if (!window) {
-        glfwTerminate();
-        fprintf(stderr, "Failed to create window.\n");
-        return -1;
-    }
-
-    glfwMakeContextCurrent(window);
-
-    auto grCtx = GrDirectContext::MakeGL(GrGLMakeAssembledInterface(nullptr, get_proc_address));
-
-    GrBackendRenderTarget backendRT(
-        SW, SH, 1 /*samples*/, 0 /*stencilBits*/, {0 /*fbo 0*/, GL_RGBA8});
-
-    SkSurfaceProps surfProps(0, kUnknown_SkPixelGeometry);
-
-    auto surf = SkSurface::MakeFromBackendRenderTarget(grCtx.get(),
-                                                       backendRT,
-                                                       kBottomLeft_GrSurfaceOrigin,
-                                                       kRGBA_8888_SkColorType,
-                                                       nullptr,
-                                                       &surfProps);
-    auto canvas = surf->getCanvas();
-    rive::SkiaRenderer renderer(canvas);
-
-    std::string source, artboard, animation, destination;
-    while (read_line(source) && read_line(artboard) && read_line(animation) &&
-           read_line(destination)) {
-        try {
-            canvas->clear(SK_ColorWHITE);
-
-            renderer.save();
-
-            RenderGoldensGrid(&renderer, source.c_str(), artboard.c_str(), animation.c_str());
-
-            renderer.restore();
-            canvas->flush();
-
-            std::vector<uint8_t> pixels(SH * SW * 4);
-            glReadPixels(0, 0, SW, SH, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
-            WritePNGFile(pixels.data(), SW, SH, true, destination.c_str());
-
-            glfwSwapBuffers(window);
-        } catch (const char* msg) {
-            fprintf(stderr, "%s: error: %s\n", source.c_str(), msg);
-            fflush(stderr);
-        } catch (...) {
-            fprintf(stderr, "error rendering %s\n", source.c_str());
-            fflush(stderr);
-        }
-        fprintf(stdout, "finished %s\n", source.c_str());
-        fflush(stdout);
-    }
-
-    return 0;
-}
-
-#endif
diff --git a/skia/goldens/src/goldens_grid.cpp b/skia/goldens/src/goldens_grid.cpp
deleted file mode 100644
index 8218870..0000000
--- a/skia/goldens/src/goldens_grid.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifdef TESTING
-
-// Don't compile this file as part of the "tests" project.
-
-#else
-
-#include "goldens_grid.hpp"
-
-#include "rive_mgr.hpp"
-#include "rive/animation/animation.hpp"
-#include "rive/animation/linear_animation_instance.hpp"
-#include "rive/animation/linear_animation.hpp"
-#include "rive/artboard.hpp"
-
-void RenderGoldensGrid(rive::Renderer* renderer,
-                       const char* source,
-                       const char* artboardName,
-                       const char* animationName) {
-    RiveMgr mgr;
-    if (!mgr.load(source, artboardName, animationName)) {
-        throw "Can't load animation";
-    }
-    auto artboard = mgr.artboard();
-    if (!artboard) {
-        throw "No artboard";
-    }
-    auto animation = mgr.animation();
-    if (!animation) {
-        throw "No animation";
-    }
-
-    const int FRAMES = H * W;
-    const double duration = animation->durationSeconds();
-    const double frameDuration = duration / FRAMES;
-    const rive::AABB dstBounds = rive::AABB(0, 0, CELL, CELL);
-
-    artboard->advance(0);
-    animation->advance(0);
-
-    renderer->translate(GAP, GAP);
-    for (int y = 0; y < H; ++y) {
-        for (int x = 0; x < W; ++x) {
-            renderer->save();
-
-            animation->apply();
-
-            renderer->translate(x * (CELL + GAP), y * (CELL + GAP));
-            renderer->align(
-                rive::Fit::cover, rive::Alignment::center, dstBounds, artboard->bounds());
-            artboard->draw(renderer);
-
-            animation->advance(frameDuration);
-            artboard->advance(frameDuration);
-
-            renderer->restore();
-        }
-    }
-}
-
-#endif
diff --git a/skia/goldens/src/goldens_grid.hpp b/skia/goldens/src/goldens_grid.hpp
deleted file mode 100644
index 881d87d..0000000
--- a/skia/goldens/src/goldens_grid.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef GOLDENS_GRID_HPP
-#define GOLDENS_GRID_HPP
-
-namespace rive {
-    class Renderer;
-}
-
-constexpr static int CELL = 256;
-constexpr static int W = 5;
-constexpr static int H = 5;
-constexpr static int GAP = 2;
-constexpr static int SW = W * CELL + (W + 1) * GAP;
-constexpr static int SH = H * CELL + (H + 1) * GAP;
-
-void RenderGoldensGrid(rive::Renderer* renderer,
-                       const char* source,
-                       const char* artboardName,
-                       const char* animationName);
-
-#endif
diff --git a/skia/utils/args.hxx b/skia/utils/args.hxx
deleted file mode 100644
index bbc521d..0000000
--- a/skia/utils/args.hxx
+++ /dev/null
@@ -1,4260 +0,0 @@
-/* Copyright (c) 2016-2017 Taylor C. Richberger <taywee@gmx.com> and Pavel
- * Belikov
- * 
- * 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.
- */
-
-/** \file args.hxx
- * \brief this single-header lets you use all of the args functionality
- *
- * The important stuff is done inside the args namespace
- */
-
-#ifndef ARGS_HXX
-#define ARGS_HXX
-
-#include <algorithm>
-#include <iterator>
-#include <exception>
-#include <functional>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <vector>
-#include <unordered_map>
-#include <unordered_set>
-#include <type_traits>
-
-#ifdef ARGS_TESTNAMESPACE
-namespace argstest
-{
-#else
-
-/** \namespace args
- * \brief contains all the functionality of the args library
- */
-namespace args
-{
-#endif
-    /** Getter to grab the value from the argument type.
-     *
-     * If the Get() function of the type returns a reference, so does this, and
-     * the value will be modifiable.
-     */
-    template <typename Option>
-    auto get(Option &option_) -> decltype(option_.Get())
-    {
-        return option_.Get();
-    }
-
-    /** (INTERNAL) Count UTF-8 glyphs
-     *
-     * This is not reliable, and will fail for combinatory glyphs, but it's
-     * good enough here for now.
-     *
-     * \param string The string to count glyphs from
-     * \return The UTF-8 glyphs in the string
-     */
-    inline std::string::size_type Glyphs(const std::string &string_)
-    {
-        std::string::size_type length = 0;
-        for (const char c: string_)
-        {
-            if ((c & 0xc0) != 0x80)
-            {
-                ++length;
-            }
-        }
-        return length;
-    }
-
-    /** (INTERNAL) Wrap a vector of words into a vector of lines
-     *
-     * Empty words are skipped. Word "\n" forces wrapping.
-     *
-     * \param begin The begin iterator
-     * \param end The end iterator
-     * \param width The width of the body
-     * \param firstlinewidth the width of the first line, defaults to the width of the body
-     * \param firstlineindent the indent of the first line, defaults to 0
-     * \return the vector of lines
-     */
-    template <typename It>
-    inline std::vector<std::string> Wrap(It begin,
-                                         It end,
-                                         const std::string::size_type width,
-                                         std::string::size_type firstlinewidth = 0,
-                                         std::string::size_type firstlineindent = 0)
-    {
-        std::vector<std::string> output;
-        std::string line(firstlineindent, ' ');
-        bool empty = true;
-
-        if (firstlinewidth == 0)
-        {
-            firstlinewidth = width;
-        }
-
-        auto currentwidth = firstlinewidth;
-
-        for (auto it = begin; it != end; ++it)
-        {
-            if (it->empty())
-            {
-                continue;
-            }
-
-            if (*it == "\n")
-            {
-                if (!empty)
-                {
-                    output.push_back(line);
-                    line.clear();
-                    empty = true;
-                    currentwidth = width;
-                }
-
-                continue;
-            }
-
-            auto itemsize = Glyphs(*it);
-            if ((line.length() + 1 + itemsize) > currentwidth)
-            {
-                if (!empty)
-                {
-                    output.push_back(line);
-                    line.clear();
-                    empty = true;
-                    currentwidth = width;
-                }
-            }
-
-            if (itemsize > 0)
-            {
-                if (!empty)
-                {
-                    line += ' ';
-                }
-
-                line += *it;
-                empty = false;
-            }
-        }
-
-        if (!empty)
-        {
-            output.push_back(line);
-        }
-
-        return output;
-    }
-
-    namespace detail
-    {
-        template <typename T>
-        std::string Join(const T& array, const std::string &delimiter)
-        {
-            std::string res;
-            for (auto &element : array)
-            {
-                if (!res.empty())
-                {
-                    res += delimiter;
-                }
-
-                res += element;
-            }
-
-            return res;
-        }
-    }
-
-    /** (INTERNAL) Wrap a string into a vector of lines
-     *
-     * This is quick and hacky, but works well enough.  You can specify a
-     * different width for the first line
-     *
-     * \param width The width of the body
-     * \param firstlinewid the width of the first line, defaults to the width of the body
-     * \return the vector of lines
-     */
-    inline std::vector<std::string> Wrap(const std::string &in, const std::string::size_type width, std::string::size_type firstlinewidth = 0)
-    {
-        // Preserve existing line breaks
-        const auto newlineloc = in.find('\n');
-        if (newlineloc != in.npos)
-        {
-            auto first = Wrap(std::string(in, 0, newlineloc), width);
-            auto second = Wrap(std::string(in, newlineloc + 1), width);
-            first.insert(
-                std::end(first),
-                std::make_move_iterator(std::begin(second)),
-                std::make_move_iterator(std::end(second)));
-            return first;
-        }
-
-        std::istringstream stream(in);
-        std::string::size_type indent = 0;
-
-        for (char c : in)
-        {
-            if (!isspace(c))
-            {
-                break;
-            }
-            ++indent;
-        }
-
-        return Wrap(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>(),
-                    width, firstlinewidth, indent);
-    }
-
-#ifdef ARGS_NOEXCEPT
-    /// Error class, for when ARGS_NOEXCEPT is defined
-    enum class Error
-    {
-        None,
-        Usage,
-        Parse,
-        Validation,
-        Required,
-        Map,
-        Extra,
-        Help,
-        Subparser,
-        Completion,
-    };
-#else
-    /** Base error class
-     */
-    class Error : public std::runtime_error
-    {
-        public:
-            Error(const std::string &problem) : std::runtime_error(problem) {}
-            virtual ~Error() {}
-    };
-
-    /** Errors that occur during usage
-     */
-    class UsageError : public Error
-    {
-        public:
-            UsageError(const std::string &problem) : Error(problem) {}
-            virtual ~UsageError() {}
-    };
-
-    /** Errors that occur during regular parsing
-     */
-    class ParseError : public Error
-    {
-        public:
-            ParseError(const std::string &problem) : Error(problem) {}
-            virtual ~ParseError() {}
-    };
-
-    /** Errors that are detected from group validation after parsing finishes
-     */
-    class ValidationError : public Error
-    {
-        public:
-            ValidationError(const std::string &problem) : Error(problem) {}
-            virtual ~ValidationError() {}
-    };
-
-    /** Errors that when a required flag is omitted
-     */
-    class RequiredError : public ValidationError
-    {
-        public:
-            RequiredError(const std::string &problem) : ValidationError(problem) {}
-            virtual ~RequiredError() {}
-    };
-
-    /** Errors in map lookups
-     */
-    class MapError : public ParseError
-    {
-        public:
-            MapError(const std::string &problem) : ParseError(problem) {}
-            virtual ~MapError() {}
-    };
-
-    /** Error that occurs when a singular flag is specified multiple times
-     */
-    class ExtraError : public ParseError
-    {
-        public:
-            ExtraError(const std::string &problem) : ParseError(problem) {}
-            virtual ~ExtraError() {}
-    };
-
-    /** An exception that indicates that the user has requested help
-     */
-    class Help : public Error
-    {
-        public:
-            Help(const std::string &flag) : Error(flag) {}
-            virtual ~Help() {}
-    };
-
-    /** (INTERNAL) An exception that emulates coroutine-like control flow for subparsers.
-     */
-    class SubparserError : public Error
-    {
-        public:
-            SubparserError() : Error("") {}
-            virtual ~SubparserError() {}
-    };
-
-    /** An exception that contains autocompletion reply
-     */
-    class Completion : public Error
-    {
-        public:
-            Completion(const std::string &flag) : Error(flag) {}
-            virtual ~Completion() {}
-    };
-#endif
-
-    /** A simple unified option type for unified initializer lists for the Matcher class.
-     */
-    struct EitherFlag
-    {
-        const bool isShort;
-        const char shortFlag;
-        const std::string longFlag;
-        EitherFlag(const std::string &flag) : isShort(false), shortFlag(), longFlag(flag) {}
-        EitherFlag(const char *flag) : isShort(false), shortFlag(), longFlag(flag) {}
-        EitherFlag(const char flag) : isShort(true), shortFlag(flag), longFlag() {}
-
-        /** Get just the long flags from an initializer list of EitherFlags
-         */
-        static std::unordered_set<std::string> GetLong(std::initializer_list<EitherFlag> flags)
-        {
-            std::unordered_set<std::string>  longFlags;
-            for (const EitherFlag &flag: flags)
-            {
-                if (!flag.isShort)
-                {
-                    longFlags.insert(flag.longFlag);
-                }
-            }
-            return longFlags;
-        }
-
-        /** Get just the short flags from an initializer list of EitherFlags
-         */
-        static std::unordered_set<char> GetShort(std::initializer_list<EitherFlag> flags)
-        {
-            std::unordered_set<char>  shortFlags;
-            for (const EitherFlag &flag: flags)
-            {
-                if (flag.isShort)
-                {
-                    shortFlags.insert(flag.shortFlag);
-                }
-            }
-            return shortFlags;
-        }
-
-        std::string str() const
-        {
-            return isShort ? std::string(1, shortFlag) : longFlag;
-        }
-
-        std::string str(const std::string &shortPrefix, const std::string &longPrefix) const
-        {
-            return isShort ? shortPrefix + std::string(1, shortFlag) : longPrefix + longFlag;
-        }
-    };
-
-
-
-    /** A class of "matchers", specifying short and flags that can possibly be
-     * matched.
-     *
-     * This is supposed to be constructed and then passed in, not used directly
-     * from user code.
-     */
-    class Matcher
-    {
-        private:
-            const std::unordered_set<char> shortFlags;
-            const std::unordered_set<std::string> longFlags;
-
-        public:
-            /** Specify short and long flags separately as iterators
-             *
-             * ex: `args::Matcher(shortFlags.begin(), shortFlags.end(), longFlags.begin(), longFlags.end())`
-             */
-            template <typename ShortIt, typename LongIt>
-            Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd) :
-                shortFlags(shortFlagsStart, shortFlagsEnd),
-                longFlags(longFlagsStart, longFlagsEnd)
-            {
-                if (shortFlags.empty() && longFlags.empty())
-                {
-#ifndef ARGS_NOEXCEPT
-                    throw UsageError("empty Matcher");
-#endif
-                }
-            }
-
-#ifdef ARGS_NOEXCEPT
-            /// Only for ARGS_NOEXCEPT
-            Error GetError() const noexcept
-            {
-                return shortFlags.empty() && longFlags.empty() ? Error::Usage : Error::None;
-            }
-#endif
-
-            /** Specify short and long flags separately as iterables
-             *
-             * ex: `args::Matcher(shortFlags, longFlags)`
-             */
-            template <typename Short, typename Long>
-            Matcher(Short &&shortIn, Long &&longIn) :
-                Matcher(std::begin(shortIn), std::end(shortIn), std::begin(longIn), std::end(longIn))
-            {}
-
-            /** Specify a mixed single initializer-list of both short and long flags
-             *
-             * This is the fancy one.  It takes a single initializer list of
-             * any number of any mixed kinds of flags.  Chars are
-             * automatically interpreted as short flags, and strings are
-             * automatically interpreted as long flags:
-             *
-             *     args::Matcher{'a'}
-             *     args::Matcher{"foo"}
-             *     args::Matcher{'h', "help"}
-             *     args::Matcher{"foo", 'f', 'F', "FoO"}
-             */
-            Matcher(std::initializer_list<EitherFlag> in) :
-                Matcher(EitherFlag::GetShort(in), EitherFlag::GetLong(in)) {}
-
-            Matcher(Matcher &&other) : shortFlags(std::move(other.shortFlags)), longFlags(std::move(other.longFlags))
-            {}
-
-            ~Matcher() {}
-
-            /** (INTERNAL) Check if there is a match of a short flag
-             */
-            bool Match(const char flag) const
-            {
-                return shortFlags.find(flag) != shortFlags.end();
-            }
-
-            /** (INTERNAL) Check if there is a match of a long flag
-             */
-            bool Match(const std::string &flag) const
-            {
-                return longFlags.find(flag) != longFlags.end();
-            }
-
-            /** (INTERNAL) Check if there is a match of a flag
-             */
-            bool Match(const EitherFlag &flag) const
-            {
-                return flag.isShort ? Match(flag.shortFlag) : Match(flag.longFlag);
-            }
-
-            /** (INTERNAL) Get all flag strings as a vector, with the prefixes embedded
-             */
-            std::vector<EitherFlag> GetFlagStrings() const
-            {
-                std::vector<EitherFlag> flagStrings;
-                flagStrings.reserve(shortFlags.size() + longFlags.size());
-                for (const char flag: shortFlags)
-                {
-                    flagStrings.emplace_back(flag);
-                }
-                for (const std::string &flag: longFlags)
-                {
-                    flagStrings.emplace_back(flag);
-                }
-                return flagStrings;
-            }
-
-            /** (INTERNAL) Get long flag if it exists or any short flag
-             */
-            EitherFlag GetLongOrAny() const
-            {
-                if (!longFlags.empty())
-                {
-                    return *longFlags.begin();
-                }
-
-                if (!shortFlags.empty())
-                {
-                    return *shortFlags.begin();
-                }
-
-                // should be unreachable
-                return ' ';
-            }
-
-            /** (INTERNAL) Get short flag if it exists or any long flag
-             */
-            EitherFlag GetShortOrAny() const
-            {
-                if (!shortFlags.empty())
-                {
-                    return *shortFlags.begin();
-                }
-
-                if (!longFlags.empty())
-                {
-                    return *longFlags.begin();
-                }
-
-                // should be unreachable
-                return ' ';
-            }
-    };
-
-    /** Attributes for flags.
-     */
-    enum class Options
-    {
-        /** Default options.
-         */
-        None = 0x0,
-
-        /** Flag can't be passed multiple times.
-         */
-        Single = 0x01,
-
-        /** Flag can't be omitted.
-         */
-        Required = 0x02,
-
-        /** Flag is excluded from usage line.
-         */
-        HiddenFromUsage = 0x04,
-
-        /** Flag is excluded from options help.
-         */
-        HiddenFromDescription = 0x08,
-
-        /** Flag is global and can be used in any subcommand.
-         */
-        Global = 0x10,
-
-        /** Flag stops a parser.
-         */
-        KickOut = 0x20,
-
-        /** Flag is excluded from auto completion.
-         */
-        HiddenFromCompletion = 0x40,
-
-        /** Flag is excluded from options help and usage line
-         */
-        Hidden = HiddenFromUsage | HiddenFromDescription | HiddenFromCompletion,
-    };
-
-    inline Options operator | (Options lhs, Options rhs)
-    {
-        return static_cast<Options>(static_cast<int>(lhs) | static_cast<int>(rhs));
-    }
-
-    inline Options operator & (Options lhs, Options rhs)
-    {
-        return static_cast<Options>(static_cast<int>(lhs) & static_cast<int>(rhs));
-    }
-
-    class FlagBase;
-    class PositionalBase;
-    class Command;
-    class ArgumentParser;
-
-    /** A simple structure of parameters for easy user-modifyable help menus
-     */
-    struct HelpParams
-    {
-        /** The width of the help menu
-         */
-        unsigned int width = 80;
-        /** The indent of the program line
-         */
-        unsigned int progindent = 2;
-        /** The indent of the program trailing lines for long parameters
-         */
-        unsigned int progtailindent = 4;
-        /** The indent of the description and epilogs
-         */
-        unsigned int descriptionindent = 4;
-        /** The indent of the flags
-         */
-        unsigned int flagindent = 6;
-        /** The indent of the flag descriptions
-         */
-        unsigned int helpindent = 40;
-        /** The additional indent each group adds
-         */
-        unsigned int eachgroupindent = 2;
-
-        /** The minimum gutter between each flag and its help
-         */
-        unsigned int gutter = 1;
-
-        /** Show the terminator when both options and positional parameters are present
-         */
-        bool showTerminator = true;
-
-        /** Show the {OPTIONS} on the prog line when this is true
-         */
-        bool showProglineOptions = true;
-
-        /** Show the positionals on the prog line when this is true
-         */
-        bool showProglinePositionals = true;
-
-        /** The prefix for short flags
-         */
-        std::string shortPrefix;
-
-        /** The prefix for long flags
-         */
-        std::string longPrefix;
-
-        /** The separator for short flags
-         */
-        std::string shortSeparator;
-
-        /** The separator for long flags
-         */
-        std::string longSeparator;
-
-        /** The program name for help generation
-         */
-        std::string programName;
-
-        /** Show command's flags
-         */
-        bool showCommandChildren = false;
-
-        /** Show command's descriptions and epilog
-         */
-        bool showCommandFullHelp = false;
-
-        /** The postfix for progline when showProglineOptions is true and command has any flags
-         */
-        std::string proglineOptions = "{OPTIONS}";
-
-        /** The prefix for progline when command has any subcommands
-         */
-        std::string proglineCommand = "COMMAND";
-
-        /** The prefix for progline value
-         */
-        std::string proglineValueOpen = " <";
-
-        /** The postfix for progline value
-         */
-        std::string proglineValueClose = ">";
-
-        /** The prefix for progline required argument
-         */
-        std::string proglineRequiredOpen = "";
-
-        /** The postfix for progline required argument
-         */
-        std::string proglineRequiredClose = "";
-
-        /** The prefix for progline non-required argument
-         */
-        std::string proglineNonrequiredOpen = "[";
-
-        /** The postfix for progline non-required argument
-         */
-        std::string proglineNonrequiredClose = "]";
-
-        /** Show flags in program line
-         */
-        bool proglineShowFlags = false;
-
-        /** Use short flags in program lines when possible
-         */
-        bool proglinePreferShortFlags = false;
-
-        /** Program line prefix
-         */
-        std::string usageString;
-
-        /** String shown in help before flags descriptions
-         */
-        std::string optionsString = "OPTIONS:";
-
-        /** Display value name after all the long and short flags
-         */
-        bool useValueNameOnce = false;
-
-        /** Show value name
-         */
-        bool showValueName = true;
-
-        /** Add newline before flag description
-         */
-        bool addNewlineBeforeDescription = false;
-
-        /** The prefix for option value
-         */
-        std::string valueOpen = "[";
-
-        /** The postfix for option value
-         */
-        std::string valueClose = "]";
-
-        /** Add choices to argument description
-         */
-        bool addChoices = false;
-
-        /** The prefix for choices
-         */
-        std::string choiceString = "\nOne of: ";
-
-        /** Add default values to argument description
-         */
-        bool addDefault = false;
-
-        /** The prefix for default values
-         */
-        std::string defaultString = "\nDefault: ";
-    };
-
-    /** A number of arguments which can be consumed by an option.
-     *
-     * Represents a closed interval [min, max].
-     */
-    struct Nargs
-    {
-        const size_t min;
-        const size_t max;
-
-        Nargs(size_t min_, size_t max_) : min{min_}, max{max_}
-        {
-#ifndef ARGS_NOEXCEPT
-            if (max < min)
-            {
-                throw UsageError("Nargs: max > min");
-            }
-#endif
-        }
-
-        Nargs(size_t num_) : min{num_}, max{num_}
-        {
-        }
-
-        friend bool operator == (const Nargs &lhs, const Nargs &rhs)
-        {
-            return lhs.min == rhs.min && lhs.max == rhs.max;
-        }
-
-        friend bool operator != (const Nargs &lhs, const Nargs &rhs)
-        {
-            return !(lhs == rhs);
-        }
-    };
-
-    /** Base class for all match types
-     */
-    class Base
-    {
-        private:
-            Options options = {};
-
-        protected:
-            bool matched = false;
-            const std::string help;
-#ifdef ARGS_NOEXCEPT
-            /// Only for ARGS_NOEXCEPT
-            mutable Error error = Error::None;
-            mutable std::string errorMsg;
-#endif
-
-        public:
-            Base(const std::string &help_, Options options_ = {}) : options(options_), help(help_) {}
-            virtual ~Base() {}
-
-            Options GetOptions() const noexcept
-            {
-                return options;
-            }
-
-            bool IsRequired() const noexcept
-            {
-                return (GetOptions() & Options::Required) != Options::None;
-            }
-
-            virtual bool Matched() const noexcept
-            {
-                return matched;
-            }
-
-            virtual void Validate(const std::string &, const std::string &) const
-            {
-            }
-
-            operator bool() const noexcept
-            {
-                return Matched();
-            }
-
-            virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(const HelpParams &, const unsigned indentLevel) const
-            {
-                std::tuple<std::string, std::string, unsigned> description;
-                std::get<1>(description) = help;
-                std::get<2>(description) = indentLevel;
-                return { std::move(description) };
-            }
-
-            virtual std::vector<Command*> GetCommands()
-            {
-                return {};
-            }
-
-            virtual bool IsGroup() const
-            {
-                return false;
-            }
-
-            virtual FlagBase *Match(const EitherFlag &)
-            {
-                return nullptr;
-            }
-
-            virtual PositionalBase *GetNextPositional()
-            {
-                return nullptr;
-            }
-
-            virtual std::vector<FlagBase*> GetAllFlags()
-            {
-                return {};
-            }
-
-            virtual bool HasFlag() const
-            {
-                return false;
-            }
-
-            virtual bool HasPositional() const
-            {
-                return false;
-            }
-
-            virtual bool HasCommand() const
-            {
-                return false;
-            }
-
-            virtual std::vector<std::string> GetProgramLine(const HelpParams &) const
-            {
-                return {};
-            }
-
-            /// Sets a kick-out value for building subparsers
-            void KickOut(bool kickout_) noexcept
-            {
-                if (kickout_)
-                {
-                    options = options | Options::KickOut;
-                }
-                else
-                {
-                    options = static_cast<Options>(static_cast<int>(options) & ~static_cast<int>(Options::KickOut));
-                }
-            }
-
-            /// Gets the kick-out value for building subparsers
-            bool KickOut() const noexcept
-            {
-                return (options & Options::KickOut) != Options::None;
-            }
-
-            virtual void Reset() noexcept
-            {
-                matched = false;
-#ifdef ARGS_NOEXCEPT
-                error = Error::None;
-                errorMsg.clear();
-#endif
-            }
-
-#ifdef ARGS_NOEXCEPT
-            /// Only for ARGS_NOEXCEPT
-            virtual Error GetError() const
-            {
-                return error;
-            }
-
-            /// Only for ARGS_NOEXCEPT
-            std::string GetErrorMsg() const
-            {
-                return errorMsg;
-            }
-#endif
-    };
-
-    /** Base class for all match types that have a name
-     */
-    class NamedBase : public Base
-    {
-        protected:
-            const std::string name;
-            bool kickout = false;
-            std::string defaultString;
-            bool defaultStringManual = false;
-            std::vector<std::string> choicesStrings;
-            bool choicesStringManual = false;
-
-            virtual std::string GetDefaultString(const HelpParams&) const { return {}; }
-
-            virtual std::vector<std::string> GetChoicesStrings(const HelpParams&) const { return {}; }
-
-            virtual std::string GetNameString(const HelpParams&) const { return Name(); }
-
-            void AddDescriptionPostfix(std::string &dest, const bool isManual, const std::string &manual, bool isGenerated, const std::string &generated, const std::string &str) const
-            {
-                if (isManual && !manual.empty())
-                {
-                    dest += str;
-                    dest += manual;
-                }
-                else if (!isManual && isGenerated && !generated.empty())
-                {
-                    dest += str;
-                    dest += generated;
-                }
-            }
-
-        public:
-            NamedBase(const std::string &name_, const std::string &help_, Options options_ = {}) : Base(help_, options_), name(name_) {}
-            virtual ~NamedBase() {}
-
-            /** Sets default value string that will be added to argument description.
-             *  Use empty string to disable it for this argument.
-             */
-            void HelpDefault(const std::string &str)
-            {
-                defaultStringManual = true;
-                defaultString = str;
-            }
-
-            /** Gets default value string that will be added to argument description.
-             */
-            std::string HelpDefault(const HelpParams &params) const
-            {
-                return defaultStringManual ? defaultString : GetDefaultString(params);
-            }
-
-            /** Sets choices strings that will be added to argument description.
-             *  Use empty vector to disable it for this argument.
-             */
-            void HelpChoices(const std::vector<std::string> &array)
-            {
-                choicesStringManual = true;
-                choicesStrings = array;
-            }
-
-            /** Gets choices strings that will be added to argument description.
-             */
-            std::vector<std::string> HelpChoices(const HelpParams &params) const
-            {
-                return choicesStringManual ? choicesStrings : GetChoicesStrings(params);
-            }
-
-            virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(const HelpParams &params, const unsigned indentLevel) const override
-            {
-                std::tuple<std::string, std::string, unsigned> description;
-                std::get<0>(description) = GetNameString(params);
-                std::get<1>(description) = help;
-                std::get<2>(description) = indentLevel;
-
-                AddDescriptionPostfix(std::get<1>(description), choicesStringManual, detail::Join(choicesStrings, ", "), params.addChoices, detail::Join(GetChoicesStrings(params), ", "), params.choiceString);
-                AddDescriptionPostfix(std::get<1>(description), defaultStringManual, defaultString, params.addDefault, GetDefaultString(params), params.defaultString);
-
-                return { std::move(description) };
-            }
-
-            virtual std::string Name() const
-            {
-                return name;
-            }
-    };
-
-    namespace detail
-    {
-        template <typename T, typename = int>
-        struct IsConvertableToString : std::false_type {};
-
-        template <typename T>
-        struct IsConvertableToString<T, decltype(std::declval<std::ostringstream&>() << std::declval<T>(), int())> : std::true_type {};
-
-        template <typename T>
-        typename std::enable_if<IsConvertableToString<T>::value, std::string>::type
-        ToString(const T &value)
-        {
-            std::ostringstream s;
-            s << value;
-            return s.str();
-        }
-
-        template <typename T>
-        typename std::enable_if<!IsConvertableToString<T>::value, std::string>::type
-        ToString(const T &)
-        {
-            return {};
-        }
-
-        template <typename T>
-        std::vector<std::string> MapKeysToStrings(const T &map)
-        {
-            std::vector<std::string> res;
-            using K = typename std::decay<decltype(std::begin(map)->first)>::type;
-            if (IsConvertableToString<K>::value)
-            {
-                for (const auto &p : map)
-                {
-                    res.push_back(detail::ToString(p.first));
-                }
-
-                std::sort(res.begin(), res.end());
-            }
-            return res;
-        }
-    }
-
-    /** Base class for all flag options
-     */
-    class FlagBase : public NamedBase
-    {
-        protected:
-            const Matcher matcher;
-
-            virtual std::string GetNameString(const HelpParams &params) const override
-            {
-                const std::string postfix = !params.showValueName || NumberOfArguments() == 0 ? std::string() : Name();
-                std::string flags;
-                const auto flagStrings = matcher.GetFlagStrings();
-                const bool useValueNameOnce = flagStrings.size() == 1 ? false : params.useValueNameOnce;
-                for (auto it = flagStrings.begin(); it != flagStrings.end(); ++it)
-                {
-                    auto &flag = *it;
-                    if (it != flagStrings.begin())
-                    {
-                        flags += ", ";
-                    }
-
-                    flags += flag.isShort ? params.shortPrefix : params.longPrefix;
-                    flags += flag.str();
-
-                    if (!postfix.empty() && (!useValueNameOnce || it + 1 == flagStrings.end()))
-                    {
-                        flags += flag.isShort ? params.shortSeparator : params.longSeparator;
-                        flags += params.valueOpen + postfix + params.valueClose;
-                    }
-                }
-
-                return flags;
-            }
-
-        public:
-            FlagBase(const std::string &name_, const std::string &help_, Matcher &&matcher_, const bool extraError_ = false) : NamedBase(name_, help_, extraError_ ? Options::Single : Options()), matcher(std::move(matcher_)) {}
-
-            FlagBase(const std::string &name_, const std::string &help_, Matcher &&matcher_, Options options_) : NamedBase(name_, help_, options_), matcher(std::move(matcher_)) {}
-
-            virtual ~FlagBase() {}
-
-            virtual FlagBase *Match(const EitherFlag &flag) override
-            {
-                if (matcher.Match(flag))
-                {
-                    if ((GetOptions() & Options::Single) != Options::None && matched)
-                    {
-                        std::ostringstream problem;
-                        problem << "Flag '" << flag.str() << "' was passed multiple times, but is only allowed to be passed once";
-#ifdef ARGS_NOEXCEPT
-                        error = Error::Extra;
-                        errorMsg = problem.str();
-#else
-                        throw ExtraError(problem.str());
-#endif
-                    }
-                    matched = true;
-                    return this;
-                }
-                return nullptr;
-            }
-
-            virtual std::vector<FlagBase*> GetAllFlags() override
-            {
-                return { this };
-            }
-
-            const Matcher &GetMatcher() const
-            {
-                return matcher;
-            }
-
-            virtual void Validate(const std::string &shortPrefix, const std::string &longPrefix) const override
-            {
-                if (!Matched() && IsRequired())
-                {
-                        std::ostringstream problem;
-                        problem << "Flag '" << matcher.GetLongOrAny().str(shortPrefix, longPrefix) << "' is required";
-#ifdef ARGS_NOEXCEPT
-                        error = Error::Required;
-                        errorMsg = problem.str();
-#else
-                        throw RequiredError(problem.str());
-#endif
-                }
-            }
-
-            virtual std::vector<std::string> GetProgramLine(const HelpParams &params) const override
-            {
-                if (!params.proglineShowFlags)
-                {
-                    return {};
-                }
-
-                const std::string postfix = NumberOfArguments() == 0 ? std::string() : Name();
-                const EitherFlag flag = params.proglinePreferShortFlags ? matcher.GetShortOrAny() : matcher.GetLongOrAny();
-                std::string res = flag.str(params.shortPrefix, params.longPrefix);
-                if (!postfix.empty())
-                {
-                    res += params.proglineValueOpen + postfix + params.proglineValueClose;
-                }
-
-                return { IsRequired() ? params.proglineRequiredOpen + res + params.proglineRequiredClose
-                                      : params.proglineNonrequiredOpen + res + params.proglineNonrequiredClose };
-            }
-
-            virtual bool HasFlag() const override
-            {
-                return true;
-            }
-
-#ifdef ARGS_NOEXCEPT
-            /// Only for ARGS_NOEXCEPT
-            virtual Error GetError() const override
-            {
-                const auto nargs = NumberOfArguments();
-                if (nargs.min > nargs.max)
-                {
-                    return Error::Usage;
-                }
-
-                const auto matcherError = matcher.GetError();
-                if (matcherError != Error::None)
-                {
-                    return matcherError;
-                }
-
-                return error;
-            }
-#endif
-
-            /** Defines how many values can be consumed by this option.
-             *
-             * \return closed interval [min, max]
-             */
-            virtual Nargs NumberOfArguments() const noexcept = 0;
-
-            /** Parse values of this option.
-             *
-             * \param value Vector of values. It's size must be in NumberOfArguments() interval.
-             */
-            virtual void ParseValue(const std::vector<std::string> &value) = 0;
-    };
-
-    /** Base class for value-accepting flag options
-     */
-    class ValueFlagBase : public FlagBase
-    {
-        public:
-            ValueFlagBase(const std::string &name_, const std::string &help_, Matcher &&matcher_, const bool extraError_ = false) : FlagBase(name_, help_, std::move(matcher_), extraError_) {}
-            ValueFlagBase(const std::string &name_, const std::string &help_, Matcher &&matcher_, Options options_) : FlagBase(name_, help_, std::move(matcher_), options_) {}
-            virtual ~ValueFlagBase() {}
-
-            virtual Nargs NumberOfArguments() const noexcept override
-            {
-                return 1;
-            }
-    };
-
-    class CompletionFlag : public ValueFlagBase
-    {
-        public:
-            std::vector<std::string> reply;
-            size_t cword = 0;
-            std::string syntax;
-
-            template <typename GroupClass>
-            CompletionFlag(GroupClass &group_, Matcher &&matcher_): ValueFlagBase("completion", "completion flag", std::move(matcher_), Options::Hidden)
-            {
-                group_.AddCompletion(*this);
-            }
-
-            virtual ~CompletionFlag() {}
-
-            virtual Nargs NumberOfArguments() const noexcept override
-            {
-                return 2;
-            }
-
-            virtual void ParseValue(const std::vector<std::string> &value_) override
-            {
-                syntax = value_.at(0);
-                std::istringstream(value_.at(1)) >> cword;
-            }
-
-            /** Get the completion reply
-             */
-            std::string Get() noexcept
-            {
-                return detail::Join(reply, "\n");
-            }
-
-            virtual void Reset() noexcept override
-            {
-                ValueFlagBase::Reset();
-                cword = 0;
-                syntax.clear();
-                reply.clear();
-            }
-    };
-
-
-    /** Base class for positional options
-     */
-    class PositionalBase : public NamedBase
-    {
-        protected:
-            bool ready;
-
-        public:
-            PositionalBase(const std::string &name_, const std::string &help_, Options options_ = {}) : NamedBase(name_, help_, options_), ready(true) {}
-            virtual ~PositionalBase() {}
-
-            bool Ready()
-            {
-                return ready;
-            }
-
-            virtual void ParseValue(const std::string &value_) = 0;
-
-            virtual void Reset() noexcept override
-            {
-                matched = false;
-                ready = true;
-#ifdef ARGS_NOEXCEPT
-                error = Error::None;
-                errorMsg.clear();
-#endif
-            }
-
-            virtual PositionalBase *GetNextPositional() override
-            {
-                return Ready() ? this : nullptr;
-            }
-
-            virtual bool HasPositional() const override
-            {
-                return true;
-            }
-
-            virtual std::vector<std::string> GetProgramLine(const HelpParams &params) const override
-            {
-                return { IsRequired() ? params.proglineRequiredOpen + Name() + params.proglineRequiredClose
-                                      : params.proglineNonrequiredOpen + Name() + params.proglineNonrequiredClose };
-            }
-
-            virtual void Validate(const std::string &, const std::string &) const override
-            {
-                if (IsRequired() && !Matched())
-                {
-                    std::ostringstream problem;
-                    problem << "Option '" << Name() << "' is required";
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Required;
-                    errorMsg = problem.str();
-#else
-                    throw RequiredError(problem.str());
-#endif
-                }
-            }
-    };
-
-    /** Class for all kinds of validating groups, including ArgumentParser
-     */
-    class Group : public Base
-    {
-        private:
-            std::vector<Base*> children;
-            std::function<bool(const Group &)> validator;
-
-        public:
-            /** Default validators
-             */
-            struct Validators
-            {
-                static bool Xor(const Group &group)
-                {
-                    return group.MatchedChildren() == 1;
-                }
-
-                static bool AtLeastOne(const Group &group)
-                {
-                    return group.MatchedChildren() >= 1;
-                }
-
-                static bool AtMostOne(const Group &group)
-                {
-                    return group.MatchedChildren() <= 1;
-                }
-
-                static bool All(const Group &group)
-                {
-                    return group.Children().size() == group.MatchedChildren();
-                }
-
-                static bool AllOrNone(const Group &group)
-                {
-                    return (All(group) || None(group));
-                }
-
-                static bool AllChildGroups(const Group &group)
-                {
-                    return std::none_of(std::begin(group.Children()), std::end(group.Children()), [](const Base* child) -> bool {
-                            return child->IsGroup() && !child->Matched();
-                            });
-                }
-
-                static bool DontCare(const Group &)
-                {
-                    return true;
-                }
-
-                static bool CareTooMuch(const Group &)
-                {
-                    return false;
-                }
-
-                static bool None(const Group &group)
-                {
-                    return group.MatchedChildren() == 0;
-                }
-            };
-            /// If help is empty, this group will not be printed in help output
-            Group(const std::string &help_ = std::string(), const std::function<bool(const Group &)> &validator_ = Validators::DontCare, Options options_ = {}) : Base(help_, options_), validator(validator_) {}
-            /// If help is empty, this group will not be printed in help output
-            Group(Group &group_, const std::string &help_ = std::string(), const std::function<bool(const Group &)> &validator_ = Validators::DontCare, Options options_ = {}) : Base(help_, options_), validator(validator_)
-            {
-                group_.Add(*this);
-            }
-            virtual ~Group() {}
-
-            /** Append a child to this Group.
-             */
-            void Add(Base &child)
-            {
-                children.emplace_back(&child);
-            }
-
-            /** Get all this group's children
-             */
-            const std::vector<Base *> &Children() const
-            {
-                return children;
-            }
-
-            /** Return the first FlagBase that matches flag, or nullptr
-             *
-             * \param flag The flag with prefixes stripped
-             * \return the first matching FlagBase pointer, or nullptr if there is no match
-             */
-            virtual FlagBase *Match(const EitherFlag &flag) override
-            {
-                for (Base *child: Children())
-                {
-                    if (FlagBase *match = child->Match(flag))
-                    {
-                        return match;
-                    }
-                }
-                return nullptr;
-            }
-
-            virtual std::vector<FlagBase*> GetAllFlags() override
-            {
-                std::vector<FlagBase*> res;
-                for (Base *child: Children())
-                {
-                    auto childRes = child->GetAllFlags();
-                    res.insert(res.end(), childRes.begin(), childRes.end());
-                }
-                return res;
-            }
-
-            virtual void Validate(const std::string &shortPrefix, const std::string &longPrefix) const override
-            {
-                for (Base *child: Children())
-                {
-                    child->Validate(shortPrefix, longPrefix);
-                }
-            }
-
-            /** Get the next ready positional, or nullptr if there is none
-             *
-             * \return the first ready PositionalBase pointer, or nullptr if there is no match
-             */
-            virtual PositionalBase *GetNextPositional() override
-            {
-                for (Base *child: Children())
-                {
-                    if (auto next = child->GetNextPositional())
-                    {
-                        return next;
-                    }
-                }
-                return nullptr;
-            }
-
-            /** Get whether this has any FlagBase children
-             *
-             * \return Whether or not there are any FlagBase children
-             */
-            virtual bool HasFlag() const override
-            {
-                return std::any_of(Children().begin(), Children().end(), [](Base *child) { return child->HasFlag(); });
-            }
-
-            /** Get whether this has any PositionalBase children
-             *
-             * \return Whether or not there are any PositionalBase children
-             */
-            virtual bool HasPositional() const override
-            {
-                return std::any_of(Children().begin(), Children().end(), [](Base *child) { return child->HasPositional(); });
-            }
-
-            /** Get whether this has any Command children
-             *
-             * \return Whether or not there are any Command children
-             */
-            virtual bool HasCommand() const override
-            {
-                return std::any_of(Children().begin(), Children().end(), [](Base *child) { return child->HasCommand(); });
-            }
-
-            /** Count the number of matched children this group has
-             */
-            std::vector<Base *>::size_type MatchedChildren() const
-            {
-                return std::count_if(std::begin(Children()), std::end(Children()), [](const Base *child){return child->Matched();});
-            }
-
-            /** Whether or not this group matches validation
-             */
-            virtual bool Matched() const noexcept override
-            {
-                return validator(*this);
-            }
-
-            /** Get validation
-             */
-            bool Get() const
-            {
-                return Matched();
-            }
-
-            /** Get all the child descriptions for help generation
-             */
-            virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(const HelpParams &params, const unsigned int indent) const override
-            {
-                std::vector<std::tuple<std::string, std::string, unsigned int>> descriptions;
-
-                // Push that group description on the back if not empty
-                unsigned addindent = 0;
-                if (!help.empty())
-                {
-                    descriptions.emplace_back(help, "", indent);
-                    addindent = 1;
-                }
-
-                for (Base *child: Children())
-                {
-                    if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
-                    {
-                        continue;
-                    }
-
-                    auto groupDescriptions = child->GetDescription(params, indent + addindent);
-                    descriptions.insert(
-                        std::end(descriptions),
-                        std::make_move_iterator(std::begin(groupDescriptions)),
-                        std::make_move_iterator(std::end(groupDescriptions)));
-                }
-                return descriptions;
-            }
-
-            /** Get the names of positional parameters
-             */
-            virtual std::vector<std::string> GetProgramLine(const HelpParams &params) const override
-            {
-                std::vector <std::string> names;
-                for (Base *child: Children())
-                {
-                    if ((child->GetOptions() & Options::HiddenFromUsage) != Options::None)
-                    {
-                        continue;
-                    }
-
-                    auto groupNames = child->GetProgramLine(params);
-                    names.insert(
-                        std::end(names),
-                        std::make_move_iterator(std::begin(groupNames)),
-                        std::make_move_iterator(std::end(groupNames)));
-                }
-                return names;
-            }
-
-            virtual std::vector<Command*> GetCommands() override
-            {
-                std::vector<Command*> res;
-                for (const auto &child : Children())
-                {
-                    auto subparsers = child->GetCommands();
-                    res.insert(std::end(res), std::begin(subparsers), std::end(subparsers));
-                }
-                return res;
-            }
-
-            virtual bool IsGroup() const override
-            {
-                return true;
-            }
-
-            virtual void Reset() noexcept override
-            {
-                Base::Reset();
-
-                for (auto &child: Children())
-                {
-                    child->Reset();
-                }
-#ifdef ARGS_NOEXCEPT
-                error = Error::None;
-                errorMsg.clear();
-#endif
-            }
-
-#ifdef ARGS_NOEXCEPT
-            /// Only for ARGS_NOEXCEPT
-            virtual Error GetError() const override
-            {
-                if (error != Error::None)
-                {
-                    return error;
-                }
-
-                auto it = std::find_if(Children().begin(), Children().end(), [](const Base *child){return child->GetError() != Error::None;});
-                if (it == Children().end())
-                {
-                    return Error::None;
-                } else
-                {
-                    return (*it)->GetError();
-                }
-            }
-#endif
-
-    };
-
-    /** Class for using global options in ArgumentParser.
-     */
-    class GlobalOptions : public Group
-    {
-        public:
-            GlobalOptions(Group &base, Base &options_) : Group(base, {}, Group::Validators::DontCare, Options::Global)
-            {
-                Add(options_);
-            }
-    };
-
-    /** Utility class for building subparsers with coroutines/callbacks.
-     *
-     * Brief example:
-     * \code
-     * Command command(argumentParser, "command", "my command", [](args::Subparser &s)
-     * {
-     *      // your command flags/positionals
-     *      s.Parse(); //required
-     *      //your command code
-     * });
-     * \endcode
-     *
-     * For ARGS_NOEXCEPT mode don't forget to check `s.GetError()` after `s.Parse()`
-     * and return if it isn't equals to args::Error::None.
-     *
-     * \sa Command
-     */
-    class Subparser : public Group
-    {
-        private:
-            std::vector<std::string> args;
-            std::vector<std::string> kicked;
-            ArgumentParser *parser = nullptr;
-            const HelpParams &helpParams;
-            const Command &command;
-            bool isParsed = false;
-
-        public:
-            Subparser(std::vector<std::string> args_, ArgumentParser &parser_, const Command &command_, const HelpParams &helpParams_)
-                : args(std::move(args_)), parser(&parser_), helpParams(helpParams_), command(command_)
-            {
-            }
-
-            Subparser(const Command &command_, const HelpParams &helpParams_) : helpParams(helpParams_), command(command_)
-            {
-            }
-
-            Subparser(const Subparser&) = delete;
-            Subparser(Subparser&&) = delete;
-            Subparser &operator = (const Subparser&) = delete;
-            Subparser &operator = (Subparser&&) = delete;
-
-            const Command &GetCommand()
-            {
-                return command;
-            }
-
-            /** (INTERNAL) Determines whether Parse was called or not.
-             */
-            bool IsParsed() const
-            {
-                return isParsed;
-            }
-
-            /** Continue parsing arguments for new command.
-             */
-            void Parse();
-
-            /** Returns a vector of kicked out arguments.
-             *
-             * \sa Base::KickOut
-             */
-            const std::vector<std::string> &KickedOut() const noexcept
-            {
-                return kicked;
-            }
-    };
-
-    /** Main class for building subparsers.
-     *
-     * /sa Subparser
-     */
-    class Command : public Group
-    {
-        private:
-            friend class Subparser;
-
-            std::string name;
-            std::string help;
-            std::string description;
-            std::string epilog;
-            std::string proglinePostfix;
-
-            std::function<void(Subparser&)> parserCoroutine;
-            bool commandIsRequired = true;
-            Command *selectedCommand = nullptr;
-
-            mutable std::vector<std::tuple<std::string, std::string, unsigned>> subparserDescription;
-            mutable std::vector<std::string> subparserProgramLine;
-            mutable bool subparserHasFlag = false;
-            mutable bool subparserHasPositional = false;
-            mutable bool subparserHasCommand = false;
-#ifdef ARGS_NOEXCEPT
-            mutable Error subparserError = Error::None;
-#endif
-            mutable Subparser *subparser = nullptr;
-
-        protected:
-
-            class RaiiSubparser
-            {
-                public:
-                    RaiiSubparser(ArgumentParser &parser_, std::vector<std::string> args_);
-                    RaiiSubparser(const Command &command_, const HelpParams &params_);
-
-                    ~RaiiSubparser()
-                    {
-                        command.subparser = oldSubparser;
-                    }
-
-                    Subparser &Parser()
-                    {
-                        return parser;
-                    }
-
-                private:
-                    const Command &command;
-                    Subparser parser;
-                    Subparser *oldSubparser;
-            };
-
-            Command() = default;
-
-            std::function<void(Subparser&)> &GetCoroutine()
-            {
-                return selectedCommand != nullptr ? selectedCommand->GetCoroutine() : parserCoroutine;
-            }
-
-            Command &SelectedCommand()
-            {
-                Command *res = this;
-                while (res->selectedCommand != nullptr)
-                {
-                    res = res->selectedCommand;
-                }
-
-                return *res;
-            }
-
-            const Command &SelectedCommand() const
-            {
-                const Command *res = this;
-                while (res->selectedCommand != nullptr)
-                {
-                    res = res->selectedCommand;
-                }
-
-                return *res;
-            }
-
-            void UpdateSubparserHelp(const HelpParams &params) const
-            {
-                if (parserCoroutine)
-                {
-                    RaiiSubparser coro(*this, params);
-#ifndef ARGS_NOEXCEPT
-                    try
-                    {
-                        parserCoroutine(coro.Parser());
-                    }
-                    catch (args::SubparserError&)
-                    {
-                    }
-#else
-                    parserCoroutine(coro.Parser());
-#endif
-                }
-            }
-
-        public:
-            Command(Group &base_, std::string name_, std::string help_, std::function<void(Subparser&)> coroutine_ = {})
-                : name(std::move(name_)), help(std::move(help_)), parserCoroutine(std::move(coroutine_))
-            {
-                base_.Add(*this);
-            }
-
-            /** The description that appears on the prog line after options
-             */
-            const std::string &ProglinePostfix() const
-            { return proglinePostfix; }
-
-            /** The description that appears on the prog line after options
-             */
-            void ProglinePostfix(const std::string &proglinePostfix_)
-            { this->proglinePostfix = proglinePostfix_; }
-
-            /** The description that appears above options
-             */
-            const std::string &Description() const
-            { return description; }
-            /** The description that appears above options
-             */
-
-            void Description(const std::string &description_)
-            { this->description = description_; }
-
-            /** The description that appears below options
-             */
-            const std::string &Epilog() const
-            { return epilog; }
-
-            /** The description that appears below options
-             */
-            void Epilog(const std::string &epilog_)
-            { this->epilog = epilog_; }
-
-            /** The name of command
-             */
-            const std::string &Name() const
-            { return name; }
-
-            /** The description of command
-             */
-            const std::string &Help() const
-            { return help; }
-
-            /** If value is true, parser will fail if no command was parsed.
-             *
-             * Default: true.
-             */
-            void RequireCommand(bool value)
-            { commandIsRequired = value; }
-
-            virtual bool IsGroup() const override
-            { return false; }
-
-            virtual bool Matched() const noexcept override
-            { return Base::Matched(); }
-
-            operator bool() const noexcept
-            { return Matched(); }
-
-            void Match() noexcept
-            { matched = true; }
-
-            void SelectCommand(Command *c) noexcept
-            {
-                selectedCommand = c;
-
-                if (c != nullptr)
-                {
-                    c->Match();
-                }
-            }
-
-            virtual FlagBase *Match(const EitherFlag &flag) override
-            {
-                if (selectedCommand != nullptr)
-                {
-                    if (auto *res = selectedCommand->Match(flag))
-                    {
-                        return res;
-                    }
-
-                    for (auto *child: Children())
-                    {
-                        if ((child->GetOptions() & Options::Global) != Options::None)
-                        {
-                            if (auto *res = child->Match(flag))
-                            {
-                                return res;
-                            }
-                        }
-                    }
-
-                    return nullptr;
-                }
-
-                if (subparser != nullptr)
-                {
-                    return subparser->Match(flag);
-                }
-
-                return Matched() ? Group::Match(flag) : nullptr;
-            }
-
-            virtual std::vector<FlagBase*> GetAllFlags() override
-            {
-                std::vector<FlagBase*> res;
-
-                if (!Matched())
-                {
-                    return res;
-                }
-
-                for (auto *child: Children())
-                {
-                    if (selectedCommand == nullptr || (child->GetOptions() & Options::Global) != Options::None)
-                    {
-                        auto childFlags = child->GetAllFlags();
-                        res.insert(res.end(), childFlags.begin(), childFlags.end());
-                    }
-                }
-
-                if (selectedCommand != nullptr)
-                {
-                    auto childFlags = selectedCommand->GetAllFlags();
-                    res.insert(res.end(), childFlags.begin(), childFlags.end());
-                }
-
-                if (subparser != nullptr)
-                {
-                    auto childFlags = subparser->GetAllFlags();
-                    res.insert(res.end(), childFlags.begin(), childFlags.end());
-                }
-
-                return res;
-            }
-
-            virtual PositionalBase *GetNextPositional() override
-            {
-                if (selectedCommand != nullptr)
-                {
-                    if (auto *res = selectedCommand->GetNextPositional())
-                    {
-                        return res;
-                    }
-
-                    for (auto *child: Children())
-                    {
-                        if ((child->GetOptions() & Options::Global) != Options::None)
-                        {
-                            if (auto *res = child->GetNextPositional())
-                            {
-                                return res;
-                            }
-                        }
-                    }
-
-                    return nullptr;
-                }
-
-                if (subparser != nullptr)
-                {
-                    return subparser->GetNextPositional();
-                }
-
-                return Matched() ? Group::GetNextPositional() : nullptr;
-            }
-
-            virtual bool HasFlag() const override
-            {
-                return subparserHasFlag || Group::HasFlag();
-            }
-
-            virtual bool HasPositional() const override
-            {
-                return subparserHasPositional || Group::HasPositional();
-            }
-
-            virtual bool HasCommand() const override
-            {
-                return true;
-            }
-
-            std::vector<std::string> GetCommandProgramLine(const HelpParams &params) const
-            {
-                UpdateSubparserHelp(params);
-
-                auto res = Group::GetProgramLine(params);
-                res.insert(res.end(), subparserProgramLine.begin(), subparserProgramLine.end());
-
-                if (!params.proglineCommand.empty() && (Group::HasCommand() || subparserHasCommand))
-                {
-                    res.insert(res.begin(), commandIsRequired ? params.proglineCommand : "[" + params.proglineCommand + "]");
-                }
-
-                if (!Name().empty())
-                {
-                    res.insert(res.begin(), Name());
-                }
-
-                if ((subparserHasFlag || Group::HasFlag()) && params.showProglineOptions && !params.proglineShowFlags)
-                {
-                    res.push_back(params.proglineOptions);
-                }
-
-                if (!ProglinePostfix().empty())
-                {
-                    std::string line;
-                    for (char c : ProglinePostfix())
-                    {
-                        if (isspace(c))
-                        {
-                            if (!line.empty())
-                            {
-                                res.push_back(line);
-                                line.clear();
-                            }
-
-                            if (c == '\n')
-                            {
-                                res.push_back("\n");
-                            }
-                        }
-                        else
-                        {
-                            line += c;
-                        }
-                    }
-
-                    if (!line.empty())
-                    {
-                        res.push_back(line);
-                    }
-                }
-
-                return res;
-            }
-
-            virtual std::vector<std::string> GetProgramLine(const HelpParams &params) const override
-            {
-                if (!Matched())
-                {
-                    return {};
-                }
-
-                return GetCommandProgramLine(params);
-            }
-
-            virtual std::vector<Command*> GetCommands() override
-            {
-                if (selectedCommand != nullptr)
-                {
-                    return selectedCommand->GetCommands();
-                }
-
-                if (Matched())
-                {
-                    return Group::GetCommands();
-                }
-
-                return { this };
-            }
-
-            virtual std::vector<std::tuple<std::string, std::string, unsigned>> GetDescription(const HelpParams &params, const unsigned int indent) const override
-            {
-                std::vector<std::tuple<std::string, std::string, unsigned>> descriptions;
-                unsigned addindent = 0;
-
-                UpdateSubparserHelp(params);
-
-                if (!Matched())
-                {
-                    if (params.showCommandFullHelp)
-                    {
-                        std::ostringstream s;
-                        bool empty = true;
-                        for (const auto &progline: GetCommandProgramLine(params))
-                        {
-                            if (!empty)
-                            {
-                                s << ' ';
-                            }
-                            else
-                            {
-                                empty = false;
-                            }
-
-                            s << progline;
-                        }
-
-                        descriptions.emplace_back(s.str(), "", indent);
-                    }
-                    else
-                    {
-                        descriptions.emplace_back(Name(), help, indent);
-                    }
-
-                    if (!params.showCommandChildren && !params.showCommandFullHelp)
-                    {
-                        return descriptions;
-                    }
-
-                    addindent = 1;
-                }
-
-                if (params.showCommandFullHelp && !Matched())
-                {
-                    descriptions.emplace_back("", "", indent + addindent);
-                    descriptions.emplace_back(Description().empty() ? Help() : Description(), "", indent + addindent);
-                    descriptions.emplace_back("", "", indent + addindent);
-                }
-
-                for (Base *child: Children())
-                {
-                    if ((child->GetOptions() & Options::HiddenFromDescription) != Options::None)
-                    {
-                        continue;
-                    }
-
-                    auto groupDescriptions = child->GetDescription(params, indent + addindent);
-                    descriptions.insert(
-                                        std::end(descriptions),
-                                        std::make_move_iterator(std::begin(groupDescriptions)),
-                                        std::make_move_iterator(std::end(groupDescriptions)));
-                }
-
-                for (auto childDescription: subparserDescription)
-                {
-                    std::get<2>(childDescription) += indent + addindent;
-                    descriptions.push_back(std::move(childDescription));
-                }
-
-                if (params.showCommandFullHelp && !Matched())
-                {
-                    descriptions.emplace_back("", "", indent + addindent);
-                    if (!Epilog().empty())
-                    {
-                        descriptions.emplace_back(Epilog(), "", indent + addindent);
-                        descriptions.emplace_back("", "", indent + addindent);
-                    }
-                }
-
-                return descriptions;
-            }
-
-            virtual void Validate(const std::string &shortprefix, const std::string &longprefix) const override
-            {
-                if (!Matched())
-                {
-                    return;
-                }
-
-                for (Base *child: Children())
-                {
-                    if (child->IsGroup() && !child->Matched())
-                    {
-                        std::ostringstream problem;
-                        problem << "Group validation failed somewhere!";
-#ifdef ARGS_NOEXCEPT
-                        error = Error::Validation;
-                        errorMsg = problem.str();
-#else
-                        throw ValidationError(problem.str());
-#endif
-                    }
-
-                    child->Validate(shortprefix, longprefix);
-                }
-
-                if (subparser != nullptr)
-                {
-                    subparser->Validate(shortprefix, longprefix);
-                }
-
-                if (selectedCommand == nullptr && commandIsRequired && (Group::HasCommand() || subparserHasCommand))
-                {
-                    std::ostringstream problem;
-                    problem << "Command is required";
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Validation;
-                    errorMsg = problem.str();
-#else
-                    throw ValidationError(problem.str());
-#endif
-                }
-            }
-
-            virtual void Reset() noexcept override
-            {
-                Group::Reset();
-                selectedCommand = nullptr;
-                subparserProgramLine.clear();
-                subparserDescription.clear();
-                subparserHasFlag = false;
-                subparserHasPositional = false;
-                subparserHasCommand = false;
-#ifdef ARGS_NOEXCEPT
-                subparserError = Error::None;
-#endif
-            }
-
-#ifdef ARGS_NOEXCEPT
-            /// Only for ARGS_NOEXCEPT
-            virtual Error GetError() const override
-            {
-                if (!Matched())
-                {
-                    return Error::None;
-                }
-
-                if (error != Error::None)
-                {
-                    return error;
-                }
-
-                if (subparserError != Error::None)
-                {
-                    return subparserError;
-                }
-
-                return Group::GetError();
-            }
-#endif
-    };
-
-    /** The main user facing command line argument parser class
-     */
-    class ArgumentParser : public Command
-    {
-        friend class Subparser;
-
-        private:
-            std::string longprefix;
-            std::string shortprefix;
-
-            std::string longseparator;
-
-            std::string terminator;
-
-            bool allowJoinedShortValue = true;
-            bool allowJoinedLongValue = true;
-            bool allowSeparateShortValue = true;
-            bool allowSeparateLongValue = true;
-
-            CompletionFlag *completion = nullptr;
-            bool readCompletion = false;
-
-        protected:
-            enum class OptionType
-            {
-                LongFlag,
-                ShortFlag,
-                Positional
-            };
-
-            OptionType ParseOption(const std::string &s, bool allowEmpty = false)
-            {
-                if (s.find(longprefix) == 0 && (allowEmpty || s.length() > longprefix.length()))
-                {
-                    return OptionType::LongFlag;
-                }
-
-                if (s.find(shortprefix) == 0 && (allowEmpty || s.length() > shortprefix.length()))
-                {
-                    return OptionType::ShortFlag;
-                }
-
-                return OptionType::Positional;
-            }
-
-            template <typename It>
-            bool Complete(FlagBase &flag, It it, It end)
-            {
-                auto nextIt = it;
-                if (!readCompletion || (++nextIt != end))
-                {
-                    return false;
-                }
-
-                const auto &chunk = *it;
-                for (auto &choice : flag.HelpChoices(helpParams))
-                {
-                    AddCompletionReply(chunk, choice);
-                }
-
-#ifndef ARGS_NOEXCEPT
-                throw Completion(completion->Get());
-#else
-                return true;
-#endif
-            }
-
-            /** (INTERNAL) Parse flag's values
-             *
-             * \param arg The string to display in error message as a flag name
-             * \param[in, out] it The iterator to first value. It will point to the last value
-             * \param end The end iterator
-             * \param joinedArg Joined value (e.g. bar in --foo=bar)
-             * \param canDiscardJoined If true joined value can be parsed as flag not as a value (as in -abcd)
-             * \param[out] values The vector to store parsed arg's values
-             */
-            template <typename It>
-            std::string ParseArgsValues(FlagBase &flag, const std::string &arg, It &it, It end,
-                                        const bool allowSeparate, const bool allowJoined,
-                                        const bool hasJoined, const std::string &joinedArg,
-                                        const bool canDiscardJoined, std::vector<std::string> &values)
-            {
-                values.clear();
-
-                Nargs nargs = flag.NumberOfArguments();
-
-                if (hasJoined && !allowJoined && nargs.min != 0)
-                {
-                    return "Flag '" + arg + "' was passed a joined argument, but these are disallowed";
-                }
-
-                if (hasJoined)
-                {
-                    if (!canDiscardJoined || nargs.max != 0)
-                    {
-                        values.push_back(joinedArg);
-                    }
-                } else if (!allowSeparate)
-                {
-                    if (nargs.min != 0)
-                    {
-                        return "Flag '" + arg + "' was passed a separate argument, but these are disallowed";
-                    }
-                } else
-                {
-                    auto valueIt = it;
-                    ++valueIt;
-
-                    while (valueIt != end &&
-                           values.size() < nargs.max &&
-                           (nargs.min == nargs.max || ParseOption(*valueIt) == OptionType::Positional))
-                    {
-                        if (Complete(flag, valueIt, end))
-                        {
-                            it = end;
-                            return "";
-                        }
-
-                        values.push_back(*valueIt);
-                        ++it;
-                        ++valueIt;
-                    }
-                }
-
-                if (values.size() > nargs.max)
-                {
-                    return "Passed an argument into a non-argument flag: " + arg;
-                } else if (values.size() < nargs.min)
-                {
-                    if (nargs.min == 1 && nargs.max == 1)
-                    {
-                        return "Flag '" + arg + "' requires an argument but received none";
-                    } else if (nargs.min == 1)
-                    {
-                        return "Flag '" + arg + "' requires at least one argument but received none";
-                    } else if (nargs.min != nargs.max)
-                    {
-                        return "Flag '" + arg + "' requires at least " + std::to_string(nargs.min) +
-                               " arguments but received " + std::to_string(values.size());
-                    } else
-                    {
-                        return "Flag '" + arg + "' requires " + std::to_string(nargs.min) +
-                               " arguments but received " + std::to_string(values.size());
-                    }
-                }
-
-                return {};
-            }
-
-            template <typename It>
-            bool ParseLong(It &it, It end)
-            {
-                const auto &chunk = *it;
-                const auto argchunk = chunk.substr(longprefix.size());
-                // Try to separate it, in case of a separator:
-                const auto separator = longseparator.empty() ? argchunk.npos : argchunk.find(longseparator);
-                // If the separator is in the argument, separate it.
-                const auto arg = (separator != argchunk.npos ?
-                    std::string(argchunk, 0, separator)
-                    : argchunk);
-                const auto joined = (separator != argchunk.npos ?
-                    argchunk.substr(separator + longseparator.size())
-                    : std::string());
-
-                if (auto flag = Match(arg))
-                {
-                    std::vector<std::string> values;
-                    const std::string errorMessage = ParseArgsValues(*flag, arg, it, end, allowSeparateLongValue, allowJoinedLongValue,
-                                                                     separator != argchunk.npos, joined, false, values);
-                    if (!errorMessage.empty())
-                    {
-#ifndef ARGS_NOEXCEPT
-                        throw ParseError(errorMessage);
-#else
-                        error = Error::Parse;
-                        errorMsg = errorMessage;
-                        return false;
-#endif
-                    }
-
-                    if (!readCompletion)
-                    {
-                        flag->ParseValue(values);
-                    }
-
-                    if (flag->KickOut())
-                    {
-                        ++it;
-                        return false;
-                    }
-                } else
-                {
-                    const std::string errorMessage("Flag could not be matched: " + arg);
-#ifndef ARGS_NOEXCEPT
-                    throw ParseError(errorMessage);
-#else
-                    error = Error::Parse;
-                    errorMsg = errorMessage;
-                    return false;
-#endif
-                }
-
-                return true;
-            }
-
-            template <typename It>
-            bool ParseShort(It &it, It end)
-            {
-                const auto &chunk = *it;
-                const auto argchunk = chunk.substr(shortprefix.size());
-                for (auto argit = std::begin(argchunk); argit != std::end(argchunk); ++argit)
-                {
-                    const auto arg = *argit;
-
-                    if (auto flag = Match(arg))
-                    {
-                        const std::string value(argit + 1, std::end(argchunk));
-                        std::vector<std::string> values;
-                        const std::string errorMessage = ParseArgsValues(*flag, std::string(1, arg), it, end,
-                                                                         allowSeparateShortValue, allowJoinedShortValue,
-                                                                         !value.empty(), value, !value.empty(), values);
-
-                        if (!errorMessage.empty())
-                        {
-#ifndef ARGS_NOEXCEPT
-                            throw ParseError(errorMessage);
-#else
-                            error = Error::Parse;
-                            errorMsg = errorMessage;
-                            return false;
-#endif
-                        }
-
-                        if (!readCompletion)
-                        {
-                            flag->ParseValue(values);
-                        }
-
-                        if (flag->KickOut())
-                        {
-                            ++it;
-                            return false;
-                        }
-
-                        if (!values.empty())
-                        {
-                            break;
-                        }
-                    } else
-                    {
-                        const std::string errorMessage("Flag could not be matched: '" + std::string(1, arg) + "'");
-#ifndef ARGS_NOEXCEPT
-                        throw ParseError(errorMessage);
-#else
-                        error = Error::Parse;
-                        errorMsg = errorMessage;
-                        return false;
-#endif
-                    }
-                }
-
-                return true;
-            }
-
-            bool AddCompletionReply(const std::string &cur, const std::string &choice)
-            {
-                if (cur.empty() || choice.find(cur) == 0)
-                {
-                    if (completion->syntax == "bash" && ParseOption(choice) == OptionType::LongFlag && choice.find(longseparator) != std::string::npos)
-                    {
-                        completion->reply.push_back(choice.substr(choice.find(longseparator) + 1));
-                    } else
-                    {
-                        completion->reply.push_back(choice);
-                    }
-                    return true;
-                }
-
-                return false;
-            }
-
-            template <typename It>
-            bool Complete(It it, It end)
-            {
-                auto nextIt = it;
-                if (!readCompletion || (++nextIt != end))
-                {
-                    return false;
-                }
-
-                const auto &chunk = *it;
-                auto pos = GetNextPositional();
-                std::vector<Command *> commands = GetCommands();
-                const auto optionType = ParseOption(chunk, true);
-
-                if (!commands.empty() && (chunk.empty() || optionType == OptionType::Positional))
-                {
-                    for (auto &cmd : commands)
-                    {
-                        if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
-                        {
-                            AddCompletionReply(chunk, cmd->Name());
-                        }
-                    }
-                } else
-                {
-                    bool hasPositionalCompletion = true;
-
-                    if (!commands.empty())
-                    {
-                        for (auto &cmd : commands)
-                        {
-                            if ((cmd->GetOptions() & Options::HiddenFromCompletion) == Options::None)
-                            {
-                                AddCompletionReply(chunk, cmd->Name());
-                            }
-                        }
-                    } else if (pos)
-                    {
-                        if ((pos->GetOptions() & Options::HiddenFromCompletion) == Options::None)
-                        {
-                            auto choices = pos->HelpChoices(helpParams);
-                            hasPositionalCompletion = !choices.empty() || optionType != OptionType::Positional;
-                            for (auto &choice : choices)
-                            {
-                                AddCompletionReply(chunk, choice);
-                            }
-                        }
-                    }
-
-                    if (hasPositionalCompletion)
-                    {
-                        auto flags = GetAllFlags();
-                        for (auto flag : flags)
-                        {
-                            if ((flag->GetOptions() & Options::HiddenFromCompletion) != Options::None)
-                            {
-                                continue;
-                            }
-
-                            auto &matcher = flag->GetMatcher();
-                            if (!AddCompletionReply(chunk, matcher.GetShortOrAny().str(shortprefix, longprefix)))
-                            {
-                                for (auto &flagName : matcher.GetFlagStrings())
-                                {
-                                    if (AddCompletionReply(chunk, flagName.str(shortprefix, longprefix)))
-                                    {
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-
-                        if (optionType == OptionType::LongFlag && allowJoinedLongValue)
-                        {
-                            const auto separator = longseparator.empty() ? chunk.npos : chunk.find(longseparator);
-                            if (separator != chunk.npos)
-                            {
-                                std::string arg(chunk, 0, separator);
-                                if (auto flag = this->Match(arg.substr(longprefix.size())))
-                                {
-                                    for (auto &choice : flag->HelpChoices(helpParams))
-                                    {
-                                        AddCompletionReply(chunk, arg + longseparator + choice);
-                                    }
-                                }
-                            }
-                        } else if (optionType == OptionType::ShortFlag && allowJoinedShortValue)
-                        {
-                            if (chunk.size() > shortprefix.size() + 1)
-                            {
-                                auto arg = chunk.at(shortprefix.size());
-                                //TODO: support -abcVALUE where a and b take no value
-                                if (auto flag = this->Match(arg))
-                                {
-                                    for (auto &choice : flag->HelpChoices(helpParams))
-                                    {
-                                        AddCompletionReply(chunk, shortprefix + arg + choice);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-
-#ifndef ARGS_NOEXCEPT
-                throw Completion(completion->Get());
-#else
-                return true;
-#endif
-            }
-
-            template <typename It>
-            It Parse(It begin, It end)
-            {
-                bool terminated = false;
-                std::vector<Command *> commands = GetCommands();
-
-                // Check all arg chunks
-                for (auto it = begin; it != end; ++it)
-                {
-                    if (Complete(it, end))
-                    {
-                        return end;
-                    }
-
-                    const auto &chunk = *it;
-
-                    if (!terminated && chunk == terminator)
-                    {
-                        terminated = true;
-                    } else if (!terminated && ParseOption(chunk) == OptionType::LongFlag)
-                    {
-                        if (!ParseLong(it, end))
-                        {
-                            return it;
-                        }
-                    } else if (!terminated && ParseOption(chunk) == OptionType::ShortFlag)
-                    {
-                        if (!ParseShort(it, end))
-                        {
-                            return it;
-                        }
-                    } else if (!terminated && !commands.empty())
-                    {
-                        auto itCommand = std::find_if(commands.begin(), commands.end(), [&chunk](Command *c) { return c->Name() == chunk; });
-                        if (itCommand == commands.end())
-                        {
-                            const std::string errorMessage("Unknown command: " + chunk);
-#ifndef ARGS_NOEXCEPT
-                            throw ParseError(errorMessage);
-#else
-                            error = Error::Parse;
-                            errorMsg = errorMessage;
-                            return it;
-#endif
-                        }
-
-                        SelectCommand(*itCommand);
-
-                        if (const auto &coroutine = GetCoroutine())
-                        {
-                            ++it;
-                            RaiiSubparser coro(*this, std::vector<std::string>(it, end));
-                            coroutine(coro.Parser());
-#ifdef ARGS_NOEXCEPT
-                            error = GetError();
-                            if (error != Error::None)
-                            {
-                                return end;
-                            }
-
-                            if (!coro.Parser().IsParsed())
-                            {
-                                error = Error::Usage;
-                                return end;
-                            }
-#else
-                            if (!coro.Parser().IsParsed())
-                            {
-                                throw UsageError("Subparser::Parse was not called");
-                            }
-#endif
-
-                            break;
-                        }
-
-                        commands = GetCommands();
-                    } else
-                    {
-                        auto pos = GetNextPositional();
-                        if (pos)
-                        {
-                            pos->ParseValue(chunk);
-
-                            if (pos->KickOut())
-                            {
-                                return ++it;
-                            }
-                        } else
-                        {
-                            const std::string errorMessage("Passed in argument, but no positional arguments were ready to receive it: " + chunk);
-#ifndef ARGS_NOEXCEPT
-                            throw ParseError(errorMessage);
-#else
-                            error = Error::Parse;
-                            errorMsg = errorMessage;
-                            return it;
-#endif
-                        }
-                    }
-
-                    if (!readCompletion && completion != nullptr && completion->Matched())
-                    {
-#ifdef ARGS_NOEXCEPT
-                        error = Error::Completion;
-#endif
-                        readCompletion = true;
-                        ++it;
-                        size_t argsLeft = std::distance(it, end);
-                        if (completion->cword == 0 || argsLeft <= 1 || completion->cword >= argsLeft)
-                        {
-#ifndef ARGS_NOEXCEPT
-                            throw Completion("");
-#endif
-                        }
-
-                        std::vector<std::string> curArgs(++it, end);
-                        curArgs.resize(completion->cword);
-
-                        if (completion->syntax == "bash")
-                        {
-                            // bash tokenizes --flag=value as --flag=value
-                            for (size_t idx = 0; idx < curArgs.size(); )
-                            {
-                                if (idx > 0 && curArgs[idx] == "=")
-                                {
-                                    curArgs[idx - 1] += "=";
-                                    if (idx + 1 < curArgs.size())
-                                    {
-                                        curArgs[idx - 1] += curArgs[idx + 1];
-                                        curArgs.erase(curArgs.begin() + idx, curArgs.begin() + idx + 2);
-                                    } else
-                                    {
-                                        curArgs.erase(curArgs.begin() + idx);
-                                    }
-                                } else
-                                {
-                                    ++idx;
-                                }
-                            }
-
-                        }
-#ifndef ARGS_NOEXCEPT
-                        try
-                        {
-                            Parse(curArgs.begin(), curArgs.end());
-                            throw Completion("");
-                        }
-                        catch (Completion &)
-                        {
-                            throw;
-                        }
-                        catch (args::Error&)
-                        {
-                            throw Completion("");
-                        }
-#else
-                        return Parse(curArgs.begin(), curArgs.end());
-#endif
-                    }
-                }
-
-                Validate(shortprefix, longprefix);
-                return end;
-            }
-
-        public:
-            HelpParams helpParams;
-
-            ArgumentParser(const std::string &description_, const std::string &epilog_ = std::string())
-            {
-                Description(description_);
-                Epilog(epilog_);
-                LongPrefix("--");
-                ShortPrefix("-");
-                LongSeparator("=");
-                Terminator("--");
-                SetArgumentSeparations(true, true, true, true);
-                matched = true;
-            }
-
-            void AddCompletion(CompletionFlag &completionFlag)
-            {
-                completion = &completionFlag;
-                Add(completionFlag);
-            }
-
-            /** The program name for help generation
-             */
-            const std::string &Prog() const
-            { return helpParams.programName; }
-            /** The program name for help generation
-             */
-            void Prog(const std::string &prog_)
-            { this->helpParams.programName = prog_; }
-
-            /** The prefix for long flags
-             */
-            const std::string &LongPrefix() const
-            { return longprefix; }
-            /** The prefix for long flags
-             */
-            void LongPrefix(const std::string &longprefix_)
-            {
-                this->longprefix = longprefix_;
-                this->helpParams.longPrefix = longprefix_;
-            }
-
-            /** The prefix for short flags
-             */
-            const std::string &ShortPrefix() const
-            { return shortprefix; }
-            /** The prefix for short flags
-             */
-            void ShortPrefix(const std::string &shortprefix_)
-            {
-                this->shortprefix = shortprefix_;
-                this->helpParams.shortPrefix = shortprefix_;
-            }
-
-            /** The separator for long flags
-             */
-            const std::string &LongSeparator() const
-            { return longseparator; }
-            /** The separator for long flags
-             */
-            void LongSeparator(const std::string &longseparator_)
-            {
-                if (longseparator_.empty())
-                {
-                    const std::string errorMessage("longseparator can not be set to empty");
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Usage;
-                    errorMsg = errorMessage;
-#else
-                    throw UsageError(errorMessage);
-#endif
-                } else
-                {
-                    this->longseparator = longseparator_;
-                    this->helpParams.longSeparator = allowJoinedLongValue ? longseparator_ : " ";
-                }
-            }
-
-            /** The terminator that forcibly separates flags from positionals
-             */
-            const std::string &Terminator() const
-            { return terminator; }
-            /** The terminator that forcibly separates flags from positionals
-             */
-            void Terminator(const std::string &terminator_)
-            { this->terminator = terminator_; }
-
-            /** Get the current argument separation parameters.
-             *
-             * See SetArgumentSeparations for details on what each one means.
-             */
-            void GetArgumentSeparations(
-                bool &allowJoinedShortValue_,
-                bool &allowJoinedLongValue_,
-                bool &allowSeparateShortValue_,
-                bool &allowSeparateLongValue_) const
-            {
-                allowJoinedShortValue_ = this->allowJoinedShortValue;
-                allowJoinedLongValue_ = this->allowJoinedLongValue;
-                allowSeparateShortValue_ = this->allowSeparateShortValue;
-                allowSeparateLongValue_ = this->allowSeparateLongValue;
-            }
-
-            /** Change allowed option separation.
-             *
-             * \param allowJoinedShortValue_ Allow a short flag that accepts an argument to be passed its argument immediately next to it (ie. in the same argv field)
-             * \param allowJoinedLongValue_ Allow a long flag that accepts an argument to be passed its argument separated by the longseparator (ie. in the same argv field)
-             * \param allowSeparateShortValue_ Allow a short flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field)
-             * \param allowSeparateLongValue_ Allow a long flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field)
-             */
-            void SetArgumentSeparations(
-                const bool allowJoinedShortValue_,
-                const bool allowJoinedLongValue_,
-                const bool allowSeparateShortValue_,
-                const bool allowSeparateLongValue_)
-            {
-                this->allowJoinedShortValue = allowJoinedShortValue_;
-                this->allowJoinedLongValue = allowJoinedLongValue_;
-                this->allowSeparateShortValue = allowSeparateShortValue_;
-                this->allowSeparateLongValue = allowSeparateLongValue_;
-
-                this->helpParams.longSeparator = allowJoinedLongValue ? longseparator : " ";
-                this->helpParams.shortSeparator = allowJoinedShortValue ? "" : " ";
-            }
-
-            /** Pass the help menu into an ostream
-             */
-            void Help(std::ostream &help_) const
-            {
-                auto &command = SelectedCommand();
-                const auto &commandDescription = command.Description().empty() ? command.Help() : command.Description();
-                const auto description_text = Wrap(commandDescription, helpParams.width - helpParams.descriptionindent);
-                const auto epilog_text = Wrap(command.Epilog(), helpParams.width - helpParams.descriptionindent);
-
-                const bool hasoptions = command.HasFlag();
-                const bool hasarguments = command.HasPositional();
-
-                std::vector<std::string> prognameline;
-                prognameline.push_back(helpParams.usageString);
-                prognameline.push_back(Prog());
-                auto commandProgLine = command.GetProgramLine(helpParams);
-                prognameline.insert(prognameline.end(), commandProgLine.begin(), commandProgLine.end());
-
-                const auto proglines = Wrap(prognameline.begin(), prognameline.end(),
-                                            helpParams.width - (helpParams.progindent + helpParams.progtailindent),
-                                            helpParams.width - helpParams.progindent);
-                auto progit = std::begin(proglines);
-                if (progit != std::end(proglines))
-                {
-                    help_ << std::string(helpParams.progindent, ' ') << *progit << '\n';
-                    ++progit;
-                }
-                for (; progit != std::end(proglines); ++progit)
-                {
-                    help_ << std::string(helpParams.progtailindent, ' ') << *progit << '\n';
-                }
-
-                help_ << '\n';
-
-                if (!description_text.empty())
-                {
-                    for (const auto &line: description_text)
-                    {
-                        help_ << std::string(helpParams.descriptionindent, ' ') << line << "\n";
-                    }
-                    help_ << "\n";
-                }
-
-                bool lastDescriptionIsNewline = false;
-
-                if (!helpParams.optionsString.empty())
-                {
-                    help_ << std::string(helpParams.progindent, ' ') << helpParams.optionsString << "\n\n";
-                }
-
-                for (const auto &desc: command.GetDescription(helpParams, 0))
-                {
-                    lastDescriptionIsNewline = std::get<0>(desc).empty() && std::get<1>(desc).empty();
-                    const auto groupindent = std::get<2>(desc) * helpParams.eachgroupindent;
-                    const auto flags = Wrap(std::get<0>(desc), helpParams.width - (helpParams.flagindent + helpParams.helpindent + helpParams.gutter));
-                    const auto info = Wrap(std::get<1>(desc), helpParams.width - (helpParams.helpindent + groupindent));
-
-                    std::string::size_type flagssize = 0;
-                    for (auto flagsit = std::begin(flags); flagsit != std::end(flags); ++flagsit)
-                    {
-                        if (flagsit != std::begin(flags))
-                        {
-                            help_ << '\n';
-                        }
-                        help_ << std::string(groupindent + helpParams.flagindent, ' ') << *flagsit;
-                        flagssize = Glyphs(*flagsit);
-                    }
-
-                    auto infoit = std::begin(info);
-                    // groupindent is on both sides of this inequality, and therefore can be removed
-                    if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info) || helpParams.addNewlineBeforeDescription)
-                    {
-                        help_ << '\n';
-                    } else
-                    {
-                        // groupindent is on both sides of the minus sign, and therefore doesn't actually need to be in here
-                        help_ << std::string(helpParams.helpindent - (helpParams.flagindent + flagssize), ' ') << *infoit << '\n';
-                        ++infoit;
-                    }
-                    for (; infoit != std::end(info); ++infoit)
-                    {
-                        help_ << std::string(groupindent + helpParams.helpindent, ' ') << *infoit << '\n';
-                    }
-                }
-                if (hasoptions && hasarguments && helpParams.showTerminator)
-                {
-                    lastDescriptionIsNewline = false;
-                    for (const auto &item: Wrap(std::string("\"") + terminator + "\" can be used to terminate flag options and force all following arguments to be treated as positional options", helpParams.width - helpParams.flagindent))
-                    {
-                        help_ << std::string(helpParams.flagindent, ' ') << item << '\n';
-                    }
-                }
-
-                if (!lastDescriptionIsNewline)
-                {
-                    help_ << "\n";
-                }
-
-                for (const auto &line: epilog_text)
-                {
-                    help_ << std::string(helpParams.descriptionindent, ' ') << line << "\n";
-                }
-            }
-
-            /** Generate a help menu as a string.
-             *
-             * \return the help text as a single string
-             */
-            std::string Help() const
-            {
-                std::ostringstream help_;
-                Help(help_);
-                return help_.str();
-            }
-
-            virtual void Reset() noexcept override
-            {
-                Command::Reset();
-                matched = true;
-                readCompletion = false;
-            }
-
-            /** Parse all arguments.
-             *
-             * \param begin an iterator to the beginning of the argument list
-             * \param end an iterator to the past-the-end element of the argument list
-             * \return the iterator after the last parsed value.  Only useful for kick-out
-             */
-            template <typename It>
-            It ParseArgs(It begin, It end)
-            {
-                // Reset all Matched statuses and errors
-                Reset();
-#ifdef ARGS_NOEXCEPT
-                error = GetError();
-                if (error != Error::None)
-                {
-                    return end;
-                }
-#endif
-                return Parse(begin, end);
-            }
-
-            /** Parse all arguments.
-             *
-             * \param args an iterable of the arguments
-             * \return the iterator after the last parsed value.  Only useful for kick-out
-             */
-            template <typename T>
-            auto ParseArgs(const T &args) -> decltype(std::begin(args))
-            {
-                return ParseArgs(std::begin(args), std::end(args));
-            }
-
-            /** Convenience function to parse the CLI from argc and argv
-             *
-             * Just assigns the program name and vectorizes arguments for passing into ParseArgs()
-             *
-             * \return whether or not all arguments were parsed.  This works for detecting kick-out, but is generally useless as it can't do anything with it.
-             */
-            bool ParseCLI(const int argc, const char * const * argv)
-            {
-                if (Prog().empty())
-                {
-                    Prog(argv[0]);
-                }
-                const std::vector<std::string> args(argv + 1, argv + argc);
-                return ParseArgs(args) == std::end(args);
-            }
-            
-            template <typename T>
-            bool ParseCLI(const T &args)
-            {
-                return ParseArgs(args) == std::end(args);
-            }
-    };
-
-    inline Command::RaiiSubparser::RaiiSubparser(ArgumentParser &parser_, std::vector<std::string> args_)
-        : command(parser_.SelectedCommand()), parser(std::move(args_), parser_, command, parser_.helpParams), oldSubparser(command.subparser)
-    {
-        command.subparser = &parser;
-    }
-
-    inline Command::RaiiSubparser::RaiiSubparser(const Command &command_, const HelpParams &params_): command(command_), parser(command, params_), oldSubparser(command.subparser)
-    {
-        command.subparser = &parser;
-    }
-
-    inline void Subparser::Parse()
-    {
-        isParsed = true;
-        Reset();
-        command.subparserDescription = GetDescription(helpParams, 0);
-        command.subparserHasFlag = HasFlag();
-        command.subparserHasPositional = HasPositional();
-        command.subparserHasCommand = HasCommand();
-        command.subparserProgramLine = GetProgramLine(helpParams);
-        if (parser == nullptr)
-        {
-#ifndef ARGS_NOEXCEPT
-            throw args::SubparserError();
-#else
-            error = Error::Subparser;
-            return;
-#endif
-        }
-
-        auto it = parser->Parse(args.begin(), args.end());
-        command.Validate(parser->ShortPrefix(), parser->LongPrefix());
-        kicked.assign(it, args.end());
-
-#ifdef ARGS_NOEXCEPT
-        command.subparserError = GetError();
-#endif
-    }
-
-    inline std::ostream &operator<<(std::ostream &os, const ArgumentParser &parser)
-    {
-        parser.Help(os);
-        return os;
-    }
-
-    /** Boolean argument matcher
-     */
-    class Flag : public FlagBase
-    {
-        public:
-            Flag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, Options options_): FlagBase(name_, help_, std::move(matcher_), options_)
-            {
-                group_.Add(*this);
-            }
-
-            Flag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const bool extraError_ = false): Flag(group_, name_, help_, std::move(matcher_), extraError_ ? Options::Single : Options::None)
-            {
-            }
-
-            virtual ~Flag() {}
-
-            /** Get whether this was matched
-             */
-            bool Get() const
-            {
-                return Matched();
-            }
-
-            virtual Nargs NumberOfArguments() const noexcept override
-            {
-                return 0;
-            }
-
-            virtual void ParseValue(const std::vector<std::string>&) override
-            {
-            }
-    };
-
-    /** Help flag class
-     *
-     * Works like a regular flag, but throws an instance of Help when it is matched
-     */
-    class HelpFlag : public Flag
-    {
-        public:
-            HelpFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, Options options_ = {}): Flag(group_, name_, help_, std::move(matcher_), options_) {}
-
-            virtual ~HelpFlag() {}
-
-            virtual void ParseValue(const std::vector<std::string> &)
-            {
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Help;
-                    errorMsg = Name();
-#else
-                    throw Help(Name());
-#endif
-            }
-
-            /** Get whether this was matched
-             */
-            bool Get() const noexcept
-            {
-                return Matched();
-            }
-    };
-
-    /** A flag class that simply counts the number of times it's matched
-     */
-    class CounterFlag : public Flag
-    {
-        private:
-            const int startcount;
-            int count;
-
-        public:
-            CounterFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const int startcount_ = 0, Options options_ = {}):
-                Flag(group_, name_, help_, std::move(matcher_), options_), startcount(startcount_), count(startcount_) {}
-
-            virtual ~CounterFlag() {}
-
-            virtual FlagBase *Match(const EitherFlag &arg) override
-            {
-                auto me = FlagBase::Match(arg);
-                if (me)
-                {
-                    ++count;
-                }
-                return me;
-            }
-
-            /** Get the count
-             */
-            int &Get() noexcept
-            {
-                return count;
-            }
-
-            virtual void Reset() noexcept override
-            {
-                FlagBase::Reset();
-                count = startcount;
-            }
-    };
-
-    /** A flag class that calls a function when it's matched
-     */
-    class ActionFlag : public FlagBase
-    {
-        private:
-            std::function<void(const std::vector<std::string> &)> action;
-            Nargs nargs;
-
-        public:
-            ActionFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, Nargs nargs_, std::function<void(const std::vector<std::string> &)> action_, Options options_ = {}):
-                FlagBase(name_, help_, std::move(matcher_), options_), action(std::move(action_)), nargs(nargs_)
-            {
-                group_.Add(*this);
-            }
-
-            ActionFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, std::function<void(const std::string &)> action_, Options options_ = {}):
-                FlagBase(name_, help_, std::move(matcher_), options_), nargs(1)
-            {
-                group_.Add(*this);
-                action = [action_](const std::vector<std::string> &a) { return action_(a.at(0)); };
-            }
-
-            ActionFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, std::function<void()> action_, Options options_ = {}):
-                FlagBase(name_, help_, std::move(matcher_), options_), nargs(0)
-            {
-                group_.Add(*this);
-                action = [action_](const std::vector<std::string> &) { return action_(); };
-            }
-
-            virtual Nargs NumberOfArguments() const noexcept override
-            { return nargs; }
-
-            virtual void ParseValue(const std::vector<std::string> &value) override
-            { action(value); }
-    };
-
-    /** A default Reader class for argument classes
-     *
-     * If destination type is assignable to std::string it uses an assignment to std::string.
-     * Otherwise ValueReader simply uses a std::istringstream to read into the destination type, and
-     * raises a ParseError if there are any characters left.
-     */
-    struct ValueReader
-    {
-        template <typename T>
-        typename std::enable_if<!std::is_assignable<T, std::string>::value, bool>::type
-        operator ()(const std::string &name, const std::string &value, T &destination)
-        {
-            std::istringstream ss(value);
-            ss >> destination >> std::ws;
-
-            if (ss.rdbuf()->in_avail() > 0)
-            {
-#ifdef ARGS_NOEXCEPT
-                (void)name;
-                return false;
-#else
-                std::ostringstream problem;
-                problem << "Argument '" << name << "' received invalid value type '" << value << "'";
-                throw ParseError(problem.str());
-#endif
-            }
-            return true;
-        }
-
-        template <typename T>
-        typename std::enable_if<std::is_assignable<T, std::string>::value, bool>::type
-        operator()(const std::string &, const std::string &value, T &destination)
-        {
-            destination = value;
-            return true;
-        }
-    };
-
-    /** An argument-accepting flag class
-     * 
-     * \tparam T the type to extract the argument as
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     */
-    template <
-        typename T,
-        typename Reader = ValueReader>
-    class ValueFlag : public ValueFlagBase
-    {
-        protected:
-            T value;
-            T defaultValue;
-
-            virtual std::string GetDefaultString(const HelpParams&) const override
-            {
-                return detail::ToString(defaultValue);
-            }
-
-        private:
-            Reader reader;
-
-        public:
-
-            ValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const T &defaultValue_, Options options_): ValueFlagBase(name_, help_, std::move(matcher_), options_), value(defaultValue_), defaultValue(defaultValue_)
-            {
-                group_.Add(*this);
-            }
-
-            ValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const T &defaultValue_ = T(), const bool extraError_ = false): ValueFlag(group_, name_, help_, std::move(matcher_), defaultValue_, extraError_ ? Options::Single : Options::None)
-            {
-            }
-
-            ValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, Options options_): ValueFlag(group_, name_, help_, std::move(matcher_), T(), options_)
-            {
-            }
-
-            virtual ~ValueFlag() {}
-
-            virtual void ParseValue(const std::vector<std::string> &values_) override
-            {
-                const std::string &value_ = values_.at(0);
-
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, this->value))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, this->value);
-#endif
-            }
-
-            virtual void Reset() noexcept override
-            {
-                ValueFlagBase::Reset();
-                value = defaultValue;
-            }
-
-            /** Get the value
-             */
-            T &Get() noexcept
-            {
-                return value;
-            }
-
-            /** Get the default value
-             */
-            const T &GetDefault() noexcept
-            {
-                return defaultValue;
-            }
-    };
-
-    /** An optional argument-accepting flag class
-     *
-     * \tparam T the type to extract the argument as
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     */
-    template <
-        typename T,
-        typename Reader = ValueReader>
-    class ImplicitValueFlag : public ValueFlag<T, Reader>
-    {
-        protected:
-            T implicitValue;
-
-        public:
-
-            ImplicitValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const T &implicitValue_, const T &defaultValue_ = T(), Options options_ = {})
-                : ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(implicitValue_)
-            {
-            }
-
-            ImplicitValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const T &defaultValue_ = T(), Options options_ = {})
-                : ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), defaultValue_, options_), implicitValue(defaultValue_)
-            {
-            }
-
-            ImplicitValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, Options options_)
-                : ValueFlag<T, Reader>(group_, name_, help_, std::move(matcher_), {}, options_), implicitValue()
-            {
-            }
-
-            virtual ~ImplicitValueFlag() {}
-
-            virtual Nargs NumberOfArguments() const noexcept override
-            {
-                return {0, 1};
-            }
-
-            virtual void ParseValue(const std::vector<std::string> &value_) override
-            {
-                if (value_.empty())
-                {
-                    this->value = implicitValue;
-                } else
-                {
-                    ValueFlag<T, Reader>::ParseValue(value_);
-                }
-            }
-    };
-
-    /** A variadic arguments accepting flag class
-     *
-     * \tparam T the type to extract the argument as
-     * \tparam List the list type that houses the values
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     */
-    template <
-        typename T,
-        template <typename...> class List = std::vector,
-        typename Reader = ValueReader>
-    class NargsValueFlag : public FlagBase
-    {
-        protected:
-
-            List<T> values;
-            const List<T> defaultValues;
-            Nargs nargs;
-            Reader reader;
-
-        public:
-
-            typedef List<T> Container;
-            typedef T value_type;
-            typedef typename Container::allocator_type allocator_type;
-            typedef typename Container::pointer pointer;
-            typedef typename Container::const_pointer const_pointer;
-            typedef T& reference;
-            typedef const T& const_reference;
-            typedef typename Container::size_type size_type;
-            typedef typename Container::difference_type difference_type;
-            typedef typename Container::iterator iterator;
-            typedef typename Container::const_iterator const_iterator;
-            typedef std::reverse_iterator<iterator> reverse_iterator;
-            typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-            NargsValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, Nargs nargs_, const List<T> &defaultValues_ = {}, Options options_ = {})
-                : FlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_),nargs(nargs_)
-            {
-                group_.Add(*this);
-            }
-
-            virtual ~NargsValueFlag() {}
-
-            virtual Nargs NumberOfArguments() const noexcept override
-            {
-                return nargs;
-            }
-
-            virtual void ParseValue(const std::vector<std::string> &values_) override
-            {
-                values.clear();
-
-                for (const std::string &value : values_)
-                {
-                    T v;
-#ifdef ARGS_NOEXCEPT
-                    if (!reader(name, value, v))
-                    {
-                        error = Error::Parse;
-                    }
-#else
-                    reader(name, value, v);
-#endif
-                    values.insert(std::end(values), v);
-                }
-            }
-
-            List<T> &Get() noexcept
-            {
-                return values;
-            }
-
-            iterator begin() noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator begin() const noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator cbegin() const noexcept
-            {
-                return values.cbegin();
-            }
-
-            iterator end() noexcept
-            {
-                return values.end();
-            }
-
-            const_iterator end() const noexcept 
-            {
-                return values.end();
-            }
-
-            const_iterator cend() const noexcept
-            {
-                return values.cend();
-            }
-
-            virtual void Reset() noexcept override
-            {
-                FlagBase::Reset();
-                values = defaultValues;
-            }
-
-            virtual FlagBase *Match(const EitherFlag &arg) override
-            {
-                const bool wasMatched = Matched();
-                auto me = FlagBase::Match(arg);
-                if (me && !wasMatched)
-                {
-                    values.clear();
-                }
-                return me;
-            }
-    };
-
-    /** An argument-accepting flag class that pushes the found values into a list
-     * 
-     * \tparam T the type to extract the argument as
-     * \tparam List the list type that houses the values
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     */
-    template <
-        typename T,
-        template <typename...> class List = std::vector,
-        typename Reader = ValueReader>
-    class ValueFlagList : public ValueFlagBase
-    {
-        private:
-            using Container = List<T>;
-            Container values;
-            const Container defaultValues;
-            Reader reader;
-
-        public:
-
-            typedef T value_type;
-            typedef typename Container::allocator_type allocator_type;
-            typedef typename Container::pointer pointer;
-            typedef typename Container::const_pointer const_pointer;
-            typedef T& reference;
-            typedef const T& const_reference;
-            typedef typename Container::size_type size_type;
-            typedef typename Container::difference_type difference_type;
-            typedef typename Container::iterator iterator;
-            typedef typename Container::const_iterator const_iterator;
-            typedef std::reverse_iterator<iterator> reverse_iterator;
-            typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-            ValueFlagList(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Container &defaultValues_ = Container(), Options options_ = {}):
-                ValueFlagBase(name_, help_, std::move(matcher_), options_), values(defaultValues_), defaultValues(defaultValues_)
-            {
-                group_.Add(*this);
-            }
-
-            virtual ~ValueFlagList() {}
-
-            virtual void ParseValue(const std::vector<std::string> &values_) override
-            {
-                const std::string &value_ = values_.at(0);
-
-                T v;
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, v))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, v);
-#endif
-                values.insert(std::end(values), v);
-            }
-
-            /** Get the values
-             */
-            Container &Get() noexcept
-            {
-                return values;
-            }
-
-            virtual std::string Name() const override
-            {
-                return name + std::string("...");
-            }
-
-            virtual void Reset() noexcept override
-            {
-                ValueFlagBase::Reset();
-                values = defaultValues;
-            }
-
-            virtual FlagBase *Match(const EitherFlag &arg) override
-            {
-                const bool wasMatched = Matched();
-                auto me = FlagBase::Match(arg);
-                if (me && !wasMatched)
-                {
-                    values.clear();
-                }
-                return me;
-            }
-
-            iterator begin() noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator begin() const noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator cbegin() const noexcept
-            {
-                return values.cbegin();
-            }
-
-            iterator end() noexcept
-            {
-                return values.end();
-            }
-
-            const_iterator end() const noexcept 
-            {
-                return values.end();
-            }
-
-            const_iterator cend() const noexcept
-            {
-                return values.cend();
-            }
-    };
-
-    /** A mapping value flag class
-     * 
-     * \tparam K the type to extract the argument as
-     * \tparam T the type to store the result as
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     * \tparam Map The Map type.  Should operate like std::map or std::unordered_map
-     */
-    template <
-        typename K,
-        typename T,
-        typename Reader = ValueReader,
-        template <typename...> class Map = std::unordered_map>
-    class MapFlag : public ValueFlagBase
-    {
-        private:
-            const Map<K, T> map;
-            T value;
-            const T defaultValue;
-            Reader reader;
-
-        protected:
-            virtual std::vector<std::string> GetChoicesStrings(const HelpParams &) const override
-            {
-                return detail::MapKeysToStrings(map);
-            }
-
-        public:
-
-            MapFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Map<K, T> &map_, const T &defaultValue_, Options options_): ValueFlagBase(name_, help_, std::move(matcher_), options_), map(map_), value(defaultValue_), defaultValue(defaultValue_)
-            {
-                group_.Add(*this);
-            }
-
-            MapFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Map<K, T> &map_, const T &defaultValue_ = T(), const bool extraError_ = false): MapFlag(group_, name_, help_, std::move(matcher_), map_, defaultValue_, extraError_ ? Options::Single : Options::None)
-            {
-            }
-
-            MapFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Map<K, T> &map_, Options options_): MapFlag(group_, name_, help_, std::move(matcher_), map_, T(), options_)
-            {
-            }
-
-            virtual ~MapFlag() {}
-
-            virtual void ParseValue(const std::vector<std::string> &values_) override
-            {
-                const std::string &value_ = values_.at(0);
-
-                K key;
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, key))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, key);
-#endif
-                auto it = map.find(key);
-                if (it == std::end(map))
-                {
-                    std::ostringstream problem;
-                    problem << "Could not find key '" << key << "' in map for arg '" << name << "'";
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Map;
-                    errorMsg = problem.str();
-#else
-                    throw MapError(problem.str());
-#endif
-                } else
-                {
-                    this->value = it->second;
-                }
-            }
-
-            /** Get the value
-             */
-            T &Get() noexcept
-            {
-                return value;
-            }
-
-            virtual void Reset() noexcept override
-            {
-                ValueFlagBase::Reset();
-                value = defaultValue;
-            }
-    };
-
-    /** A mapping value flag list class
-     * 
-     * \tparam K the type to extract the argument as
-     * \tparam T the type to store the result as
-     * \tparam List the list type that houses the values
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     * \tparam Map The Map type.  Should operate like std::map or std::unordered_map
-     */
-    template <
-        typename K,
-        typename T,
-        template <typename...> class List = std::vector,
-        typename Reader = ValueReader,
-        template <typename...> class Map = std::unordered_map>
-    class MapFlagList : public ValueFlagBase
-    {
-        private:
-            using Container = List<T>;
-            const Map<K, T> map;
-            Container values;
-            const Container defaultValues;
-            Reader reader;
-
-        protected:
-            virtual std::vector<std::string> GetChoicesStrings(const HelpParams &) const override
-            {
-                return detail::MapKeysToStrings(map);
-            }
-
-        public:
-            typedef T value_type;
-            typedef typename Container::allocator_type allocator_type;
-            typedef typename Container::pointer pointer;
-            typedef typename Container::const_pointer const_pointer;
-            typedef T& reference;
-            typedef const T& const_reference;
-            typedef typename Container::size_type size_type;
-            typedef typename Container::difference_type difference_type;
-            typedef typename Container::iterator iterator;
-            typedef typename Container::const_iterator const_iterator;
-            typedef std::reverse_iterator<iterator> reverse_iterator;
-            typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-            MapFlagList(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Map<K, T> &map_, const Container &defaultValues_ = Container()): ValueFlagBase(name_, help_, std::move(matcher_)), map(map_), values(defaultValues_), defaultValues(defaultValues_)
-            {
-                group_.Add(*this);
-            }
-
-            virtual ~MapFlagList() {}
-
-            virtual void ParseValue(const std::vector<std::string> &values_) override
-            {
-                const std::string &value = values_.at(0);
-
-                K key;
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value, key))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value, key);
-#endif
-                auto it = map.find(key);
-                if (it == std::end(map))
-                {
-                    std::ostringstream problem;
-                    problem << "Could not find key '" << key << "' in map for arg '" << name << "'";
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Map;
-                    errorMsg = problem.str();
-#else
-                    throw MapError(problem.str());
-#endif
-                } else
-                {
-                    this->values.emplace_back(it->second);
-                }
-            }
-
-            /** Get the value
-             */
-            Container &Get() noexcept
-            {
-                return values;
-            }
-
-            virtual std::string Name() const override
-            {
-                return name + std::string("...");
-            }
-
-            virtual void Reset() noexcept override
-            {
-                ValueFlagBase::Reset();
-                values = defaultValues;
-            }
-
-            virtual FlagBase *Match(const EitherFlag &arg) override
-            {
-                const bool wasMatched = Matched();
-                auto me = FlagBase::Match(arg);
-                if (me && !wasMatched)
-                {
-                    values.clear();
-                }
-                return me;
-            }
-
-            iterator begin() noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator begin() const noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator cbegin() const noexcept
-            {
-                return values.cbegin();
-            }
-
-            iterator end() noexcept
-            {
-                return values.end();
-            }
-
-            const_iterator end() const noexcept 
-            {
-                return values.end();
-            }
-
-            const_iterator cend() const noexcept
-            {
-                return values.cend();
-            }
-    };
-
-    /** A positional argument class
-     *
-     * \tparam T the type to extract the argument as
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     */
-    template <
-        typename T,
-        typename Reader = ValueReader>
-    class Positional : public PositionalBase
-    {
-        private:
-            T value;
-            const T defaultValue;
-            Reader reader;
-        public:
-            Positional(Group &group_, const std::string &name_, const std::string &help_, const T &defaultValue_ = T(), Options options_ = {}): PositionalBase(name_, help_, options_), value(defaultValue_), defaultValue(defaultValue_)
-            {
-                group_.Add(*this);
-            }
-
-            Positional(Group &group_, const std::string &name_, const std::string &help_, Options options_): Positional(group_, name_, help_, T(), options_)
-            {
-            }
-
-            virtual ~Positional() {}
-
-            virtual void ParseValue(const std::string &value_) override
-            {
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, this->value))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, this->value);
-#endif
-                ready = false;
-                matched = true;
-            }
-
-            /** Get the value
-             */
-            T &Get() noexcept
-            {
-                return value;
-            }
-
-            virtual void Reset() noexcept override
-            {
-                PositionalBase::Reset();
-                value = defaultValue;
-            }
-    };
-
-    /** A positional argument class that pushes the found values into a list
-     * 
-     * \tparam T the type to extract the argument as
-     * \tparam List the list type that houses the values
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     */
-    template <
-        typename T,
-        template <typename...> class List = std::vector,
-        typename Reader = ValueReader>
-    class PositionalList : public PositionalBase
-    {
-        private:
-            using Container = List<T>;
-            Container values;
-            const Container defaultValues;
-            Reader reader;
-
-        public:
-            typedef T value_type;
-            typedef typename Container::allocator_type allocator_type;
-            typedef typename Container::pointer pointer;
-            typedef typename Container::const_pointer const_pointer;
-            typedef T& reference;
-            typedef const T& const_reference;
-            typedef typename Container::size_type size_type;
-            typedef typename Container::difference_type difference_type;
-            typedef typename Container::iterator iterator;
-            typedef typename Container::const_iterator const_iterator;
-            typedef std::reverse_iterator<iterator> reverse_iterator;
-            typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-            PositionalList(Group &group_, const std::string &name_, const std::string &help_, const Container &defaultValues_ = Container(), Options options_ = {}): PositionalBase(name_, help_, options_), values(defaultValues_), defaultValues(defaultValues_)
-            {
-                group_.Add(*this);
-            }
-
-            PositionalList(Group &group_, const std::string &name_, const std::string &help_, Options options_): PositionalList(group_, name_, help_, {}, options_)
-            {
-            }
-
-            virtual ~PositionalList() {}
-
-            virtual void ParseValue(const std::string &value_) override
-            {
-                T v;
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, v))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, v);
-#endif
-                values.insert(std::end(values), v);
-                matched = true;
-            }
-
-            virtual std::string Name() const override
-            {
-                return name + std::string("...");
-            }
-
-            /** Get the values
-             */
-            Container &Get() noexcept
-            {
-                return values;
-            }
-
-            virtual void Reset() noexcept override
-            {
-                PositionalBase::Reset();
-                values = defaultValues;
-            }
-
-            virtual PositionalBase *GetNextPositional() override
-            {
-                const bool wasMatched = Matched();
-                auto me = PositionalBase::GetNextPositional();
-                if (me && !wasMatched)
-                {
-                    values.clear();
-                }
-                return me;
-            }
-
-            iterator begin() noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator begin() const noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator cbegin() const noexcept
-            {
-                return values.cbegin();
-            }
-
-            iterator end() noexcept
-            {
-                return values.end();
-            }
-
-            const_iterator end() const noexcept 
-            {
-                return values.end();
-            }
-
-            const_iterator cend() const noexcept
-            {
-                return values.cend();
-            }
-    };
-
-    /** A positional argument mapping class
-     * 
-     * \tparam K the type to extract the argument as
-     * \tparam T the type to store the result as
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     * \tparam Map The Map type.  Should operate like std::map or std::unordered_map
-     */
-    template <
-        typename K,
-        typename T,
-        typename Reader = ValueReader,
-        template <typename...> class Map = std::unordered_map>
-    class MapPositional : public PositionalBase
-    {
-        private:
-            const Map<K, T> map;
-            T value;
-            const T defaultValue;
-            Reader reader;
-
-        protected:
-            virtual std::vector<std::string> GetChoicesStrings(const HelpParams &) const override
-            {
-                return detail::MapKeysToStrings(map);
-            }
-
-        public:
-
-            MapPositional(Group &group_, const std::string &name_, const std::string &help_, const Map<K, T> &map_, const T &defaultValue_ = T(), Options options_ = {}):
-                PositionalBase(name_, help_, options_), map(map_), value(defaultValue_), defaultValue(defaultValue_)
-            {
-                group_.Add(*this);
-            }
-
-            virtual ~MapPositional() {}
-
-            virtual void ParseValue(const std::string &value_) override
-            {
-                K key;
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, key))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, key);
-#endif
-                auto it = map.find(key);
-                if (it == std::end(map))
-                {
-                    std::ostringstream problem;
-                    problem << "Could not find key '" << key << "' in map for arg '" << name << "'";
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Map;
-                    errorMsg = problem.str();
-#else
-                    throw MapError(problem.str());
-#endif
-                } else
-                {
-                    this->value = it->second;
-                    ready = false;
-                    matched = true;
-                }
-            }
-
-            /** Get the value
-             */
-            T &Get() noexcept
-            {
-                return value;
-            }
-
-            virtual void Reset() noexcept override
-            {
-                PositionalBase::Reset();
-                value = defaultValue;
-            }
-    };
-
-    /** A positional argument mapping list class
-     * 
-     * \tparam K the type to extract the argument as
-     * \tparam T the type to store the result as
-     * \tparam List the list type that houses the values
-     * \tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)
-     * \tparam Map The Map type.  Should operate like std::map or std::unordered_map
-     */
-    template <
-        typename K,
-        typename T,
-        template <typename...> class List = std::vector,
-        typename Reader = ValueReader,
-        template <typename...> class Map = std::unordered_map>
-    class MapPositionalList : public PositionalBase
-    {
-        private:
-            using Container = List<T>;
-
-            const Map<K, T> map;
-            Container values;
-            const Container defaultValues;
-            Reader reader;
-
-        protected:
-            virtual std::vector<std::string> GetChoicesStrings(const HelpParams &) const override
-            {
-                return detail::MapKeysToStrings(map);
-            }
-
-        public:
-            typedef T value_type;
-            typedef typename Container::allocator_type allocator_type;
-            typedef typename Container::pointer pointer;
-            typedef typename Container::const_pointer const_pointer;
-            typedef T& reference;
-            typedef const T& const_reference;
-            typedef typename Container::size_type size_type;
-            typedef typename Container::difference_type difference_type;
-            typedef typename Container::iterator iterator;
-            typedef typename Container::const_iterator const_iterator;
-            typedef std::reverse_iterator<iterator> reverse_iterator;
-            typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-            MapPositionalList(Group &group_, const std::string &name_, const std::string &help_, const Map<K, T> &map_, const Container &defaultValues_ = Container(), Options options_ = {}):
-                PositionalBase(name_, help_, options_), map(map_), values(defaultValues_), defaultValues(defaultValues_)
-            {
-                group_.Add(*this);
-            }
-
-            virtual ~MapPositionalList() {}
-
-            virtual void ParseValue(const std::string &value_) override
-            {
-                K key;
-#ifdef ARGS_NOEXCEPT
-                if (!reader(name, value_, key))
-                {
-                    error = Error::Parse;
-                }
-#else
-                reader(name, value_, key);
-#endif
-                auto it = map.find(key);
-                if (it == std::end(map))
-                {
-                    std::ostringstream problem;
-                    problem << "Could not find key '" << key << "' in map for arg '" << name << "'";
-#ifdef ARGS_NOEXCEPT
-                    error = Error::Map;
-                    errorMsg = problem.str();
-#else
-                    throw MapError(problem.str());
-#endif
-                } else
-                {
-                    this->values.emplace_back(it->second);
-                    matched = true;
-                }
-            }
-
-            /** Get the value
-             */
-            Container &Get() noexcept
-            {
-                return values;
-            }
-
-            virtual std::string Name() const override
-            {
-                return name + std::string("...");
-            }
-
-            virtual void Reset() noexcept override
-            {
-                PositionalBase::Reset();
-                values = defaultValues;
-            }
-
-            virtual PositionalBase *GetNextPositional() override
-            {
-                const bool wasMatched = Matched();
-                auto me = PositionalBase::GetNextPositional();
-                if (me && !wasMatched)
-                {
-                    values.clear();
-                }
-                return me;
-            }
-
-            iterator begin() noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator begin() const noexcept
-            {
-                return values.begin();
-            }
-
-            const_iterator cbegin() const noexcept
-            {
-                return values.cbegin();
-            }
-
-            iterator end() noexcept
-            {
-                return values.end();
-            }
-
-            const_iterator end() const noexcept 
-            {
-                return values.end();
-            }
-
-            const_iterator cend() const noexcept
-            {
-                return values.cend();
-            }
-    };
-}
-
-#endif
diff --git a/skia/utils/rive_mgr.cpp b/skia/utils/rive_mgr.cpp
deleted file mode 100644
index 3e8026f..0000000
--- a/skia/utils/rive_mgr.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "rive_mgr.hpp"
-#include "rive/animation/linear_animation_instance.hpp"
-#include "rive/artboard.hpp"
-#include "rive/file.hpp"
-
-struct AutoClose {
-    FILE* m_File;
-
-    AutoClose(FILE* file) : m_File(file) {}
-    ~AutoClose() { this->close(); }
-
-    void close() {
-        if (m_File) {
-            fclose(m_File);
-            m_File = nullptr;
-        }
-    }
-};
-
-bool RiveMgr::load(const char filename[], const char artboard[], const char animation[]) {
-    m_File = nullptr;
-    m_Artboard = nullptr;
-    m_Animation = nullptr;
-
-    m_File = RiveMgr::loadFile(filename);
-    if (m_File) {
-        m_Artboard = m_File->artboardNamed(artboard);
-        if (m_Artboard) {
-            m_Animation = m_Artboard->animationNamed(animation);
-        }
-    }
-    return m_File != nullptr;
-}
-
-static void log(const char msg[], const char arg[] = nullptr) {
-    std::string err(msg);
-    if (arg) {
-        err = err + std::string(arg);
-    }
-    fprintf(stderr, "%s\n", err.c_str());
-}
-
-std::unique_ptr<rive::File> RiveMgr::loadFile(const char filename[]) {
-    AutoClose afc(fopen(filename, "rb"));
-    FILE* fp = afc.m_File;
-
-    if (fp == nullptr) {
-        log("Failed to open file ", filename);
-        return nullptr;
-    }
-
-    fseek(fp, 0, SEEK_END);
-    auto length = ftell(fp);
-    fseek(fp, 0, SEEK_SET);
-
-    std::vector<uint8_t> bytes(length);
-
-    if (fread(bytes.data(), 1, length, fp) != length) {
-        log("Failed to read file into bytes array ", filename);
-        return nullptr;
-    }
-
-    auto reader = rive::BinaryReader(bytes.data(), length);
-    auto file = rive::File::import(reader);
-
-    if (!file) {
-        log("Failed to read bytes into Rive file ", filename);
-    }
-    return file;
-}
diff --git a/skia/utils/rive_mgr.hpp b/skia/utils/rive_mgr.hpp
deleted file mode 100644
index d3d351b..0000000
--- a/skia/utils/rive_mgr.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _RIVE_MGR_HPP_
-#define _RIVE_MGR_HPP_
-
-#include "rive/animation/animation.hpp"
-#include "rive/animation/linear_animation.hpp"
-#include "rive/artboard.hpp"
-#include "rive/file.hpp"
-#include <memory>
-
-class RiveMgr {
-    std::unique_ptr<rive::File> m_File;
-    std::unique_ptr<rive::ArtboardInstance> m_Artboard;
-    std::unique_ptr<rive::LinearAnimationInstance> m_Animation;
-
-public:
-    RiveMgr() {}
-
-    bool load(const char path[], const char artboard[], const char animation[]);
-
-    rive::File* file() const { return m_File.get(); }
-    rive::ArtboardInstance* artboard() const { return m_Artboard.get(); }
-    rive::LinearAnimationInstance* animation() const { return m_Animation.get(); }
-
-    static std::unique_ptr<rive::File> loadFile(const char filename[]);
-};
-
-#endif