diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8cf43cb302f41259c07175fe54a26c8db58c2ed2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+doc/*.cpp
+doc/*.out
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 34e13ad9b1d97598fa472e42392b766957034157..04e07e10721f7e6ad1bc376831df992273fe7768 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,573 +1,721 @@
 stages:
     - build
     - test
+
 variables:
     GIT_STRATEGY: clone
     GIT_SUBMODULE_STRATEGY: recursive
 
-compile_install_g++9:
+.compile_install_template: &compile_install_definition
     stage: build
     script:
+        - SRC_DIR=`pwd`
         - mkdir build
-        - ./doc/sample_extractor.p6 doc
         - cd build
-        - CXX=g++-9 CC=gcc-9 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+        - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${SRC_DIR}
+        - cmake --build .
         - make install
-        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | g++-9 `pkg-config --libs --cflags libclapp` -I../third_party/GSL/include/ --std=c++17 -o out -x c++ -
-    tags:
-        - g++-9
-        - cmake
-    artifacts:
-        paths:
-            - build
+        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | ${CXX} `pkg-config --libs --cflags libclapp` -I${SRC_DIR}/third_party/GSL/include/ --std=c++17 -o out -x c++ -
 
-compile_release_g++9:
+.compile_template: &compile_definition
     stage: build
     script:
+        - SRC_DIR=`pwd`
         - mkdir build
-        - ./doc/sample_extractor.p6 doc
         - cd build
-        - CXX=g++-9 CC=gcc-9 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
-    tags:
-        - g++-9
-        - cmake
+        - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${ADDITIONAL_OPTION} -G "${GENERATOR}" ${SRC_DIR}
+        - cmake --build .
     artifacts:
         paths:
             - build
 
-test_release_g++9:
-    stage: test
+.compile_clang_tidy_template: &compile_clang_tidy_definition
+    stage: build
     script:
+        - SRC_DIR=`pwd`
+        - mkdir build
         - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="gcov-9"
-    tags:
-        - g++-9
-        - cmake
-    dependencies:
-        - compile_release_g++9
+        - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCLANG_TIDY=${CLANG_TIDY} -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DlibClaPP_BUILD_COVERAGE=On -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DlibClaPP_CLANG_TIDY=On ${SRC_DIR}
+        - cmake --build .
 
-compile_debug_g++9:
-    stage: build
+.test_gcov_template: &test_gcov_definition
+    stage: test
     script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
         - cd build
-        - CXX=g++-9 CC=gcc-9 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-        - make -j2 VERBOSE=1
-    tags:
-        - g++-9
-        - cmake
-    artifacts:
-        paths:
-            - build
+        - ctest -V -R libclapp_tests
+        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ -e doc -e ../doc/ --gcov-executable="${GCOV_EXECUTABLE}"
+        - ctest -V -E libclapp_tests
+        - cd ../
 
-test_debug_g++9:
+.test_template: &test_definition
     stage: test
     script:
         - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="gcov-9"
+        - ctest -V
+        - cd ../
+
+compile_install_release_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Release"
     tags:
         - g++-9
         - cmake
-    coverage: '/^TOTAL.*\s+(\d+%)$/'
-    dependencies:
-        - compile_debug_g++9
+    <<: *compile_install_definition
 
-compile_example_release_g++9:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-9 CC=gcc-9 cmake -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_install_debug_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Release"
     tags:
         - g++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_install_definition
 
-compile_install_g++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-8 CC=gcc-8 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
-        - make install
-        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | g++-8 `pkg-config --libs --cflags libclapp` -I../third_party/GSL/include/ --std=c++17 -o out -x c++ -
+compile_install_debug_g++8:
+    variables:
+        CXX: "g++-8"
+        CC: "gcc-8"
+        BUILD_TYPE: "Debug"
     tags:
         - g++-8
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_install_definition
 
-compile_release_g++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-8 CC=gcc-8 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_install_release_g++8:
+    variables:
+        CXX: "g++-8"
+        CC: "gcc-8"
+        BUILD_TYPE: "Release"
     tags:
         - g++-8
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_install_definition
 
-test_release_g++8:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="gcov-8"
+compile_install_debug_g++7:
+    variables:
+        CXX: "g++-7"
+        CC: "gcc-7"
+        BUILD_TYPE: "Debug"
+    tags:
+        - g++-7
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_release_g++7:
+    variables:
+        CXX: "g++-7"
+        CC: "gcc-7"
+        BUILD_TYPE: "Release"
+    tags:
+        - g++-7
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_debug_clang++7:
+    variables:
+        CXX: "clang++-7"
+        CC: "clang-7"
+        BUILD_TYPE: "Debug"
+    tags:
+        - clang++-7
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_release_clang++7:
+    variables:
+        CXX: "clang++-7"
+        CC: "clang-7"
+        BUILD_TYPE: "Release"
+    tags:
+        - clang++-7
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_debug_clang++8:
+    variables:
+        CXX: "clang++-8"
+        CC: "clang-8"
+        BUILD_TYPE: "Debug"
+    tags:
+        - clang++-8
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_release_clang++8:
+    variables:
+        CXX: "clang++-8"
+        CC: "clang-8"
+        BUILD_TYPE: "Release"
+    tags:
+        - clang++-8
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_debug_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Debug"
+    tags:
+        - clang++-9
+        - cmake
+    <<: *compile_install_definition
+
+compile_install_release_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Release"
+    tags:
+        - clang++-9
+        - cmake
+    <<: *compile_install_definition
+
+compile_release_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
+    tags:
+        - g++-9
+        - cmake
+    <<: *compile_definition
+
+test_gcov_release_g++9:
+    variables:
+        GCOV_EXECUTABLE: "gcov-9"
+    tags:
+        - g++-9
+        - cmake
+    needs:
+        - job: compile_release_g++9
+          artifacts: true
+    <<: *test_gcov_definition
+
+compile_debug_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+    tags:
+        - g++-9
+        - cmake
+    <<: *compile_definition
+
+test_gcov_debug_g++9:
+    variables:
+        GCOV_EXECUTABLE: "gcov-9"
+    tags:
+        - g++-9
+        - cmake
+    needs:
+        - job: compile_debug_g++9
+          artifacts: true
+    coverage: '/^TOTAL.*\s+(\d+%)$/'
+    <<: *test_gcov_definition
+
+compile_release_g++8:
+    variables:
+        CXX: "g++-8"
+        CC: "gcc-8"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
     tags:
         - g++-8
         - cmake
-    dependencies:
-        - compile_release_g++8
+    <<: *compile_definition
 
-compile_example_release_g++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-8 CC=gcc-8 cmake -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+test_gcov_release_g++8:
+    variables:
+        GCOV_EXECUTABLE: "gcov-8"
     tags:
         - g++-8
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_release_g++8
+          artifacts: true
+    <<: *test_gcov_definition
 
 compile_debug_g++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-8 CC=gcc-8 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-        - make -j2 VERBOSE=1
+    variables:
+        CXX: "g++-8"
+        CC: "gcc-8"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
     tags:
         - g++-8
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-test_debug_g++8:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="gcov-8"
+test_gcov_debug_g++8:
+    variables:
+        GCOV_EXECUTABLE: "gcov-8"
     tags:
         - g++-8
         - cmake
+    needs:
+        - job: compile_debug_g++8
+          artifacts: true
     coverage: '/^TOTAL.*\s+(\d+%)$/'
-    dependencies:
-        - compile_debug_g++8
+    <<: *test_gcov_definition
 
-compile_install_g++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-7 CC=gcc-7 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
-        - make install
-        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | g++-7 `pkg-config --libs --cflags libclapp` -I../third_party/GSL/include/ --std=c++17 -o out -x c++ -
+compile_release_g++7:
+    variables:
+        CXX: "g++-7"
+        CC: "gcc-7"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
     tags:
         - g++-7
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-compile_release_g++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-7 CC=gcc-7 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+test_gcov_release_g++7:
+    variables:
+        GCOV_EXECUTABLE: "gcov-7"
     tags:
         - g++-7
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_release_g++7
+          artifacts: true
+    <<: *test_gcov_definition
 
-test_release_g++7:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="gcov-7"
+compile_debug_g++7:
+    variables:
+        CXX: "g++-7"
+        CC: "gcc-7"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
     tags:
         - g++-7
         - cmake
-    dependencies:
-        - compile_release_g++7
+    <<: *compile_definition
 
-compile_debug_g++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-7 CC=gcc-7 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-        - make -j2 VERBOSE=1
+test_gcov_debug_g++7:
+    variables:
+        GCOV_EXECUTABLE: "gcov-7"
     tags:
         - g++-7
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_debug_g++7
+          artifacts: true
+    coverage: '/^TOTAL.*\s+(\d+%)$/'
+    <<: *test_gcov_definition
 
-test_debug_g++7:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="gcov-7"
+compile_release_clang++7:
+    variables:
+        CXX: "clang++-7"
+        CC: "clang-7"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
     tags:
-        - g++-7
+        - clang++-7
+        - cmake
+    <<: *compile_definition
+
+test_gcov_release_clang++7:
+    variables:
+        GCOV_EXECUTABLE: "llvm-cov-7 gcov"
+    tags:
+        - clang++-7
         - cmake
+    needs:
+        - job: compile_release_clang++7
+          artifacts: true
+    <<: *test_gcov_definition
+
+compile_debug_clang++7:
+    variables:
+        CXX: "clang++-7"
+        CC: "clang-7"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+    tags:
+        - clang++-7
+        - cmake
+    <<: *compile_definition
+
+test_gcov_debug_clang++7:
+    variables:
+        GCOV_EXECUTABLE: "llvm-cov-7 gcov"
+    tags:
+        - clang++-7
+        - cmake
+    needs:
+        - job: compile_debug_clang++7
+          artifacts: true
     coverage: '/^TOTAL.*\s+(\d+%)$/'
-    dependencies:
-        - compile_debug_g++7
+    <<: *test_gcov_definition
 
-compile_example_release_g++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=g++-7 CC=gcc-7 cmake -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_release_clang++8:
+    variables:
+        CXX: "clang++-8"
+        CC: "clang-8"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
     tags:
-        - g++-7
+        - clang++-8
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-compile_install_clang++9:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-9 CC=clang-9 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
-        - make install
-        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | clang++-9 `pkg-config --libs --cflags libclapp` -I../third_party/GSL/include/ --std=c++17 -o out -x c++ -
+test_gcov_release_clang++8:
+    variables:
+        GCOV_EXECUTABLE: "llvm-cov-8 gcov"
+    tags:
+        - clang++-8
+        - cmake
+    needs:
+        - job: compile_release_clang++8
+          artifacts: true
+    <<: *test_gcov_definition
+
+compile_debug_clang++8:
+    variables:
+        CXX: "clang++-8"
+        CC: "clang-8"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+    tags:
+        - clang++-8
+        - cmake
+    <<: *compile_definition
+
+test_gcov_debug_clang++8:
+    variables:
+        GCOV_EXECUTABLE: "llvm-cov-8 gcov"
+    tags:
+        - clang++-8
+        - cmake
+    needs:
+        - job: compile_debug_clang++8
+          artifacts: true
+    coverage: '/^TOTAL.*\s+(\d+%)$/'
+    <<: *test_gcov_definition
+
+compile_release_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
     tags:
         - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
+
+test_gcov_release_clang++9:
+    variables:
+        GCOV_EXECUTABLE: "llvm-cov-9 gcov"
+    tags:
+        - clang++-9
+        - cmake
+    needs:
+        - job: compile_release_clang++9
+          artifacts: true
+    <<: *test_gcov_definition
 
 compile_debug_clang++9:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-9 CC=clang-9 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-        - make -j2 VERBOSE=1
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
     tags:
         - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-test_debug_clang++9:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="llvm-cov-9 gcov"
+test_gcov_debug_clang++9:
+    variables:
+        GCOV_EXECUTABLE: "llvm-cov-9 gcov"
     tags:
         - clang++-9
         - cmake
+    needs:
+        - job: compile_debug_clang++9
+          artifacts: true
     coverage: '/^TOTAL.*\s+(\d+%)$/'
-    dependencies:
-        - compile_debug_clang++9
+    <<: *test_gcov_definition
 
-clang-tidy-9:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-9 CC=clang-9 cmake -DCLANG_TIDY=clang-tidy-9 -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DlibClaPP_BUILD_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug -DlibClaPP_CLANG_TIDY=On ..
-        - make VERBOSE=1
+compile_debug_clang-tidy-7:
+    variables:
+        CXX: "clang++-7"
+        CC: "clang-7"
+        CLANG_TIDY: "clang-tidy-7"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+    tags:
+        - clang++-7
+        - cmake
+    <<: *compile_clang_tidy_definition
+
+compile_debug_clang-tidy-8:
+    variables:
+        CXX: "clang++-8"
+        CC: "clang-8"
+        CLANG_TIDY: "clang-tidy-8"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
     tags:
         - clang++-8
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_clang_tidy_definition
 
-compile_release_clang++9:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-9 CC=clang-9 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_debug_clang-tidy-9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        CLANG_TIDY: "clang-tidy-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
     tags:
         - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_clang_tidy_definition
 
-test_release_clang++9:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="llvm-cov-9 gcov"
+compile_install_debug_ninja_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Ninja"
     tags:
         - clang++-9
         - cmake
-    dependencies:
-        - compile_release_clang++9
+    <<: *compile_install_definition
 
-compile_example_release_clang++9:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-9 CC=clang-9 cmake -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_install_release_ninja_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Ninja"
     tags:
         - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_install_definition
 
-compile_install_clang++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-8 CC=clang-8 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
-        - make install
-        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | clang++-8 `pkg-config --libs --cflags libclapp` -I../third_party/GSL/include/ --std=c++17 -o out -x c++ -
+compile_release_ninja_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Ninja"
     tags:
-        - clang++-8
+        - g++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-compile_debug_clang++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-8 CC=clang-8 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-        - make -j2 VERBOSE=1
+test_gcov_release_ninja_g++9:
+    variables:
+        GCOV_EXECUTABLE: "gcov-9"
     tags:
-        - clang++-8
+        - g++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_release_ninja_g++9
+          artifacts: true
+    <<: *test_gcov_definition
 
-test_debug_clang++8:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="llvm-cov-8 gcov"
+compile_debug_ninja_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Ninja"
     tags:
-        - clang++-8
+        - g++-9
         - cmake
+    <<: *compile_definition
+
+test_gcov_debug_ninja_g++9:
+    variables:
+        GCOV_EXECUTABLE: "gcov-9"
+    tags:
+        - g++-9
+        - cmake
+    needs:
+        - job: compile_debug_ninja_g++9
+          artifacts: true
     coverage: '/^TOTAL.*\s+(\d+%)$/'
-    dependencies:
-        - compile_debug_clang++8
+    <<: *test_gcov_definition
+
+#TODO: address sanitizer currently gives false positives on arm64
+#compile_release_address_sanitizer_g++9:
+#    variables:
+#        CXX: "g++-9"
+#        CC: "gcc-9"
+#        BUILD_TYPE: "Release"
+#        GENERATOR: "Unix Makefiles"
+#        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_ADDRESS=On"
+#    tags:
+#        - g++-9
+#        - cmake
+#    <<: *compile_definition
+#
+#test_release_address_sanitizer_g++9:
+#    tags:
+#        - g++-9
+#        - cmake
+#    needs:
+#        - job: compile_release_address_sanitizer_g++9
+#          artifacts: true
+#    <<: *test_definition
+#
+#compile_debug_address_sanitizer_g++9:
+#    variables:
+#        CXX: "g++-9"
+#        CC: "gcc-9"
+#        BUILD_TYPE: "Debug"
+#        GENERATOR: "Unix Makefiles"
+#        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_ADDRESS=On"
+#    tags:
+#        - g++-9
+#        - cmake
+#    <<: *compile_definition
+#
+#test_debug_address_sanitizer_g++9:
+#    tags:
+#        - g++-9
+#        - cmake
+#    needs:
+#        - job: compile_debug_address_sanitizer_g++9
+#          artifacts: true
+#    coverage: '/^TOTAL.*\s+(\d+%)$/'
+#    <<: *test_definition
+
+compile_release_undefined_behavior_sanitizer_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
+        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR=On"
+    tags:
+        - g++-9
+        - cmake
+    <<: *compile_definition
 
-clang-tidy-8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-8 CC=clang-8 cmake -DCLANG_TIDY=clang-tidy-8 -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DlibClaPP_BUILD_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug -DlibClaPP_CLANG_TIDY=On ..
-        - make VERBOSE=1
+test_release_undefined_behavior_sanitizer_g++9:
     tags:
-        - clang++-8
+        - g++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_release_undefined_behavior_sanitizer_g++9
+          artifacts: true
+    <<: *test_definition
 
-compile_release_clang++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-8 CC=clang-8 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_debug_undefined_behavior_sanitizer_g++9:
+    variables:
+        CXX: "g++-9"
+        CC: "gcc-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR=On"
     tags:
-        - clang++-8
+        - g++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-test_release_clang++8:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="llvm-cov-8 gcov"
+test_debug_undefined_behavior_sanitizer_g++9:
     tags:
-        - clang++-8
+        - g++-9
         - cmake
-    dependencies:
-        - compile_release_clang++8
+    needs:
+        - job: compile_debug_undefined_behavior_sanitizer_g++9
+          artifacts: true
+    coverage: '/^TOTAL.*\s+(\d+%)$/'
+    <<: *test_definition
 
-compile_example_release_clang++8:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-8 CC=clang-8 cmake -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+compile_release_address_sanitizer_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
+        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_ADDRESS=On"
     tags:
-        - clang++-8
+        - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-compile_install_clang++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-7 CC=clang-7 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
-        - make install
-        - echo -e '#include<clapp/main_parser.h>\n#include<clapp/build_info.h>\n#include<iostream>\nint main (int argc, char *argv[]) {\nstd::cout << clapp::build_info::project_name << " v" << clapp::build_info::version << std::endl;\n}' | clang++-7 `pkg-config --libs --cflags libclapp` -I../third_party/GSL/include/ --std=c++17 -o out -x c++ -
+test_release_address_sanitizer_clang++9:
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_release_address_sanitizer_clang++9
+          artifacts: true
+    <<: *test_definition
 
-compile_debug_clang++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-7 CC=clang-7 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DlibClaPP_BUILD_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug ..
-        - make -j2 VERBOSE=1
+compile_debug_address_sanitizer_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_ADDRESS=On"
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-test_debug_clang++7:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="llvm-cov-7 gcov"
+test_debug_address_sanitizer_clang++9:
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
+    needs:
+        - job: compile_debug_address_sanitizer_clang++9
+          artifacts: true
     coverage: '/^TOTAL.*\s+(\d+%)$/'
-    dependencies:
-        - compile_debug_clang++7
+    <<: *test_definition
 
-clang-tidy-7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-7 CC=clang-7 cmake -DCLANG_TIDY=clang-tidy-7 -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DlibClaPP_BUILD_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug -DlibClaPP_CLANG_TIDY=On ..
-        - make VERBOSE=1
+compile_release_undefined_behavior_sanitizer_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Release"
+        GENERATOR: "Unix Makefiles"
+        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR=On"
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    <<: *compile_definition
 
-compile_release_clang++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-7 CC=clang-7 cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+test_release_undefined_behavior_sanitizer_clang++9:
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_release_undefined_behavior_sanitizer_clang++9
+          artifacts: true
+    <<: *test_definition
 
-test_release_clang++7:
-    stage: test
-    script:
-        - cd build
-        - ./tests/libclapp_tests
-        - gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/ --gcov-executable="llvm-cov-7 gcov"
+compile_debug_undefined_behavior_sanitizer_clang++9:
+    variables:
+        CXX: "clang++-9"
+        CC: "clang-9"
+        BUILD_TYPE: "Debug"
+        GENERATOR: "Unix Makefiles"
+        ADDITIONAL_OPTION: "-DlibClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR=On"
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
-    dependencies:
-        - compile_release_clang++7
+    <<: *compile_definition
 
-compile_example_release_clang++7:
-    stage: build
-    script:
-        - mkdir build
-        - ./doc/sample_extractor.p6 doc
-        - cd build
-        - CXX=clang++-7 CC=clang-7 cmake -DlibClaPP_BUILD_DOC_CODE=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Release ..
-        - make -j2 VERBOSE=1
+test_debug_undefined_behavior_sanitizer_clang++9:
     tags:
-        - clang++-7
+        - clang++-9
         - cmake
-    artifacts:
-        paths:
-            - build
+    needs:
+        - job: compile_debug_undefined_behavior_sanitizer_clang++9
+          artifacts: true
+    coverage: '/^TOTAL.*\s+(\d+%)$/'
+    <<: *test_definition
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a9f856ef49993615ce857aaec3854273828b18e0..2af91c7561ae18c359e495944b50c233c3bed9a7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,5 @@
 cmake_minimum_required(VERSION 3.8.0)
-set(CMAKE_VERBOSE_MAKEFILE ON)
-set(libClaPP_PROJECT_NAME "libClaPP")
-project("${libClaPP_PROJECT_NAME}")
+project("libClaPP" VERSION 0.2.0)
 include(CTest)
 include(CheckCXXCompilerFlag)
 include(GNUInstallDirs)
@@ -17,7 +15,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0")
 set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
 
 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
-    list(APPEND libClaPP_TEST_COMPILE_OPTIONS -Wall -Wextra -Wunreachable-code -Wfloat-equal -Wunused-parameter -Werror -pedantic-errors -Wcast-align -Wcast-qual -Wpointer-arith -Wwrite-strings -Wstrict-overflow=1 -Wformat=2 -Wlogical-op -Wduplicated-cond -Wduplicated-branches -Wdouble-promotion -Wold-style-cast -Wshadow -Wwrite-strings -Wuninitialized -Wconversion -Wunused -Wno-missing-braces -Wnarrowing -Wconversion-null -Wuseless-cast -Wsign-conversion -Wrestrict -Wnull-dereference)
+    list(APPEND libClaPP_TEST_COMPILE_OPTIONS -Wall -Wextra -Wunreachable-code -Wfloat-equal -Werror -pedantic-errors -Wcast-align -Wcast-qual -Wpointer-arith -Wwrite-strings -Wstrict-overflow=2 -Wformat=2 -Wlogical-op -Wduplicated-cond -Wduplicated-branches -Wdouble-promotion -Wold-style-cast -Wshadow -Wwrite-strings -Wuninitialized -Wconversion -Wunused -Wno-missing-braces -Wnarrowing -Wconversion-null -Wuseless-cast -Wsign-conversion -Wrestrict -Wnull-dereference -Wmisleading-indentation -Wnon-virtual-dtor -Woverloaded-virtual)
     set(libClaPP_COMPILE_OPTIONS ${libClaPP_TEST_COMPILE_OPTIONS})
     list(APPEND libClaPP_COMPILE_OPTIONS -Weffc++)
 elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
@@ -26,21 +24,33 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
     list(APPEND libClaPP_TEST_COMPILE_OPTION -Wno-global-constructors)
 endif()
 
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
-
 CHECK_CXX_COMPILER_FLAG("-lstdc++fs" COMPILER_SUPPORTS_FILESYSTEM)
 if(COMPILER_SUPPORTS_FILESYSTEM)
     set(libClaPP_FS_LINKER_FLAG "-lstdc++fs")
 endif()
 
+find_package(PkgConfig REQUIRED)
+string(TIMESTAMP libClaPP_CONFIG_TIME "%Y-%m-%d %H:%M:%S")
+set (THIRD_PARTY_DIR "${PROJECT_SOURCE_DIR}/third_party")
+
 option(libClaPP_CLANG_TIDY "Clang-Tidy." Off)
+option(libClaPP_CPPCHECK "CPPCheck." Off)
 option(libClaPP_BUILD_TESTS "Build tests." Off)
 option(libClaPP_BUILD_EXAMPLES "Build examples." Off)
 option(libClaPP_BUILD_DOC_CODE "Build doc code." Off)
 option(libClaPP_BUILD_COVERAGE "Cretae gcov build." Off)
 option(libClaPP_SUBMODULE_DEPENDENCIES "Use dependencies from git submodules." Off)
+option(libClaPP_ENABLE_IPO "Enable Iterprocedural Optimization, aka Link Time Optimization (LTO)" Off)
+
+if(libClaPP_ENABLE_IPO)
+  include(CheckIPOSupported)
+  check_ipo_supported(RESULT result OUTPUT output)
+  if(result)
+    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
+  else()
+    message(SEND_ERROR "IPO is not supported: ${output}")
+  endif()
+endif()
 
 if(libClaPP_BUILD_COVERAGE)
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
@@ -61,18 +71,27 @@ if(libClaPP_CLANG_TIDY)
 
     if(CLANG_TIDY)
         message(STATUS "clang-tidy found: ${CLANG_TIDY}")
-        set(CLANG_TIDY_ARGS "${CLANG_TIDY}" "-header-filter=src/include;-warnings-as-errors=*;-checks=*,-google-runtime-references,-fuchsia-default-arguments,-fuchsia-overloaded-operator,-cert-dcl50-cpp,-clang-diagnostic-unused-command-line-argument")
+        set(CLANG_TIDY_ARGS "${CLANG_TIDY}" "-header-filter=src/include;-warnings-as-errors=*;-checks=*,-google-runtime-references,-fuchsia-default-arguments,-fuchsia-overloaded-operator,-cert-dcl50-cpp,-clang-diagnostic-unused-command-line-argument,-modernize-use-trailing-return-type,-fuchsia-default-arguments-calls")
     endif()
 endif()
 
-find_package(PkgConfig REQUIRED)
+if(libClaPP_CPPCHECK)
+  if(CMAKE_VERSION VERSION_GREATER 3.10)
+    find_program(CPPCHECK cppcheck)
+    if(CPPCHECK)
+        set(CMAKE_CXX_CPPCHECK ${CPPCHECK} --enable=all --suppress=*:${CMAKE_CURRENT_SOURCE_DIR}/src/include/clapp/filesystem.h:27 --suppress=*:${THIRD_PARTY_DIR}/* --inconclusive -v -i${THIRD_PARTY_DIR})
+    else()
+      message(SEND_ERROR "CPPCheck requested but executable not found.")
+    endif()
+  else()
+    message(SEND_ERROR "CPPCheck requested but current CMAKE is not compatible.")
+  endif()
+endif()
 
-set (project_VERSION_MAJOR 0)
-set (project_VERSION_MINOR 1)
-set (project_VERSION_PATCH_LEVEL 0)
-string(TIMESTAMP project_CONFIG_TIME "%Y-%m-%d %H:%M:%S")
+add_library(ClaPP_OPTIONS INTERFACE)
+target_compile_features(ClaPP_OPTIONS INTERFACE cxx_std_17)
 
-set (THIRD_PARTY_DIR "${PROJECT_SOURCE_DIR}/third_party")
+include(cmake/sanitizer.cmake)
 
 add_library(libClaPP_GSL INTERFACE)
 if(libClaPP_SUBMODULE_DEPENDENCIES)
@@ -112,6 +131,7 @@ else()
     endif()
 endif()
 
+enable_testing()
 add_subdirectory(src)
 
 if(libClaPP_BUILD_EXAMPLES)
diff --git a/README.md b/README.md
index 405d568dbff58e0b86fec0e94401f05bf5a93591..a5e03577fedffbd27dc7543f1eb344cfcf07b6bd 100644
--- a/README.md
+++ b/README.md
@@ -8,56 +8,69 @@
 
 libClaPP:
 =========
-[![pipeline](../badges/master/pipeline.svg)](../commits/master/)
-[![coverage](../badges/master/coverage.svg)](../commits/master/)
+[![pipeline status](https://git.libclapp.org/libclapp/clapp/badges/master/pipeline.svg)](https://git.libclapp.org/libclapp/clapp/-/commits/master)
+[![coverage report](https://git.libclapp.org/libclapp/clapp/badges/master/coverage.svg)](https://git.libclapp.org/libclapp/clapp/-/commits/master)
 
 libClaPP is an open source command line argument processing library for C++.
 It supports the processing of GNU options (long and short options) as well as positional arguments.
+It is a strongly typed library that can be used to parse the command line arguments into the correct type,
+validate the arguments using custom constraints and automatically generates a help message with respect
+to the types and the constraints.
 
 Build:
 ------
 
 ### Dependencies:
-libClaPP only depends on the [GSL](https://github.com/microsoft/GSL).
-If you want to build the unit tests, also [google test](https://github.com/google/googletest) is required.
+libClaPP only depends on the [GSL](https://github.com/microsoft/GSL), but this library is shipped as git-submodule dependency within this git repository.
 
-### Build the library
-Since all dependencies are already included in this repository as submodules, you may prefer to use the shipped dependencies via the CMake option `libClaPP_SUBMODULE_DEPENDENCIES` enabled:
+If the unit tests of this libray should be built, also [google test](https://github.com/google/googletest) is required (is also shipped as git-submodule dependency).
+If the listings in the [doc/](doc/)-folder should be extracted and build too, a Raku-(Perl 6)-interpreter is required. A very common Raku interpreter is [Rakudo](https://rakudo.org/), which can be installed on Debian/Ubuntu by executing `apt install rakudo`.
+
+### Build the library:
+Since all build dependencies are already included in this repository as submodules, you may prefer to use the shipped dependencies via the CMake option `libClaPP_SUBMODULE_DEPENDENCIES` enabled:
 
     git clone --recurse-submodules https://git.libclapp.org/libclapp/clapp.git
     mkdir build
     cd build
     cmake .. -DlibClaPP_SUBMODULE_DEPENDENCIES=On
-    make
+    cmake --build .
 
+#### Build with system libraries:
 But if all dependencies are installed on your system, the following steps are sufficient.
 
     git clone https://git.libclapp.org/libclapp/clapp.git
     mkdir build
     cd build
     cmake ..
-    make
+    cmake --build .
 
-Build the library in debug mode with submodules, unitests and check code coverage:
+#### Build the library in debug mode with submodules, unitests and check code coverage:
 
     git clone --recurse-submodules https://git.libclapp.org/libclapp/clapp.git
     mkdir build
     cd build
     cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-    make
-    ./tests/libclapp_tests
+    cmake --build .
+    ctest -V -R libclapp_tests
     gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/
 
-Build the library in debug mode with submodules, unitests, examples and check code coverage:
+#### Build the library in debug mode with submodules, unitests, examples and check code coverage:
 
     git clone --recurse-submodules https://git.libclapp.org/libclapp/clapp.git
     mkdir build
     cd build
     cmake -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_BUILD_COVERAGE=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DCMAKE_BUILD_TYPE=Debug ..
-    make
-    ./tests/libclapp_tests
+    cmake --build .
+    ctest -V -R libclapp_tests
     gcovr -r ../ -e ../third_party/ -e ../tests/ -e ../examples/
+    ctest -V -E libclapp_tests
+
+#### Build with gcc/clang sanitizers:
+LibClaPP can be built with the following sanitizers: Address sanitizer, memory sanitizer, undefined behavior sanitizer or a thread sanitizer.
+To enable these sanitizers, one of the following options must be set: `libClaPP_ENABLE_SANITIZER_ADDRESS`, `libClaPP_ENABLE_SANITIZER_MEMORY`,
+`libClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR`, `libClaPP_ENABLE_SANITIZER_THREAD`.
 
+For easy switching between different sanitizers, the tool `ccmake` may be used instead of pure `cmake`.
 
 ### Install the library
 
@@ -69,23 +82,16 @@ To uninstall the library, remove all files that were installed:
 
     xargs rm < install_manifest.txt
 
-Terminology:
--------------
-In this project the following terms are used:
-
-* Option: An option can be either a short option or a long option. 
-    A short option consists of a single `-` followed by single character (e.g. `-h`).
-    A long option consists of two `--` followed by an arbitrary string (e.g. `--help`).
-* Parameter: Some options may require additional parameters (.e.g. `--file=/path/to/file`).
-* Argument: An argument is the short form for positional argument. 
-    Thus, arguments higly depend on the position where they occur. 
-    Unlinke to options that may occur anywhere else.
-* Sub-Parser: A subparser is always implicitly the last argument of a the current parser.
-    Once this argument is given, a completely new parsing instance is started.
+Documentation:
+--------------
+A short documentation of libClaPP is available in [doc/doc.md](doc/doc.md).
 
 Example:
 --------
 Some examples can be found in the [examples](examples) folder.
+Additionally, [doc/doc.md](doc/doc.md) also contains a few examples.
+
+For a quick start take a look at [examples/short_example.cpp](examples/short_example.cpp).
 
 Coverage:
 ---------
@@ -97,3 +103,12 @@ Clang-Tidy:
 -----------
 
     CXX=clang++-7 CC=clang-7 cmake -DCLANG_TIDY=clang-tidy-7 -DlibClaPP_BUILD_TESTS=On -DlibClaPP_BUILD_EXAMPLES=On -DlibClaPP_SUBMODULE_DEPENDENCIES=On -DlibClaPP_BUILD_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug -DlibClaPP_CLANG_TIDY=On ..
+
+Clang-Format:
+-------------
+
+This project uses a clang-format style based on the Google style (`clang-format-7 -style=Google -dump-config`) but modified a bit (see [.clang-format](.clang-format)).
+
+To format the whole project, use the following command:
+
+    clang-format-7 -i examples/*.cpp examples/*.h examples/*.hpp src/clapp/*.cpp src/include/clapp/*.hpp src/include/clapp/*.h tests/*.cpp tests/*.h tests/*.hpp
diff --git a/cmake/git.cmake b/cmake/git.cmake
index 341a32ed5dc3d559b38e14febde3de7dbdabdc73..0ea9b40ffbf01cf62e5f1d83803dd6024cc4d58e 100644
--- a/cmake/git.cmake
+++ b/cmake/git.cmake
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.8.0)
 
-message(STATUS "Resolving GIT Version")
+message(STATUS "Resolving GIT Version for libClaPP")
 
 find_package(Git)
 
@@ -19,7 +19,7 @@ endif()
 
 message(STATUS "trying git `${GIT_EXECUTABLE}`:")
 execute_process(
-  COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_SOURCE_DIR} rev-parse --abbrev-ref HEAD
+  COMMAND ${GIT_EXECUTABLE} -C ${libClaPP_SOURCE_DIR} rev-parse --abbrev-ref HEAD
   WORKING_DIRECTORY "${local_dir}"
   OUTPUT_VARIABLE libClaPP_GIT_BRANCH
   ERROR_QUIET
@@ -27,15 +27,24 @@ execute_process(
   RESULT_VARIABLE libClaPP_result_branch
 )
 execute_process(
-  COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_SOURCE_DIR} rev-parse --short HEAD
+  COMMAND ${GIT_EXECUTABLE} -C ${libClaPP_SOURCE_DIR} describe --dirty --broken --always
   WORKING_DIRECTORY "${local_dir}"
   OUTPUT_VARIABLE libClaPP_GIT_HASH
   ERROR_QUIET
   OUTPUT_STRIP_TRAILING_WHITESPACE
   RESULT_VARIABLE libClaPP_result_hash
 )
-if(NOT ((libClaPP_result_hash EQUAL 0) AND (libClaPP_result_branch EQUAL 0)))
+execute_process(
+  COMMAND ${GIT_EXECUTABLE} -C ${libClaPP_SOURCE_DIR} describe --dirty --broken --always --tags
+  WORKING_DIRECTORY "${local_dir}"
+  OUTPUT_VARIABLE libClaPP_GIT_DESCRIPTION
+  ERROR_QUIET
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+  RESULT_VARIABLE libClaPP_result_description
+)
+if(NOT ((libClaPP_result_hash EQUAL 0) AND (libClaPP_result_branch EQUAL 0) AND (libClaPP_result_description EQUAL 0)))
     set(libClaPP_GIT_HASH "unknown")
     set(libClaPP_GIT_BRANCH "unknown")
+    set(libClaPP_GIT_DESCRIPTION "unknown")
 endif()
-message(STATUS "GIT branch: ${libClaPP_GIT_BRANCH}, GIT hash: ${libClaPP_GIT_HASH}")
+message(STATUS "GIT branch: ${libClaPP_GIT_BRANCH}, GIT hash: ${libClaPP_GIT_HASH}, GIT description: ${libClaPP_GIT_DESCRIPTION}")
diff --git a/cmake/sanitizer.cmake b/cmake/sanitizer.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..104fbd1fdc1113bbd38e4df0627f2418f19be908
--- /dev/null
+++ b/cmake/sanitizer.cmake
@@ -0,0 +1,37 @@
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    set(libClaPP_SANITIZERS "")
+
+    option(libClaPP_ENABLE_SANITIZER_ADDRESS "Address sanitizer" FALSE)
+    if(libClaPP_ENABLE_SANITIZER_ADDRESS)
+      list(APPEND libClaPP_SANITIZERS "address")
+    endif()
+
+    option(libClaPP_ENABLE_SANITIZER_MEMORY "Memory sanitizer" FALSE)
+    if(libClaPP_ENABLE_SANITIZER_MEMORY)
+      list(APPEND libClaPP_SANITIZERS "memory")
+    endif()
+
+    option(libClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Undefined behavior sanitizer" FALSE)
+    if(libClaPP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR)
+      list(APPEND libClaPP_SANITIZERS "undefined")
+    endif()
+
+    option(libClaPP_ENABLE_SANITIZER_THREAD "Thread sanitizer" FALSE)
+    if(libClaPP_ENABLE_SANITIZER_THREAD)
+      list(APPEND libClaPP_SANITIZERS "thread")
+    endif()
+
+    list(JOIN libClaPP_SANITIZERS "," libClaPP_LIST_OF_SANITIZERS)
+endif()
+
+if(libClaPP_LIST_OF_SANITIZERS)
+    message(STATUS "Using the following sanitizers: ${libClaPP_LIST_OF_SANITIZERS}")
+    if(NOT "${libClaPP_LIST_OF_SANITIZERS}" STREQUAL "")
+        target_compile_options(ClaPP_OPTIONS
+                               INTERFACE -fsanitize=${libClaPP_LIST_OF_SANITIZERS})
+        target_link_libraries(ClaPP_OPTIONS
+                              INTERFACE -fsanitize=${libClaPP_LIST_OF_SANITIZERS})
+    endif()
+else()
+    message(STATUS "Using no sanitizers")
+endif()
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 1303f2699a3733fbd5fc251c011a3316dbfdaa02..49a669c5e07129f3b9ae72169abf0e9c8cb341fa 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -1,6 +1,24 @@
+if(CLANG_TIDY)
+    set(CLANG_TIDY_DOC_ARGS "${CLANG_TIDY_ARGS},-misc-non-private-member-variables-in-classes,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers")
+endif()
+
+find_program(RAKU_EXECUTABLE NAMES raku perl6)
+
+add_custom_command( OUTPUT simple_sub_parser.cpp simple_main_parser.cpp DEPENDS doc.md
+    COMMAND ${RAKU_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/sample_extractor.p6 ${CMAKE_CURRENT_SOURCE_DIR})
+
 add_executable(libclapp_doc_simple_main_parser simple_main_parser.cpp)
 target_link_libraries(libclapp_doc_simple_main_parser clapp)
 target_compile_options(libclapp_doc_simple_main_parser PRIVATE ${libClaPP_COMPILE_OPTIONS})
 if(CLANG_TIDY)
-  set_target_properties(libclapp_doc_simple_main_parser PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS}")
+  set_target_properties(libclapp_doc_simple_main_parser PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_DOC_ARGS}")
+endif()
+add_test(NAME libclapp_doc_simple_main_parser_test COMMAND ${RAKU_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/sample_executor.p6 simple_main_parser.out)
+
+add_executable(libclapp_doc_simple_sub_parser simple_sub_parser.cpp)
+target_link_libraries(libclapp_doc_simple_sub_parser clapp)
+target_compile_options(libclapp_doc_simple_sub_parser PRIVATE ${libClaPP_COMPILE_OPTIONS})
+if(CLANG_TIDY)
+  set_target_properties(libclapp_doc_simple_sub_parser PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_DOC_ARGS}")
 endif()
+add_test(NAME libclapp_doc_simple_sub_parser_test COMMAND ${RAKU_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/sample_executor.p6 simple_sub_parser.out)
diff --git a/doc/doc.md b/doc/doc.md
index 606b5d46bfcbf31fe8a2f3ee1afce4b9bc20c075..79a1cbf1109ea1f27c2e0f56058d92b35f61efb5 100644
--- a/doc/doc.md
+++ b/doc/doc.md
@@ -1,11 +1,162 @@
-Value types for arguments or option parameters:
-===============================================
+Introduction:
+=============
+
+In libClaPP the following Terminology is used:
+
+Terminology:
+-------------
+In this project the following terms are used:
+
+* Option: An option can be either a short option or a long option.
+    A short option consists of a single `-` followed by single character (e.g. `-h`).
+    A long option consists of two `--` followed by an arbitrary string (e.g. `--help`).
+* Parameter: Some options may require additional parameters (.e.g. `--file=/path/to/file`).
+* Argument: An argument is the short form for positional argument.
+    Thus, arguments higly depend on the position where they occur.
+    Unlinke to options that may occur anywhere else.
+* Sub-Parser: A subparser is always implicitly the last argument of a the current parser.
+    Once this argument is given, a completely new parsing instance is started.
+
+Outlook:
+--------
+This document provides an overview of the features of libClaPP.
+
+The first section starts with the individual value types (for options and arguments). 
+This includes an introduction to the supported CLI-options and CLI-arguments.
+Also, a complete collection of shipped types is given. Including a description, how
+custom types can be used.
+Finally, additional options for options, arguments or their parameters are described (conaining
+constraints or additional help information).
+
+The next section concludes with the different parser types: main-parser and sub-parser.
+This section also contains some complete examples that show, how a ClaPP-based parser looks like.
+
+Examples:
+---------
+This document already contains some short examples that show the basic usage of this library.
+However, some further examples can be found in the [../examples](../examples) folder.
+
+
+Value types for arguments or options with or without parameters:
+================================================================
 This library supports different types for positional arguments and option parameters.
 The following subsection introduces all supported types and how additional types can be added.
 In the subsection below, some argument or option parameter restrictions are introduced.
 
-Supported argument or option parameter types:
----------------------------------------------
+CLI-Options:
+------------
+
+### CLI-Option construction:
+
+In general, the constructors of all shipped options have these signatures:
+
+```c++
+ABSTRACT_OPTION(basic_parser_t& parser, LONG_OPTION long_option, SHORT_OPTION short_option, const std::string& description, ADDITIONAL_PARAMS... params);
+ABSTRACT_OPTION(basic_parser_t& parser, LONG_OPTION long_option, const std::string& description, ADDITIONAL_PARAMS... params);
+ABSTRACT_OPTION(basic_parser_t& parser, SHORT_OPTION short_option, const std::string& description, ADDITIONAL_PARAMS... params);
+```
+
+where `LONG_OPTION`, `SHORT_OPTION` and `ADDITIONAL_PARAMS` are placeholders for the following types:
+* `LONG_OPTION` can either be a std::string, a c-string or a std::vector<std::string>.
+* `SHORT_OPTION` can either be a char or a std::vector<char>.
+* `ADDITIONAL_PARAMS` are the variadic types that involve additional parameters for the option (For a complete collection of additional parameters see [Additional parameters for arguments or options](#additional-parameters-for-arguments-or-options)).
+
+Currently, there exist different types of options:
+* non-parameter options: These options do not support any parameters. I.e. the CLI parser only checks if the option is given or not. One example is the common `--help|-h` option.
+* parameter options: Some options require parameters. I.e. options that take numbers, strings or paths. The parameters must be given directly after the option either separated with `=` or with ` `.
+Examples are `--string-opt='parameter'` or `--string-opt 'parameter'`. 
+* vector-parameter options: These are required, if parameter options can be given multiple times. In this case, the parsed parameters are stored in a `std::vector`. E.g. `--path /tmp/xxx --path=/tmp/yyy`.
+
+As a default, all options are optional. If an option is required, the additional parameter `clapp::purpose_t::mandatory` must be given to the constructor.
+
+A complete colletion of supported options is available in [Complete collection of supported argument or option parameter types](#complete-collection-of-supported-argument-or-option-parameter-types).
+
+Example constructor calls for some different options are the following lines:
+
+```c++
+clapp::option::uint8_param_option_t{parser_inst, "--long-uint8-param", "a description for an unit8-param", clapp::purpose_t::mandatory};
+clapp::option::sec_param_option_t{parser_inst, "-s", "number of seconds"}
+clapp::option::vector_path_param_option_t{parser_inst, "--path", '-p', "a path the the required file", clapp::value::path_exists_t{}};
+clapp::option::vector_path_param_option_t{parser_inst, {"--file", "--f"}, '-f', "a path to the required file", clapp::value::path_exists_t{}};
+```
+
+### CLI-Option usage:
+In general, all shipped CLI-options can be used in similar ways, as all support the following methods:
+
+```c++
+template<typename T>
+T value() const;
+explicit operator bool() const;
+bool has_value() const;
+bool given() const noexcept;
+```
+
+The method `value()` can be used to retrieve the parsed value from a CLI-option.
+If the CLI-parser could not parse the option value from the command line arguments (i.e. the CLI-option contains no value),
+a call to `value()` would throw a `clapp::exception::value_undefined_t`-exception.
+To check if `value()` would throw without calling `value()` directly, the methods `has_value()` or `operator bool()`
+can be used. Both return `false`, if a call to `value()` would throw and `true` if a call to `value()` would not throw.
+
+If the CLI option was constructed with an additional `clapp::value::default_value_t`-parameter, a call to `T value()` will 
+never throw, as `value()` would return the default value.
+To distinguish between default values and given values, the method `given()` can be used: 
+`given()` returns `false`, if `value()` would return the default value from the additional `clapp::value::default_value_t`-parameter 
+and it returns `true`, if `value()` would return a value that is parsed from the CLI arguments.
+
+Positional CLI-Arguments:
+-------------------------
+
+In general, the constructors of all shipped (positional) arguments have these signature:
+
+```c++
+ABSTRACT_ARGUMENT(basic_parser_t& parser, const std::string& argument, const std::string& description, ADDITIONAL_PARAMS... params);
+```
+
+where `ADDITIONAL_PARAMS` are placeholders for variadic types that involve additional parameters for the argument (For a complete collection of additional parameters see [Additional parameters for arguments or options](#additional-parameters-for-arguments-or-options)).
+
+Currently, there exist two types of positional arguments:
+* regular arguments: are positional arguments that are either mandatory or optional. Note, that mandatory arguments must be registered before optional arguments. Otherwise, positional arguments can't be assigned uniquely.
+* variadic arguments: sometimes, it is required to give a variable number of arguments. In this case, variadic position argument types can be used. Similar to the optional arguments before, it is required to define all mandatory arguments before variadic arguments are registered. Also note, that optional arguments and variadic arguments can't be used together. In order to make sure, that the arguments can be parsed uniquely.
+
+As a default, all arguments are mandatory. If an argument is optional, the additional parameter `clapp::purpose_t::optional` must be given to the constructor.
+
+A complete colletion of supported arguments is available in [Complete collection of supported argument or option parameter types](#complete-collection-of-supported-argument-or-option-parameter-types).
+
+
+Example constructor calls for arguments are the following lines:
+
+```c++
+clapp::string_argument_t string_arg{parser_inst, "string-arg", "String argument"};
+clapp::int32_argument_t int_arg{parser_inst, "int-arg", "Int argument", clapp::purpose_t::optional};
+clapp::variadic_string_argument_t variadic_string_arg{parser_inst, "variadic-string-arg", "Variadic String argument"};
+```
+
+### CLI-Argument usage:
+In general, all shipped CLI-arguments can be used in similar ways, as all support the following methods:
+
+```c++
+template<typename T>
+T value() const;
+explicit operator bool() const;
+bool has_value() const;
+bool given() const noexcept;
+```
+
+The method `value()` can be used to retrieve the parsed value from a CLI-argument.
+If the CLI-parser could not parse the argument value from the command line arguments (i.e. the CLI-argument contains no value),
+a call to `value()` would throw a `clapp::exception::value_undefined_t`-exception.
+To check if `value()` would throw without calling `value()` directly, the methods `has_value()` or `operator bool()`
+can be used. Both return `false`, if a call to `value()` would throw and `true` if a call to `value()` would not throw.
+
+If the CLI argument was constructed with an additional `clapp::value::default_value_t`-parameter, a call to `T value()` will 
+never throw, as `value()` would return the default value.
+To distinguish between default values and given values, the method `given()` can be used: 
+`given()` returns `false`, if `value()` would return the default value from the additional `clapp::value::default_value_t`-parameter 
+and it returns `true`, if `value()` would return a value that is parsed from the CLI arguments.
+
+
+Complete collection of supported argument or option parameter types:
+--------------------------------------------------------------------
 
 ### String values:
 The most basic types for CLI options are string types (`std::string`), as all values in the `argv` parameter can be converted implicitly to (`std::string`).
@@ -30,9 +181,10 @@ The following integral types are supported:
 * `std::uint64_t`
 
 As input format for these values the following formats can be used:
-* `[+-][1-9][0-9]*`: Decimal numbers
-* `[+-]0[0-9]+`: Octal numbers
-* `[+-]0x[0-9]+`: Hexadecial numbers
+* `[+-]?[1-9][0-9]*`: Decimal numbers
+* `[+-]?0[0-7]+`: Octal numbers
+* `[+-]?0[Xx][0-9a-fA-F]+`: Hexadecial numbers
+
 If one of these values contains a `.`, only the decimals before this `.` are used. 
 Subsequent decimals are truncted.
 
@@ -77,11 +229,12 @@ If integral values should be used as option parameters, the following types can
 * `clapp::option::vector_int32_param_option_t`
 * `clapp::option::vector_int64_param_option_t`
 
+
 ### Filesystem path values:
 It is also possible to pass regular filesystem paths as argument or option parameter. 
 The underlying type is the standardized filesystem type `std::filesystem::path`.
 
-If filesystem path values should be used for positional arguments, the following types can be used:
+If filesystem path values should be used as positional arguments, the following types can be used:
 * `clapp::argument::path_argument_t`
 * `clapp::argument::variadic_path_argument_t`
 
@@ -89,30 +242,88 @@ If filesystem path values should be used as option parameters, the following typ
 * `clapp::option::path_param_option_t`
 * `clapp::option::vector_path_param_option_t`
 
+### Floating point values:
+Besides the classic integer values, it is also possible to use floating point values as arguments or options.
+The underlying types are the standardized types `double` or `float`.
+
+If floating point values should be used as positional arguments, the following types can be used:
+* `clapp::argument::double_argument_t`
+* `clapp::argument::float_argument_t`
+* `clapp::argument::variadic_double_argument_t`
+* `clapp::argument::variadic_float_argument_t`
+
+If floating point values should be used as otion parameters, the following types can be used:
+* `clapp::option::double_param_option_t`
+* `clapp::option::float_param_option_t`
+* `clapp::option::vector_double_param_option_t`
+* `clapp::option::vector_float_param_option_t`
+
+As input format for these values the following formats can be used:
+* `[+-]?[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?`: Decimal numbers (with optional decimal exponent base 10)
+* `[+-]?0[xX][0-9a-fA-F]+(\.[0-9]*)?([pP][+-]?[0-9a-fA-F]+)?`: Hexadecial numbers (with optional decimal exponent base 2)
+* `[+-]?[Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])?`: INF or INFINITY case insensitive with optional sign.
+* `[+-]?[Nn][Aa][Nn]?`: NAN case insensitive with optional sign.
+
+### Chrono values:
+It is also possible to use crhono types as arguments or options.
+The underlying types are the standardized types `std::chrono::hours`...`std::chrono::nanoseconds`.
+
+If chrono values should be used as positional arguments, the following types can be used:
+* `clapp::argument::ns_argument_t`
+* `clapp::argument::us_argument_t`
+* `clapp::argument::ms_argument_t`
+* `clapp::argument::sec_argument_t`
+* `clapp::argument::min_argument_t`
+* `clapp::argument::hours_argument_t`
+* `clapp::argument::variadic_ns_argument_t`
+* `clapp::argument::variadic_us_argument_t`
+* `clapp::argument::variadic_ms_argument_t`
+* `clapp::argument::variadic_sec_argument_t`
+* `clapp::argument::variadic_min_argument_t`
+* `clapp::argument::variadic_hours_argument_t`
+
+If chrono values should be used as option parameters, the following types can be used:
+* `clapp::option::ns_param_option_t`
+* `clapp::option::us_param_option_t`
+* `clapp::option::ms_param_option_t`
+* `clapp::option::sec_param_option_t`
+* `clapp::option::min_param_option_t`
+* `clapp::option::hours_param_option_t`
+* `clapp::option::vector_ns_param_option_t`
+* `clapp::option::vector_us_param_option_t`
+* `clapp::option::vector_ms_param_option_t`
+* `clapp::option::vector_sec_param_option_t`
+* `clapp::option::vector_min_param_option_t`
+* `clapp::option::vector_hours_param_option_t`
+
 ### Custom types:
 Sometimes it is required to use custom types as argument or option parameter. For example the following enum declaration:
 
-    enum class my_type_t {value1, value2, value3};
+```c++
+enum class my_type_t {value1, value2, value3};
+```
 
 In order to allow this (or other types) as argument or option parameter, first it is required to create a new template specialization for the function `template<typename T> T clapp::value::convert_value<T>(const std::string_view param)`:
 
-    template<>
-    my_type_t clapp::value::convert_value<my_type_t>(const std::string_view param) {
-        if(param == "value1") {
-            return my_type_t::value1;
-        } else if(param == "value2") {
-            return my_type_t::value2;
-        } else if(param == "value3") {
-            return my_type_t::value3;
-        } else {
-            throw std::runtime_error("Invalid value for my_type_t.");
-        }
+```c++
+template<>
+my_type_t clapp::value::convert_value<my_type_t>(const std::string_view param) {
+    if(param == "value1") {
+        return my_type_t::value1;
+    } else if(param == "value2") {
+        return my_type_t::value2;
+    } else if(param == "value3") {
+        return my_type_t::value3;
+    } else {
+        throw std::runtime_error("Invalid value for my_type_t.");
     }
+}
+```
 
 As you can see in this example, it is perfectly fine to throw an exception, if the parsed value is invalid..
 
-Restrictions for arguments or option parameters
------------------------------------------------
+Additional parameters for arguments or options
+----------------------------------------------
 It is possible to define restrictions for arguments and option parameters.
 This restrictions can be given to the argument or option parameter types in an arbitrary order as one of the variadic parameters.
 
@@ -124,8 +335,10 @@ As a default (i.e. no mandatory is given), each option is optional!
 
 Some example options are: 
 
-    clapp::option::int32_param_option_t int_opt{ptr_to_parser, "option", 'o', "Description for mandatory option.", clapp::purpose_t::mandatory};
-    clapp::option::bool_option_t int_opt{ptr_to_parser, "yes", 'y', "Description for optional option.", clapp::purpose_t::optional};
+```c++
+clapp::option::int32_param_option_t int_opt{ptr_to_parser, "option", 'o', "Description for mandatory option.", clapp::purpose_t::mandatory};
+clapp::option::bool_option_t int_opt{ptr_to_parser, "yes", 'y', "Description for optional option.", clapp::purpose_t::optional};
+```
 
 Arguments can also be mandatory or optional:
 * Mandatory arguments must always be given. This is also reflected in the help message: `<argument>`.
@@ -134,8 +347,10 @@ As a default (i.e. no optional is given), each argument is mandatory!
 
 Some example arguments are: 
 
-    clapp::argument::int32_argument_t int_arg{ptr_to_parser, "argument", "Description for mandatory argument.", clapp::purpose_t::mandatory};
-    clapp::argument::bool_option_t int_opt{ptr_to_parser, "argument", "Description for optional argument.", clapp::purpose_t::optional};
+```c++
+clapp::argument::int32_argument_t int_arg{ptr_to_parser, "argument", "Description for mandatory argument.", clapp::purpose_t::mandatory};
+clapp::argument::bool_option_t int_opt{ptr_to_parser, "argument", "Description for optional argument.", clapp::purpose_t::optional};
+```
 
 ### Default value:
 In order to provide a default value for arguments or option parameters, there exists the class `clapp::value::default_value_t`.
@@ -147,8 +362,10 @@ A default value is also reflected in the help message, as `(default-value: <valu
 
 Examples are:
 
-    clapp::option::int32_option_t int_opt{ptr_to_parser, "int-option", 'i', "Description for optional option.", clapp::purpose_t::optional, clapp::value::default_value_t{10}};
-    clapp::option::string_argument_t string_arg{ptr_to_parser, "string-argument", "Description for optional argument.", clapp::purpose_t::optional, clapp::value::default_value_t{"default-string"}};
+```c++
+clapp::option::int32_option_t int_opt{ptr_to_parser, "int-option", 'i', "Description for optional option.", clapp::purpose_t::optional, clapp::value::default_value_t{10}};
+clapp::option::string_argument_t string_arg{ptr_to_parser, "string-argument", "Description for optional argument.", clapp::purpose_t::optional, clapp::value::default_value_t{"default-string"}};
+```
 
 ### Min/Max value:
 In order to provide a range check for arguments or option parameters, there exists the class `clapp::value::min_max_value_t`.
@@ -159,8 +376,10 @@ A min/max value is also reflected in the help message, as `(constraint: [<min>,<
 
 Examples are:
 
-    clapp::option::int32_option_t int_opt{ptr_to_parser, "int-option", 'i', "Description for int-option.", clapp::value::min_max_value_t{10, 20}};
-    clapp::option::int32_argument_t int_arg{ptr_to_parser, "int-argument", "Description for int-argument.", clapp::value::min_max_value_t{20, 40}};
+```c++
+clapp::option::int32_option_t int_opt{ptr_to_parser, "int-option", 'i', "Description for int-option.", clapp::value::min_max_value_t{10, 20}};
+clapp::option::int32_argument_t int_arg{ptr_to_parser, "int-argument", "Description for int-argument.", clapp::value::min_max_value_t{20, 40}};
+```
 
 ### Path exists:
 In order to provide a check for filesystem-path arguments or option parameters, there exists the class `clapp::value::path_exists_t`.
@@ -173,8 +392,10 @@ Note: this class may only be used for filesystem path values.
 
 Examples are:
 
-    clapp::option::path_param_option_t file_opt{ptr_to_parser, "filename-option", 'f', "Description for filename option.", clapp::value::path_exists_t{}};
-    clapp::option::path_argument_t file_arg{ptr_to_parser, "filenem-argument", "Description for filename argument.", clapp::value::path_exists_t{}};
+```c++
+clapp::option::path_param_option_t file_opt{ptr_to_parser, "filename-option", 'f', "Description for filename option.", clapp::value::path_exists_t{}};
+clapp::option::path_argument_t file_arg{ptr_to_parser, "filenem-argument", "Description for filename argument.", clapp::value::path_exists_t{}};
+```
 
 ### Custom restrictions:
 Of course, it is possible to create own restriction classes. 
@@ -192,14 +413,93 @@ Parser:
 Main Parser:
 ------------
 The main parser is the key element of the libClaPP CLI parsing library.
-Typically, it is a derivied class with the base class `clapp::parser::basic_main_parser_t`.
-One of the benefit of the libClaPP library is that all arguments and options can be registered 
+Typically, it is a derivied class of the base class `clapp::parser::basic_main_parser_t`.
+One of the benefits of the libClaPP library is that all arguments and options can be registered
 as class members.
-Thus, by simply passing around a reference (or a pointer) to the main parser, all parsed options 
-or arguments are condensed in a class instance.
+Thus, by simply passing around a reference (or a pointer) to this main parser, all parsed
+arguments or option can be be accessed easily.
+
+### Main parser construction:
+The main-parser base class `clapp::parser::basic_main_parser_t` contains only one constructor.
+This constructor has no arguments, but since it is a base-class, you can extend it easily by
+your derived class. See the listing below for an example.
+
+### Main parser usage:
+The main-parser base class `clapp::parser::basic_main_parser_t` is shipped with several useful methods.
+Most of them are listed here, but for a complete collection take a look at
+[src/include/clapp/main_parser.h](src/include/clapp/main_parser.h).
+Since the main-parser base class `clapp::parser::basic_main_parser_t` is itself derived from
+`clapp::parser::basic_parser_t`, you may also look at
+[src/include/clapp/parser.h](src/include/clapp/parser.h)
+for a complete collection of derived methods.
+
+```c++
+void parse(int argc, const char* const* argv);
+void parse(const arg_t& arg);
+void parse_and_validate(int argc, const char* const* argv);
+void validate() const;
+void validate_recursive() const;
+explicit operator bool() const;
+std::string get_executable() const;
+std::string gen_help_msg(std::size_t rec_depth) const;
+std::size_t get_num_processed_arguments() const;
+const basic_parser_t& get_active_parser() const;
+```
+#### The `parse()` methods:
+The `parse()` methods can be used to parse the command line arguments.
+These functions may throw exceptions of type `clapp::clapp_exception_t` (or a derived type of this type).
+For example, if invalid or unknown options are given, or given values could not be converted to the required type.
+But these functions only try to parse the values.
+Thus, in order to check if all mandatory options and arguments are given, the methods `validate()`, `validate_recursive()` or `parse_and_validate()` may be used.
+
+#### The `validate()` method:
+The `validate()` method can be used to check the requirements of the parsed result.
+Thus, it checks if all mandatory arguments or options were given and ensures that all constraints are met.
+Note: this method only validates all arguments or options of the current parser instance. Thus, if subparsers are used, the `validate()` method ignores all subparsers. If you want to validate the main-parser and all sub-parsers, use `validate_recursive()`.
+If the validation fails, it throws an exception of type `clapp::clapp_exception_t` (or a derived type of this type).
+
+#### The `validate_recursive()` method:
+This method ensures that all mandatory arguments or options were given and ensures that all constraints are met. (Similar to the `validate()` method in the `validate()` section).
+The only difference is, that it validates all subparsers too.
+This is done in a recursive way.
+Thus, it validates the current parser and subparsers that were selected by the cli-parameters.
+
+#### The `parse_and_validate()` method:
+This method is a combination of the `parse()`- and `validate_recursive()`-methods.
+Thus, it first parses the cli-arguments and if the parsing succeeds, it validates the parsed results.
+
+#### The `operator bool()` method:
+For main-parsers, this method always returns `true`, if an executable is set.
+If an executable is set, it can be requested by calling `get_executable()`.
+
+#### The `get_executable()` method:
+This method returns the name of the executable that is used in the cli-arguments.
+If it is not set, the exception `no_executable_exception_t` is thrown.
+
+#### The `gen_help_msg()` method:
+This method generates the usage message of the parser class.
+This output is the same as it would be generated by the `help_option_t`-option.
+`gen_help_msg()` requires an additional parameter `rec_depth`:
+It controls the depth of the help message.
+I.e. the number of encapsulated (sub-)parsers.
+A number of 0 does not include any subparsers and would only include the main parser.
+
+#### The `get_num_processed_arguments()` method:
+This method reurns how many arguments were given via the cli-interface.
+
+#### The `get_active_parser()` method:
+This method returns a reference to the selected (sub-)parser.
+If no sub-parser was selected by the cli-arguments, this method returns a reference
+to this current main-parser instance. If a sub-parser was selected it would return a reference to
+this sub-parser.
+
+### Example code listing for a main parser:
+The following code-listing illustrates a very basic example of a main parser with an option and a
+string argument:
 
 [//]:#begin_cpp_listing_simple_main_parser
 ```c++
+#include <cassert>
 #include <clapp/argument.h>
 #include <clapp/main_parser.h>
 #include <clapp/option.h>
@@ -216,7 +516,7 @@ class cli_parser_t : public clapp::basic_main_parser_t {
 
     clapp::string_argument_t string_arg{*this, "string-arg", "String argument"};
 
-    //explicitly delete copy/move-ctors and assignmet operators 
+    //delete copy/move-ctors and assignmet operators (CppCoreGuideline C.21):
     explicit cli_parser_t(const cli_parser_t &) = delete;
     explicit cli_parser_t(cli_parser_t &&) noexcept = delete;
     cli_parser_t &operator=(const cli_parser_t &) = delete;
@@ -228,12 +528,332 @@ cli_parser_t::~cli_parser_t() = default;
 int main(int argc, char *argv[]) {
     try {
         cli_parser_t cp{argc, argv};  // parses and validates cli-arguments
-
-        Expects(cp.string_arg);  // parser ensures mandatory arguments are given
+        Ensures(cp.string_arg);  // parser ensures mandatory arguments are given
         std::cout << "string-arg: " << cp.string_arg.value() << std::endl;
     } catch (std::exception &e) {
         std::cout << "Caught Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
     }
+    return EXIT_SUCCESS;
 }
 ```
 [//]:#end_cpp_listing_simple_main_parser
+
+Note: The previous listing explicitly deletes the copy/move assignment operators and the copy/move constructors.
+Depending on your code style, this may not be necessary, as `clapp::basic_main_parser_t` already deletes the copy/move assignment operators and the copy/move constructors.
+But if you want to be conformant to [CppCoreGuideline C.21](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all), you should declare them.
+
+### Example cli-outputs when using the previous listing:
+If the previous example listing is executed, you get the following output:
+[//]:#begin_calls_simple_main_parser
+```bash
+# Print the help message:
+$ ./libclapp_doc_simple_main_parser -h  # this is the same as with option `--help`
+Usage:
+./libclapp_doc_simple_main_parser <string-arg> [-h|--help]
+
+  Mandatory Arguments:
+    string-arg String argument
+
+  Optional Options:
+    -h|--help  Show help options.
+
+# Give mandatory argument:
+$ ./libclapp_doc_simple_main_parser my-string
+string-arg: my-string
+
+# Give no mandatory argument throws:
+$ ./libclapp_doc_simple_main_parser
+Caught Exception: Mandatory argument 'string-arg' not given.
+
+```
+[//]:#end_calls_simple_main_parser
+
+Sub Parser:
+-----------
+The sub-parser is another key element of the libClaPP CLI parsing library.
+Typically, it is a derivied class of the base class `clapp::parser::basic_sub_parser_t`.
+
+In particular, if you want to have different cli-interface modes, a sub-parser may be what you want:
+A sub parser is similar to a main-parser, as it also contains different arguments and options, 
+but it is typically invoked by the surrounding main parser, if a special keyword is given in the CLI 
+arguments.
+Thus, typically there is no need to invoke a sub-parser directly.
+
+Typically, a sub parser can be used to switch between different modes of a program, that need different
+arguments or options.
+A typical example is the git command: By calling `git log` or `git commit` you get different cli options and arguments each.
+In the context of libclapp it is required to define a sub parser that handles the `log` options and arguments 
+and another sub parser that handles the `commit` options and arguments.
+
+For example, if it is required that a binary supports 3 modi: a default mode and two additional modes: mode1 and mode2.
+The default mode is active, if none of the additional modes was activated. Both modes can define other arguments and options:
+
+Note: if sup-parsers are used, these sub-parsers always take the role of the last argument.
+Thus, if at least one sub-parser is registered, no variadic or optional arguments can be used.
+Furthermore, if a sub-parser is registered before an argument, the arument position will always be before registered sub-parsers.
+
+Note: sub-parsers can be stacked. I.e. a sub-parser can itself contain other sub-parsers which iself can contain additional sub-parsers.
+
+### Sub parser construction:
+The sub-parser base class `clapp::parser::basic_sub_parser_t` contains only one constructor:
+
+```c++
+basic_sub_parser_t(basic_parser_t& parser, const std::string& sub_parser_name, const std::string& description);
+```
+
+Similar to the option and argument constructors, the first argument is a reference to the surrounding parser (i.e. a main parser or other sub-parsers.
+The other two arguments are the name of the sub-parser and a description of the sub-parser.
+See the listing below for an example how a sub-parser can be created.
+
+### Sub parser usage:
+The sub-parser base class `clapp::parser::basic_sub_parser_t` is shipped with several useful methods.
+Most of them are listed here, but for a complete collection take a look at
+[src/include/clapp/sub_parser.h](src/include/clapp/sub_parser.h).
+Since the sub-parser base class `clapp::parser::basic_sub_parser_t` is itself derived from
+`clapp::parser::basic_parser_t`, you may also look at
+[src/include/clapp/parser.h](src/include/clapp/parser.h)
+for a complete collection of derived methods.
+
+```c++
+void validate() const;
+void validate_recursive() const;
+bool is_active() const;
+explicit operator bool() const;
+std::string get_sub_parser_name() const;
+std::size_t get_num_processed_arguments() const;
+const basic_parser_t& get_active_parser() const;
+```
+
+#### The `validate()` method:
+The `validate()` method is similar to `basic_main_parser::validate()` and thus can be used to check the requirements of the parsed result.
+Thus, it checks if all mandatory arguments or options were given and ensures that all constraints are met.
+Note: this method only validates all arguments or options of the current parser instance. Thus, if further subparsers are used, the `validate()` method ignores all subparsers. If you want to validate this sub-parser and all furhter sub-parsers, use `validate_recursive()`.
+If the validation fails, it throws an exception of type `clapp::clapp_exception_t` (or a derived type of this type).
+
+#### The `validate_recursive()` method:
+This method is similar to `basic_main_parser::validate_recursive()` and thus ensures that all mandatory arguments or options were given and ensures that all constraints are met. (Similar to the `validate()` method in the `validate()` section).
+The only difference is, that it validates all subparsers too.
+This is done in a recursive way.
+Thus, it validates the current parser and subparsers that were selected by the cli-parameters.
+
+#### The `bool is_active()` method:
+This method always returns `true`, if the sub-parser is selected by the cli-arguments.
+If other sub-parsers are selected (that are not members of this sub-parser), this method returns `false`.
+
+#### The `operator bool()` method:
+For sub-parsers this method always returns `true`, if the sub-parser is selected by the cli-arguments.
+(See also method `is_active()`.)
+
+#### The `get_sub_parser_name()` method:
+This method returns the name of the sub-parser.
+
+#### The `get_num_processed_arguments()` method:
+This method reurns how many arguments were given via the cli-interface.
+
+#### The `get_active_parser()` method:
+This method returns a reference to the selected sub-parser (if it is a member of this sub-parser).
+If no sub-parser-member was selected by the cli-arguments, this method returns a reference
+to this sub-parser instance. If a sub-parser was selected it would return a reference to
+this sub-parser.
+
+### Example code listing for sub-parsers:
+
+[//]:#begin_cpp_listing_simple_sub_parser
+```c++
+#include <cassert>
+#include <clapp/argument.h>
+#include <clapp/main_parser.h>
+#include <clapp/option.h>
+#include <clapp/sub_parser.h>
+
+class cli_parser_t : public clapp::basic_main_parser_t {
+   public:
+    cli_parser_t(int argc, const char *const *argv) {
+        parse_and_validate(argc, argv);
+    }
+
+    ~cli_parser_t() override;
+
+    clapp::help_option_t help{*this, "help", 'h', "Show help options."};
+
+    clapp::int32_param_option_t int_opt{*this, 'i', "Int option"};
+
+    class mode1_parser_t : public clapp::basic_sub_parser_t {
+       public:
+        using clapp::basic_sub_parser_t::basic_sub_parser_t;
+
+        ~mode1_parser_t() override;
+
+        clapp::help_option_t help{*this, "help", 'h', "Show help options."};
+
+        clapp::string_param_option_t string{*this, 's', "String param option."};
+
+        //delete copy/move-ctors and assignmet operators (CppCoreGuideline C.21):
+        explicit mode1_parser_t(const mode1_parser_t &) = delete;
+        explicit mode1_parser_t(mode1_parser_t &&) noexcept = delete;
+        mode1_parser_t &operator=(const mode1_parser_t &) = delete;
+        mode1_parser_t &operator=(mode1_parser_t &&) noexcept = delete;
+    };
+
+    class mode2_parser_t : public clapp::basic_sub_parser_t {
+       public:
+        using clapp::basic_sub_parser_t::basic_sub_parser_t;
+
+        ~mode2_parser_t() override;
+
+        clapp::help_option_t help{*this, "help", 'h', "Show help options."};
+
+        clapp::string_argument_t string_arg{
+            *this, "string-arg", "String argument"};
+
+        //delete copy/move-ctors and assignmet operators (CppCoreGuideline C.21):
+        explicit mode2_parser_t(const mode2_parser_t &) = delete;
+        explicit mode2_parser_t(mode2_parser_t &&) noexcept = delete;
+        mode2_parser_t &operator=(const mode2_parser_t &) = delete;
+        mode2_parser_t &operator=(mode2_parser_t &&) noexcept = delete;
+    };
+
+    mode1_parser_t mode1{*this, "mode1", "mode1 sub-parser."};
+    mode2_parser_t mode2{*this, "mode2", "mode2 sub-parser."};
+
+    //delete copy/move-ctors and assignmet operators (CppCoreGuideline C.21):
+    explicit cli_parser_t(const cli_parser_t &) = delete;
+    explicit cli_parser_t(cli_parser_t &&) noexcept = delete;
+    cli_parser_t &operator=(const cli_parser_t &) = delete;
+    cli_parser_t &operator=(cli_parser_t &&) noexcept = delete;
+};
+
+cli_parser_t::~cli_parser_t() = default;
+cli_parser_t::mode1_parser_t::~mode1_parser_t() = default;
+cli_parser_t::mode2_parser_t::~mode2_parser_t() = default;
+
+int main(int argc, char *argv[]) {
+    try {
+        cli_parser_t cp{argc, argv};  // parses and validates cli-arguments
+
+        if(cp.mode1) {
+            std::cout << "mode1: ";
+            if(cp.mode1.string) {
+                std::cout << "string: '" << cp.mode1.string.value() << "' ";
+            }
+            if(cp.int_opt){
+                std::cout << "int-opt: '" << cp.int_opt.value() << "' ";
+            }
+            std::cout << std::endl;
+        } else if(cp.mode2) {
+            std::cout << "mode2: ";
+            Ensures(cp.mode2.string_arg);  // parser ensures mandatory arguments are given
+            std::cout << "string_arg: '" << cp.mode2.string_arg.value() << "'" << std::endl;
+        } else {
+            std::cout << "default mode: ";
+            if(cp.int_opt){
+                std::cout << "int-opt: '" << cp.int_opt.value() << "'";
+            }
+            std::cout << std::endl;
+        }
+    } catch (std::exception &e) {
+        std::cout << "Caught Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
+```
+[//]:#end_cpp_listing_simple_sub_parser
+The mode1-subparser is configured to inherit all options and arguments from the main-parser,
+while the mode2-subparser doesn't inherit anything from the main-parser.
+This behavior can be controlled by the fourth (optional) bool argument that is given to the
+subparser-constructors: Giving `true` or no argument enables this feature.
+While giving `false` disables the interitation from the parent parser.
+
+### Example cli-outputs when using the sub-parser listing:
+[//]:#begin_calls_simple_sub_parser
+```bash
+# Print the overall help message:
+$ ./libclapp_doc_simple_sub_parser --help
+Usage:
+./libclapp_doc_simple_sub_parser [-h|--help] [-i=<arg>] mode1 [-h|--help] [-s=<arg>]
+./libclapp_doc_simple_sub_parser [-h|--help] [-i=<arg>] mode2 <string-arg> [-h|--help]
+./libclapp_doc_simple_sub_parser [-h|--help] [-i=<arg>]
+
+  Subparser:
+    mode1          mode1 sub-parser.
+      Optional Options:
+        -h|--help  Show help options.
+        -s=<arg>   String param option.
+
+
+    mode2          mode2 sub-parser.
+      Mandatory Arguments:
+        string-arg String argument
+
+      Optional Options:
+        -h|--help  Show help options.
+
+
+  Optional Options:
+    -h|--help      Show help options.
+    -i=<arg>       Int option
+
+# Print the help message of mode1:
+$ ./libclapp_doc_simple_sub_parser mode1 -h
+Usage:
+./libclapp_doc_simple_sub_parser [-h|--help] [-i=<arg>] mode1 [-h|--help] [-s=<arg>]
+
+  Optional Options:
+    -h|--help  Show help options.
+    -s=<arg>   String param option.
+
+# Print the help message of mode2:
+$ ./libclapp_doc_simple_sub_parser mode2 --help
+Usage:
+./libclapp_doc_simple_sub_parser [-h|--help] [-i=<arg>] mode2 <string-arg> [-h|--help]
+
+  Mandatory Arguments:
+    string-arg String argument
+
+  Optional Options:
+    -h|--help  Show help options.
+
+# Give no sub-parser:
+$ ./libclapp_doc_simple_sub_parser
+default mode: 
+
+# Give no sub-parser, but optional int-option `-i`:
+$ ./libclapp_doc_simple_sub_parser -i 12                    #decimal
+default mode: int-opt: '12'
+
+# Give invalid sub-parser:
+$ ./libclapp_doc_simple_sub_parser mode
+Caught Exception: Unknown argument/sub-parser 'mode'.
+
+# Give sub-parser `mode1`:
+$ ./libclapp_doc_simple_sub_parser mode1
+mode1: 
+
+# Give sub-parser `mode1` and optional int-option `-i`:
+$ ./libclapp_doc_simple_sub_parser -i 011 mode1             #octal
+mode1: int-opt: '9' 
+
+# Give sub-parser `mode1` and optional string-option `-s`:
+$ ./libclapp_doc_simple_sub_parser mode1 -s str
+mode1: string: 'str' 
+
+# Give sub-parser `mode1` and optional string-option `-s` and int-option `-i`:
+$ ./libclapp_doc_simple_sub_parser -i=0x10 mode1 -s=str     #hex
+mode1: string: 'str' int-opt: '16' 
+
+# Give sub-parser `mode2` without mandatory string-argument `string-arg`:
+$ ./libclapp_doc_simple_sub_parser mode2
+Caught Exception: Mandatory argument 'string-arg' not given.
+
+# Give sub-parser `mode2` with mandatory string-argument `string-arg`:
+$ ./libclapp_doc_simple_sub_parser mode2 argument
+mode2: string_arg: 'argument'
+
+# Give sub-parser `mode2` with mandatory string-argument `string-arg` and invalid option `-i`:
+$ ./libclapp_doc_simple_sub_parser mode2 argument -i 1
+Caught Exception: Invalid (sub-)parser option '-i'
+
+```
+[//]:#end_calls_simple_sub_parser
diff --git a/doc/sample_executor.p6 b/doc/sample_executor.p6
new file mode 100755
index 0000000000000000000000000000000000000000..f53fa0f9be25aab1491a7b1ffb86d426af40add8
--- /dev/null
+++ b/doc/sample_executor.p6
@@ -0,0 +1,39 @@
+#!/usr/bin/perl6
+use v6;
+use Test;
+
+sub exec(Str $comment, Str $cmd, Str $expected_output) {
+    my $output = qqx{$cmd};
+    is($output, $expected_output.substr(0, *-1), "testing '" ~ $comment ~ "': '" ~ $cmd ~ "'");
+}
+
+sub MAIN($out_file) {
+    my Str $output;
+    my Str $cmd;
+    my Str $comment;
+
+    say "Executing '" ~ $out_file ~ "'";
+    my $contents = $out_file.IO.slurp;
+
+    for $contents.lines -> $line {
+        if $line ~~ /^^\#' '$<comment>=[.+]$$/ {
+             if $output and $cmd and $comment {
+                exec($comment, $cmd, $output);
+                $output = Nil;
+                $cmd = Nil;
+                $comment = Nil;
+            }
+            $comment = $<comment>.Str;
+        } elsif $line ~~ /^^\$' '$<cmd>=[.+]$$/ {
+            $cmd = $<cmd>.Str;
+        } else {
+            $output ~= $line ~ "\n";
+        }
+    }
+
+    if $output and $cmd and $comment {
+        exec($comment, $cmd, $output);
+    }
+
+    done-testing;
+}
diff --git a/doc/sample_extractor.p6 b/doc/sample_extractor.p6
index dd71a33c5934d4b32824edd5dfbd7215d015c95c..a9db03988c379de3b4a14f05b463c5de8ebbb77f 100755
--- a/doc/sample_extractor.p6
+++ b/doc/sample_extractor.p6
@@ -1,28 +1,53 @@
 #!/usr/bin/perl6
+use v6;
 
 sub MAIN($doc_dir) {
-    chdir $doc_dir;
     for dir(test => /^ .* \. cpp$/) -> $file {
         say "Removing " ~ $file;
         unlink($file);
     }
+
+    for dir(test => /^ .* \. out$/) -> $file {
+        say "Removing " ~ $file;
+        unlink($file);
+    }
     
     my Str $listing_name;
-    
-    for 'doc.md'.IO.lines -> $line {
+    my Str $calls_name;
+
+    my Str $file = $doc_dir ~ '/doc.md';
+    say "Extracting from '" ~ $file ~ "'.";
+
+    for $file.IO.lines -> $line {
         if $listing_name and $line ~~ /^^\[\/\/\]\:\#end_cpp_listing_$<name>=[\w+]$$/ {
             $listing_name eq $<name>.Str 
                 or die "Unexpected listing name. Expected: '" 
                     ~ $listing_name ~ "' received: '" ~ $<name>.Str ~ "'.";
+            say "Created " ~ $listing_name ~ ".cpp";
             $listing_name=Nil;
         }
+        if $calls_name and $line ~~ /^^\[\/\/\]\:\#end_calls_$<name>=[\w+]$$/ {
+            $calls_name eq $<name>.Str 
+                or die "Unexpected calls name. Expected: '" 
+                    ~ $calls_name ~ "' received: '" ~ $<name>.Str ~ "'.";
+            say "Created " ~ $calls_name ~ ".out";
+            $calls_name=Nil;
+        }
         if $listing_name {
             unless $line ~~ /^^\`\`\`/ {
                 spurt $listing_name ~ ".cpp", $line ~ "\n", :append;
             }
         }
+        if $calls_name {
+            unless $line ~~ /^^\`\`\`/ {
+                spurt $calls_name ~ ".out", $line ~ "\n", :append;
+            }
+        }
         if !$listing_name and $line ~~ /^^\[\/\/\]\:\#begin_cpp_listing_$<name>=[\w+]$$/ {
             $listing_name = $<name>.Str;
         }
+        if !$calls_name and $line ~~ /^^\[\/\/\]\:\#begin_calls_$<name>=[\w+]$$/ {
+            $calls_name = $<name>.Str;
+        }
     }
 }
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 3c8ceabb7bb17da5f04ef44869817c3925590117..35238ec08543e1b84033438a5e1b30afa318a60d 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,25 +1,35 @@
+if(CLANG_TIDY)
+    set(CLANG_TIDY_EX_ARGS "${CLANG_TIDY_ARGS},-misc-non-private-member-variables-in-classes,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers")
+endif()
+
 if(libClaPP_FS_LINKER_FLAG)
-    add_executable(libclapp_example_full full_example.cpp)
-    target_link_libraries(libclapp_example_full clapp ${libClaPP_FS_LINKER_FLAG})
-    target_compile_options(libclapp_example_full PRIVATE ${libClaPP_COMPILE_OPTIONS})
+    add_executable(libclapp_example_large large_example.cpp)
+    target_link_libraries(libclapp_example_large clapp ${libClaPP_FS_LINKER_FLAG})
+    target_compile_options(libclapp_example_large PRIVATE ${libClaPP_COMPILE_OPTIONS})
     if(CLANG_TIDY)
-      set_target_properties(libclapp_example_full PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS}")
+        set_target_properties(libclapp_example_large PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EX_ARGS}")
     endif()
-    install(TARGETS libclapp_example_full DESTINATION ${CMAKE_INSTALL_BINDIR})
+    install(TARGETS libclapp_example_large DESTINATION ${CMAKE_INSTALL_BINDIR})
+    configure_file(test_large_example.sh test_large_example.sh COPYONLY)
+    add_test(NAME large_example_tests COMMAND test_large_example.sh WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 endif()
 
 add_executable(libclapp_example_short short_example.cpp)
 target_link_libraries(libclapp_example_short clapp)
 target_compile_options(libclapp_example_short PRIVATE ${libClaPP_COMPILE_OPTIONS})
 if(CLANG_TIDY)
-  set_target_properties(libclapp_example_short PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS}")
+  set_target_properties(libclapp_example_short PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EX_ARGS}")
 endif()
 install(TARGETS libclapp_example_short DESTINATION ${CMAKE_INSTALL_BINDIR})
+configure_file(test_short_example.sh test_short_example.sh COPYONLY)
+add_test(NAME short_example_tests COMMAND test_short_example.sh WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 
 add_executable(libclapp_example_sub_parser sub_parser_example.cpp)
 target_link_libraries(libclapp_example_sub_parser clapp)
 target_compile_options(libclapp_example_sub_parser PRIVATE ${libClaPP_COMPILE_OPTIONS})
 if(CLANG_TIDY)
-  set_target_properties(libclapp_example_sub_parser PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS}")
+  set_target_properties(libclapp_example_sub_parser PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EX_ARGS}")
 endif()
 install(TARGETS libclapp_example_sub_parser DESTINATION ${CMAKE_INSTALL_BINDIR})
+configure_file(test_sub_parser_example.sh test_sub_parser_example.sh COPYONLY)
+add_test(NAME sub_parser_example_tests COMMAND test_sub_parser_example.sh WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/examples/large_example.cpp b/examples/large_example.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f94e41111dbbd145ce21b74593f438596cab0409
--- /dev/null
+++ b/examples/large_example.cpp
@@ -0,0 +1,396 @@
+#include <clapp/argument.h>
+#include <clapp/build_info.h>
+#include <clapp/main_parser.h>
+#include <clapp/option.h>
+#include <clapp/sub_parser.h>
+#include <clapp/value.h>
+#include <iostream>
+
+using string_argument_t = clapp::basic_argument_t<std::string>;
+using variadic_string_argument_t =
+    clapp::basic_variadic_argument_t<std::string>;
+using int_argument_t = clapp::basic_argument_t<std::int32_t>;
+using variadic_int_argument_t = clapp::basic_variadic_argument_t<std::int32_t>;
+
+enum class entry_t { entry1, entry2 };
+
+class entry_value_constraint_t {
+   public:
+    [[nodiscard]] static std::string append_restriction_text() {
+        return "possible values: entry1, entry2";
+    }
+};
+
+using string_param_t = clapp::basic_param_option_t<std::string>;
+
+using string_vector_param_t = clapp::basic_vector_param_option_t<std::string>;
+
+using int32_param_t = clapp::basic_param_option_t<std::int32_t>;
+
+using entry_param_t = clapp::basic_param_option_t<entry_t>;
+
+using entry_argument_t = clapp::basic_argument_t<entry_t>;
+
+struct no_action_t {};
+
+struct restriction_t {
+    [[nodiscard]] static std::string append_restriction_text() {
+        return "restriction";
+    }
+};
+
+class cli_parser_t : public clapp::basic_main_parser_t {
+   public:
+    cli_parser_t() = default;
+
+    cli_parser_t(int argc, const char *const *argv) : cli_parser_t{} {
+        parse(argc, argv);
+    }
+
+    explicit cli_parser_t(const cli_parser_t &) = delete;
+    explicit cli_parser_t(cli_parser_t &&) noexcept = delete;
+    cli_parser_t &operator=(const cli_parser_t &) = delete;
+    cli_parser_t &operator=(cli_parser_t &&) noexcept = delete;
+
+    ~cli_parser_t() override;
+
+    class cmd1_parser_t : public clapp::basic_sub_parser_t {
+       public:
+        using clapp::basic_sub_parser_t::basic_sub_parser_t;
+
+        explicit cmd1_parser_t(const cmd1_parser_t &) = delete;
+        explicit cmd1_parser_t(cmd1_parser_t &&) noexcept = delete;
+        cmd1_parser_t &operator=(const cmd1_parser_t &) = delete;
+        cmd1_parser_t &operator=(cmd1_parser_t &&) noexcept = delete;
+
+        ~cmd1_parser_t() override;
+        clapp::bool_option_t help{*this, "help", 'h', "Show help options."};
+        clapp::bool_option_t short_bool{*this, 'b', "Short bool option.",
+                                        purpose_t::mandatory};
+        string_param_t string{*this, 's', "String param option."};
+
+        entry_argument_t entry_arg{*this, "entry-arg", "Entry argument",
+                                   entry_value_constraint_t{}};
+
+        int_argument_t int_arg{*this, "int-arg", "Int argument",
+                               clapp::min_max_value_t<std::int32_t>{5, 10}};
+        string_argument_t string_arg_x{
+            *this, "string-arg-x", "String argument x", purpose_t::optional,
+            clapp::default_value_t<std::string>{"abaa"}};
+    };
+
+    class cmd2_parser_t : public clapp::basic_sub_parser_t {
+       public:
+        using clapp::basic_sub_parser_t::basic_sub_parser_t;
+
+        explicit cmd2_parser_t(const cmd2_parser_t &) = delete;
+        explicit cmd2_parser_t(cmd2_parser_t &&) noexcept = delete;
+        cmd2_parser_t &operator=(const cmd2_parser_t &) = delete;
+        cmd2_parser_t &operator=(cmd2_parser_t &&) noexcept = delete;
+
+        ~cmd2_parser_t() override;
+        clapp::bool_option_t help{*this, "help", 'h', "Show help options."};
+        string_argument_t string_arg_x{
+            *this, "string-arg-x", "String argument x", purpose_t::optional,
+            clapp::default_value_t<std::string>{"default-string-arg-x"}};
+        variadic_int_argument_t int_arg{
+            *this, "variadic-int-arg", "Int argument", purpose_t::optional,
+            clapp::min_max_value_t<std::int32_t>{5, 10}};
+        // string_argument_t string_arg_y{*this, "string-arg-y", "String
+        // argument x", purpose_t::optional};//TODO: ensure that this throws
+    };
+
+    cmd1_parser_t cmd1{*this, "cmd1", "First usable command."};
+    cmd2_parser_t cmd2{*this, "cmd2", "Second usable command."};
+
+    string_argument_t string_arg{*this, "string-arg", "String argument"};
+    // string_argument_t string_arg_2{*this, "string-arg-2", "String argument
+    // 2", purpose_t::optional};//TODO: ensure that this throws...
+
+    clapp::help_option_t help{*this, "help", 'h', "Show help options."};
+    clapp::bool_option_t short_bool{*this, 'b', "Short bool option."};
+    clapp::bool_option_t long_bool{*this, "long-bool", "Long bool option."};
+    clapp::bool_option_t restricted_bool{
+        *this,           "restricted", 'r', "restricted bool option.",
+        restriction_t{}, no_action_t{}};
+    clapp::bool_option_t mandatory_bool{
+        *this, 'o', "Mandatory short bool option.", purpose_t::mandatory};
+    clapp::bool_option_t mandatory_restricted_bool{
+        *this,
+        "mandatory-restricted",
+        'm',
+        "Mandatory restricted bool option.",
+        purpose_t::mandatory,
+        restriction_t{}};
+
+    clapp::hours_param_option_t hours{
+        *this, "hours", "hours option.",
+        clapp::default_value_t<std::chrono::hours>{std::chrono::hours{100}}};
+    clapp::min_param_option_t minutes{
+        *this, "minutes", "minutes option.",
+        clapp::min_max_value_t<std::chrono::minutes>{std::chrono::minutes{0},
+                                                     std::chrono::minutes{7}}};
+    clapp::sec_param_option_t seconds{*this, "seconds", "seconds option."};
+    clapp::ms_param_option_t milliseconds{*this, "milliseconds",
+                                          "milliseconds option."};
+    clapp::us_param_option_t microseconds{*this, "microseconds",
+                                          "microseconds option."};
+    clapp::ns_param_option_t nanoseconds{*this, "nanoseconds",
+                                         "nanoseconds option."};
+
+    clapp::count_option_t verbose{*this,
+                                  "verbose",
+                                  'v',
+                                  "Verbose option.",
+                                  clapp::min_max_value_t<std::size_t>{0, 7},
+                                  clapp::default_value_t<std::size_t>{2}};
+    clapp::count_option_t count{*this, 'c', "Count option ",
+                                purpose_t::mandatory};
+
+    string_param_t string_param{*this, "string", 's', "String option 1."};
+
+    string_vector_param_t string_vector_param{*this, "string-vector",
+                                              "String vector param."};
+
+#ifdef CLAPP_FS_AVAIL
+    clapp::path_param_option_t test_file{*this, "test-file", "Test File.",
+                                         clapp::path_exists_t {}};
+#endif
+
+    entry_param_t entry_param{*this,
+                              "entry",
+                              'e',
+                              "Entry option 1. ",
+                              entry_value_constraint_t{},
+                              purpose_t::mandatory};
+
+    int32_param_t mandatory_int{*this, "mandatory-int", "Mandatory Int option.",
+                                purpose_t::mandatory};
+    int32_param_t default_int{*this, "default-int", "Default Int option.",
+                              clapp::default_value_t<std::int32_t>{10}};
+    int32_param_t optional_int{*this, "optional-int", "Optional Int option."};
+
+    int32_param_t constrained_int{
+        *this, "constrained-int",
+        'f',   "Constrained default Int option.",
+        15,    clapp::min_max_value_t<std::int32_t>{10, 20}};
+};
+
+std::ostream &operator<<(std::ostream &out, const entry_t &e);
+
+template <>
+entry_t clapp::value::convert_value<entry_t>(std::string_view param);
+
+void process_cmd1(const cli_parser_t::cmd1_parser_t &cmd1);
+
+void process_cmd2(const cli_parser_t::cmd2_parser_t &cmd2);
+
+cli_parser_t::~cli_parser_t() = default;
+cli_parser_t::cmd1_parser_t::~cmd1_parser_t() = default;
+cli_parser_t::cmd2_parser_t::~cmd2_parser_t() = default;
+
+std::ostream &operator<<(std::ostream &out, const entry_t &e) {
+    if (e == entry_t::entry1) {
+        out << "entry1";
+    } else if (e == entry_t::entry2) {
+        out << "entry2";
+    }
+    return out;
+}
+
+template <>
+entry_t clapp::value::convert_value<entry_t>(const std::string_view param) {
+    if (param == "entry1") {
+        return entry_t::entry1;
+    }
+    if (param == "entry2") {
+        return entry_t::entry2;
+    }
+    throw std::runtime_error("Invalid enum param type.");
+}
+
+void process_cmd1(const cli_parser_t::cmd1_parser_t &cmd1) {
+    if (cmd1.help.value()) {
+        std::cout << "Usage: \n"
+                  << cmd1.get_sub_parser_name() << ' ' << cmd1.gen_help_msg(0);
+        return;
+    }
+
+    cmd1.validate();
+
+    if (cmd1.string) {
+        std::cout << "string: " << cmd1.string.value() << "\n";
+    } else {
+        std::cout << "string: not given\n";
+    }
+
+    if (cmd1.int_arg) {
+        std::cout << "int-arg: " << cmd1.int_arg.value() << "\n";
+    } else {
+        std::cout << "int-arg: not given\n";
+    }
+
+    if (cmd1.string_arg_x) {
+        std::cout << "string-arg-x: " << cmd1.string_arg_x.value() << "\n";
+    } else {
+        std::cout << "string-arg-x: not given\n";
+    }
+
+    if (cmd1.entry_arg) {
+        std::cout << "entry-arg: " << cmd1.entry_arg.value() << "\n";
+    } else {
+        std::cout << "entry-arg: not given\n";
+    }
+}
+
+void process_cmd2(const cli_parser_t::cmd2_parser_t &cmd2) {
+    if (cmd2.help.value()) {
+        std::cout << "Usage: \n"
+                  << cmd2.get_sub_parser_name() << ' ' << cmd2.gen_help_msg(0);
+        return;
+    }
+
+    cmd2.validate();
+
+    if (cmd2.string_arg_x) {
+        std::cout << "string-arg-x: " << cmd2.string_arg_x.value() << "\n";
+    } else {
+        std::cout << "string-arg-x: not given\n";
+    }
+
+    if (cmd2.int_arg) {
+        std::cout << "int_arg (size: " << cmd2.int_arg.value().size() << "): ";
+        for (auto &val : cmd2.int_arg.value()) {
+            std::cout << val << ", ";
+        }
+        std::cout << "\n";
+    } else {
+        std::cout << "int_arg: not given\n";
+    }
+}
+
+int main(int argc, char *argv[]) {
+    try {
+        std::cout << clapp::build_info::build_info_string << std::endl;
+        // create parser and parse the args
+        // cli_parser_t cp;
+        // cp.parse(argc, argv);
+        // or do it all in one.
+        cli_parser_t cp{argc, argv};
+
+        if (!cp) {
+            std::cout << "Parsing failed!" << std::endl;
+            return EXIT_FAILURE;
+        }
+
+        if (cp.help.value()) {
+            std::cout << "Usage: \n"
+                      << cp.get_executable() << ' ' << cp.gen_help_msg(0);
+            return EXIT_SUCCESS;
+        }
+
+        cp.validate();
+
+        if (cp.string_arg) {
+            std::cout << "string-arg: " << cp.string_arg.value() << "\n";
+        } else {
+            std::cout << "string-arg: not given\n";
+        }
+
+        if (cp.verbose.given()) {
+            std::cout << "verbose: " << cp.verbose.value() << "\n";
+        } else {
+            std::cout << "verbose: not given\n";
+        }
+
+        if (cp.string_param) {
+            std::cout << "string_param: '" << cp.string_param.value() << "'\n";
+        } else {
+            std::cout << "string_param: not given\n";
+        }
+
+        if (cp.string_vector_param) {
+            std::cout << "string_vector_param (size: "
+                      << cp.string_vector_param.value().size() << "): ";
+            for (auto &val : cp.string_vector_param.value()) {
+                std::cout << val << ", ";
+            }
+            std::cout << "\n";
+
+        } else {
+            std::cout << "string_vector_param: not given\n";
+        }
+
+        if (cp.short_bool.given()) {
+            std::cout << "short_bool: given\n";
+        } else {
+            std::cout << "short_bool: not given\n";
+        }
+
+        if (cp.restricted_bool.given()) {
+            std::cout << "restricted_bool: given\n";
+        } else {
+            std::cout << "restricted_bool: not given\n";
+        }
+
+        if (cp.long_bool.given()) {
+            std::cout << "long_bool: " << cp.long_bool.value() << "\n";
+        } else {
+            std::cout << "long_bool: not given\n";
+        }
+
+        if (cp.count.given()) {
+            std::cout << "count: " << cp.count.value() << "\n";
+        } else {
+            std::cout << "count: not given\n";
+        }
+
+#ifdef CLAPP_FS_AVAIL
+        if (cp.test_file) {
+            std::cout << "test-file: " << cp.test_file.value() << "\n";
+        } else {
+            std::cout << "test-file: not given\n";
+        }
+#else
+        std::cout << "without fs\n";
+#endif
+
+        if (cp.constrained_int) {
+            std::cout << "constrained_int: " << cp.constrained_int.value()
+                      << "\n";
+        } else {
+            std::cout << "constrained_int: not given\n";
+        }
+        std::cout << "mandatory_bool: " << cp.mandatory_bool.value() << "\n";
+
+        std::cout << "mandatory_int: " << cp.mandatory_int.value() << "\n";
+        std::cout << "default_int: " << cp.default_int.value() << "\n";
+
+        if (cp.optional_int) {
+            std::cout << "optional_int: " << cp.optional_int.value() << "\n";
+        }
+
+        std::cout << "entry_param: '" << cp.entry_param.value() << "'\n";
+
+        if (cp.cmd1) {
+            std::cout << "cmd1 given" << std::endl;
+            process_cmd1(cp.cmd1);
+        } else {
+            std::cout << "cmd1 not given" << std::endl;
+        }
+
+        if (cp.cmd2) {
+            std::cout << "cmd2 given" << std::endl;
+            process_cmd2(cp.cmd2);
+        } else {
+            std::cout << "cmd2 not given" << std::endl;
+        }
+    } catch (clapp::exception::clapp_exception_t &e) {
+        std::cout << "Caught ClaPP-Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
+    } catch (std::exception &e) {
+        std::cout << "Caught Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/examples/short_example.cpp b/examples/short_example.cpp
index 2b18a70da0a0e87227c1d2930502bfd3f73aa17a..df119f38ea3dfec4e7e0ac1ad5a4de01d1a4adfa 100644
--- a/examples/short_example.cpp
+++ b/examples/short_example.cpp
@@ -7,8 +7,7 @@
 [[noreturn]] void print_version_and_exit();
 
 [[noreturn]] void print_version_and_exit() {
-    std::cout << clapp::build_info::project_name << " "
-              << clapp::build_info::version << "" << std::endl;
+    std::cout << clapp::build_info::build_info_string << std::endl;
     exit(EXIT_SUCCESS);
 }
 
@@ -101,7 +100,10 @@ int main(int argc, char *argv[]) {
         }
     } catch (clapp::exception::clapp_exception_t &e) {
         std::cout << "Caught ClaPP-Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
     } catch (std::exception &e) {
         std::cout << "Caught Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
     }
+    return EXIT_SUCCESS;
 }
diff --git a/examples/sub_parser_example.cpp b/examples/sub_parser_example.cpp
index a4d59e90e4c00306a320c86f3a2d01be9a12e49e..5876ca1775a7d681724151ef2a67caaed0ec04bd 100644
--- a/examples/sub_parser_example.cpp
+++ b/examples/sub_parser_example.cpp
@@ -8,8 +8,7 @@
 [[noreturn]] void print_version_and_exit();
 
 [[noreturn]] void print_version_and_exit() {
-    std::cout << clapp::build_info::project_name << " "
-              << clapp::build_info::version << "" << std::endl;
+    std::cout << clapp::build_info::build_info_string << std::endl;
     exit(EXIT_SUCCESS);
 }
 
@@ -56,7 +55,6 @@ class cli_parser_t : public clapp::basic_main_parser_t {
 
         ~first_parser_t() override;
 
-        // if a help message for subparser is required, define it...
         clapp::help_option_t help{*this, "help", 'h', "Show help options."};
 
         clapp::bool_option_t short_bool{*this, 'b', "Short bool option.",
@@ -85,7 +83,6 @@ class cli_parser_t : public clapp::basic_main_parser_t {
 
         ~second_parser_t() override;
 
-        // if a help message for subparser is required, define it...
         clapp::help_option_t help{*this, "help", 'h', "Show help options."};
 
         clapp::int32_argument_t int_arg{
@@ -186,7 +183,10 @@ int main(int argc, char *argv[]) {
         }
     } catch (clapp::exception::clapp_exception_t &e) {
         std::cout << "Caught ClaPP-Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
     } catch (std::exception &e) {
         std::cout << "Caught Exception: " << e.what() << std::endl;
+        return EXIT_FAILURE;
     }
+    return EXIT_SUCCESS;
 }
diff --git a/examples/test_large_example.sh b/examples/test_large_example.sh
new file mode 100755
index 0000000000000000000000000000000000000000..eecb5e7bf25bec54c9d67ee50eb246c43d5218b8
--- /dev/null
+++ b/examples/test_large_example.sh
@@ -0,0 +1,122 @@
+#!/usr/bin/env bats
+
+FIRST_LINE_REGEX='^libClaPP\ v.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} [a-zA-Z]+\-Build: '
+CLAPP_EXCEPTION_REGEX='^Caught\ ClaPP-Exception:.*$'
+
+@test "large-example: no arguments/options given throws" {
+    run ./libclapp_example_large
+    [ "$status" -eq 1 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [[ "${lines[1]}" =~ $CLAPP_EXCEPTION_REGEX ]]
+}
+
+@test "large-example: show help with long option --help" {
+    run ./libclapp_example_large --help
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [ "${lines[1]}" = "Usage:" ]
+}
+
+@test "large-example: show help with short option -h" {
+    run ./libclapp_example_large -h
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [ "${lines[1]}" = "Usage:" ]
+}
+
+@test "large-example: give all mandatory options/arguments" {
+    run ./libclapp_example_large str -o -m -c -e entry1 --mandatory-int 1
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [ "${lines[1]}" = "string-arg: str" ]
+    [ "${lines[2]}" = "verbose: not given" ]
+    [ "${lines[3]}" = "string_param: not given" ]
+    [ "${lines[4]}" = "string_vector_param: not given" ]
+    [ "${lines[5]}" = "short_bool: not given" ]
+    [ "${lines[6]}" = "restricted_bool: not given" ]
+    [ "${lines[7]}" = "long_bool: not given" ]
+    [ "${lines[8]}" = "count: 1" ]
+    [ "${lines[9]}" = "test-file: not given" ]
+    [ "${lines[10]}" = "constrained_int: not given" ]
+    [ "${lines[11]}" = "mandatory_bool: 1" ]
+    [ "${lines[12]}" = "mandatory_int: 1" ]
+    [ "${lines[13]}" = "default_int: 10" ]
+    [ "${lines[14]}" = "entry_param: 'entry1'" ]
+    [ "${lines[15]}" = "cmd1 not given" ]
+    [ "${lines[16]}" = "cmd2 not given" ]
+}
+
+@test "large-example: give mandatory and optional options/arguments" {
+    run ./libclapp_example_large str -o -m -c -e entry2 --mandatory-int 3 -b --long-bool -r --hours=10 --minutes 6 --seconds 8 --milliseconds 10 --microseconds 123 --nanoseconds 100 -v --verbose -s string --string-vector vec1 --string-vector=vec2 --test-file=/tmp --default-int=12 --optional-int 1 -f 15
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [ "${lines[1]}" = "string-arg: str" ]
+    [ "${lines[2]}" = "verbose: 4" ]
+    [ "${lines[3]}" = "string_param: 'string'" ]
+    [ "${lines[4]}" = "string_vector_param (size: 2): vec1, vec2, " ]
+    [ "${lines[5]}" = "short_bool: given" ]
+    [ "${lines[6]}" = "restricted_bool: given" ]
+    [ "${lines[7]}" = "long_bool: 1" ]
+    [ "${lines[8]}" = "count: 1" ]
+    [ "${lines[9]}" = "test-file: \"/tmp\"" ]
+    [ "${lines[10]}" = "constrained_int: 15" ]
+    [ "${lines[11]}" = "mandatory_bool: 1" ]
+    [ "${lines[12]}" = "mandatory_int: 3" ]
+    [ "${lines[13]}" = "default_int: 12" ]
+    [ "${lines[14]}" = "optional_int: 1" ]
+    [ "${lines[15]}" = "entry_param: 'entry2'" ]
+    [ "${lines[16]}" = "cmd1 not given" ]
+    [ "${lines[17]}" = "cmd2 not given" ]
+}
+
+@test "large-example: give mandatory and optional options/arguments as well as cmd1" {
+    run ./libclapp_example_large str -o -m -c -e entry2 --mandatory-int 3 -b --long-bool -r --hours=10 --minutes 6 --seconds 8 --milliseconds 10 --microseconds 123 --nanoseconds 100 --verbose -s string --string-vector vec1 --string-vector=vec2 --test-file=/tmp --default-int=12 --optional-int 1 -f 15 cmd1 -s 1 -b entry1 7
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [ "${lines[1]}" = "string-arg: str" ]
+    [ "${lines[2]}" = "verbose: 3" ]
+    [ "${lines[3]}" = "string_param: 'string'" ]
+    [ "${lines[4]}" = "string_vector_param (size: 2): vec1, vec2, " ]
+    [ "${lines[5]}" = "short_bool: given" ]
+    [ "${lines[6]}" = "restricted_bool: given" ]
+    [ "${lines[7]}" = "long_bool: 1" ]
+    [ "${lines[8]}" = "count: 1" ]
+    [ "${lines[9]}" = "test-file: \"/tmp\"" ]
+    [ "${lines[10]}" = "constrained_int: 15" ]
+    [ "${lines[11]}" = "mandatory_bool: 1" ]
+    [ "${lines[12]}" = "mandatory_int: 3" ]
+    [ "${lines[13]}" = "default_int: 12" ]
+    [ "${lines[14]}" = "optional_int: 1" ]
+    [ "${lines[15]}" = "entry_param: 'entry2'" ]
+    [ "${lines[16]}" = "cmd1 given" ]
+    [ "${lines[17]}" = "string: 1" ]
+    [ "${lines[18]}" = "int-arg: 7" ]
+    [ "${lines[19]}" = "string-arg-x: abaa" ]
+    [ "${lines[20]}" = "entry-arg: entry1" ]
+    [ "${lines[21]}" = "cmd2 not given" ]
+}
+
+@test "large-example: give mandatory and optional options/arguments as well as cmd2" {
+    run ./libclapp_example_large str -o -m -c -e entry2 --mandatory-int 3 -b --long-bool -r --hours=10 --minutes 6 --seconds 8 --milliseconds 10 --microseconds 123 --nanoseconds 100 -v --verbose -s string --string-vector vec1 --string-vector=vec2 --test-file=/tmp --default-int=12 --optional-int 1 -f 15 cmd2 string1 5 6 7
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $FIRST_LINE_REGEX ]]
+    [ "${lines[1]}" = "string-arg: str" ]
+    [ "${lines[2]}" = "verbose: 4" ]
+    [ "${lines[3]}" = "string_param: 'string'" ]
+    [ "${lines[4]}" = "string_vector_param (size: 2): vec1, vec2, " ]
+    [ "${lines[5]}" = "short_bool: given" ]
+    [ "${lines[6]}" = "restricted_bool: given" ]
+    [ "${lines[7]}" = "long_bool: 1" ]
+    [ "${lines[8]}" = "count: 1" ]
+    [ "${lines[9]}" = "test-file: \"/tmp\"" ]
+    [ "${lines[10]}" = "constrained_int: 15" ]
+    [ "${lines[11]}" = "mandatory_bool: 1" ]
+    [ "${lines[12]}" = "mandatory_int: 3" ]
+    [ "${lines[13]}" = "default_int: 12" ]
+    [ "${lines[14]}" = "optional_int: 1" ]
+    [ "${lines[15]}" = "entry_param: 'entry2'" ]
+    [ "${lines[16]}" = "cmd1 not given" ]
+    [ "${lines[17]}" = "cmd2 given" ]
+    [ "${lines[18]}" = "string-arg-x: string1" ]
+    [ "${lines[19]}" = "int_arg (size: 3): 5, 6, 7, " ]
+}
diff --git a/examples/test_short_example.sh b/examples/test_short_example.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4a74b93773ee18a85b460cd31903dbf9751bb7c8
--- /dev/null
+++ b/examples/test_short_example.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/env bats
+
+VERSION_REGEX='^libClaPP\ v.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} [a-zA-Z]+\-Build: '
+CLAPP_EXCEPTION_REGEX='^Caught\ ClaPP-Exception:.*$'
+
+@test "short-example: no arguments/options given throws" {
+    run ./libclapp_example_short
+    [ "$status" -eq 1 ]
+    [[ "${lines[0]}" =~ $CLAPP_EXCEPTION_REGEX ]]
+}
+
+@test "short-example: show help with long option --help" {
+    run ./libclapp_example_short --help
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "Usage:" ]
+}
+
+@test "short-example: show help with short option -h" {
+    run ./libclapp_example_short -h
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "Usage:" ]
+}
+
+@test "short-example: show help with short option -?" {
+    run ./libclapp_example_short -?
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "Usage:" ]
+}
+
+@test "short-example: show version with long option --version" {
+    run ./libclapp_example_short --version
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $VERSION_REGEX ]]
+}
+
+@test "short-example: show version with long option --vers" {
+    run ./libclapp_example_short --vers
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $VERSION_REGEX ]]
+}
+
+@test "short-example: show version with short option -v" {
+    run ./libclapp_example_short -v
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $VERSION_REGEX ]]
+}
+
+@test "short-example: give only mandatory arguments fails" {
+    run ./libclapp_example_short string 7
+    [ "$status" -eq 1 ]
+    [[ "${lines[0]}" =~ $CLAPP_EXCEPTION_REGEX ]]
+}
+
+@test "short-example: give only mandatory short option -s fails" {
+    run ./libclapp_example_short -s option_string
+    [ "$status" -eq 1 ]
+    [[ "${lines[0]}" =~ $CLAPP_EXCEPTION_REGEX ]]
+}
+
+@test "short-example: give only mandatory short option -1 fails" {
+    run ./libclapp_example_short -1=option_string
+    [ "$status" -eq 1 ]
+    [[ "${lines[0]}" =~ $CLAPP_EXCEPTION_REGEX ]]
+}
+
+@test "short-example: give only mandatory short option --string fails" {
+    run ./libclapp_example_short --string option_string
+    [ "$status" -eq 1 ]
+    [[ "${lines[0]}" =~ $CLAPP_EXCEPTION_REGEX ]]
+}
+
+@test "short-example: give only mandatory arguments and long option succeed" {
+    run ./libclapp_example_short string 8 --string opt_string
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "string-arg: string" ]
+    [ "${lines[1]}" = "int-arg: 8" ]
+    [ "${lines[2]}" = "variadic-string-arg: not given" ]
+    [ "${lines[3]}" = "string_param: 'opt_string'" ]
+    [ "${lines[4]}" = "string_vector_param: not given" ]
+}
+
+@test "short-example: give only mandatory arguments and short option succeeds" {
+    run ./libclapp_example_short -s opt_string_short str 7
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "string-arg: str" ]
+    [ "${lines[1]}" = "int-arg: 7" ]
+    [ "${lines[2]}" = "variadic-string-arg: not given" ]
+    [ "${lines[3]}" = "string_param: 'opt_string_short'" ]
+    [ "${lines[4]}" = "string_vector_param: not given" ]
+}
+
+@test "short-example: give only mandatory arguments and short option with variadic argument succeeds" {
+    run ./libclapp_example_short s 6 var1 var2 var3 -s opt_string_short
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "string-arg: s" ]
+    [ "${lines[1]}" = "int-arg: 6" ]
+    [ "${lines[2]}" = "variadic-string-arg (size: 3): var1, var2, var3, " ]
+    [ "${lines[3]}" = "string_param: 'opt_string_short'" ]
+    [ "${lines[4]}" = "string_vector_param: not given" ]
+}
+
+@test "short-example: give only mandatory arguments and long option with variadic argument succeeds" {
+    run ./libclapp_example_short s 6 --string-vector var1 --string-vector var2 --string-vector var3 --string opt_string_long
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "string-arg: s" ]
+    [ "${lines[1]}" = "int-arg: 6" ]
+    [ "${lines[2]}" = "variadic-string-arg: not given" ]
+    [ "${lines[3]}" = "string_param: 'opt_string_long'" ]
+    [ "${lines[4]}" = "string_vector_param (size: 3): var1, var2, var3, " ]
+}
diff --git a/examples/test_sub_parser_example.sh b/examples/test_sub_parser_example.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7065cb8c8a9c7d95b9a9c05a118a146ad8523dcc
--- /dev/null
+++ b/examples/test_sub_parser_example.sh
@@ -0,0 +1,97 @@
+#!/usr/bin/env bats
+
+VERSION_REGEX='^libClaPP\ v.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} [a-zA-Z]+\-Build: '
+CLAPP_EXCEPTION_REGEX='^Caught\ ClaPP-Exception:.*$'
+
+@test "sub-parser-example: no arguments/options given throws" {
+    run ./libclapp_example_sub_parser
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 2" ]
+    [ "${lines[1]}" = "first parser not active" ]
+    [ "${lines[2]}" = "second parser not active" ]
+}
+
+@test "sub-parser-example: show help with long option --help" {
+    run ./libclapp_example_sub_parser --help
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "Usage:" ]
+}
+
+@test "sub-parser-example: show help with short option -h" {
+    run ./libclapp_example_sub_parser -h
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "Usage:" ]
+}
+
+@test "sub-parser-example: show version with long option --version" {
+    run ./libclapp_example_sub_parser --version
+    [ "$status" -eq 0 ]
+    [[ "${lines[0]}" =~ $VERSION_REGEX ]]
+}
+
+@test "sub-parser-example: give verbose options multiple times" {
+    run ./libclapp_example_sub_parser --verbose -v
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 4" ]
+    [ "${lines[1]}" = "first parser not active" ]
+    [ "${lines[2]}" = "second parser not active" ]
+}
+
+@test "sub-parser-example: first: give only mandatory short option -b" {
+    run ./libclapp_example_sub_parser first -b
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 2" ]
+    [ "${lines[1]}" = "first parser active" ]
+    [ "${lines[2]}" = "short_bool: 1" ]
+    [ "${lines[3]}" = "string: not given" ]
+    [ "${lines[4]}" = "string-arg-x: abaa" ]
+    [ "${lines[5]}" = "double-opt: 10" ]
+    [ "${lines[6]}" = "second parser not active" ]
+}
+
+@test "sub-parser-example: first: give only mandatory short option -b and optional option -d" {
+    run ./libclapp_example_sub_parser first -b -d 11
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 2" ]
+    [ "${lines[1]}" = "first parser active" ]
+    [ "${lines[2]}" = "short_bool: 1" ]
+    [ "${lines[3]}" = "string: not given" ]
+    [ "${lines[4]}" = "string-arg-x: abaa" ]
+    [ "${lines[5]}" = "double-opt: 11" ]
+    [ "${lines[6]}" = "second parser not active" ]
+}
+
+@test "sub-parser-example: first: give only mandatory short option -b and optional option -s" {
+    run ./libclapp_example_sub_parser first -b -s string
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 2" ]
+    [ "${lines[1]}" = "first parser active" ]
+    [ "${lines[2]}" = "short_bool: 1" ]
+    [ "${lines[3]}" = "string: string" ]
+    [ "${lines[4]}" = "string-arg-x: abaa" ]
+    [ "${lines[5]}" = "double-opt: 10" ]
+    [ "${lines[6]}" = "second parser not active" ]
+}
+
+@test "sub-parser-example: second: give only mandatory args" {
+    run ./libclapp_example_sub_parser second 9 121
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 2" ]
+    [ "${lines[1]}" = "first parser not active" ]
+    [ "${lines[2]}" = "second parser active" ]
+    [ "${lines[3]}" = "int-arg: 9" ]
+    [ "${lines[4]}" = "double-arg: 121" ]
+    [ "${lines[5]}" = "string-arg-x: default-string-arg-x" ]
+    [ "${lines[6]}" = "variadic-int-arg: not given" ]
+}
+@test "sub-parser-example: second: give only mandatory args and optional args" {
+    run ./libclapp_example_sub_parser second 9 121 string-arg 6 7
+    [ "$status" -eq 0 ]
+    [ "${lines[0]}" = "verbose: 2" ]
+    [ "${lines[1]}" = "first parser not active" ]
+    [ "${lines[2]}" = "second parser active" ]
+    [ "${lines[3]}" = "int-arg: 9" ]
+    [ "${lines[4]}" = "double-arg: 121" ]
+    [ "${lines[5]}" = "string-arg-x: string-arg" ]
+    [ "${lines[6]}" = "variadic-int-arg (size: 2): 6, 7, " ]
+}
diff --git a/src/clapp/CMakeLists.txt b/src/clapp/CMakeLists.txt
index 291ce40ac8b5f07cab6273a612e6de26915d4ea4..cbf5a46fc2571c82d20ddf13b4efaef143c98f97 100644
--- a/src/clapp/CMakeLists.txt
+++ b/src/clapp/CMakeLists.txt
@@ -3,9 +3,9 @@ set(libClaPP_INCLUDE_DIRS $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../inclu
     $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>)
 target_include_directories(clapp PRIVATE ${libClaPP_INCLUDE_DIRS}
   SYSTEM INTERFACE ${libClaPP_INCLUDE_DIRS} $<INSTALL_INTERFACE:../include>)
-target_link_libraries(clapp PUBLIC libClaPP_GSL ${libClaPP_FS_LINKER_FLAG})
+target_link_libraries(clapp PUBLIC ClaPP_OPTIONS libClaPP_GSL ${libClaPP_FS_LINKER_FLAG})
 target_compile_options(clapp PRIVATE ${libClaPP_COMPILE_OPTIONS})
-set_target_properties(clapp PROPERTIES VERSION "${project_VERSION_MAJOR}.${project_VERSION_MINOR}" POSITION_INDEPENDENT_CODE ON)
+set_target_properties(clapp PROPERTIES VERSION "${libClaPP_VERSION}" POSITION_INDEPENDENT_CODE ON)
 if(CLANG_TIDY)
   set_target_properties(clapp PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS}")
 endif()
diff --git a/src/clapp/exception.cpp b/src/clapp/exception.cpp
index 78332ccd5803f3be3e1f47e1dbe21bc51e053997..c75fe81889bfa0477c8c51e89c016deefe1ec286 100644
--- a/src/clapp/exception.cpp
+++ b/src/clapp/exception.cpp
@@ -160,10 +160,10 @@ clapp::exception::parser_exception_t::~parser_exception_t() noexcept = default;
 
 clapp::exception::sub_parser_exception_t::sub_parser_exception_t(
     const char* message)
-    : clapp_exception_t(message) {}
+    : parser_exception_t(message) {}
 clapp::exception::sub_parser_exception_t::sub_parser_exception_t(
     const std::string& message)
-    : clapp_exception_t(message) {}
+    : parser_exception_t(message) {}
 clapp::exception::sub_parser_exception_t::sub_parser_exception_t(
     const sub_parser_exception_t&) = default;
 clapp::exception::sub_parser_exception_t&
@@ -176,3 +176,41 @@ clapp::exception::sub_parser_exception_t::operator=(
     sub_parser_exception_t&&) noexcept = default;
 clapp::exception::sub_parser_exception_t::~sub_parser_exception_t() noexcept =
     default;
+
+clapp::exception::main_parser_exception_t::main_parser_exception_t(
+    const char* message)
+    : parser_exception_t(message) {}
+clapp::exception::main_parser_exception_t::main_parser_exception_t(
+    const std::string& message)
+    : parser_exception_t(message) {}
+clapp::exception::main_parser_exception_t::main_parser_exception_t(
+    const main_parser_exception_t&) = default;
+clapp::exception::main_parser_exception_t&
+clapp::exception::main_parser_exception_t::operator=(
+    const main_parser_exception_t&) = default;
+clapp::exception::main_parser_exception_t::main_parser_exception_t(
+    main_parser_exception_t&&) noexcept = default;
+clapp::exception::main_parser_exception_t&
+clapp::exception::main_parser_exception_t::operator=(
+    main_parser_exception_t&&) noexcept = default;
+clapp::exception::main_parser_exception_t::~main_parser_exception_t() noexcept =
+    default;
+
+clapp::exception::no_executable_exception_t::no_executable_exception_t(
+    const char* message)
+    : main_parser_exception_t(message) {}
+clapp::exception::no_executable_exception_t::no_executable_exception_t(
+    const std::string& message)
+    : main_parser_exception_t(message) {}
+clapp::exception::no_executable_exception_t::no_executable_exception_t(
+    const no_executable_exception_t&) = default;
+clapp::exception::no_executable_exception_t&
+clapp::exception::no_executable_exception_t::operator=(
+    const no_executable_exception_t&) = default;
+clapp::exception::no_executable_exception_t::no_executable_exception_t(
+    no_executable_exception_t&&) noexcept = default;
+clapp::exception::no_executable_exception_t&
+clapp::exception::no_executable_exception_t::operator=(
+    no_executable_exception_t&&) noexcept = default;
+clapp::exception::no_executable_exception_t::
+    ~no_executable_exception_t() noexcept = default;
diff --git a/src/clapp/main_parser.cpp b/src/clapp/main_parser.cpp
index 722f8ae347364123072605d2a82fdffed2165ce3..94cf3b825e57edc51b339bc348e13a9c8995ce58 100644
--- a/src/clapp/main_parser.cpp
+++ b/src/clapp/main_parser.cpp
@@ -13,6 +13,7 @@
 // SOFTWARE.
 ///////////////////////////////////////////////////////////////////////////////
 
+#include <clapp/exception.h>
 #include <clapp/main_parser.h>
 
 clapp::parser::basic_main_parser_t::basic_main_parser_t() = default;
@@ -24,7 +25,10 @@ clapp::parser::basic_main_parser_t::operator bool() const {
 }
 
 std::string clapp::parser::basic_main_parser_t::get_executable() const {
-    return executable.value();
+    if (executable.has_value()) {
+        return executable.value();
+    }
+    throw no_executable_exception_t{"The parser does not know the executable."};
 }
 
 void clapp::parser::basic_main_parser_t::parse(int argc,
@@ -45,6 +49,16 @@ void clapp::parser::basic_main_parser_t::parse_and_validate(
     validate_recursive();
 }
 
-std::string clapp::parser::basic_main_parser_t::gen_help_prefix() const {
-    return basic_parser_t::gen_help_prefix() + get_executable();
+std::string clapp::parser::basic_main_parser_t::gen_short_line_prefix() const {
+    return get_executable() + gen_short_line();
+}
+
+void clapp::parser::basic_main_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+std::size_t clapp::parser::basic_main_parser_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
 }
diff --git a/src/clapp/parser.cpp b/src/clapp/parser.cpp
index 7abf014d71da22a2c308363ee0524567f949c4b1..988897fc7f520b939aaa857babb4ab9ae5bfd0ca 100644
--- a/src/clapp/parser.cpp
+++ b/src/clapp/parser.cpp
@@ -76,8 +76,8 @@ clapp::parser::basic_parser_t::get_optional_argument_descriptions() {
 }
 
 void clapp::parser::basic_parser_t::reg(reg_sub_parser_conf_t&& config) {
-    if (max_option_string_size < config.sub_parser_name.size()) {
-        max_option_string_size = config.sub_parser_name.size();
+    if (get_max_option_string_size() < config.sub_parser_name.size()) {
+        set_max_option_string_size(config.sub_parser_name.size());
     }
 
     if (!get_optional_argument_descriptions().empty()) {
@@ -105,124 +105,205 @@ void clapp::parser::basic_parser_t::reg(reg_sub_parser_conf_t&& config) {
     }
 
     get_sub_parser_descriptions().push_back(
-        {config.sub_parser_name, std::move(config.description)});
+        {config.sub_parser_name, std::move(config.description), config.parser});
 
     get_sub_parsers().emplace(std::move(config.sub_parser_name), config.parser);
 }
 
-std::string clapp::parser::basic_parser_t::gen_help_prefix() const {
-    return "Usage: \n";
+std::string clapp::parser::basic_parser_t::gen_usage_prefix() {
+    return "Usage:\n";
 }
 
-std::string clapp::parser::basic_parser_t::gen_help_msg() const {
-    std::string arg_line;
-    std::string sub_parser_desc;
-    std::string mandatory_option_desc;
-    std::string optional_option_desc;
-    std::string mandatory_argument_desc;
-    std::string optional_argument_desc;
-    if (!mandatory_option_descriptions.empty()) {
-        mandatory_option_desc = "\nMandatory Options:\n";
-        for (const option_description_container_t& desc_cont :
-             mandatory_option_descriptions) {
-            mandatory_option_desc +=
-                "  " + desc_cont.option_string +
-                std::string(
-                    max_option_string_size + 1 - desc_cont.option_string.size(),
-                    ' ') +
-                desc_cont.description + "\n";
-            arg_line += desc_cont.option_string;
-            if (desc_cont.option_type ==
-                clapp::basic_parser_t::option_type_t::vector) {
-                arg_line += "...";
-            }
-            arg_line += " ";
+clapp::parser::basic_parser_t::help_contents_t
+clapp::parser::basic_parser_t::gen_detailed_help_contents() const {
+    help_contents_t ret;
+    for (const argument_description_container_t& desc_cont :
+         mandatory_argument_descriptions) {
+        ret.mandatory_arguments.emplace_back(
+            help_line_t{"  " + desc_cont.argument_string +
+                            std::string(get_max_option_string_size() + 1 -
+                                            desc_cont.argument_string.size(),
+                                        ' '),
+                        desc_cont.description});
+    }
+
+    for (const option_description_container_t& desc_cont :
+         mandatory_option_descriptions) {
+        ret.mandatory_options.emplace_back(
+            help_line_t{"  " + desc_cont.option_string +
+                            std::string(get_max_option_string_size() + 1 -
+                                            desc_cont.option_string.size(),
+                                        ' '),
+                        desc_cont.description});
+    }
+
+    for (const argument_description_container_t& desc_cont :
+         optional_argument_descriptions) {
+        ret.optional_arguments.emplace_back(
+            help_line_t{"  " + desc_cont.argument_string +
+                            std::string(get_max_option_string_size() + 1 -
+                                            desc_cont.argument_string.size(),
+                                        ' '),
+                        desc_cont.description});
+    }
+
+    for (const option_description_container_t& desc_cont :
+         optional_option_descriptions) {
+        ret.optional_options.emplace_back(
+            help_line_t{"  " + desc_cont.option_string +
+                            std::string(get_max_option_string_size() + 1 -
+                                            desc_cont.option_string.size(),
+                                        ' '),
+                        desc_cont.description});
+    }
+
+    for (const sub_parser_description_container_t& desc_cont :
+         sub_parser_descriptions) {
+        ret.sub_parser.emplace(
+            desc_cont.sub_parser_string,
+            sub_parser_line_t{
+                "  " + desc_cont.sub_parser_string +
+                    std::string(get_max_option_string_size() + 1 -
+                                    desc_cont.sub_parser_string.size(),
+                                ' '),
+                desc_cont.description, desc_cont.parser});
+    }
+
+    return ret;
+}
+
+std::string clapp::parser::basic_parser_t::gen_short_line() const {
+    std::string short_line;
+    for (const argument_description_container_t& desc_cont :
+         mandatory_argument_descriptions) {
+        short_line += " <" + desc_cont.argument_string + ">";
+        if (desc_cont.argument_type ==
+            clapp::basic_parser_t::argument_type_t::variadic) {
+            short_line += "...";
         }
     }
 
-    if (!optional_option_descriptions.empty()) {
-        optional_option_desc = "\nOptional Options:\n";
-        for (const option_description_container_t& desc_cont :
-             optional_option_descriptions) {
-            optional_option_desc +=
-                "  " + desc_cont.option_string +
-                std::string(
-                    max_option_string_size + 1 - desc_cont.option_string.size(),
-                    ' ') +
-                desc_cont.description + "\n";
-            arg_line += "[" + desc_cont.option_string;
-            if (desc_cont.option_type ==
-                clapp::basic_parser_t::option_type_t::vector) {
-                arg_line += "...";
-            }
-            arg_line += "] ";
+    for (const option_description_container_t& desc_cont :
+         mandatory_option_descriptions) {
+        short_line += " " + desc_cont.option_string;
+        if (desc_cont.option_type ==
+            clapp::basic_parser_t::option_type_t::vector) {
+            short_line += "...";
         }
     }
 
-    if (!mandatory_argument_descriptions.empty()) {
-        mandatory_argument_desc = "\nMandatory Arguments:\n";
-
-        for (const argument_description_container_t& desc_cont :
-             mandatory_argument_descriptions) {
-            mandatory_argument_desc +=
-                "  " + desc_cont.argument_string +
-                std::string(max_option_string_size + 1 -
-                                desc_cont.argument_string.size(),
-                            ' ') +
-                desc_cont.description + "\n";
-            arg_line += "<" + desc_cont.argument_string + ">";
-            if (desc_cont.argument_type ==
-                clapp::basic_parser_t::argument_type_t::variadic) {
-                arg_line += "...";
-            }
-            arg_line += " ";
+    for (const argument_description_container_t& desc_cont :
+         optional_argument_descriptions) {
+        short_line += " [<" + desc_cont.argument_string + ">";
+        if (desc_cont.argument_type ==
+            clapp::basic_parser_t::argument_type_t::variadic) {
+            short_line += "...";
         }
+        short_line += "]";
     }
 
-    if (!optional_argument_descriptions.empty()) {
-        optional_argument_desc = "\nOptional Arguments:\n";
+    for (const option_description_container_t& desc_cont :
+         optional_option_descriptions) {
+        short_line += " [" + desc_cont.option_string;
+        if (desc_cont.option_type ==
+            clapp::basic_parser_t::option_type_t::vector) {
+            short_line += "...";
+        }
+        short_line += "]";
+    }
 
-        for (const argument_description_container_t& desc_cont :
-             optional_argument_descriptions) {
-            optional_argument_desc +=
-                "  " + desc_cont.argument_string +
-                std::string(max_option_string_size + 1 -
-                                desc_cont.argument_string.size(),
-                            ' ') +
-                desc_cont.description + "\n";
+    return short_line;
+}
 
-            arg_line += "[<" + desc_cont.argument_string + ">";
-            if (desc_cont.argument_type ==
-                clapp::basic_parser_t::argument_type_t::variadic) {
-                arg_line += "...";
-            }
-            arg_line += "] ";
+std::string clapp::parser::basic_parser_t::gen_opt_arg_lines(
+    const clapp::parser::basic_parser_t::help_contents_t& help_contents,
+    const std::size_t num_spaces) {
+    std::string ret;
+    if (!help_contents.mandatory_arguments.empty()) {
+        ret += "\n" + std::string(num_spaces + num_sub_spaces, ' ') +
+               "Mandatory Arguments:\n";
+        for (const help_line_t& line : help_contents.mandatory_arguments) {
+            ret += std::string(num_spaces + num_sub_spaces, ' ') + line.name +
+                   line.description + '\n';
         }
     }
 
-    if (!sub_parser_descriptions.empty()) {
-        sub_parser_desc = "\nAvailable sub-parsers:\n";
+    if (!help_contents.mandatory_options.empty()) {
+        ret += "\n" + std::string(num_spaces + num_sub_spaces, ' ') +
+               "Mandatory Options:\n";
+        for (const help_line_t& line : help_contents.mandatory_options) {
+            ret += std::string(num_spaces + num_sub_spaces, ' ') + line.name +
+                   line.description + '\n';
+        }
+    }
+
+    if (!help_contents.optional_arguments.empty()) {
+        ret += "\n" + std::string(num_spaces + num_sub_spaces, ' ') +
+               "Optional Arguments:\n";
+        for (const help_line_t& line : help_contents.optional_arguments) {
+            ret += std::string(num_spaces + num_sub_spaces, ' ') + line.name +
+                   line.description + '\n';
+        }
+    }
+
+    if (!help_contents.optional_options.empty()) {
+        ret += "\n" + std::string(num_spaces + num_sub_spaces, ' ') +
+               "Optional Options:\n";
+        for (const help_line_t& line : help_contents.optional_options) {
+            ret += std::string(num_spaces + num_sub_spaces, ' ') + line.name +
+                   line.description + '\n';
+        }
+    }
+    return ret;
+}
+
+std::string clapp::parser::basic_parser_t::gen_help_desc(
+    const std::size_t num_spaces, const std::size_t rec_depth) const {
+    std::string ret{};
+    clapp::parser::basic_parser_t::help_contents_t help_contents{
+        gen_detailed_help_contents()};
+
+    if (!help_contents.sub_parser.empty()) {
+        ret +=
+            "\n" + std::string(num_spaces + num_sub_spaces, ' ') + "Subparser:";
+        for (auto const& item : help_contents.sub_parser) {
+            ret += '\n' + std::string(num_spaces + num_sub_spaces, ' ') +
+                   item.second.name + item.second.description;
+            if (rec_depth > 0) {
+                ret += item.second.parser.gen_help_desc(
+                           num_spaces + num_sub_spaces * 2, rec_depth - 1) +
+                       '\n';
+            }
+        }
+    }
+    ret += gen_opt_arg_lines(help_contents, num_spaces);
+    return ret;
+}
 
+std::string clapp::parser::basic_parser_t::gen_short_lines(
+    const std::size_t rec_depth) const {
+    std::string short_lines{};
+    if (rec_depth > 0) {
         for (const sub_parser_description_container_t& desc_cont :
              sub_parser_descriptions) {
-            sub_parser_desc +=
-                "  " + desc_cont.sub_parser_string +
-                std::string(max_option_string_size + 1 -
-                                desc_cont.sub_parser_string.size(),
-                            ' ') +
-                desc_cont.description + "\n";
+            short_lines += desc_cont.parser.gen_short_line_prefix() + "\n";
         }
-        arg_line += "<sub-parser> [sub-parser args/opts...] ";
     }
+    short_lines += gen_short_line_prefix() + "\n";
+    return short_lines;
+}
 
-    return arg_line + "\n" + mandatory_argument_desc + optional_argument_desc +
-           sub_parser_desc + mandatory_option_desc + optional_option_desc;
+std::string clapp::parser::basic_parser_t::gen_help_msg(
+    const std::size_t rec_depth) const {
+    const clapp::parser::basic_parser_t& parser{get_active_parser()};
+    return parser.gen_short_lines(rec_depth) +
+           parser.gen_help_desc(0, rec_depth);
 }
 
 clapp::parser::basic_parser_t::arg_iterator
 clapp::basic_parser_t::process_parse_result(
     const arg_iterator it,
-    const clapp::basic_parser_t::parse_result_t& parse_result) const {
+    const clapp::basic_parser_t::parse_result_t& parse_result) {
     if (it == parse_result.it) {
         if (parse_result.short_option) {
             std::stringstream ss;
@@ -394,9 +475,20 @@ clapp::value::found_func_t
 clapp::parser::basic_parser_t::gen_func_print_help_and_exit(
     const int exit_code) const {
     return found_func_t{[this, exit_code]() {
-        std::cout << gen_help_prefix() + " " + gen_help_msg();
+        constexpr std::size_t max_rec_depth{65535};
+        std::cout << gen_usage_prefix() + gen_help_msg(max_rec_depth);
         exit(exit_code);
     }};
 }
 
+const clapp::parser::basic_parser_t&
+clapp::parser::basic_parser_t::get_active_parser() const {
+    for (auto const& item : sub_parsers) {
+        if (item.second.is_active()) {
+            return item.second.get_active_parser();
+        }
+    }
+    return *this;
+}
+
 clapp::parser::basic_parser_t::~basic_parser_t() = default;
diff --git a/src/clapp/sub_parser.cpp b/src/clapp/sub_parser.cpp
index 244a41fb7d2784f768795a7ce4c7ce99aba834ca..88822762976a37aa74f22d0b4f0042747cc82b24 100644
--- a/src/clapp/sub_parser.cpp
+++ b/src/clapp/sub_parser.cpp
@@ -17,35 +17,37 @@
 
 clapp::parser::basic_sub_parser_t::~basic_sub_parser_t() = default;
 
-clapp::parser::basic_sub_parser_t::operator bool() const { return active; }
-
-std::string clapp::parser::basic_sub_parser_t::get_sub_parser_name() const {
-    return sub_parser_name;
-}
-
 void clapp::parser::basic_sub_parser_t::sub_parse(arg_iterator begin,
                                                   arg_iterator end) {
     active = true;
     for (arg_iterator it = begin; it != end;) {
         std::string_view option{*it};
         parse_result_t parse_result{parse(option, it, end)};
-        if (it == parse_result.it && parse_parent) {
-            parse_result = parent_parser.parse(option, it, end);
-        }
         it = process_parse_result(it, parse_result);
     }
 }
 
 clapp::parser::basic_sub_parser_t::basic_sub_parser_t(
     clapp::basic_parser_t& parser, std::string sub_parser_name_arg,
-    std::string description_arg, bool parse_parent_arg)
+    std::string description_arg)
     : parent_parser{parser},
       sub_parser_name{std::move(sub_parser_name_arg)},
-      description{std::move(description_arg)},
-      parse_parent{parse_parent_arg} {
+      description{std::move(description_arg)} {
     parser.reg(reg_sub_parser_conf_t{*this, sub_parser_name, description});
 }
 
-std::string clapp::parser::basic_sub_parser_t::gen_help_prefix() const {
-    return parent_parser.gen_help_prefix() + ' ' + sub_parser_name;
+std::string clapp::parser::basic_sub_parser_t::gen_short_line_prefix() const {
+    return parent_parser.gen_short_line_prefix() + " " + sub_parser_name +
+           gen_short_line();
+}
+
+void clapp::parser::basic_sub_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    parent_parser.set_max_option_string_size(max_option_size +
+                                             num_sub_spaces * 2);
+}
+
+std::size_t clapp::parser::basic_sub_parser_t::get_max_option_string_size()
+    const {
+    return parent_parser.get_max_option_string_size() - num_sub_spaces * 2;
 }
diff --git a/src/clapp/value.cpp b/src/clapp/value.cpp
index 6439f00a643874cc5684bcdb843692f22034170d..b692137951b3d40f85caebb4f5e1761b752fd332 100644
--- a/src/clapp/value.cpp
+++ b/src/clapp/value.cpp
@@ -165,7 +165,7 @@ std::string clapp::path_exists_t::append_restriction_text() {
 }
 
 void clapp::path_exists_t::validate(const clapp::fs::path& path,
-                                    const std::string& param_name) const {
+                                    const std::string& param_name) {
     if (!clapp::fs::exists(path)) {
         std::stringstream ss;
         ss << "CLI value " << path << " for '" << param_name
diff --git a/src/include/clapp/argument.h b/src/include/clapp/argument.h
index a9468da409d0b5f90f59e0ddc3ff4a690f24d842..d289dbdc5bc6d7c92fae9ff48a605769b11052d8 100644
--- a/src/include/clapp/argument.h
+++ b/src/include/clapp/argument.h
@@ -36,7 +36,8 @@ using variadic_value_func_t = std::function<std::vector<T>(void)>;
 
 template <typename T>
 struct argument_callbacks_t {
-    basic_parser_t::argument_func_t af;
+    using argument_func_t = basic_parser_t::argument_func_t;
+    argument_func_t af;
     std::optional<given_func_t> given;
     std::optional<has_value_func_t> has_value;
     std::optional<arg_value_func_t<T>> value;
@@ -44,7 +45,8 @@ struct argument_callbacks_t {
 
 template <typename T>
 struct variadic_argument_callbacks_t {
-    basic_parser_t::argument_func_t af;
+    using argument_func_t = basic_parser_t::argument_func_t;
+    argument_func_t af;
     std::optional<given_func_t> given;
     std::optional<has_value_func_t> has_value;
     std::optional<variadic_value_func_t<T>> value;
@@ -107,6 +109,7 @@ class basic_argument_t {
     basic_argument_t(basic_parser_t& parser, const std::string& argument_name,
                      const std::string& description, Params&&... parameters);
     constexpr explicit operator bool() const noexcept;
+    constexpr bool has_value() const noexcept;
     T value() const;
     constexpr bool given() const noexcept;
 
@@ -133,7 +136,8 @@ class basic_variadic_argument_t {
                               const std::string& argument_name,
                               const std::string& description,
                               Params&&... parameters);
-    constexpr explicit operator bool() const noexcept;
+    inline explicit operator bool() const noexcept;
+    inline bool has_value() const noexcept;
     std::vector<T> value() const;
     constexpr bool given() const noexcept;
 
diff --git a/src/include/clapp/argument.hpp b/src/include/clapp/argument.hpp
index 28b4b8bafeba42971c9f7cbc07d326064c1dc211..f98629b4c9dccaa5bf776f8b446b3d170a260cff 100644
--- a/src/include/clapp/argument.hpp
+++ b/src/include/clapp/argument.hpp
@@ -113,13 +113,15 @@ ARG_CONF clapp::argument::gen_arg_conf(
     CALLBACKS&& callbacks, const std::string& argument_name,
     std::vector<typename arg_params_t<T>::validate_func_t>&& validate_funcs,
     const std::string& description, basic_parser_t::purpose_t purpose) {
+    using optional_arg_validate_func_t =
+        std::optional<basic_parser_t::validate_func_t>;
+    optional_arg_validate_func_t arg_validate_func{gen_arg_validate_func<T>(
+        std::move(callbacks.value), std::move(callbacks.has_value),
+        std::move(callbacks.given), std::move(validate_funcs), argument_name,
+        purpose)};
+
     return ARG_CONF{std::move(callbacks.af), argument_name, description,
-                    gen_arg_validate_func<T>(std::move(callbacks.value),
-                                             std::move(callbacks.has_value),
-                                             std::move(callbacks.given),
-                                             std::move(validate_funcs),
-                                             argument_name, purpose),
-                    purpose};
+                    std::move(arg_validate_func), purpose};
 }
 
 template <typename T, typename ARG_CONF, typename CALLBACKS, typename... Params>
@@ -185,6 +187,12 @@ constexpr clapp::argument::basic_argument_t<T>::operator bool() const noexcept {
     return _value.has_value();
 }
 
+template <typename T>
+constexpr bool clapp::argument::basic_argument_t<T>::has_value() const
+    noexcept {
+    return _value.has_value();
+}
+
 template <typename T>
 T clapp::argument::basic_argument_t<T>::value() const {
     if (_value) {
@@ -240,9 +248,15 @@ clapp::argument::basic_variadic_argument_t<T>::basic_variadic_argument_t(
 }
 
 template <typename T>
-constexpr clapp::argument::basic_variadic_argument_t<T>::operator bool() const
+inline clapp::argument::basic_variadic_argument_t<T>::operator bool() const
+    noexcept {
+    return !_value.empty();
+}
+
+template <typename T>
+inline bool clapp::argument::basic_variadic_argument_t<T>::has_value() const
     noexcept {
-    return _value.size() > 0;
+    return !_value.empty();
 }
 
 template <typename T>
diff --git a/src/include/clapp/build_info.h.in b/src/include/clapp/build_info.h.in
index d092878eecf03ef0e9a71a079e1b2179d3335e30..f30e7eeb6ce6e45fcd4d179f1d6922b62eb48b89 100644
--- a/src/include/clapp/build_info.h.in
+++ b/src/include/clapp/build_info.h.in
@@ -19,22 +19,22 @@
 #include <cstddef>
 #include <cstdint>
 namespace clapp {
-
 inline namespace build_info {
-constexpr const char* project_name = "@libClaPP_PROJECT_NAME@";
-constexpr std::size_t version_major = @project_VERSION_MAJOR@;
-constexpr std::size_t version_minor = @project_VERSION_MINOR@;
-constexpr std::size_t version_patch_level = @project_VERSION_PATCH_LEVEL@;
-constexpr const char* version =
-    "@project_VERSION_MAJOR@.@project_VERSION_MINOR@"
-    ".@project_VERSION_PATCH_LEVEL@";
-constexpr const char* git_hash = "@libClaPP_GIT_HASH@";
-constexpr const char* git_branch = "@libClaPP_GIT_BRANCH@";
-constexpr const char* config_time = "@project_CONFIG_TIME@";
-constexpr const char* build_type = "@CMAKE_BUILD_TYPE@";
-
+constexpr const char * project_name = "@CMAKE_PROJECT_NAME@";
+constexpr std::size_t version_major = @libClaPP_VERSION_MAJOR@;
+constexpr std::size_t version_minor = @libClaPP_VERSION_MINOR@;
+constexpr std::size_t version_patch = @libClaPP_VERSION_PATCH@;
+constexpr const char *version = "@libClaPP_VERSION@";
+constexpr const char *git_hash = "@libClaPP_GIT_HASH@";
+constexpr const char *git_branch = "@libClaPP_GIT_BRANCH@";
+constexpr const char *git_description = "@libClaPP_GIT_DESCRIPTION@";
+constexpr const char *config_time = "@libClaPP_CONFIG_TIME@";
+constexpr const char *build_type = "@CMAKE_BUILD_TYPE@";
+constexpr const char *build_info_string = "@CMAKE_PROJECT_NAME@ "
+        "v.@libClaPP_VERSION@ @CMAKE_BUILD_TYPE@-Build: "
+        "@libClaPP_GIT_BRANCH@:@libClaPP_GIT_HASH@ "
+        "(@libClaPP_GIT_DESCRIPTION@)";
 }  // namespace build_info
-
 }  // namespace clapp
 
 #endif
diff --git a/src/include/clapp/exception.h b/src/include/clapp/exception.h
index acf6535040cbd9109461c86a23dc968e013d7d7c..2b97da9662af93510a717a8db6897993d481c4fc 100644
--- a/src/include/clapp/exception.h
+++ b/src/include/clapp/exception.h
@@ -119,7 +119,7 @@ class parser_exception_t : public clapp_exception_t {
     ~parser_exception_t() noexcept override;
 };
 
-class sub_parser_exception_t : public clapp_exception_t {
+class sub_parser_exception_t : public parser_exception_t {
    public:
     explicit sub_parser_exception_t(const char* message);
     explicit sub_parser_exception_t(const std::string& message);
@@ -130,6 +130,28 @@ class sub_parser_exception_t : public clapp_exception_t {
     ~sub_parser_exception_t() noexcept override;
 };
 
+class main_parser_exception_t : public parser_exception_t {
+   public:
+    explicit main_parser_exception_t(const char* message);
+    explicit main_parser_exception_t(const std::string& message);
+    main_parser_exception_t(const main_parser_exception_t&);
+    main_parser_exception_t& operator=(const main_parser_exception_t&);
+    main_parser_exception_t(main_parser_exception_t&&) noexcept;
+    main_parser_exception_t& operator=(main_parser_exception_t&&) noexcept;
+    ~main_parser_exception_t() noexcept override;
+};
+
+class no_executable_exception_t : public main_parser_exception_t {
+   public:
+    explicit no_executable_exception_t(const char* message);
+    explicit no_executable_exception_t(const std::string& message);
+    no_executable_exception_t(const no_executable_exception_t&);
+    no_executable_exception_t& operator=(const no_executable_exception_t&);
+    no_executable_exception_t(no_executable_exception_t&&) noexcept;
+    no_executable_exception_t& operator=(no_executable_exception_t&&) noexcept;
+    ~no_executable_exception_t() noexcept override;
+};
+
 }  // namespace exception
 }  // namespace clapp
 
diff --git a/src/include/clapp/main_parser.h b/src/include/clapp/main_parser.h
index 01f671441befa83ff82b203ca11ed59a11237001..026e95a32e268e83f747a72e7ff840539fd81277 100644
--- a/src/include/clapp/main_parser.h
+++ b/src/include/clapp/main_parser.h
@@ -35,9 +35,13 @@ class basic_main_parser_t : public basic_parser_t {
     explicit operator bool() const;
     std::string get_executable() const;
 
-    std::string gen_help_prefix() const override;
+    std::string gen_short_line_prefix() const override;
+
+    void set_max_option_string_size(const std::size_t max_option_size) override;
+    std::size_t get_max_option_string_size() const override;
 
    private:
+    std::size_t max_option_string_size{0};
     std::optional<std::string> executable{};
 };
 
diff --git a/src/include/clapp/option.h b/src/include/clapp/option.h
index 4aaf84102b2569841606c964ccfc6b68c08e6cf7..38ad2aa5b39255aafc393b9e7bce3ed00b5a3c7f 100644
--- a/src/include/clapp/option.h
+++ b/src/include/clapp/option.h
@@ -35,8 +35,10 @@ using vector_value_func_t = std::function<std::vector<T>(void)>;
 
 template <typename T>
 struct option_callbacks_t {
-    basic_parser_t::long_opt_func_t loh;
-    basic_parser_t::short_opt_func_t soh;
+    using long_opt_func_t = basic_parser_t::long_opt_func_t;
+    using short_opt_func_t = basic_parser_t::short_opt_func_t;
+    long_opt_func_t loh;
+    short_opt_func_t soh;
     std::optional<given_func_t> given;
     std::optional<has_value_func_t> has_value;
     std::optional<value_func_t<T>> value;
@@ -44,8 +46,10 @@ struct option_callbacks_t {
 
 template <typename T>
 struct option_param_callbacks_t {
-    basic_parser_t::long_opt_param_func_t loh;
-    basic_parser_t::short_opt_param_func_t soh;
+    using long_opt_func_t = basic_parser_t::long_opt_param_func_t;
+    using short_opt_func_t = basic_parser_t::short_opt_param_func_t;
+    long_opt_func_t loh;
+    short_opt_func_t soh;
     std::optional<given_func_t> given;
     std::optional<has_value_func_t> has_value;
     std::optional<value_func_t<T>> value;
@@ -53,8 +57,10 @@ struct option_param_callbacks_t {
 
 template <typename T>
 struct option_vector_param_callbacks_t {
-    basic_parser_t::long_opt_param_func_t loh;
-    basic_parser_t::short_opt_param_func_t soh;
+    using long_opt_func_t = basic_parser_t::long_opt_param_func_t;
+    using short_opt_func_t = basic_parser_t::short_opt_param_func_t;
+    long_opt_func_t loh;
+    short_opt_func_t soh;
     std::optional<given_func_t> given;
     std::optional<has_value_func_t> has_value;
     std::optional<vector_value_func_t<T>> value;
@@ -97,7 +103,8 @@ class basic_param_option_t {
     basic_param_option_t& operator=(const basic_param_option_t&) = delete;
     basic_param_option_t& operator=(basic_param_option_t&&) noexcept = delete;
 
-    inline explicit operator bool() const;
+    constexpr explicit operator bool() const noexcept;
+    constexpr bool has_value() const noexcept;
     T value() const;
     constexpr bool given() const noexcept;
 
@@ -130,7 +137,8 @@ class basic_vector_param_option_t {
     basic_vector_param_option_t& operator=(
         basic_vector_param_option_t&&) noexcept = delete;
 
-    inline explicit operator bool() const;
+    inline explicit operator bool() const noexcept;
+    inline bool has_value() const noexcept;
     std::vector<T> value() const;
     constexpr bool given() const noexcept;
 
@@ -161,6 +169,8 @@ class basic_option_t {
 
     virtual ~basic_option_t();
 
+    constexpr explicit operator bool() const noexcept;
+    constexpr bool has_value() const noexcept;
     T value() const;
     bool given() const;
 
@@ -181,8 +191,6 @@ class bool_option_t : public basic_option_t<bool> {
 
     ~bool_option_t() override;
 
-    inline explicit operator bool() const;
-
    private:
     void found_entry();
     static callbacks_t create_callbacks(bool_option_t* inst);
@@ -215,8 +223,6 @@ class count_option_t : public basic_option_t<std::uint32_t> {
 
     ~count_option_t() override;
 
-    inline explicit operator bool() const;
-
    private:
     void found_entry();
     static callbacks_t create_callbacks(count_option_t* inst);
@@ -329,8 +335,6 @@ using vector_uint64_param_option_t =
     clapp::basic_vector_param_option_t<std::uint64_t>;
 using vector_double_param_option_t = clapp::basic_vector_param_option_t<double>;
 using vector_float_param_option_t = clapp::basic_vector_param_option_t<float>;
-using vector_double_param_option_t = clapp::basic_vector_param_option_t<double>;
-using vector_float_param_option_t = clapp::basic_vector_param_option_t<float>;
 using vector_ns_param_option_t =
     clapp::basic_vector_param_option_t<std::chrono::nanoseconds>;
 using vector_us_param_option_t =
diff --git a/src/include/clapp/option.hpp b/src/include/clapp/option.hpp
index b64bf1df52518486decd9731526157fd39a96097..b00fb9ef601466b0361ceaf047aa9531a059d4ff 100644
--- a/src/include/clapp/option.hpp
+++ b/src/include/clapp/option.hpp
@@ -181,7 +181,7 @@ clapp::option::opt_conf_container_t<T, OPT_CONF> clapp::option::gen_opt_conf(
     }
     return gen_opt_conf1<T, OPT_CONF>(
         std::forward<CALLBACKS>(callbacks),
-        std::vector<std::string>{std::string{std::forward<T1>(single_option)}},
+        std::vector<std::string>{{std::forward<T1>(single_option)}},
         std::vector<char>{}, std::move(description),
         std::forward<Params>(parameters)...);
 }
@@ -261,13 +261,30 @@ OPT_CONF clapp::option::gen_opt_conf2(
     const std::string& description, basic_parser_t::purpose_t purpose) {
     std::string option_string{
         OPT_CONF::create_option_string(short_option, long_option)};
-    return OPT_CONF{gen_short_option(std::move(callbacks.soh), short_option),
-                    gen_long_option(std::move(callbacks.loh), long_option),
-                    gen_opt_validate_func<T>(std::move(callbacks.value),
-                                             std::move(callbacks.has_value),
-                                             std::move(callbacks.given),
-                                             std::move(validate_funcs),
-                                             option_string, purpose),
+
+    using short_opt_func_t = typename std::decay_t<CALLBACKS>::short_opt_func_t;
+    using short_opt_conf_vec_t =
+        std::vector<clapp::parser::basic_parser_t::basic_short_opt_conf_t<
+            short_opt_func_t>>;
+    short_opt_conf_vec_t short_options{
+        gen_short_option(std::move(callbacks.soh), short_option)};
+
+    using long_opt_func_t = typename std::decay_t<CALLBACKS>::long_opt_func_t;
+    using long_opt_conf_vec_t = std::vector<
+        clapp::parser::basic_parser_t::basic_long_opt_conf_t<long_opt_func_t>>;
+    long_opt_conf_vec_t long_options{
+        gen_long_option(std::move(callbacks.loh), long_option)};
+
+    using optional_validate_func_t =
+        std::optional<basic_parser_t::validate_func_t>;
+    optional_validate_func_t opt_validate_func{gen_opt_validate_func<T>(
+        std::move(callbacks.value), std::move(callbacks.has_value),
+        std::move(callbacks.given), std::move(validate_funcs), option_string,
+        purpose)};
+
+    return OPT_CONF{std::move(short_options),
+                    std::move(long_options),
+                    std::move(opt_validate_func),
                     std::move(option_string),
                     description,
                     purpose};
@@ -313,7 +330,14 @@ void clapp::option::basic_param_option_t<T>::found_entry(
 }
 
 template <typename T>
-inline clapp::option::basic_param_option_t<T>::operator bool() const {
+constexpr clapp::option::basic_param_option_t<T>::operator bool() const
+    noexcept {
+    return _value.has_value();
+}
+
+template <typename T>
+constexpr bool clapp::option::basic_param_option_t<T>::has_value() const
+    noexcept {
     return _value.has_value();
 }
 
@@ -377,8 +401,15 @@ void clapp::option::basic_vector_param_option_t<T>::found_entry(
 }
 
 template <typename T>
-inline clapp::option::basic_vector_param_option_t<T>::operator bool() const {
-    return _value.size() > 0;
+inline clapp::option::basic_vector_param_option_t<T>::operator bool() const
+    noexcept {
+    return !_value.empty();
+}
+
+template <typename T>
+inline bool clapp::option::basic_vector_param_option_t<T>::has_value() const
+    noexcept {
+    return !_value.empty();
 }
 
 template <typename T>
@@ -421,6 +452,16 @@ bool clapp::option::basic_option_t<T>::given() const {
     return _given;
 }
 
+template <typename T>
+constexpr clapp::option::basic_option_t<T>::operator bool() const noexcept {
+    return _value.has_value();
+}
+
+template <typename T>
+constexpr bool clapp::option::basic_option_t<T>::has_value() const noexcept {
+    return _value.has_value();
+}
+
 template <typename... Params>
 clapp::option::bool_option_t::bool_option_t(clapp::basic_parser_t& parser,
                                             Params... parameters)
@@ -458,14 +499,4 @@ clapp::option::count_option_t::count_option_t(clapp::basic_parser_t& parser,
     }
 }
 
-inline clapp::option::bool_option_t::operator bool() const {
-    Expects(_value.has_value());
-    return _value.value();
-}
-
-inline clapp::option::count_option_t::operator bool() const {
-    Expects(_value.has_value());
-    return _value.value() > 0;
-}
-
 #endif
diff --git a/src/include/clapp/parser.h b/src/include/clapp/parser.h
index a0d3c4e0f9167d5c6199a22f63ff18067a4fedf0..876287f7b908fa8c3e0486007117b9b92760d804 100644
--- a/src/include/clapp/parser.h
+++ b/src/include/clapp/parser.h
@@ -71,6 +71,25 @@ class basic_parser_t {
         argument_type_t argument_type;
     };
 
+    struct help_line_t {
+        std::string name;
+        std::string description;
+    };
+
+    struct sub_parser_line_t {
+        std::string name;
+        std::string description;
+        basic_sub_parser_t& parser;
+    };
+
+    struct help_contents_t {
+        std::vector<help_line_t> mandatory_arguments{};
+        std::vector<help_line_t> optional_arguments{};
+        std::vector<help_line_t> mandatory_options{};
+        std::vector<help_line_t> optional_options{};
+        std::map<std::string, sub_parser_line_t> sub_parser{};
+    };
+
     template <typename short_option_func_t, typename long_option_func_t,
               option_type_t option_type>
     struct reg_option_conf_t {
@@ -140,6 +159,7 @@ class basic_parser_t {
     struct sub_parser_description_container_t {
         std::string sub_parser_string;
         std::string description;
+        basic_sub_parser_t& parser;
     };
 
     struct argument_description_container_t {
@@ -183,8 +203,8 @@ class basic_parser_t {
         std::optional<std::string> long_option;
     };
 
-    arg_iterator process_parse_result(arg_iterator it,
-                                      const parse_result_t& parse_result) const;
+    static arg_iterator process_parse_result(
+        arg_iterator it, const parse_result_t& parse_result);
     void parse(arg_iterator begin, arg_iterator end);
     parse_result_t parse(std::string_view option, arg_iterator it,
                          arg_iterator end);
@@ -193,12 +213,28 @@ class basic_parser_t {
 
     void validate_recursive() const;
 
-    virtual std::string gen_help_prefix() const;
-    std::string gen_help_msg() const;
+    std::string gen_short_line() const;
+    std::string gen_short_lines(std::size_t rec_depth) const;
+    virtual std::string gen_short_line_prefix() const = 0;
+    static std::string gen_usage_prefix();
+    virtual help_contents_t gen_detailed_help_contents() const;
+    static std::string gen_opt_arg_lines(const help_contents_t& help_contents,
+                                         const std::size_t num_spaces);
+
+    std::string gen_help_desc(std::size_t num_spaces,
+                              std::size_t rec_depth) const;
+    std::string gen_help_msg(std::size_t rec_depth) const;
     value::found_func_t gen_func_print_help_and_exit(int exit_code) const;
 
     std::size_t get_num_processed_arguments() const;
 
+    virtual void set_max_option_string_size(
+        const std::size_t max_option_size) = 0;
+    virtual std::size_t get_max_option_string_size() const = 0;
+
+    inline virtual bool is_active() const noexcept;
+    const basic_parser_t& get_active_parser() const;
+
    protected:
     sub_parsers_map_t& get_sub_parsers();
     long_options_map_t& get_long_options();
@@ -231,8 +267,10 @@ class basic_parser_t {
     sub_parser_descriptions_vec_t sub_parser_descriptions{};
     argument_descriptions_vec_t mandatory_argument_descriptions{};
     argument_descriptions_vec_t optional_argument_descriptions{};
-    std::size_t max_option_string_size{0};
     std::size_t num_processed_arguments{0};
+
+   public:
+    constexpr static std::size_t num_sub_spaces{2u};
 };
 
 }  // namespace parser
diff --git a/src/include/clapp/parser.hpp b/src/include/clapp/parser.hpp
index 7cac92a98e9c6ad9bf082b6a9482d3fe0412bdee..11a9dbd0ed087f51acb1d0e9f2f4795991373bc9 100644
--- a/src/include/clapp/parser.hpp
+++ b/src/include/clapp/parser.hpp
@@ -72,8 +72,8 @@ void clapp::parser::basic_parser_t::reg(
         config.option_string += "=<arg>";
     }
 
-    if (max_option_string_size < config.option_string.size()) {
-        max_option_string_size = config.option_string.size();
+    if (get_max_option_string_size() < config.option_string.size()) {
+        set_max_option_string_size(config.option_string.size());
     }
 
     option_description_container_t desc{std::move(config.option_string),
@@ -99,13 +99,13 @@ void clapp::parser::basic_parser_t::reg(
     if (num_arguments > 0 && get_arguments()[num_arguments - 1].argument_type ==
                                  argument_type_t::variadic) {
         std::stringstream ss;
-        ss << "Can't register argument '" << config.argument_name
+        ss << "Can't register regular argument '" << config.argument_name
            << "' when variadic arguments are already registered.";
         throw clapp::exception::argument_exception_t(ss.str());
     }
 
-    if (max_option_string_size < config.argument_name.size()) {
-        max_option_string_size = config.argument_name.size();
+    if (get_max_option_string_size() < config.argument_name.size()) {
+        set_max_option_string_size(config.argument_name.size());
     }
 
     if (config.purpose == purpose_t::mandatory) {
@@ -182,4 +182,8 @@ std::string clapp::parser::basic_parser_t::reg_option_conf_t<
     return option_string;
 }
 
+inline bool clapp::parser::basic_parser_t::is_active() const noexcept {
+    return true;
+}
+
 #endif
diff --git a/src/include/clapp/sub_parser.h b/src/include/clapp/sub_parser.h
index 9d2423ffa8bdce0cdc0e76dff0468e162d541e10..77287b17319757702e558592f7f8f3a1933e4128 100644
--- a/src/include/clapp/sub_parser.h
+++ b/src/include/clapp/sub_parser.h
@@ -24,24 +24,31 @@ inline namespace parser {
 class basic_sub_parser_t : public basic_parser_t {
    public:
     basic_sub_parser_t(basic_parser_t& parser, std::string sub_parser_name_arg,
-                       std::string description_arg,
-                       bool parse_parent_arg = true);
+                       std::string description_arg);
     ~basic_sub_parser_t() override;
-    explicit operator bool() const;
-    std::string get_sub_parser_name() const;
+
+    inline bool is_active() const noexcept override;
+    constexpr explicit operator bool() const noexcept;
+
+    inline std::string get_sub_parser_name() const;
     void sub_parse(arg_iterator begin, arg_iterator end);
-    std::string gen_help_prefix() const override;
+
+    std::string gen_short_line_prefix() const override;
+
+    void set_max_option_string_size(const std::size_t max_option_size) override;
+    std::size_t get_max_option_string_size() const override;
 
    private:
     basic_parser_t& parent_parser;
     std::string sub_parser_name;
     std::string description;
     bool active{false};
-    bool parse_parent;
 };
 
 }  // namespace parser
 
 }  // namespace clapp
 
+#include <clapp/sub_parser.hpp>
+
 #endif
diff --git a/src/include/clapp/sub_parser.hpp b/src/include/clapp/sub_parser.hpp
index b3a2c54bc3289bfc2093066ccddbcb91fdc20751..5883f4501559b7b8114e31bf90bdb8259e960225 100644
--- a/src/include/clapp/sub_parser.hpp
+++ b/src/include/clapp/sub_parser.hpp
@@ -18,39 +18,17 @@
 
 #include <clapp/sub_parser.h>
 
-clapp::parser::basic_sub_parser_::operator bool() const { return active; }
-
-std::string clapp::parser::basic_sub_parser_::get_sub_parser_name() const {
+inline std::string clapp::parser::basic_sub_parser_t::get_sub_parser_name()
+    const {
     return sub_parser_name;
 }
 
-void clapp::parser::basic_sub_parser_::sub_parse(arg_iterator begin,
-                                                 arg_iterator end) {
-    active = true;
-    for (arg_iterator it = begin; it != end;) {
-        std::string_view option{*it};
-        clapp::basic_parser::parse_result_t parse_result{
-            parse(option, it, end)};
-        if (it == parse_result.it && parse_parent) {
-            parse_result = parent_parser.parse(option, it, end);
-        }
-        it = process_parse_result(it, parse_result);
-    }
+inline bool clapp::parser::basic_sub_parser_t::is_active() const noexcept {
+    return active;
 }
 
-clapp::parser::basic_sub_parser_::basic_sub_parser_(
-    clapp::basic_parser& parser, const std::string& _sub_parser_name,
-    const std::string& _description, bool _parse_parent)
-    : basic_parser{},
-      parent_parser{parser},
-      sub_parser_name{_sub_parser_name},
-      description{_description},
-      parse_parent{_parse_parent} {
-    parser.reg(
-        reg_sub_parser_conf_t{[this](arg_iterator begin, arg_iterator end) {
-                                  return this->sub_parse(begin, end);
-                              },
-                              sub_parser_name, description});
+constexpr clapp::parser::basic_sub_parser_t::operator bool() const noexcept {
+    return active;
 }
 
 #endif
diff --git a/src/include/clapp/value.h b/src/include/clapp/value.h
index 9a3c846a0de47916efba888bf68d5accb7b9ba89..f57f10294c337237eb48e3013dd7cb634c94f15a 100644
--- a/src/include/clapp/value.h
+++ b/src/include/clapp/value.h
@@ -73,9 +73,9 @@ class found_func_t {
 #ifdef CLAPP_FS_AVAIL
 class path_exists_t {
    public:
-    std::string append_restriction_text();
+    static std::string append_restriction_text();
 
-    void validate(const fs::path &path, const std::string &param_name) const;
+    static void validate(const fs::path &path, const std::string &param_name);
 };
 #endif
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 74a3ae8a341218a028d18d482f5764fa74d3a079..d5db6696ec67934fcfe144f9e69366bcf15eb50f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,10 +1,10 @@
-set(sources value.cpp argument.cpp option.cpp parser.cpp sub_parser.cpp main_parser.cpp exception.cpp)
+set(sources value.cpp argument.cpp option.cpp parser.cpp sub_parser.cpp main_parser.cpp exception.cpp build_info.cpp)
 
 add_executable(libclapp_tests ${sources})
 target_link_libraries(libclapp_tests libClaPP_gmock_main clapp)
 target_compile_options(libclapp_tests PRIVATE ${libClaPP_TEST_COMPILE_OPTIONS})
 install(TARGETS libclapp_tests DESTINATION ${CMAKE_INSTALL_BINDIR})
 if(CLANG_TIDY)
-  set_target_properties(libclapp_tests PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS},-llvm-include-order,-clang-diagnostic-global-constructors,-hicpp-special-member-functions,-cppcoreguidelines-owning-memory,-cert-err58-cpp,-cppcoreguidelines-special-member-functions,-clang-diagnostic-used-but-marked-unused,-cppcoreguidelines-pro-type-vararg,-clang-diagnostic-covered-switch-default,-hicpp-vararg,-fuchsia-statically-constructed-objects,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto")
+  set_target_properties(libclapp_tests PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_ARGS},-llvm-include-order,-clang-diagnostic-global-constructors,-hicpp-special-member-functions,-cppcoreguidelines-owning-memory,-cert-err58-cpp,-cppcoreguidelines-special-member-functions,-clang-diagnostic-used-but-marked-unused,-cppcoreguidelines-pro-type-vararg,-clang-diagnostic-covered-switch-default,-hicpp-vararg,-fuchsia-statically-constructed-objects,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-misc-non-private-member-variables-in-classes,-cppcoreguidelines-non-private-member-variables-in-classes,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays,-cppcoreguidelines-avoid-c-arrays")
 endif()
-
+add_test(NAME libclapp_tests COMMAND libclapp_tests)
diff --git a/tests/argument.cpp b/tests/argument.cpp
index ca4b9997f4e5b82d32d1207127a0d5634a71e3a6..e3a1952c26d8ddc39d8ff8328134e07f664fecd1 100644
--- a/tests/argument.cpp
+++ b/tests/argument.cpp
@@ -4,6 +4,8 @@
 
 class argument_test_parser_t : public clapp::parser::basic_parser_t {
    public:
+    ~argument_test_parser_t() override;
+
     using clapp::parser::basic_parser_t::purpose_t;
 
     using clapp::parser::basic_parser_t::argument_descriptions_vec_t;
@@ -16,12 +18,29 @@ class argument_test_parser_t : public clapp::parser::basic_parser_t {
     using clapp::parser::basic_parser_t::get_optional_argument_descriptions;
     using clapp::parser::basic_parser_t::get_validate_functions;
 
-   public:
-    ~argument_test_parser_t() override;
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 argument_test_parser_t::~argument_test_parser_t() = default;
 
+std::string argument_test_parser_t::gen_short_line_prefix() const {
+    return "arg-test-parser" + gen_short_line();
+}
+
+void argument_test_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+std::size_t argument_test_parser_t::get_max_option_string_size() const {
+    return max_option_string_size;
+}
+
 class simple_argument_sub_parser_t : public clapp::parser::basic_sub_parser_t {
     using clapp::parser::basic_sub_parser_t::basic_sub_parser_t;
 
@@ -31,7 +50,7 @@ class simple_argument_sub_parser_t : public clapp::parser::basic_sub_parser_t {
 
 simple_argument_sub_parser_t::~simple_argument_sub_parser_t() = default;
 
-TEST(argument, basic_argument_construct_to_short_argument_name_throws) {
+TEST(argument, basicArgumentConstructToShortArgumentNameThrows) {
     const std::string arg_name;
     const std::string arg_desc{"description"};
     argument_test_parser_t tp;
@@ -39,9 +58,8 @@ TEST(argument, basic_argument_construct_to_short_argument_name_throws) {
                  clapp::exception::argument_exception_t);
 }
 
-TEST(
-    argument,
-    basic_argument_construct_variadic_argument_and_register_another_argument_throws) {
+TEST(argument,
+     basicArgumentConstructVariadicArgumentAndRegisterAnotherArgumentThrows) {
     const std::string variadic_arg_name{"variadic"};
     const std::string arg_name{"arg"};
     const std::string arg_desc{"description"};
@@ -52,9 +70,8 @@ TEST(
                  clapp::exception::argument_exception_t);
 }
 
-TEST(
-    argument,
-    basic_argument_construct_optional_argument_and_register_mandatory_argument_throws) {
+TEST(argument,
+     basicArgumentConstructOptionalArgumentAndRegisterMandatoryArgumentThrows) {
     const std::string optional_arg_name{"variadic"};
     const std::string arg_name{"arg"};
     const std::string arg_desc{"description"};
@@ -66,8 +83,7 @@ TEST(
                  clapp::exception::argument_exception_t);
 }
 
-TEST(argument,
-     basic_argument_construct_sub_parser_and_register_argument_throws) {
+TEST(argument, basicArgumentConstructSubParserAndRegisterArgumentThrows) {
     const std::string arg_name{"arg"};
     const std::string arg_desc{"description"};
     argument_test_parser_t tp;
@@ -79,7 +95,7 @@ TEST(argument,
                  clapp::exception::argument_exception_t);
 }
 
-TEST(argument, basic_argument_found_func_long) {
+TEST(argument, basicArgumentFoundFuncLong) {
     const std::string arg_name{"arg"};
     const std::string arg_desc{"description"};
 
@@ -101,7 +117,7 @@ TEST(argument, basic_argument_found_func_long) {
     ASSERT_THAT(ss.str(), testing::StrEq("this is a test"));
 }
 
-TEST(argument, basic_argument_construct_simple) {
+TEST(argument, basicArgumentConstructSimple) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"description"};
     argument_test_parser_t tp;
@@ -136,7 +152,7 @@ TEST(argument, basic_argument_construct_simple) {
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(argument, basic_argument_construct_mandatory) {
+TEST(argument, basicArgumentConstructMandatory) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"description"};
     argument_test_parser_t tp;
@@ -172,7 +188,7 @@ TEST(argument, basic_argument_construct_mandatory) {
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(argument, basic_argument_construct_optional) {
+TEST(argument, basicArgumentConstructOptional) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"description"};
     argument_test_parser_t tp;
@@ -206,7 +222,7 @@ TEST(argument, basic_argument_construct_optional) {
     ASSERT_THAT(arg.value(), testing::Eq(12345));
 }
 
-TEST(argument, basic_argument_construct_optional_default_value) {
+TEST(argument, basicArgumentConstructOptionalDefaultValue) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"description"};
     argument_test_parser_t tp;
@@ -244,7 +260,7 @@ TEST(argument, basic_argument_construct_optional_default_value) {
     ASSERT_THAT(arg.value(), testing::Eq(123));
 }
 
-TEST(argument, basic_argument_construct_mandatory_default_value) {
+TEST(argument, basicArgumentConstructMandatoryDefaultValue) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"desciption"};
     const std::uint32_t default_value{1123};
@@ -286,10 +302,10 @@ TEST(argument, basic_argument_construct_mandatory_default_value) {
     args[0].func("0x12341234");
     ASSERT_THAT(static_cast<bool>(arg), testing::Eq(true));
     ASSERT_THAT(arg.given(), testing::Eq(true));
-    ASSERT_THAT(arg.value(), testing::Eq(0x12341234u));
+    ASSERT_THAT(arg.value(), testing::Eq(0x12341234U));
 }
 
-TEST(argument, basic_argument_construct_optional_default_value_min_max) {
+TEST(argument, basicArgumentConstructOptionalDefaultValueMinMax) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"desciption"};
     argument_test_parser_t tp;
@@ -341,7 +357,7 @@ TEST(argument, basic_argument_construct_optional_default_value_min_max) {
     ASSERT_THROW(validate_funcs[0](), clapp::exception::out_of_range_t);
 }
 
-TEST(argument, basic_argument_construct_mandatory_path_exists) {
+TEST(argument, basicArgumentConstructMandatoryPathExists) {
     const std::string arg_name1{"arg"};
     const std::string arg_desc1{"desc"};
     argument_test_parser_t tp;
@@ -389,7 +405,7 @@ TEST(argument, basic_argument_construct_mandatory_path_exists) {
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(argument, basic_variadic_argument_found_func_long) {
+TEST(argument, basicVariadicArgumentFoundFuncLong) {
     const std::string arg_name{"arg"};
     const std::string arg_desc{"description"};
 
@@ -417,7 +433,7 @@ TEST(argument, basic_variadic_argument_found_func_long) {
     ASSERT_THAT(ss.str(), testing::StrEq("this is a testthis is a test"));
 }
 
-TEST(argument, basic_variadic_argument_construct_simple) {
+TEST(argument, basicVariadicArgumentConstructSimple) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"desc"};
     argument_test_parser_t tp;
@@ -467,7 +483,7 @@ TEST(argument, basic_variadic_argument_construct_simple) {
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(argument, basic_variadic_argument_construct_simple_optional) {
+TEST(argument, basicVariadicArgumentConstructSimpleOptional) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"desc"};
     argument_test_parser_t tp;
@@ -512,7 +528,7 @@ TEST(argument, basic_variadic_argument_construct_simple_optional) {
                 testing::Eq(std::vector<std::string>{"ccc", "aba"}));
 }
 
-TEST(argument, basic_variadic_argument_construct_simple_optional_min_max) {
+TEST(argument, basicVariadicArgumentConstructSimpleOptionalMinMax) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"desc"};
     const clapp::value::min_max_value_t<std::int64_t> min_max{-2, 10};
@@ -569,7 +585,7 @@ TEST(argument, basic_variadic_argument_construct_simple_optional_min_max) {
     ASSERT_THROW(validate_funcs[0](), clapp::exception::out_of_range_t);
 }
 
-TEST(argument, basic_variadic_argument_construct_simple_default_value_throws) {
+TEST(argument, basicVariadicArgumentConstructSimpleDefaultValueThrows) {
     const std::string arg_name{"argument name"};
     const std::string arg_desc{"desc"};
     const clapp::value::default_value_t<std::int8_t> default_value{10};
diff --git a/tests/build_info.cpp b/tests/build_info.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1c07fcfa256228f7ac2d9d23d629b6b8be5ad33
--- /dev/null
+++ b/tests/build_info.cpp
@@ -0,0 +1,20 @@
+#include <clapp/build_info.h>
+#include <gmock/gmock.h>
+
+TEST(buildInfo, version) {
+    std::stringstream ss;
+    ss << clapp::build_info::version_major << "."
+       << clapp::build_info::version_minor << "."
+       << clapp::build_info::version_patch;
+    ASSERT_THAT(clapp::build_info::version, testing::StrEq(ss.str()));
+}
+
+TEST(buildInfo, buildInfoString) {
+    std::stringstream ss;
+    ss << clapp::build_info::project_name << " v." << clapp::build_info::version
+       << " " << clapp::build_info::build_type
+       << "-Build: " << clapp::build_info::git_branch << ":"
+       << clapp::build_info::git_hash << " ("
+       << clapp::build_info::git_description << ")";
+    ASSERT_THAT(clapp::build_info::build_info_string, testing::StrEq(ss.str()));
+}
diff --git a/tests/exception.cpp b/tests/exception.cpp
index 9499696ac993aac4537699a72037f69db2520be4..8311e35884cc2cf63212eef272ae8c03a32fcbac 100644
--- a/tests/exception.cpp
+++ b/tests/exception.cpp
@@ -1,7 +1,10 @@
 #include <clapp/exception.h>
 #include <gmock/gmock.h>
 
-TEST(exception, clapp_exception_t) {
+TEST(exception, clappExceptionT) {
+    static_assert(std::is_base_of<std::runtime_error,
+                                  clapp::exception::clapp_exception_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -18,7 +21,12 @@ TEST(exception, clapp_exception_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, invalid_value_t) {
+TEST(exception, invalidValueT) {
+    static_assert(std::is_base_of<std::runtime_error,
+                                  clapp::exception::invalid_value_t>::value);
+    static_assert(std::is_base_of<clapp::exception::clapp_exception_t,
+                                  clapp::exception::invalid_value_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -35,7 +43,12 @@ TEST(exception, invalid_value_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, value_undefined_t) {
+TEST(exception, valueUndefinedT) {
+    static_assert(std::is_base_of<std::runtime_error,
+                                  clapp::exception::value_undefined_t>::value);
+    static_assert(std::is_base_of<clapp::exception::clapp_exception_t,
+                                  clapp::exception::value_undefined_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -52,7 +65,12 @@ TEST(exception, value_undefined_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, out_of_range_t) {
+TEST(exception, outOfRangeT) {
+    static_assert(std::is_base_of<std::runtime_error,
+                                  clapp::exception::out_of_range_t>::value);
+    static_assert(std::is_base_of<clapp::exception::clapp_exception_t,
+                                  clapp::exception::out_of_range_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -69,7 +87,14 @@ TEST(exception, out_of_range_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, path_does_not_exist_t) {
+TEST(exception, pathDoesNotExistT) {
+    static_assert(
+        std::is_base_of<std::runtime_error,
+                        clapp::exception::path_does_not_exist_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::clapp_exception_t,
+                        clapp::exception::path_does_not_exist_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -86,7 +111,12 @@ TEST(exception, path_does_not_exist_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, option_exception_t) {
+TEST(exception, optionExceptionT) {
+    static_assert(std::is_base_of<std::runtime_error,
+                                  clapp::exception::option_exception_t>::value);
+    static_assert(std::is_base_of<clapp::exception::clapp_exception_t,
+                                  clapp::exception::option_exception_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -103,7 +133,14 @@ TEST(exception, option_exception_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, option_param_exception_t) {
+TEST(exception, optionParamExceptionT) {
+    static_assert(
+        std::is_base_of<std::runtime_error,
+                        clapp::exception::option_param_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::clapp_exception_t,
+                        clapp::exception::option_param_exception_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -120,7 +157,14 @@ TEST(exception, option_param_exception_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, argument_exception_t) {
+TEST(exception, argumentExceptionT) {
+    static_assert(
+        std::is_base_of<std::runtime_error,
+                        clapp::exception::argument_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::clapp_exception_t,
+                        clapp::exception::argument_exception_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -137,7 +181,12 @@ TEST(exception, argument_exception_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, parser_exception_t) {
+TEST(exception, parserExceptionT) {
+    static_assert(std::is_base_of<std::runtime_error,
+                                  clapp::exception::parser_exception_t>::value);
+    static_assert(std::is_base_of<clapp::exception::clapp_exception_t,
+                                  clapp::exception::parser_exception_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -154,7 +203,17 @@ TEST(exception, parser_exception_t) {
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
 
-TEST(exception, sub_parser_exception_t) {
+TEST(exception, subParserExceptionT) {
+    static_assert(
+        std::is_base_of<std::runtime_error,
+                        clapp::exception::sub_parser_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::clapp_exception_t,
+                        clapp::exception::sub_parser_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::parser_exception_t,
+                        clapp::exception::sub_parser_exception_t>::value);
+
     const std::string msg{"message"};
     const std::string msg2{"message2"};
 
@@ -170,3 +229,60 @@ TEST(exception, sub_parser_exception_t) {
     ASSERT_THAT(ce3.what(), testing::StrEq(msg2));
     ASSERT_THAT(ce4.what(), testing::StrEq(msg));
 }
+
+TEST(exception, mainParserExceptionT) {
+    static_assert(
+        std::is_base_of<std::runtime_error,
+                        clapp::exception::main_parser_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::clapp_exception_t,
+                        clapp::exception::main_parser_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::parser_exception_t,
+                        clapp::exception::main_parser_exception_t>::value);
+
+    const std::string msg{"message"};
+    const std::string msg2{"message2"};
+
+    clapp::exception::main_parser_exception_t ce1{msg.c_str()};
+    clapp::exception::main_parser_exception_t ce2{msg2};
+
+    clapp::exception::main_parser_exception_t ce3{ce1};
+    clapp::exception::main_parser_exception_t ce4{std::move(ce1)};
+
+    ce4 = ce3;
+    ce3 = std::move(ce2);
+
+    ASSERT_THAT(ce3.what(), testing::StrEq(msg2));
+    ASSERT_THAT(ce4.what(), testing::StrEq(msg));
+}
+
+TEST(exception, noExecutableExceptionT) {
+    static_assert(
+        std::is_base_of<std::runtime_error,
+                        clapp::exception::no_executable_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::clapp_exception_t,
+                        clapp::exception::no_executable_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::parser_exception_t,
+                        clapp::exception::no_executable_exception_t>::value);
+    static_assert(
+        std::is_base_of<clapp::exception::main_parser_exception_t,
+                        clapp::exception::no_executable_exception_t>::value);
+
+    const std::string msg{"message"};
+    const std::string msg2{"message2"};
+
+    clapp::exception::no_executable_exception_t ce1{msg.c_str()};
+    clapp::exception::no_executable_exception_t ce2{msg2};
+
+    clapp::exception::no_executable_exception_t ce3{ce1};
+    clapp::exception::no_executable_exception_t ce4{std::move(ce1)};
+
+    ce4 = ce3;
+    ce3 = std::move(ce2);
+
+    ASSERT_THAT(ce3.what(), testing::StrEq(msg2));
+    ASSERT_THAT(ce4.what(), testing::StrEq(msg));
+}
diff --git a/tests/main_parser.cpp b/tests/main_parser.cpp
index a210b2835df5546aad6fa18e32aa41e93d7e0928..46189a62e9e18f17d7cef2d92057cbae82e3d6c5 100644
--- a/tests/main_parser.cpp
+++ b/tests/main_parser.cpp
@@ -10,26 +10,64 @@ class empty_main_parser_t : public clapp::parser::basic_main_parser_t {
 
 empty_main_parser_t::~empty_main_parser_t() = default;
 
-TEST(main_parser, construct_main_parser) {
+TEST(mainParser, constructMainParser) {
     constexpr const char* const argv[]{"main", nullptr};
-    empty_main_parser_t tp;
+    empty_main_parser_t emp;
 
-    tp.parse(1, static_cast<const char* const*>(argv));
-    ASSERT_THAT(static_cast<bool>(tp), testing::Eq(true));
-    ASSERT_THAT(tp.get_executable(), testing::StrEq("main"));
+    emp.parse(1, static_cast<const char* const*>(argv));
 }
 
-TEST(parser, construct_main_parser_and_gen_help_prefix) {
+TEST(mainParser, constructMainParserBoolOperator) {
+    constexpr const char* const argv[]{"main-exec", nullptr};
+    empty_main_parser_t emp;
+    ASSERT_THAT(static_cast<bool>(emp), testing::Eq(false));
+
+    emp.parse(1, static_cast<const char* const*>(argv));
+    ASSERT_THAT(static_cast<bool>(emp), testing::Eq(true));
+}
+
+TEST(mainParser, constructMainParserGetExecutable) {
+    constexpr const char* const argv[]{"main-exec", nullptr};
+    empty_main_parser_t emp;
+    ASSERT_THROW(emp.get_executable(),
+                 clapp::exception::no_executable_exception_t);
+
+    emp.parse(1, static_cast<const char* const*>(argv));
+    ASSERT_THAT(emp.get_executable(), testing::StrEq("main-exec"));
+}
+
+TEST(mainParser, constructMainParserAndGenHelpPrefix) {
     constexpr const char* const argv[]{"main", nullptr};
-    empty_main_parser_t tp;
+    empty_main_parser_t emp;
 
-    tp.parse(1, static_cast<const char* const*>(argv));
-    ASSERT_THAT(tp.gen_help_prefix(), testing::StrEq("Usage: \nmain"));
+    emp.parse(1, static_cast<const char* const*>(argv));
+    ASSERT_THAT(emp.gen_short_line_prefix(), testing::StrEq("main"));
 }
 
-TEST(parser, construct_main_parser_parse_and_validate) {
+TEST(mainParser, constructMainParserParseAndValidate) {
     constexpr const char* const argv[]{"main", nullptr};
-    empty_main_parser_t tp;
+    empty_main_parser_t emp;
+
+    emp.parse_and_validate(1, static_cast<const char* const*>(argv));
+}
+
+TEST(mainParser, constructMainParserIsActiveIsTrue) {
+    empty_main_parser_t emp;
+    ASSERT_THAT(emp.is_active(), testing::Eq(true));
+}
+
+TEST(mainParser, constructMainParserGetActiveReturnsThisRef) {
+    empty_main_parser_t emp;
+    ASSERT_THAT(&emp.get_active_parser(), testing::Eq(&emp));
+}
+
+TEST(mainParser, constructMainParserGetMaxOptionStringSize) {
+    empty_main_parser_t emp;
+    ASSERT_THAT(emp.get_max_option_string_size(), testing::Eq(0));
+}
 
-    tp.parse_and_validate(1, static_cast<const char* const*>(argv));
+TEST(mainParser, constructMainParserSetMaxOptionStringSize) {
+    empty_main_parser_t emp;
+    emp.set_max_option_string_size(4);
+    ASSERT_THAT(emp.get_max_option_string_size(), testing::Eq(4));
 }
diff --git a/tests/option.cpp b/tests/option.cpp
index 62a305f969cb5bb8b11db779fcdd76f544c443cc..06bfdbd1cd875a5020ed654f736c152b4c4a14a7 100644
--- a/tests/option.cpp
+++ b/tests/option.cpp
@@ -26,10 +26,30 @@ class option_test_parser_t : public clapp::parser::basic_parser_t {
     using clapp::parser::basic_parser_t::get_optional_option_descriptions;
     using clapp::parser::basic_parser_t::get_short_options;
     using clapp::parser::basic_parser_t::get_validate_functions;
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 option_test_parser_t::~option_test_parser_t() = default;
 
+std::string option_test_parser_t::gen_short_line_prefix() const {
+    return "opt-test-parser" + gen_short_line();
+}
+
+void option_test_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+std::size_t option_test_parser_t::get_max_option_string_size() const {
+    return max_option_string_size;
+}
+
 class test_option_t : public clapp::option::basic_option_t<std::int32_t> {
    public:
     template <typename... Params>
@@ -73,7 +93,7 @@ test_option_t::callbacks_t test_option_t::create_callbacks(
         [inst]() { return inst->value(); }};
 }
 
-TEST(option, basic_option_construct_value_throws) {
+TEST(option, basicOptionConstructValueThrows) {
     const std::string long_opt{"long"};
     const std::string opt_desc{"description"};
     option_test_parser_t tp;
@@ -81,7 +101,7 @@ TEST(option, basic_option_construct_value_throws) {
     ASSERT_THROW(opt.value(), clapp::exception::value_undefined_t);
 }
 
-TEST(option, bool_option_construct_long_option_twice_throws) {
+TEST(option, boolOptionConstructLongOptionTwiceThrows) {
     const std::string long_opt{"long"};
     const std::string opt_desc{"description"};
     option_test_parser_t tp;
@@ -90,7 +110,7 @@ TEST(option, bool_option_construct_long_option_twice_throws) {
                  clapp::exception::option_exception_t);
 }
 
-TEST(option, bool_option_construct_short_option_twice_throws) {
+TEST(option, boolOptionConstructShortOptionTwiceThrows) {
     const char short_opt{'s'};
     const std::string opt_desc{"description"};
     option_test_parser_t tp;
@@ -99,7 +119,7 @@ TEST(option, bool_option_construct_short_option_twice_throws) {
                  clapp::exception::option_exception_t);
 }
 
-TEST(option, bool_option_construct_long) {
+TEST(option, boolOptionConstructLongString) {
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"description"};
 
@@ -134,17 +154,114 @@ TEST(option, bool_option_construct_long) {
     option_test_parser_t::long_opt_func_t long_opt_func{
         std::get<option_test_parser_t::long_opt_func_t>(long_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt.given(), testing::Eq(false));
+    ASSERT_THAT(opt.value(), testing::Eq(false));
+
+    long_opt_func(long_opt_name);
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt.given(), testing::Eq(true));
+    ASSERT_THAT(opt.value(), testing::Eq(true));
+}
+
+TEST(option, boolOptionConstructLongCstring) {
+    constexpr const char* long_opt_name{"long-cstring"};
+    constexpr const char* opt_desc{"description"};
+
+    option_test_parser_t tp;
+    clapp::option::bool_option_t opt{tp, long_opt_name, opt_desc};
+    option_test_parser_t::long_options_map_t long_options{
+        tp.get_long_options()};
+    option_test_parser_t::short_options_map_t short_options{
+        tp.get_short_options()};
+    ASSERT_THAT(tp.get_mandatory_option_descriptions().size(), testing::Eq(0));
+    option_test_parser_t::option_descriptions_vec_t descs{
+        tp.get_optional_option_descriptions()};
+    option_test_parser_t::validate_func_vec_t validate_funcs{
+        tp.get_validate_functions()};
+    ASSERT_THAT(validate_funcs.size(), testing::Eq(0));
+
+    ASSERT_THAT(descs.size(), testing::Eq(1));
+    ASSERT_THAT(descs[0].option_string,
+                testing::StrEq(std::string{"--"} + long_opt_name));
+    ASSERT_THAT(descs[0].description, testing::StrEq(opt_desc));
+    ASSERT_THAT(descs[0].option_type,
+                testing::Eq(option_test_parser_t::option_type_t::scalar));
+
+    ASSERT_THAT(short_options.size(), testing::Eq(0));
+    ASSERT_THAT(long_options.size(), testing::Eq(1));
+    ASSERT_THAT(long_options.count(long_opt_name), testing::Eq(1));
+    option_test_parser_t::long_opt_variant_t long_opt_func_variant{
+        long_options.find(long_opt_name)->second};
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::long_opt_func_t>(
+                    long_opt_func_variant),
+                testing::Eq(true));
+    option_test_parser_t::long_opt_func_t long_opt_func{
+        std::get<option_test_parser_t::long_opt_func_t>(long_opt_func_variant)};
+
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(false));
 
     long_opt_func(long_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(true));
 }
 
-TEST(option, bool_option_construct_short) {
+TEST(option, boolOptionConstructLongVec) {
+    const std::string long_opt_name{"long2"};
+    const std::string opt_desc{"description2"};
+
+    option_test_parser_t tp;
+    clapp::option::bool_option_t opt{
+        tp, std::vector<std::string>{long_opt_name}, opt_desc};
+    option_test_parser_t::long_options_map_t long_options{
+        tp.get_long_options()};
+    option_test_parser_t::short_options_map_t short_options{
+        tp.get_short_options()};
+    ASSERT_THAT(tp.get_mandatory_option_descriptions().size(), testing::Eq(0));
+    option_test_parser_t::option_descriptions_vec_t descs{
+        tp.get_optional_option_descriptions()};
+    option_test_parser_t::validate_func_vec_t validate_funcs{
+        tp.get_validate_functions()};
+    ASSERT_THAT(validate_funcs.size(), testing::Eq(0));
+
+    ASSERT_THAT(descs.size(), testing::Eq(1));
+    ASSERT_THAT(descs[0].option_string,
+                testing::StrEq(std::string{"--"} + long_opt_name));
+    ASSERT_THAT(descs[0].description, testing::StrEq(opt_desc));
+    ASSERT_THAT(descs[0].option_type,
+                testing::Eq(option_test_parser_t::option_type_t::scalar));
+
+    ASSERT_THAT(short_options.size(), testing::Eq(0));
+    ASSERT_THAT(long_options.size(), testing::Eq(1));
+    ASSERT_THAT(long_options.count(long_opt_name), testing::Eq(1));
+    option_test_parser_t::long_opt_variant_t long_opt_func_variant{
+        long_options.find(long_opt_name)->second};
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::long_opt_func_t>(
+                    long_opt_func_variant),
+                testing::Eq(true));
+    option_test_parser_t::long_opt_func_t long_opt_func{
+        std::get<option_test_parser_t::long_opt_func_t>(long_opt_func_variant)};
+
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt.given(), testing::Eq(false));
+    ASSERT_THAT(opt.value(), testing::Eq(false));
+
+    long_opt_func(long_opt_name);
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt.given(), testing::Eq(true));
+    ASSERT_THAT(opt.value(), testing::Eq(true));
+}
+
+TEST(option, boolOptionConstructShort) {
     const char short_opt_name{'o'};
     const std::string opt_desc{"description"};
 
@@ -180,17 +297,19 @@ TEST(option, bool_option_construct_short) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(false));
 
     short_opt_func(short_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(true));
 }
 
-TEST(option, bool_option_construct_long_and_short) {
+TEST(option, boolOptionConstructLongAndShortWithStrings) {
     const std::string long_opt_name1{"option-name1"};
     const char short_opt_name1{'o'};
     const std::string opt_desc1{"description1"};
@@ -203,8 +322,113 @@ TEST(option, bool_option_construct_long_and_short) {
 
     clapp::option::bool_option_t opt1{tp, long_opt_name1, short_opt_name1,
                                       opt_desc1};
-    clapp::option::bool_option_t opt2{tp, long_opt_name2, short_opt_name2,
-                                      opt_desc2};
+    clapp::option::bool_option_t opt2{
+        tp, std::vector<std::string>{long_opt_name2},
+        std::vector<char>{short_opt_name2}, opt_desc2};
+    option_test_parser_t::long_options_map_t long_options{
+        tp.get_long_options()};
+    option_test_parser_t::short_options_map_t short_options{
+        tp.get_short_options()};
+    ASSERT_THAT(tp.get_mandatory_option_descriptions().size(), testing::Eq(0));
+    option_test_parser_t::option_descriptions_vec_t descs{
+        tp.get_optional_option_descriptions()};
+    option_test_parser_t::validate_func_vec_t validate_funcs{
+        tp.get_validate_functions()};
+    ASSERT_THAT(validate_funcs.size(), testing::Eq(0));
+
+    ASSERT_THAT(descs.size(), testing::Eq(2));
+    ASSERT_THAT(descs[0].option_string,
+                testing::StrEq(std::string{"-"} + short_opt_name1 + "|--" +
+                               long_opt_name1));
+    ASSERT_THAT(descs[0].description, testing::StrEq(opt_desc1));
+    ASSERT_THAT(descs[0].option_type,
+                testing::Eq(option_test_parser_t::option_type_t::scalar));
+    ASSERT_THAT(descs[1].option_string,
+                testing::StrEq(std::string{"-"} + short_opt_name2 + "|--" +
+                               long_opt_name2));
+    ASSERT_THAT(descs[1].description, testing::StrEq(opt_desc2));
+    ASSERT_THAT(descs[1].option_type,
+                testing::Eq(option_test_parser_t::option_type_t::scalar));
+
+    ASSERT_THAT(long_options.size(), testing::Eq(2));
+    ASSERT_THAT(long_options.count(long_opt_name1), testing::Eq(1));
+    ASSERT_THAT(long_options.count(long_opt_name2), testing::Eq(1));
+    option_test_parser_t::long_opt_variant_t long_opt_func_variant1{
+        long_options.find(long_opt_name1)->second};
+    option_test_parser_t::long_opt_variant_t long_opt_func_variant2{
+        long_options.find(long_opt_name2)->second};
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::long_opt_func_t>(
+                    long_opt_func_variant1),
+                testing::Eq(true));
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::long_opt_func_t>(
+                    long_opt_func_variant2),
+                testing::Eq(true));
+    option_test_parser_t::long_opt_func_t long_opt_func1{
+        std::get<option_test_parser_t::long_opt_func_t>(
+            long_opt_func_variant1)};
+    option_test_parser_t::long_opt_func_t long_opt_func2{
+        std::get<option_test_parser_t::long_opt_func_t>(
+            long_opt_func_variant2)};
+
+    ASSERT_THAT(short_options.size(), testing::Eq(2));
+    ASSERT_THAT(short_options.count(short_opt_name1), testing::Eq(1));
+    ASSERT_THAT(short_options.count(short_opt_name2), testing::Eq(1));
+    option_test_parser_t::short_opt_variant_t short_opt_func_variant1{
+        short_options.find(short_opt_name1)->second};
+    option_test_parser_t::short_opt_variant_t short_opt_func_variant2{
+        short_options.find(short_opt_name2)->second};
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::short_opt_func_t>(
+                    short_opt_func_variant1),
+                testing::Eq(true));
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::short_opt_func_t>(
+                    short_opt_func_variant2),
+                testing::Eq(true));
+    option_test_parser_t::short_opt_func_t short_opt_func1{
+        std::get<option_test_parser_t::short_opt_func_t>(
+            short_opt_func_variant1)};
+    option_test_parser_t::short_opt_func_t short_opt_func2{
+        std::get<option_test_parser_t::short_opt_func_t>(
+            short_opt_func_variant2)};
+
+    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt1.given(), testing::Eq(false));
+    ASSERT_THAT(opt1.value(), testing::Eq(false));
+
+    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt2.given(), testing::Eq(false));
+    ASSERT_THAT(opt2.value(), testing::Eq(false));
+
+    long_opt_func1(long_opt_name1);
+    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt1.given(), testing::Eq(true));
+    ASSERT_THAT(opt1.value(), testing::Eq(true));
+
+    short_opt_func2(short_opt_name2);
+    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt2.given(), testing::Eq(true));
+    ASSERT_THAT(opt2.value(), testing::Eq(true));
+}
+
+TEST(option, boolOptionConstructLongAndShortWithCStrings) {
+    constexpr const char* long_opt_name1{"option-name-a"};
+    constexpr char short_opt_name1{'a'};
+    constexpr const char* opt_desc1{"description1"};
+
+    constexpr const char* long_opt_name2{"option-name-b"};
+    constexpr char short_opt_name2{'b'};
+    constexpr const char* opt_desc2{"description2"};
+
+    option_test_parser_t tp;
+
+    clapp::option::bool_option_t opt1{tp, long_opt_name1, short_opt_name1,
+                                      opt_desc1};
+    clapp::option::bool_option_t opt2{
+        tp, std::vector<std::string>{long_opt_name2},
+        std::vector<char>{short_opt_name2}, opt_desc2};
     option_test_parser_t::long_options_map_t long_options{
         tp.get_long_options()};
     option_test_parser_t::short_options_map_t short_options{
@@ -270,26 +494,134 @@ TEST(option, bool_option_construct_long_and_short) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant2)};
 
-    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
     ASSERT_THAT(opt1.given(), testing::Eq(false));
     ASSERT_THAT(opt1.value(), testing::Eq(false));
 
-    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
     ASSERT_THAT(opt2.given(), testing::Eq(false));
     ASSERT_THAT(opt2.value(), testing::Eq(false));
 
     long_opt_func1(long_opt_name1);
     ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
     ASSERT_THAT(opt1.given(), testing::Eq(true));
     ASSERT_THAT(opt1.value(), testing::Eq(true));
 
     short_opt_func2(short_opt_name2);
     ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
     ASSERT_THAT(opt2.given(), testing::Eq(true));
     ASSERT_THAT(opt2.value(), testing::Eq(true));
 }
 
-TEST(option, bool_option_found_func_long) {
+TEST(option, boolOptionConstructLongAndShortWithCStrings2) {
+    constexpr const char* long_opt_name1{"option-name-x"};
+    constexpr char short_opt_name1{'x'};
+    constexpr const char* opt_desc1{"description1"};
+
+    constexpr const char* long_opt_name2{"option-name-y"};
+    constexpr char short_opt_name2{'y'};
+    constexpr const char* opt_desc2{"description2"};
+
+    option_test_parser_t tp;
+
+    clapp::option::bool_option_t opt1{tp,
+                                      std::vector<std::string>{long_opt_name1},
+                                      short_opt_name1, opt_desc1};
+    clapp::option::bool_option_t opt2{
+        tp, long_opt_name2, std::vector<char>{short_opt_name2}, opt_desc2};
+    option_test_parser_t::long_options_map_t long_options{
+        tp.get_long_options()};
+    option_test_parser_t::short_options_map_t short_options{
+        tp.get_short_options()};
+    ASSERT_THAT(tp.get_mandatory_option_descriptions().size(), testing::Eq(0));
+    option_test_parser_t::option_descriptions_vec_t descs{
+        tp.get_optional_option_descriptions()};
+    option_test_parser_t::validate_func_vec_t validate_funcs{
+        tp.get_validate_functions()};
+    ASSERT_THAT(validate_funcs.size(), testing::Eq(0));
+
+    ASSERT_THAT(descs.size(), testing::Eq(2));
+    ASSERT_THAT(descs[0].option_string,
+                testing::StrEq(std::string{"-"} + short_opt_name1 + "|--" +
+                               long_opt_name1));
+    ASSERT_THAT(descs[0].description, testing::StrEq(opt_desc1));
+    ASSERT_THAT(descs[0].option_type,
+                testing::Eq(option_test_parser_t::option_type_t::scalar));
+    ASSERT_THAT(descs[1].option_string,
+                testing::StrEq(std::string{"-"} + short_opt_name2 + "|--" +
+                               long_opt_name2));
+    ASSERT_THAT(descs[1].description, testing::StrEq(opt_desc2));
+    ASSERT_THAT(descs[1].option_type,
+                testing::Eq(option_test_parser_t::option_type_t::scalar));
+
+    ASSERT_THAT(long_options.size(), testing::Eq(2));
+    ASSERT_THAT(long_options.count(long_opt_name1), testing::Eq(1));
+    ASSERT_THAT(long_options.count(long_opt_name2), testing::Eq(1));
+    option_test_parser_t::long_opt_variant_t long_opt_func_variant1{
+        long_options.find(long_opt_name1)->second};
+    option_test_parser_t::long_opt_variant_t long_opt_func_variant2{
+        long_options.find(long_opt_name2)->second};
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::long_opt_func_t>(
+                    long_opt_func_variant1),
+                testing::Eq(true));
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::long_opt_func_t>(
+                    long_opt_func_variant2),
+                testing::Eq(true));
+    option_test_parser_t::long_opt_func_t long_opt_func1{
+        std::get<option_test_parser_t::long_opt_func_t>(
+            long_opt_func_variant1)};
+    option_test_parser_t::long_opt_func_t long_opt_func2{
+        std::get<option_test_parser_t::long_opt_func_t>(
+            long_opt_func_variant2)};
+
+    ASSERT_THAT(short_options.size(), testing::Eq(2));
+    ASSERT_THAT(short_options.count(short_opt_name1), testing::Eq(1));
+    ASSERT_THAT(short_options.count(short_opt_name2), testing::Eq(1));
+    option_test_parser_t::short_opt_variant_t short_opt_func_variant1{
+        short_options.find(short_opt_name1)->second};
+    option_test_parser_t::short_opt_variant_t short_opt_func_variant2{
+        short_options.find(short_opt_name2)->second};
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::short_opt_func_t>(
+                    short_opt_func_variant1),
+                testing::Eq(true));
+    ASSERT_THAT(std::holds_alternative<option_test_parser_t::short_opt_func_t>(
+                    short_opt_func_variant2),
+                testing::Eq(true));
+    option_test_parser_t::short_opt_func_t short_opt_func1{
+        std::get<option_test_parser_t::short_opt_func_t>(
+            short_opt_func_variant1)};
+    option_test_parser_t::short_opt_func_t short_opt_func2{
+        std::get<option_test_parser_t::short_opt_func_t>(
+            short_opt_func_variant2)};
+
+    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt1.given(), testing::Eq(false));
+    ASSERT_THAT(opt1.value(), testing::Eq(false));
+
+    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt2.given(), testing::Eq(false));
+    ASSERT_THAT(opt2.value(), testing::Eq(false));
+
+    long_opt_func1(long_opt_name1);
+    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt1.given(), testing::Eq(true));
+    ASSERT_THAT(opt1.value(), testing::Eq(true));
+
+    short_opt_func2(short_opt_name2);
+    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
+    ASSERT_THAT(opt2.given(), testing::Eq(true));
+    ASSERT_THAT(opt2.value(), testing::Eq(true));
+}
+
+TEST(option, boolOptionFoundFuncLong) {
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"description"};
 
@@ -317,7 +649,7 @@ TEST(option, bool_option_found_func_long) {
     ASSERT_THAT(ss.str(), testing::StrEq("this is a test"));
 }
 
-TEST(option, bool_option_construct_long_mandatory) {
+TEST(option, boolOptionConstructLongMandatory) {
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"description"};
 
@@ -354,7 +686,8 @@ TEST(option, bool_option_construct_long_mandatory) {
     option_test_parser_t::long_opt_func_t long_opt_func{
         std::get<option_test_parser_t::long_opt_func_t>(long_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(false));
     ASSERT_THROW(validate_funcs[0](),
@@ -362,12 +695,13 @@ TEST(option, bool_option_construct_long_mandatory) {
 
     long_opt_func(long_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(true));
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(option, help_option_construct_long) {
+TEST(option, helpOptionConstructLong) {
     const std::string long_opt_name{"long"};
     const char short_opt_name{'s'};
     const std::string opt_desc{"description"};
@@ -414,25 +748,30 @@ TEST(option, help_option_construct_long) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(false));
 
     testing::internal::CaptureStdout();
     ASSERT_EXIT(long_opt_func(long_opt_name), ::testing::ExitedWithCode(0), "");
-    ASSERT_THAT(testing::internal::GetCapturedStdout(),
-                testing::StrEq("Usage: \n [-s|--long] \n\nOptional Options:\n  "
-                               "-s|--long description\n"));
+    ASSERT_THAT(
+        testing::internal::GetCapturedStdout(),
+        testing::StrEq(
+            "Usage:\nopt-test-parser [-s|--long]\n\n  Optional Options:\n    "
+            "-s|--long description\n"));
 
     testing::internal::CaptureStdout();
     ASSERT_EXIT(short_opt_func(short_opt_name), ::testing::ExitedWithCode(0),
                 "");
-    ASSERT_THAT(testing::internal::GetCapturedStdout(),
-                testing::StrEq("Usage: \n [-s|--long] \n\nOptional Options:\n  "
-                               "-s|--long description\n"));
+    ASSERT_THAT(
+        testing::internal::GetCapturedStdout(),
+        testing::StrEq(
+            "Usage:\nopt-test-parser [-s|--long]\n\n  Optional Options:\n    "
+            "-s|--long description\n"));
 }
 
-TEST(option, count_option_construct_long) {
+TEST(option, countOptionConstructLong) {
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"description 2"};
 
@@ -467,22 +806,25 @@ TEST(option, count_option_construct_long) {
     option_test_parser_t::long_opt_func_t long_opt_func{
         std::get<option_test_parser_t::long_opt_func_t>(long_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(0));
 
     long_opt_func(long_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(1));
 
     long_opt_func(long_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(2));
 }
 
-TEST(option, count_option_construct_short) {
+TEST(option, countOptionConstructShort) {
     const char short_opt_name{'i'};
     const std::string opt_desc{"description 3"};
 
@@ -518,7 +860,8 @@ TEST(option, count_option_construct_short) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(0));
 
@@ -526,11 +869,12 @@ TEST(option, count_option_construct_short) {
     short_opt_func(short_opt_name);
     short_opt_func(short_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(3));
 }
 
-TEST(option, count_option_construct_long_and_short) {
+TEST(option, countOptionConstructLongAndShort) {
     const std::string long_opt_name1{"option-name1"};
     const char short_opt_name1{'o'};
     const std::string opt_desc1{"description1"};
@@ -610,17 +954,20 @@ TEST(option, count_option_construct_long_and_short) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant2)};
 
-    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
     ASSERT_THAT(opt1.given(), testing::Eq(false));
     ASSERT_THAT(opt1.value(), testing::Eq(0));
 
-    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
     ASSERT_THAT(opt2.given(), testing::Eq(false));
     ASSERT_THAT(opt2.value(), testing::Eq(0));
 
     long_opt_func1(long_opt_name1);
     short_opt_func1(short_opt_name1);
     ASSERT_THAT(static_cast<bool>(opt1), testing::Eq(true));
+    ASSERT_THAT(opt1.has_value(), testing::Eq(true));
     ASSERT_THAT(opt1.given(), testing::Eq(true));
     ASSERT_THAT(opt1.value(), testing::Eq(2));
 
@@ -629,16 +976,19 @@ TEST(option, count_option_construct_long_and_short) {
     long_opt_func2(long_opt_name2);
     short_opt_func2(short_opt_name2);
     ASSERT_THAT(static_cast<bool>(opt2), testing::Eq(true));
+    ASSERT_THAT(opt2.has_value(), testing::Eq(true));
     ASSERT_THAT(opt2.given(), testing::Eq(true));
     ASSERT_THAT(opt2.value(), testing::Eq(4));
 }
 
-TEST(option, count_option_construct_short_min_max) {
+TEST(option, countOptionConstructShortMinMax) {
     const char short_opt_name{'i'};
     const std::string opt_desc{"description 3"};
+    constexpr std::uint32_t min_value{0};
+    constexpr std::uint32_t max_value{5};
 
     option_test_parser_t tp;
-    clapp::value::min_max_value_t<std::uint32_t> min_max{0, 5};
+    clapp::value::min_max_value_t<std::uint32_t> min_max{min_value, max_value};
     clapp::option::count_option_t opt{tp, short_opt_name, opt_desc, min_max};
     option_test_parser_t::long_options_map_t long_options{
         tp.get_long_options()};
@@ -672,7 +1022,8 @@ TEST(option, count_option_construct_short_min_max) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(0));
     ASSERT_NO_THROW(validate_funcs[0]());
@@ -682,24 +1033,27 @@ TEST(option, count_option_construct_short_min_max) {
     short_opt_func(short_opt_name);
     short_opt_func(short_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(4));
     ASSERT_NO_THROW(validate_funcs[0]());
 
     short_opt_func(short_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(5));
     ASSERT_NO_THROW(validate_funcs[0]());
 
     short_opt_func(short_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(6));
     ASSERT_THROW(validate_funcs[0](), clapp::exception::out_of_range_t);
 }
 
-TEST(option, count_option_construct_long_default) {
+TEST(option, countOptionConstructLongDefault) {
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"desc"};
 
@@ -739,16 +1093,18 @@ TEST(option, count_option_construct_long_default) {
         std::get<option_test_parser_t::long_opt_func_t>(long_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(4));
 
     long_opt_func(long_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(5));
 }
 
-TEST(option, count_option_found_func_short) {
+TEST(option, countOptionFoundFuncShort) {
     const char short_opt_name{'c'};
     const std::string opt_desc{"description"};
 
@@ -774,7 +1130,8 @@ TEST(option, count_option_found_func_short) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(0));
     ASSERT_THAT(ss.str(), testing::StrEq(""));
@@ -783,11 +1140,12 @@ TEST(option, count_option_found_func_short) {
     ASSERT_THAT(ss.str(), testing::StrEq("this is another test"));
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(1));
 }
 
-TEST(option, count_option_construct_short_mandatory) {
+TEST(option, countOptionConstructShortMandatory) {
     const char short_opt_name{'i'};
     const std::string opt_desc{"description 3"};
 
@@ -825,7 +1183,8 @@ TEST(option, count_option_construct_short_mandatory) {
         std::get<option_test_parser_t::short_opt_func_t>(
             short_opt_func_variant)};
 
-    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(0));
     ASSERT_THROW(validate_funcs[0](), clapp::exception::option_exception_t);
@@ -834,12 +1193,13 @@ TEST(option, count_option_construct_short_mandatory) {
     short_opt_func(short_opt_name);
     short_opt_func(short_opt_name);
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(3));
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(option, string_param_option_construct_short) {
+TEST(option, stringParamOptionConstructShort) {
     const char short_opt_name{'s'};
     const std::string opt_desc{"string description"};
 
@@ -877,16 +1237,18 @@ TEST(option, string_param_option_construct_short) {
             short_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THROW(opt.value(), clapp::exception::value_undefined_t);
 
     short_opt_func(short_opt_name, "string");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::StrEq("string"));
 }
 
-TEST(option, string_param_option_found_func_short) {
+TEST(option, stringParamOptionFoundFuncShort) {
     const char short_opt_name{'s'};
     const std::string opt_desc{"description"};
 
@@ -915,17 +1277,19 @@ TEST(option, string_param_option_found_func_short) {
             short_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(ss.str(), testing::StrEq(""));
     short_opt_func(short_opt_name, "param");
 
     ASSERT_THAT(ss.str(), testing::StrEq("this is another test for params"));
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::StrEq("param"));
 }
 
-TEST(option, string_param_option_construct_long_mandatory) {
+TEST(option, stringParamOptionConstructLongMandatory) {
     const std::string long_opt_name{"string"};
     const std::string opt_desc{"string description"};
 
@@ -965,18 +1329,20 @@ TEST(option, string_param_option_construct_long_mandatory) {
             long_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THROW(opt.value(), clapp::exception::value_undefined_t);
     ASSERT_THROW(validate_funcs[0](), clapp::exception::option_exception_t);
 
     long_opt_func(long_opt_name, "string");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::StrEq("string"));
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(option, int_param_option_construct_long_and_short_mandatory) {
+TEST(option, intParamOptionConstructLongAndShortMandatory) {
     const std::string long_opt_name{"int"};
     const char short_opt_name{'i'};
     const std::string opt_desc{"int description"};
@@ -1047,24 +1413,27 @@ TEST(option, int_param_option_construct_long_and_short_mandatory) {
             long_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq(default_value));
     ASSERT_THROW(validate_funcs[0](), clapp::exception::option_exception_t);
 
     long_opt_func(long_opt_name, "123");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(123));
     ASSERT_THROW(validate_funcs[0](), clapp::exception::out_of_range_t);
 
     short_opt_func(short_opt_name, "0x2f");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value(), testing::Eq(0x2f));
     ASSERT_NO_THROW(validate_funcs[0]());
 }
 
-TEST(option, vector_string_param_option_construct_with_default_throws) {
+TEST(option, vectorStringParamOptionConstructWithDefaultThrows) {
     const char short_opt_name{'s'};
     const std::string opt_desc{"string description"};
 
@@ -1076,7 +1445,7 @@ TEST(option, vector_string_param_option_construct_with_default_throws) {
         clapp::exception::option_param_exception_t);
 }
 
-TEST(option, vector_string_param_option_construct_short) {
+TEST(option, vectorStringParamOptionConstructShort) {
     const char short_opt_name{'s'};
     const std::string opt_desc{"string description"};
 
@@ -1116,11 +1485,13 @@ TEST(option, vector_string_param_option_construct_short) {
             short_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq((std::vector<std::string>{})));
 
     short_opt_func(short_opt_name, "string");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     std::vector<std::string> vec{opt.value()};
     ASSERT_THAT(vec.size(), testing::Eq(1));
@@ -1128,6 +1499,7 @@ TEST(option, vector_string_param_option_construct_short) {
 
     short_opt_func(short_opt_name, "string2");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     vec = opt.value();
     ASSERT_THAT(vec.size(), testing::Eq(2));
@@ -1135,7 +1507,7 @@ TEST(option, vector_string_param_option_construct_short) {
     ASSERT_THAT(vec[1], testing::StrEq("string2"));
 }
 
-TEST(option, vector_string_param_option_construct_long_mandatory) {
+TEST(option, vectorStringParamOptionConstructLongMandatory) {
     const std::string long_opt_name{"string"};
     const std::string opt_desc{"string description"};
 
@@ -1176,6 +1548,7 @@ TEST(option, vector_string_param_option_construct_long_mandatory) {
             long_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq((std::vector<std::string>{})));
     ASSERT_THROW(validate_funcs[0](),
@@ -1183,6 +1556,7 @@ TEST(option, vector_string_param_option_construct_long_mandatory) {
 
     long_opt_func(long_opt_name, "string");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     std::vector<std::string> vec{opt.value()};
     ASSERT_THAT(vec.size(), testing::Eq(1));
@@ -1190,6 +1564,7 @@ TEST(option, vector_string_param_option_construct_long_mandatory) {
 
     long_opt_func(long_opt_name, "string2");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     vec = opt.value();
     ASSERT_THAT(vec.size(), testing::Eq(2));
@@ -1198,6 +1573,7 @@ TEST(option, vector_string_param_option_construct_long_mandatory) {
 
     long_opt_func(long_opt_name, "string3");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     vec = opt.value();
     ASSERT_THAT(vec.size(), testing::Eq(3));
@@ -1206,7 +1582,7 @@ TEST(option, vector_string_param_option_construct_long_mandatory) {
     ASSERT_THAT(vec[2], testing::StrEq("string3"));
 }
 
-TEST(option, vector_string_param_option_found_func_short) {
+TEST(option, vectorStringParamOptionFoundFuncShort) {
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"description"};
 
@@ -1234,6 +1610,7 @@ TEST(option, vector_string_param_option_found_func_short) {
             long_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(ss.str(), testing::StrEq(""));
     ASSERT_THAT(opt.value().size(), testing::Eq(0));
@@ -1241,16 +1618,19 @@ TEST(option, vector_string_param_option_found_func_short) {
 
     ASSERT_THAT(ss.str(), testing::StrEq("this is another test for params"));
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     ASSERT_THAT(opt.value().size(), testing::Eq(1));
     ASSERT_THAT(opt.value()[0], testing::StrEq("param"));
 }
 
-TEST(option, vector_string_param_option_construct_long_and_short_min_max) {
+TEST(option, vectorStringParamOptionConstructLongAndShortMinMax) {
     const char short_opt_name{'s'};
     const std::string long_opt_name{"long"};
     const std::string opt_desc{"int description"};
-    clapp::value::min_max_value_t<std::uint8_t> min_max{10, 20};
+    const int min_value{10};
+    const int max_value{20};
+    clapp::value::min_max_value_t<std::uint8_t> min_max{min_value, max_value};
 
     option_test_parser_t tp;
     clapp::option::vector_uint8_param_option_t opt{
@@ -1301,12 +1681,14 @@ TEST(option, vector_string_param_option_construct_long_and_short_min_max) {
             short_opt_func_variant)};
 
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(false));
+    ASSERT_THAT(opt.has_value(), testing::Eq(false));
     ASSERT_THAT(opt.given(), testing::Eq(false));
     ASSERT_THAT(opt.value(), testing::Eq((std::vector<std::uint8_t>{})));
     ASSERT_NO_THROW(validate_funcs[0]());
 
     short_opt_func(short_opt_name, "0x12");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     std::vector<std::uint8_t> vec{opt.value()};
     ASSERT_THAT(vec.size(), testing::Eq(1));
@@ -1315,6 +1697,7 @@ TEST(option, vector_string_param_option_construct_long_and_short_min_max) {
 
     long_opt_func(long_opt_name, "12");
     ASSERT_THAT(static_cast<bool>(opt), testing::Eq(true));
+    ASSERT_THAT(opt.has_value(), testing::Eq(true));
     ASSERT_THAT(opt.given(), testing::Eq(true));
     vec = opt.value();
     ASSERT_THAT(vec.size(), testing::Eq(2));
@@ -1333,7 +1716,7 @@ TEST(option, vector_string_param_option_construct_long_and_short_min_max) {
     ASSERT_THROW(validate_funcs[0](), clapp::exception::out_of_range_t);
 }
 
-TEST(option, invalid_long_option_construct) {
+TEST(option, invalidLongOptionConstruct) {
     const std::string long_opt_name1{"long\n"};
     const std::string long_opt_name2{"long\t"};
     const std::string long_opt_name3{"long\r"};
@@ -1377,7 +1760,7 @@ TEST(option, invalid_long_option_construct) {
                  clapp::exception::option_exception_t);
 }
 
-TEST(option, invalid_short_option_construct) {
+TEST(option, invalidShortOptionConstruct) {
     const char short_opt_name1{'\n'};
     const char short_opt_name2{'\t'};
     const char short_opt_name3{'\r'};
@@ -1421,95 +1804,70 @@ TEST(option, invalid_short_option_construct) {
                  clapp::exception::option_exception_t);
 }
 
-struct mock_t {
-    MOCK_METHOD(std::int32_t, value_func, ());
-    MOCK_METHOD(bool, given_func, ());
-    MOCK_METHOD(bool, has_value_func, ());
-    MOCK_METHOD(void, validate_func,
-                (const std::int32_t&, const std::string& option_string));
-};
-
-TEST(option, gen_opt_validate_func) {
+TEST(option, genOptValidateFunc) {
     using int32_value_func_t = std::function<std::int32_t(void)>;
     using int32_validate_func_t = std::function<void(
         const std::int32_t&, const std::string& option_string)>;
 
     {
-        mock_t mock;
         std::optional<option_test_parser_t::validate_func_t> validate_func{
             clapp::option::gen_opt_validate_func<std::int32_t,
                                                  int32_value_func_t>(
-                std::nullopt, std::nullopt,
-                [&mock]() { return mock.given_func(); },
+                std::nullopt, std::nullopt, []() { return false; },
                 std::vector<int32_validate_func_t>{}, "option string",
                 option_test_parser_t::purpose_t::mandatory)};
         ASSERT_THAT(validate_func.has_value(), testing::Eq(true));
-        EXPECT_CALL(mock, given_func())
-            .Times(1)
-            .WillOnce(testing::Return(false));
         ASSERT_THROW((*validate_func)(), clapp::exception::option_exception_t);
     }
 
     {
-        mock_t mock;
         std::optional<option_test_parser_t::validate_func_t> validate_func{
             clapp::option::gen_opt_validate_func<std::int32_t,
                                                  int32_value_func_t>(
-                std::nullopt, [&mock]() { return mock.has_value_func(); },
-                [&mock]() { return mock.given_func(); },
-                std::vector<int32_validate_func_t>{}, "option string",
-                option_test_parser_t::purpose_t::mandatory)};
+                std::nullopt,
+                []() -> bool { throw std::runtime_error{"unexpected call"}; },
+                []() { return true; }, std::vector<int32_validate_func_t>{},
+                "option string", option_test_parser_t::purpose_t::mandatory)};
         ASSERT_THAT(validate_func.has_value(), testing::Eq(true));
-        EXPECT_CALL(mock, given_func())
-            .Times(1)
-            .WillOnce(testing::Return(true));
         ASSERT_NO_THROW((*validate_func)());
     }
 
     {
-        mock_t mock;
+        constexpr std::int32_t return_value{10};
         std::optional<option_test_parser_t::validate_func_t> validate_func{
             clapp::option::gen_opt_validate_func<std::int32_t,
                                                  int32_value_func_t>(
-                [&mock]() { return mock.value_func(); },
-                [&mock]() { return mock.has_value_func(); },
-                [&mock]() { return mock.given_func(); },
+                []() { return return_value; }, []() { return true; },
+                []() { return true; },
                 std::vector<int32_validate_func_t>{
-                    [&mock](const std::int32_t& value,
-                            const std::string& option_string) {
-                        mock.validate_func(value, option_string);
+                    [](const std::int32_t& value,
+                       const std::string& option_string) {
+                        if (option_string != "option string") {
+                            throw std::runtime_error{"option_string invalid"};
+                        }
+                        if (value != return_value) {
+                            throw std::runtime_error{"value invalid"};
+                        }
                     }},
                 "option string", option_test_parser_t::purpose_t::mandatory)};
         ASSERT_THAT(validate_func.has_value(), testing::Eq(true));
-        EXPECT_CALL(mock, value_func()).Times(1).WillOnce(testing::Return(10));
-        EXPECT_CALL(mock, has_value_func())
-            .Times(1)
-            .WillOnce(testing::Return(true));
-        EXPECT_CALL(mock, given_func())
-            .Times(1)
-            .WillOnce(testing::Return(true));
-        EXPECT_CALL(mock, validate_func(10, testing::StrEq("option string")))
-            .Times(1);
         ASSERT_NO_THROW((*validate_func)());
     }
 
     {
-        mock_t mock;
         std::optional<option_test_parser_t::validate_func_t> validate_func{
             clapp::option::gen_opt_validate_func<std::int32_t,
                                                  int32_value_func_t>(
-                std::nullopt, std::nullopt,
-                [&mock]() { return mock.given_func(); },
+                std::nullopt, std::nullopt, []() { return true; },
                 std::vector<int32_validate_func_t>{
-                    [&mock](const std::int32_t& value,
-                            const std::string& option_string) {
-                        mock.validate_func(value, option_string);
+                    [](const std::int32_t& /*value*/,
+                       const std::string& option_string) {
+                        if (option_string != "option string") {
+                            throw std::runtime_error{"option_string invalid"};
+                        }
                     }},
                 "option string", option_test_parser_t::purpose_t::mandatory)};
         ASSERT_THAT(validate_func.has_value(), testing::Eq(true));
-        EXPECT_CALL(mock, given_func())
-            .Times(1)
-            .WillOnce(testing::Return(true));
         ASSERT_THROW((*validate_func)(),
                      clapp::exception::option_param_exception_t);
     }
diff --git a/tests/parser.cpp b/tests/parser.cpp
index 24bed075f888e25498a49bae851b6fd7ec2bfabd..37fa64cbf2132665da48eeafcae059e7edc47a7d 100644
--- a/tests/parser.cpp
+++ b/tests/parser.cpp
@@ -14,21 +14,44 @@ class empty_basic_parser_t : public clapp::basic_parser_t {
    public:
     using clapp::basic_parser_t::basic_parser_t;
     ~empty_basic_parser_t() override;
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 empty_basic_parser_t::~empty_basic_parser_t() = default;
 
+[[nodiscard]] std::string empty_basic_parser_t::gen_short_line_prefix() const {
+    return "arg-test-parser" + gen_short_line();
+}
+
+void empty_basic_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t empty_basic_parser_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
 class simple_test_parser_t : public clapp::basic_parser_t {
    public:
     using clapp::basic_parser_t::basic_parser_t;
     ~simple_test_parser_t() override;
 
+    static constexpr std::int32_t min_int{10};
+    static constexpr std::int32_t max_int{200};
+
     clapp::option::bool_option_t bool_option{*this, "bool", 'b',
                                              "Bool option."};
 
     clapp::option::int32_param_option_t int_option{
         *this, "int", 'i', "Int option.",
-        clapp::value::min_max_value_t<std::int32_t>{10, 200}};
+        clapp::value::min_max_value_t<std::int32_t>{min_int, max_int}};
 
     clapp::argument::string_argument_t string_arg{*this, "arg-name",
                                                   "Arg desc"};
@@ -36,10 +59,31 @@ class simple_test_parser_t : public clapp::basic_parser_t {
     clapp::argument::variadic_string_argument_t variadic_string_arg{
         *this, "variadic-arg-name", "Variadic arg desc",
         clapp::basic_parser_t::purpose_t::optional};
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 simple_test_parser_t::~simple_test_parser_t() = default;
 
+[[nodiscard]] std::string simple_test_parser_t::gen_short_line_prefix() const {
+    return "simple-test-parser" + gen_short_line();
+}
+
+void simple_test_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t simple_test_parser_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
 class simple_test_parser2_t : public clapp::basic_parser_t {
    public:
     using clapp::basic_parser_t::basic_parser_t;
@@ -52,21 +96,45 @@ class simple_test_parser2_t : public clapp::basic_parser_t {
     clapp::argument::string_argument_t string_arg{
         *this, "arg-name", "Arg desc",
         clapp::basic_parser_t::purpose_t::optional};
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 simple_test_parser2_t::~simple_test_parser2_t() = default;
 
+[[nodiscard]] std::string simple_test_parser2_t::gen_short_line_prefix() const {
+    return "simple-test-parser2" + gen_short_line();
+}
+
+void simple_test_parser2_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t simple_test_parser2_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
 class simple_test_parser3_t : public clapp::basic_parser_t {
    public:
     using clapp::basic_parser_t::basic_parser_t;
     ~simple_test_parser3_t() override;
 
+    static constexpr std::int32_t min_int{10};
+    static constexpr std::int32_t max_int{200};
+
     clapp::option::vector_int64_param_option_t int_option{
         *this,
         "int",
         'i',
         "Int option.",
-        clapp::value::min_max_value_t<std::int64_t>{10, 200},
+        clapp::value::min_max_value_t<std::int64_t>{min_int, max_int},
         clapp::basic_parser_t::purpose_t::mandatory};
 
     clapp::option::vector_string_param_option_t string_option{
@@ -76,15 +144,40 @@ class simple_test_parser3_t : public clapp::basic_parser_t {
     clapp::argument::variadic_string_argument_t variadic_string_arg{
         *this, "variadic-arg-name", "Variadic arg desc",
         clapp::basic_parser_t::purpose_t::mandatory};
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 simple_test_parser3_t::~simple_test_parser3_t() = default;
 
+[[nodiscard]] std::string simple_test_parser3_t::gen_short_line_prefix() const {
+    return "simple-test-parser3" + gen_short_line();
+}
+
+void simple_test_parser3_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t simple_test_parser3_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
 class sub_parser_container_t : public clapp::basic_parser_t {
    public:
     using clapp::basic_parser_t::basic_parser_t;
     ~sub_parser_container_t() override;
 
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
     clapp::option::bool_option_t bool_option{*this, "bool", 'b',
                                              "Bool option."};
 
@@ -110,22 +203,39 @@ class sub_parser_container_t : public clapp::basic_parser_t {
     };
 
     simple_sub_parser_t sub_parser{*this, "sub-parser", "Sub parser desc"};
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 sub_parser_container_t::simple_sub_parser_t::~simple_sub_parser_t() = default;
 sub_parser_container_t::~sub_parser_container_t() = default;
 
-TEST(parser, construct_empty_basic_parser) { empty_basic_parser_t ebp; }
+[[nodiscard]] std::string sub_parser_container_t::gen_short_line_prefix()
+    const {
+    return "sub_parser_container" + gen_short_line();
+}
+
+void sub_parser_container_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
 
-TEST(parser, construct_empty_basic_parser_and_parse_empty_arguments) {
+[[nodiscard]] std::size_t sub_parser_container_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
+TEST(parser, constructEmptyBasicParser) { empty_basic_parser_t ebp; }
+
+TEST(parser, constructEmptyBasicParserAndParseEmptyArguments) {
     constexpr const char* const argv[]{nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     empty_basic_parser_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
 }
 
-TEST(parser,
-     construct_empty_basic_parser_and_parse_and_validate_empty_arguments) {
+TEST(parser, constructEmptyBasicParserAndParseAndValidateEmptyArguments) {
     constexpr const char* const argv[]{nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     empty_basic_parser_t ebp;
@@ -133,85 +243,116 @@ TEST(parser,
     ASSERT_NO_THROW(ebp.validate());
 }
 
-TEST(parser, construct_empty_basic_parser_and_gen_help_prefix) {
+TEST(parser, constructEmptyBasicParserAndGenUsagePrefix) {
+    empty_basic_parser_t ebp;
+    ASSERT_THAT(ebp.gen_usage_prefix(), testing::StrEq("Usage:\n"));
+}
+
+TEST(parser, constructEmptyBasicParserAndGenHelpMessage) {
+    empty_basic_parser_t ebp;
+    ASSERT_THAT(ebp.gen_help_msg(255), testing::StrEq("arg-test-parser\n"));
+}
+
+TEST(parser, constructEmptyBasicParserIsActiveIsTrue) {
     empty_basic_parser_t ebp;
-    ASSERT_THAT(ebp.gen_help_prefix(), testing::StrEq("Usage: \n"));
+    ASSERT_THAT(ebp.is_active(), testing::Eq(true));
 }
 
-TEST(parser, construct_empty_basic_parser_and_gen_help_message) {
+TEST(parser, constructEmptyBasicParserGetActiveReturnsThisRef) {
     empty_basic_parser_t ebp;
-    ASSERT_THAT(ebp.gen_help_msg(), testing::StrEq("\n"));
+    ASSERT_THAT(&ebp.get_active_parser(), testing::Eq(&ebp));
 }
 
-TEST(parser, gen_func_print_help_and_exit) {
+TEST(parser, genFuncPrintHelpAndExit) {
     empty_basic_parser_t ebp;
     clapp::value::found_func_t ff{
         ebp.gen_func_print_help_and_exit(EXIT_SUCCESS)};
     testing::internal::CaptureStdout();
     ASSERT_EXIT(ff.found(), ::testing::ExitedWithCode(0), "");
     std::string output = testing::internal::GetCapturedStdout();
-    ASSERT_THAT(output, testing::StrEq("Usage: \n \n"));
+    ASSERT_THAT(output, testing::StrEq("Usage:\narg-test-parser\n"));
 }
 
-TEST(parser, construct_simple_test_parser_and_gen_help_message) {
+TEST(parser, constructSimpleTestParserAndGenHelpMessage) {
     simple_test_parser_t stp;
+    constexpr std::size_t max_option_string_size{25};
+    stp.set_max_option_string_size(max_option_string_size);
     ASSERT_THAT(
-        stp.gen_help_msg(),
+        stp.gen_help_msg(255),
         testing::StrEq(
-            "[-b|--bool] [-i|--int=<arg>] <arg-name> [<variadic-arg-name>...] "
-            "\n\nMandatory Arguments:\n  arg-name          Arg desc\n\n"
-            "Optional Arguments:\n  variadic-arg-name Variadic arg desc "
-            "(variadic argument)\n\n"
-            "Optional Options:\n  -b|--bool         Bool option.\n"
-            "  -i|--int=<arg>    Int option. (constraint: [10,200])\n"));
+            "simple-test-parser <arg-name> [<variadic-arg-name>...] "
+            "[-b|--bool] [-i|--int=<arg>]\n\n  Mandatory Arguments:\n    "
+            "arg-name                  Arg desc\n\n  Optional Arguments:\n    "
+            "variadic-arg-name         Variadic arg desc (variadic "
+            "argument)\n\n  Optional Options:\n    -b|--bool                 "
+            "Bool option.\n    -i|--int=<arg>            Int option. "
+            "(constraint: [10,200])\n"));
 }
 
-TEST(parser, construct_simple_test_parser2_and_gen_help_message) {
+TEST(parser, constructSimpleTestParser2AndGenHelpMessage) {
     simple_test_parser2_t stp;
+    constexpr std::size_t max_option_string_size{20};
+    stp.set_max_option_string_size(max_option_string_size);
     ASSERT_THAT(
-        stp.gen_help_msg(),
-        testing::StrEq("-c|--count [<arg-name>] \n\n"
-                       "Optional Arguments:\n  arg-name   Arg desc\n\n"
-                       "Mandatory Options:\n  -c|--count Count option.\n"));
+        stp.gen_help_msg(255),
+        testing::StrEq(
+            "simple-test-parser2 -c|--count [<arg-name>]\n\n  Mandatory "
+            "Options:\n    -c|--count           Count option.\n\n  Optional "
+            "Arguments:\n    arg-name             Arg desc\n"));
 }
 
-TEST(parser, construct_simple_test_parser3_and_gen_help_message) {
+TEST(parser, constructSimpleTestParser3AndGenHelpMessage) {
     simple_test_parser3_t stp;
+    constexpr std::size_t max_option_string_size{30};
+    stp.set_max_option_string_size(max_option_string_size);
     ASSERT_THAT(
-        stp.gen_help_msg(),
+        stp.gen_help_msg(255),
         testing::StrEq(
-            "-i|--int=<arg>... [-s|--str=<arg>...] <variadic-arg-name>... \n\n"
-            "Mandatory Arguments:\n  variadic-arg-name Variadic arg desc "
-            "(variadic argument)\n\n"
-            "Mandatory Options:\n  -i|--int=<arg>    Int option. (vector "
-            "option, constraint: [10,200])\n\n"
-            "Optional Options:\n  -s|--str=<arg>    String option. (vector "
-            "option)\n"));
+            "simple-test-parser3 <variadic-arg-name>... -i|--int=<arg>... "
+            "[-s|--str=<arg>...]\n\n  Mandatory Arguments:\n    "
+            "variadic-arg-name              Variadic arg desc (variadic "
+            "argument)\n\n  Mandatory Options:\n    -i|--int=<arg>             "
+            "    Int option. (vector option, constraint: [10,200])\n\n  "
+            "Optional Options:\n    -s|--str=<arg>                 String "
+            "option. (vector option)\n"));
 }
 
-TEST(parser, construct_sub_parser_container_and_gen_help_message) {
+TEST(parser, constructSubParserContainerAndGenHelpMessage) {
     sub_parser_container_t spc;
-    ASSERT_THAT(spc.gen_help_msg(),
-                testing::StrEq(
-                    "[-b|--bool] [-2|--second] <arg-name> <sub-parser> "
-                    "[sub-parser args/opts...] \n\n"
-                    "Mandatory Arguments:\n  arg-name    Arg desc\n\n"
-                    "Available sub-parsers:\n  sub-parser  Sub parser desc\n\n"
-                    "Optional Options:\n  -b|--bool   Bool option.\n  "
-                    "-2|--second Second bool option.\n"));
+    constexpr std::size_t max_option_string_size{25};
+    spc.set_max_option_string_size(max_option_string_size);
+    ASSERT_THAT(
+        spc.gen_help_msg(255),
+        testing::StrEq(
+            "sub_parser_container <arg-name> [-b|--bool] [-2|--second] "
+            "sub-parser [<sub-arg-name>] [-b|--bool] "
+            "[-s|--string=<arg>]\nsub_parser_container <arg-name> [-b|--bool] "
+            "[-2|--second]\n\n  Subparser:\n    sub-parser                Sub "
+            "parser desc\n      Optional Arguments:\n        sub-arg-name      "
+            "    Sub arg desc\n\n      Optional Options:\n        -b|--bool    "
+            "         Bool option.\n        -s|--string=<arg>     String "
+            "option.\n\n\n  Mandatory Arguments:\n    arg-name                 "
+            " Arg desc\n\n  Optional Options:\n    -b|--bool                 "
+            "Bool option.\n    -2|--second               Second bool "
+            "option.\n"));
 }
 
-TEST(parser, construct_sub_parser_container_and_gen_sub_parser_help_message) {
+TEST(parser, constructSubParserContainerAndGenSubParserHelpMessage) {
     sub_parser_container_t spc;
-    ASSERT_THAT(spc.sub_parser.gen_help_msg(),
-                testing::StrEq(
-                    "[-b|--bool] [-s|--string=<arg>] [<sub-arg-name>] \n\n"
-                    "Optional Arguments:\n  sub-arg-name      Sub arg desc\n\n"
-                    "Optional Options:\n  -b|--bool         Bool option.\n"
-                    "  -s|--string=<arg> String option.\n"));
+    constexpr std::size_t max_option_string_size{35};
+    spc.set_max_option_string_size(max_option_string_size);
+    ASSERT_THAT(
+        spc.sub_parser.gen_help_msg(255),
+        testing::StrEq(
+            "sub_parser_container <arg-name> [-b|--bool] [-2|--second] "
+            "sub-parser [<sub-arg-name>] [-b|--bool] [-s|--string=<arg>]\n\n  "
+            "Optional Arguments:\n    sub-arg-name                    Sub arg "
+            "desc\n\n  Optional Options:\n    -b|--bool                       "
+            "Bool option.\n    -s|--string=<arg>               String "
+            "option.\n"));
 }
 
-TEST(parser, construct_empty_basic_parser_and_parse_unknown_arguments_throws) {
+TEST(parser, constructEmptyBasicParserAndParseUnknownArgumentsThrows) {
     constexpr const char* const argv[]{"unknown-argument", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     empty_basic_parser_t ebp;
@@ -219,8 +360,7 @@ TEST(parser, construct_empty_basic_parser_and_parse_unknown_arguments_throws) {
                  clapp::exception::clapp_exception_t);
 }
 
-TEST(parser,
-     construct_empty_basic_parser_and_parse_unknown_long_option_throws) {
+TEST(parser, constructEmptyBasicParserAndParseUnknownLongOptionThrows) {
     constexpr const char* const argv[]{"--long-option", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     empty_basic_parser_t ebp;
@@ -228,8 +368,7 @@ TEST(parser,
                  clapp::exception::option_exception_t);
 }
 
-TEST(parser,
-     construct_empty_basic_parser_and_parse_unknown_short_option_throws) {
+TEST(parser, constructEmptyBasicParserAndParseUnknownShortOptionThrows) {
     constexpr const char* const argv[]{"-s", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     empty_basic_parser_t ebp;
@@ -237,9 +376,7 @@ TEST(parser,
                  clapp::exception::option_exception_t);
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_and_parse_long_bool_option_with_param_throws) {
+TEST(parser, constructSimpleTestParserAndParseLongBoolOptionWithParamThrows) {
     constexpr const char* const argv[]{"--bool=param", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
@@ -247,8 +384,7 @@ TEST(
                  clapp::exception::option_param_exception_t);
 }
 
-TEST(parser,
-     construct_simple_test_parser_and_parse_short_option_with_param_throws) {
+TEST(parser, constructSimpleTestParserAndParseShortOptionWithParamThrows) {
     constexpr const char* const argv[]{"-b=param", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
@@ -256,9 +392,7 @@ TEST(parser,
                  clapp::exception::option_param_exception_t);
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_and_parse_long_int_option_without_param_throws) {
+TEST(parser, constructSimpleTestParserAndParseLongIntOptionWithoutParamThrows) {
     constexpr const char* const argv[]{"--int", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
@@ -266,9 +400,8 @@ TEST(
                  clapp::exception::option_param_exception_t);
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_and_parse_short_int_option_without_param_throws) {
+TEST(parser,
+     constructSimpleTestParserAndParseShortIntOptionWithoutParamThrows) {
     constexpr const char* const argv[]{"-i", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
@@ -276,9 +409,8 @@ TEST(
                  clapp::exception::option_param_exception_t);
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_and_parse_short_int_option_without_param_throws2) {
+TEST(parser,
+     constructSimpleTestParserAndParseShortIntOptionWithoutParamThrows2) {
     constexpr const char* const argv[]{"-ib", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
@@ -286,9 +418,8 @@ TEST(
                  clapp::exception::option_param_exception_t);
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_parse_without_argument_and_validate_recursive_throws) {
+TEST(parser,
+     constructSimpleTestParserParseWithoutArgumentAndValidateRecursiveThrows) {
     constexpr const char* const argv[]{nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
@@ -298,13 +429,14 @@ TEST(
                  clapp::exception::argument_exception_t);
 }
 
-TEST(parser,
-     construct_simple_test_parser_parse_argument_and_validate_recursive) {
+TEST(parser, constructSimpleTestParserParseArgumentAndValidateRecursive) {
     constexpr const char* const argv[]{"argument", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
-    ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.value(), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(ebp.int_option), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(ebp.string_arg), testing::Eq(true));
     ASSERT_THAT(ebp.string_arg.value(), testing::Eq("argument"));
@@ -315,12 +447,14 @@ TEST(parser,
 
 TEST(
     parser,
-    construct_simple_test_parser_parse_argument_and_short_option_without_params_and_validate_recursive) {
+    constructSimpleTestParserParseArgumentAndShortOptionWithoutParamsAndValidateRecursive) {
     constexpr const char* const argv[]{"-b", "arg", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
     ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.value(), testing::Eq(true));
     ASSERT_THAT(static_cast<bool>(ebp.int_option), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(ebp.string_arg), testing::Eq(true));
     ASSERT_THAT(ebp.string_arg.value(), testing::StrEq("arg"));
@@ -329,14 +463,15 @@ TEST(
     ASSERT_NO_THROW(ebp.validate_recursive());
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_parse_argument_and_long_option_with_param_and_validate) {
+TEST(parser,
+     constructSimpleTestParserParseArgumentAndLongOptionWithParamAndValidate) {
     constexpr const char* const argv[]{"--int", "123", "arg", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
-    ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.value(), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(ebp.int_option), testing::Eq(true));
     ASSERT_THAT(ebp.int_option.value(), testing::Eq(123));
     ASSERT_THAT(static_cast<bool>(ebp.string_arg), testing::Eq(true));
@@ -348,13 +483,15 @@ TEST(
 
 TEST(
     parser,
-    construct_simple_test_parser_parse_argument_variadic_argument_and_long_option_with_param_and_validate) {
+    constructSimpleTestParserParseArgumentVariadicArgumentAndLongOptionWithParamAndValidate) {
     constexpr const char* const argv[]{"--int=123", "arg", "varg0", "varg1",
                                        nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
-    ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.value(), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(ebp.int_option), testing::Eq(true));
     ASSERT_THAT(ebp.int_option.value(), testing::Eq(123));
     ASSERT_THAT(static_cast<bool>(ebp.string_arg), testing::Eq(true));
@@ -367,14 +504,13 @@ TEST(
     ASSERT_NO_THROW(ebp.validate_recursive());
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser_parse_argument_and_short_options_and_validate) {
+TEST(parser, constructSimpleTestParserParseArgumentAndShortOptionsAndValidate) {
     constexpr const char* const argv[]{"-bi=123", "arg", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
     ASSERT_THAT(static_cast<bool>(ebp.bool_option), testing::Eq(true));
+    ASSERT_THAT(ebp.bool_option.has_value(), testing::Eq(true));
     ASSERT_THAT(ebp.bool_option.value(), testing::Eq(true));
     ASSERT_THAT(static_cast<bool>(ebp.int_option), testing::Eq(true));
     ASSERT_THAT(ebp.int_option.value(), testing::Eq(123));
@@ -384,9 +520,7 @@ TEST(
     ASSERT_NO_THROW(ebp.validate_recursive());
 }
 
-TEST(
-    parser,
-    construct_simple_test_parser2_and_parse_long_count_option_with_param_throws) {
+TEST(parser, constructSimpleTestParser2AndParseLongCountOptionWithParamThrows) {
     constexpr const char* const argv[]{"--count=param", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser2_t ebp;
@@ -394,30 +528,31 @@ TEST(
                  clapp::option_param_exception_t);
 }
 
-TEST(parser,
-     construct_simple_test_parser2_parse_without_mandatory_option_throws) {
+TEST(parser, constructSimpleTestParser2ParseWithoutMandatoryOptionThrows) {
     constexpr const char* const argv[]{nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser2_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
-    ASSERT_THAT(static_cast<bool>(ebp.count_option), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(ebp.count_option), testing::Eq(true));
+    ASSERT_THAT(ebp.count_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(ebp.count_option.value(), testing::Eq(0));
     ASSERT_THROW(ebp.validate(), clapp::option_param_exception_t);
 }
 
-TEST(parser,
-     construct_simple_test_parser2_parse_option_without_param_and_validate) {
+TEST(parser, constructSimpleTestParser2ParseOptionWithoutParamAndValidate) {
     constexpr const char* const argv[]{"-c", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser2_t ebp;
     ASSERT_NO_THROW(ebp.parse(arg.cbegin(), arg.cend()));
     ASSERT_THAT(static_cast<bool>(ebp.count_option), testing::Eq(true));
+    ASSERT_THAT(ebp.count_option.has_value(), testing::Eq(true));
     ASSERT_THAT(ebp.count_option.value(), testing::Eq(1));
     ASSERT_NO_THROW(ebp.validate());
 }
 
 TEST(
     parser,
-    construct_simple_test_parser2_parse_option_without_param_optional_argument_and_validate) {
+    constructSimpleTestParser2ParseOptionWithoutParamOptionalArgumentAndValidate) {
     constexpr const char* const argv[]{"-c", "opt-arg", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     simple_test_parser2_t ebp;
@@ -429,7 +564,7 @@ TEST(
     ASSERT_NO_THROW(ebp.validate());
 }
 
-TEST(parser, construct_sub_parser_container_parse_subparser_and_validate) {
+TEST(parser, constructSubParserContainerParseSubparserAndValidate) {
     constexpr const char* const argv[]{"string-arg", "sub-parser", "-bs=param",
                                        nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
@@ -437,31 +572,41 @@ TEST(parser, construct_sub_parser_container_parse_subparser_and_validate) {
     ASSERT_NO_THROW(spc.parse(arg.cbegin(), arg.cend()));
     ASSERT_THAT(static_cast<bool>(spc.string_arg), testing::Eq(true));
     ASSERT_THAT(spc.string_arg.value(), testing::StrEq("string-arg"));
-    ASSERT_THAT(static_cast<bool>(spc.bool_option), testing::Eq(false));
-    ASSERT_THAT(static_cast<bool>(spc.bool_option2), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(spc.bool_option), testing::Eq(true));
+    ASSERT_THAT(spc.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(spc.bool_option.value(), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(spc.bool_option2), testing::Eq(true));
+    ASSERT_THAT(spc.bool_option2.has_value(), testing::Eq(true));
+    ASSERT_THAT(spc.bool_option2.value(), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(spc.sub_parser.bool_option),
                 testing::Eq(true));
     ASSERT_THAT(spc.sub_parser.bool_option.value(), testing::Eq(true));
+    ASSERT_THAT(spc.sub_parser.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(spc.sub_parser.bool_option.value(), testing::Eq(true));
     ASSERT_THAT(static_cast<bool>(spc.sub_parser.string_option),
                 testing::Eq(true));
     ASSERT_THAT(spc.sub_parser.string_option.value(), testing::StrEq("param"));
     ASSERT_NO_THROW(spc.validate());
 }
 
-TEST(parser, construct_sub_parser_container_parse_subparser_and_validate2) {
-    constexpr const char* const argv[]{"string-arg", "-b", "sub-parser", "-s",
-                                       "param",      "-2", nullptr};
+TEST(parser, constructSubParserContainerParseSubparserAndValidate2) {
+    constexpr const char* const argv[]{
+        "string-arg", "-b", "-2", "sub-parser", "-s", "param", nullptr};
     const clapp::parser::arg_t arg{parser_make_arg_t(argv)};
     sub_parser_container_t spc;
     ASSERT_NO_THROW(spc.parse(arg.cbegin(), arg.cend()));
     ASSERT_THAT(static_cast<bool>(spc.string_arg), testing::Eq(true));
     ASSERT_THAT(spc.string_arg.value(), testing::StrEq("string-arg"));
     ASSERT_THAT(static_cast<bool>(spc.bool_option), testing::Eq(true));
+    ASSERT_THAT(spc.bool_option.has_value(), testing::Eq(true));
     ASSERT_THAT(spc.bool_option.value(), testing::Eq(true));
     ASSERT_THAT(static_cast<bool>(spc.bool_option2), testing::Eq(true));
+    ASSERT_THAT(spc.bool_option2.has_value(), testing::Eq(true));
     ASSERT_THAT(spc.bool_option2.value(), testing::Eq(true));
     ASSERT_THAT(static_cast<bool>(spc.sub_parser.bool_option),
-                testing::Eq(false));
+                testing::Eq(true));
+    ASSERT_THAT(spc.sub_parser.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(spc.sub_parser.bool_option.value(), testing::Eq(false));
     ASSERT_THAT(static_cast<bool>(spc.sub_parser.string_option),
                 testing::Eq(true));
     ASSERT_THAT(spc.sub_parser.string_option.value(), testing::StrEq("param"));
diff --git a/tests/sub_parser.cpp b/tests/sub_parser.cpp
index d0e8a25f29bf207338bf2dabda063df8fe663080..4a51e85f0a7e0ddf286bbcd3ea648e5466aa5649 100644
--- a/tests/sub_parser.cpp
+++ b/tests/sub_parser.cpp
@@ -19,10 +19,31 @@ class empty_test_parser_t : public clapp::parser::basic_parser_t {
     using clapp::parser::basic_parser_t::get_sub_parsers;
 
     ~empty_test_parser_t() override;
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 empty_test_parser_t::~empty_test_parser_t() = default;
 
+[[nodiscard]] std::string empty_test_parser_t::gen_short_line_prefix() const {
+    return "empty-test-parser" + gen_short_line();
+}
+
+void empty_test_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t empty_test_parser_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
 class empty_sub_parser_t : public clapp::parser::basic_sub_parser_t {
    public:
     using clapp::parser::basic_sub_parser_t::basic_sub_parser_t;
@@ -44,15 +65,38 @@ class simple_test_sub_parser_t : public clapp::parser::basic_parser_t {
                                                "Count option."};
 
     ~simple_test_sub_parser_t() override;
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 simple_test_sub_parser_t::~simple_test_sub_parser_t() = default;
 
+[[nodiscard]] std::string simple_test_sub_parser_t::gen_short_line_prefix()
+    const {
+    return "simple-test-sub-parser" + gen_short_line();
+}
+
+void simple_test_sub_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t simple_test_sub_parser_t::get_max_option_string_size()
+    const {
+    return max_option_string_size;
+}
+
 class simple_sub_parser_t : public clapp::parser::basic_sub_parser_t {
    public:
     using clapp::parser::basic_sub_parser_t::basic_sub_parser_t;
-    clapp::option::bool_option_t bool_option{*this, "bool", 'b',
-                                             "Bool option."};
+    clapp::option::bool_option_t bool_option{
+        *this, "bool", 'b', "Bool option.",
+        basic_parser_t::purpose_t::mandatory};
 
     ~simple_sub_parser_t() override;
 };
@@ -66,11 +110,33 @@ class variadic_argument_test_sub_parser_t
         *this, "arg", "Arg"};
 
     ~variadic_argument_test_sub_parser_t() override;
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 variadic_argument_test_sub_parser_t::~variadic_argument_test_sub_parser_t() =
     default;
 
+[[nodiscard]] std::string
+variadic_argument_test_sub_parser_t::gen_short_line_prefix() const {
+    return "variadic-argument-test-sub-parser" + gen_short_line();
+}
+
+void variadic_argument_test_sub_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t
+variadic_argument_test_sub_parser_t::get_max_option_string_size() const {
+    return max_option_string_size;
+}
+
 class optional_argument_test_sub_parser_t
     : public clapp::parser::basic_parser_t {
    public:
@@ -78,12 +144,34 @@ class optional_argument_test_sub_parser_t
         *this, "arg", "Arg", clapp::basic_parser_t::purpose_t::optional};
 
     ~optional_argument_test_sub_parser_t() override;
+
+    [[nodiscard]] std::string gen_short_line_prefix() const override;
+    void set_max_option_string_size(std::size_t max_option_size) override;
+    [[nodiscard]] std::size_t get_max_option_string_size() const override;
+
+   private:
+    std::size_t max_option_string_size{0};
 };
 
 optional_argument_test_sub_parser_t::~optional_argument_test_sub_parser_t() =
     default;
 
-TEST(sub_parser, construct_empty_sub_parser_and_parse_empty_arguments) {
+[[nodiscard]] std::string
+optional_argument_test_sub_parser_t::gen_short_line_prefix() const {
+    return "optional-argument-test-sub-parser" + gen_short_line();
+}
+
+void optional_argument_test_sub_parser_t::set_max_option_string_size(
+    const std::size_t max_option_size) {
+    max_option_string_size = max_option_size;
+}
+
+[[nodiscard]] std::size_t
+optional_argument_test_sub_parser_t::get_max_option_string_size() const {
+    return max_option_string_size;
+}
+
+TEST(subParser, constructEmptySubParserAndParseEmptyArguments) {
     const std::string sub_parser{"sub"};
     const std::string description{"sub parser"};
 
@@ -107,7 +195,7 @@ TEST(sub_parser, construct_empty_sub_parser_and_parse_empty_arguments) {
     tp.parse(arg.cbegin(), arg.cend());
 }
 
-TEST(sub_parser, construct_simple_sub_parser_and_parse_sub_option) {
+TEST(subParser, constructSimpleSubParserAndParseSubOption) {
     const std::string sub_parser{"subbb"};
     const std::string description{"subbb parser"};
 
@@ -129,16 +217,18 @@ TEST(sub_parser, construct_simple_sub_parser_and_parse_sub_option) {
     ASSERT_THAT(static_cast<bool>(sub), testing::Eq(false));
     ASSERT_THAT(sub.get_sub_parser_name(), testing::StrEq(sub_parser));
 
-    ASSERT_THAT(static_cast<bool>(sub.bool_option), testing::Eq(false));
+    ASSERT_THAT(static_cast<bool>(sub.bool_option), testing::Eq(true));
+    ASSERT_THAT(sub.bool_option.has_value(), testing::Eq(true));
+    ASSERT_THAT(sub.bool_option.value(), testing::Eq(false));
     tp.parse(arg.cbegin(), arg.cend());
     ASSERT_THAT(static_cast<bool>(sub.bool_option), testing::Eq(true));
 }
 
-TEST(sub_parser, construct_simple_sub_parser_and_parse_base_option) {
+TEST(subParser, constructSimpleSubParserAndParseBaseOption) {
     const std::string sub_parser{"subbb"};
     const std::string description{"subbb parser"};
 
-    constexpr const char* const argv[]{"subbb", "--count", nullptr};
+    constexpr const char* const argv[]{"--count", "subbb", "-b", nullptr};
     const clapp::parser::arg_t arg{sub_parser_make_arg_t(argv)};
 
     simple_test_sub_parser_t tp;
@@ -161,69 +251,93 @@ TEST(sub_parser, construct_simple_sub_parser_and_parse_base_option) {
     ASSERT_THAT(tp.count_option.value(), testing::Eq(1));
 }
 
-TEST(sub_parser, construct_simple_sub_parser_and_ignore_main_option) {
-    const std::string sub_parser{"subbb"};
-    const std::string description{"subbb parser"};
-
-    constexpr const char* const argv[]{"subbb", "--count", nullptr};
-    const clapp::parser::arg_t arg{sub_parser_make_arg_t(argv)};
+TEST(subParser, constructSubParserWithSameNameThrows) {
+    const std::string sub_parser{"sub"};
+    const std::string description{"sub parser"};
 
     simple_test_sub_parser_t tp;
-    simple_sub_parser_t sub{tp, sub_parser, description, false};
-
-    simple_test_sub_parser_t::sub_parsers_map_t long_options{
-        tp.get_sub_parsers()};
-    simple_test_sub_parser_t::sub_parser_descriptions_vec_t descs{
-        tp.get_sub_parser_descriptions()};
-
-    ASSERT_THAT(descs.size(), testing::Eq(1));
-    ASSERT_THAT(descs[0].sub_parser_string, testing::StrEq(sub_parser));
-    ASSERT_THAT(descs[0].description, testing::StrEq(description));
+    simple_sub_parser_t sub{tp, sub_parser, description};
+    ASSERT_THROW((simple_sub_parser_t{tp, sub_parser, description}),
+                 clapp::exception::sub_parser_exception_t);
+}
 
-    ASSERT_THAT(static_cast<bool>(sub), testing::Eq(false));
-    ASSERT_THAT(sub.get_sub_parser_name(), testing::StrEq(sub_parser));
+TEST(subParser, constructSubParserWithVariadicArgumentsParserThrows) {
+    const std::string sub_parser{"sub"};
+    const std::string description{"sub parser"};
 
-    ASSERT_THAT(tp.count_option.value(), testing::Eq(0));
-    ASSERT_THROW(tp.parse(arg.cbegin(), arg.cend()),
-                 clapp::exception::option_exception_t);
-    ASSERT_THAT(tp.count_option.value(), testing::Eq(0));
-    ASSERT_NO_THROW(tp.validate_recursive());
+    variadic_argument_test_sub_parser_t tp;
+    ASSERT_THROW((simple_sub_parser_t{tp, sub_parser, description}),
+                 clapp::exception::sub_parser_exception_t);
 }
 
-TEST(sub_parser, construct_sub_parser_with_same_name_throws) {
+TEST(subParser, constructSubParserWithOptionalArgumentParserThrows) {
     const std::string sub_parser{"sub"};
     const std::string description{"sub parser"};
 
-    simple_test_sub_parser_t tp;
-    simple_sub_parser_t sub{tp, sub_parser, description, false};
-    ASSERT_THROW((simple_sub_parser_t{tp, sub_parser, description, false}),
+    optional_argument_test_sub_parser_t tp;
+    ASSERT_THROW((simple_sub_parser_t{tp, sub_parser, description}),
                  clapp::exception::sub_parser_exception_t);
 }
 
-TEST(sub_parser, construct_sub_parser_with_variadic_arguments_parser_throws) {
+TEST(subParser, constructSubParserAndGenHelpPrefix) {
     const std::string sub_parser{"sub"};
     const std::string description{"sub parser"};
 
-    variadic_argument_test_sub_parser_t tp;
-    ASSERT_THROW((simple_sub_parser_t{tp, sub_parser, description, false}),
-                 clapp::exception::sub_parser_exception_t);
+    empty_test_parser_t tp;
+    empty_sub_parser_t sub{tp, sub_parser, description};
+
+    ASSERT_THAT(sub.gen_short_line_prefix(),
+                testing::StrEq("empty-test-parser sub"));
 }
 
-TEST(sub_parser, construct_sub_parser_with_optional_argument_parser_throws) {
+TEST(subParser, constructSubParserIsActiveIsFalse) {
     const std::string sub_parser{"sub"};
     const std::string description{"sub parser"};
 
-    optional_argument_test_sub_parser_t tp;
-    ASSERT_THROW((simple_sub_parser_t{tp, sub_parser, description, false}),
-                 clapp::exception::sub_parser_exception_t);
+    empty_test_parser_t tp;
+    empty_sub_parser_t sub{tp, sub_parser, description};
+    ASSERT_THAT(sub.is_active(), testing::Eq(false));
 }
 
-TEST(parser, construct_sub_parser_and_gen_help_prefix) {
+TEST(subParser, constructSubParserAfterParsingSubBecomesActive) {
     const std::string sub_parser{"sub"};
     const std::string description{"sub parser"};
+    constexpr const char* const argv[]{"sub", nullptr};
+    const clapp::parser::arg_t arg{sub_parser_make_arg_t(argv)};
 
     empty_test_parser_t tp;
     empty_sub_parser_t sub{tp, sub_parser, description};
 
-    ASSERT_THAT(sub.gen_help_prefix(), testing::StrEq("Usage: \n sub"));
+    ASSERT_THAT(&tp.get_active_parser(), testing::Eq(&tp));
+    ASSERT_THAT(sub.is_active(), testing::Eq(false));
+
+    tp.parse(arg.cbegin(), arg.cend());
+    ASSERT_THAT(sub.is_active(), testing::Eq(true));
+    ASSERT_THAT(&tp.get_active_parser(), testing::Eq(&sub));
+}
+
+TEST(subParser, constructSubParserAndValidateRecursiveDoNotThrow) {
+    const std::string sub_parser{"sub"};
+    const std::string description{"sub parser"};
+    constexpr const char* const argv[]{"sub", "-b", nullptr};
+    const clapp::parser::arg_t arg{sub_parser_make_arg_t(argv)};
+
+    empty_test_parser_t tp;
+    simple_sub_parser_t sub{tp, sub_parser, description};
+
+    tp.parse(arg.cbegin(), arg.cend());
+    ASSERT_NO_THROW(tp.validate_recursive());
+}
+
+TEST(subParser, constructSubParserAndValidateRecursiveDoThrow) {
+    const std::string sub_parser{"sub"};
+    const std::string description{"sub parser"};
+    constexpr const char* const argv[]{"sub", nullptr};
+    const clapp::parser::arg_t arg{sub_parser_make_arg_t(argv)};
+
+    empty_test_parser_t tp;
+    simple_sub_parser_t sub{tp, sub_parser, description};
+
+    tp.parse(arg.cbegin(), arg.cend());
+    ASSERT_THROW(tp.validate_recursive(), clapp::clapp_exception_t);
 }
diff --git a/tests/value.cpp b/tests/value.cpp
index 8eb3072bfaa6fe969142ef5c636411baba351aec..14d40d6c36bf1928ee33e77e12d56c05770af426 100644
--- a/tests/value.cpp
+++ b/tests/value.cpp
@@ -2,33 +2,33 @@
 #include <clapp/value.h>
 #include <gmock/gmock.h>
 
-TEST(value, convert_value_string) {
+TEST(value, convertValueString) {
     ASSERT_THAT(clapp::value::convert_value<std::string>("aba"),
                 testing::Eq(std::string{"aba"}));
     ASSERT_THAT(clapp::value::convert_value<std::string>("abba"),
                 testing::Eq(std::string{"abba"}));
 }
 
-TEST(value, convert_value_path) {
+TEST(value, convertValuePath) {
     ASSERT_THAT(clapp::value::convert_value<clapp::fs::path>("/tmp/test"),
                 testing::Eq(clapp::fs::path{"/tmp/test"}));
 }
 
-TEST(value, convert_value_uint8_t) {
+TEST(value, convertValueUint8T) {
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("0"),
-                testing::Eq(std::uint8_t{0u}));
+                testing::Eq(std::uint8_t{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("100"),
-                testing::Eq(std::uint8_t{100u}));
+                testing::Eq(std::uint8_t{100U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("255"),
-                testing::Eq(std::uint8_t{255u}));
+                testing::Eq(std::uint8_t{255U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("2.555"),
-                testing::Eq(std::uint8_t{2}));
+                testing::Eq(std::uint8_t{2U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("0xab"),
-                testing::Eq(std::uint8_t{0xabu}));
+                testing::Eq(std::uint8_t{0xabU}));
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("0xff"),
-                testing::Eq(std::uint8_t{0xffu}));
+                testing::Eq(std::uint8_t{0xffU}));
     ASSERT_THAT(clapp::value::convert_value<std::uint8_t>("077"),
-                testing::Eq(std::uint8_t{077}));
+                testing::Eq(std::uint8_t{077U}));
     ASSERT_THROW(clapp::value::convert_value<std::uint8_t>("256"),
                  clapp::exception::out_of_range_t);
     ASSERT_THROW(clapp::value::convert_value<std::uint8_t>("-1"),
@@ -37,21 +37,21 @@ TEST(value, convert_value_uint8_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_uint16_t) {
+TEST(value, convertValueUint16T) {
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("0"),
-                testing::Eq(std::uint16_t{0u}));
+                testing::Eq(std::uint16_t{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("1000"),
-                testing::Eq(std::uint16_t{1000u}));
+                testing::Eq(std::uint16_t{1000U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("65535"),
-                testing::Eq(std::uint16_t{65535u}));
+                testing::Eq(std::uint16_t{65535U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("2222.555"),
-                testing::Eq(std::uint16_t{2222}));
+                testing::Eq(std::uint16_t{2222U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("0xffab"),
-                testing::Eq(std::uint16_t{0xffabu}));
+                testing::Eq(std::uint16_t{0xffabU}));
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("0xffff"),
-                testing::Eq(std::uint16_t{0xffffu}));
+                testing::Eq(std::uint16_t{0xffffU}));
     ASSERT_THAT(clapp::value::convert_value<std::uint16_t>("01234"),
-                testing::Eq(std::uint16_t{01234u}));
+                testing::Eq(std::uint16_t{01234U}));
     ASSERT_THROW(clapp::value::convert_value<std::uint16_t>("65536"),
                  clapp::exception::out_of_range_t);
     ASSERT_THROW(clapp::value::convert_value<std::uint16_t>("-100"),
@@ -60,19 +60,19 @@ TEST(value, convert_value_uint16_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_uint32_t) {
+TEST(value, convertValueUint32T) {
     ASSERT_THAT(clapp::value::convert_value<std::uint32_t>("0"),
-                testing::Eq(std::uint32_t{0u}));
+                testing::Eq(std::uint32_t{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint32_t>("10000"),
-                testing::Eq(std::uint32_t{10000u}));
+                testing::Eq(std::uint32_t{10000U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint32_t>("4294967295"),
-                testing::Eq(std::uint32_t{4294967295u}));
+                testing::Eq(std::uint32_t{4294967295U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint32_t>("0xffab"),
-                testing::Eq(std::uint32_t{0xffabu}));
+                testing::Eq(std::uint32_t{0xffabU}));
     ASSERT_THAT(clapp::value::convert_value<std::uint32_t>("0xffffffff"),
-                testing::Eq(std::uint32_t{0xffffffffu}));
+                testing::Eq(std::uint32_t{0xffffffffU}));
     ASSERT_THAT(clapp::value::convert_value<std::uint32_t>("0123456"),
-                testing::Eq(std::uint32_t{0123456u}));
+                testing::Eq(std::uint32_t{0123456U}));
     ASSERT_THROW(clapp::value::convert_value<std::uint32_t>("4294967296"),
                  clapp::exception::out_of_range_t);
     ASSERT_THROW(clapp::value::convert_value<std::uint32_t>("-10000"),
@@ -81,21 +81,21 @@ TEST(value, convert_value_uint32_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_uint64_t) {
+TEST(value, convertValueUint64T) {
     ASSERT_THAT(clapp::value::convert_value<std::uint64_t>("0"),
-                testing::Eq(std::uint64_t{0u}));
+                testing::Eq(std::uint64_t{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::uint64_t>("1000000"),
-                testing::Eq(std::uint64_t{1000000u}));
+                testing::Eq(std::uint64_t{1000000U}));
     ASSERT_THAT(
         clapp::value::convert_value<std::uint64_t>("18446744073709551615"),
-        testing::Eq(std::uint64_t{18446744073709551615ull}));
+        testing::Eq(std::uint64_t{18446744073709551615ULL}));
     ASSERT_THAT(clapp::value::convert_value<std::uint64_t>("0xffab"),
-                testing::Eq(std::uint64_t{0xffabu}));
+                testing::Eq(std::uint64_t{0xffabU}));
     ASSERT_THAT(
         clapp::value::convert_value<std::uint64_t>("0xffffffffffffffff"),
-        testing::Eq(std::uint64_t{0xffffffffffffffffull}));
+        testing::Eq(std::uint64_t{0xffffffffffffffffULL}));
     ASSERT_THAT(clapp::value::convert_value<std::uint64_t>("012345671234"),
-                testing::Eq(std::uint64_t{012345671234ull}));
+                testing::Eq(std::uint64_t{012345671234ULL}));
     ASSERT_THROW(
         clapp::value::convert_value<std::uint64_t>("18446744073709551616"),
         clapp::exception::out_of_range_t);
@@ -103,7 +103,7 @@ TEST(value, convert_value_uint64_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_int8_t) {
+TEST(value, convertValueInt8T) {
     ASSERT_THAT(clapp::value::convert_value<std::int8_t>("0"),
                 testing::Eq(std::int8_t{0}));
     ASSERT_THAT(clapp::value::convert_value<std::int8_t>("100"),
@@ -128,7 +128,7 @@ TEST(value, convert_value_int8_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_int16_t) {
+TEST(value, convertValueInt16T) {
     ASSERT_THAT(clapp::value::convert_value<std::int16_t>("0"),
                 testing::Eq(std::int16_t{0}));
     ASSERT_THAT(clapp::value::convert_value<std::int16_t>("10000"),
@@ -144,7 +144,7 @@ TEST(value, convert_value_int16_t) {
     ASSERT_THAT(clapp::value::convert_value<std::int16_t>("-0x7fff"),
                 testing::Eq(std::int16_t{-0x7fff}));
     ASSERT_THAT(clapp::value::convert_value<std::int16_t>("-01234"),
-                testing::Eq(std::int16_t{-01234ll}));
+                testing::Eq(std::int16_t{-01234LL}));
     ASSERT_THROW(clapp::value::convert_value<std::int16_t>("32768"),
                  clapp::exception::out_of_range_t);
     ASSERT_THROW(clapp::value::convert_value<std::int16_t>("-32769"),
@@ -153,7 +153,7 @@ TEST(value, convert_value_int16_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_int32_t) {
+TEST(value, convertValueInt32T) {
     ASSERT_THAT(clapp::value::convert_value<std::int32_t>("0"),
                 testing::Eq(std::int32_t{0}));
     ASSERT_THAT(clapp::value::convert_value<std::int32_t>("1000000"),
@@ -165,11 +165,11 @@ TEST(value, convert_value_int32_t) {
     ASSERT_THAT(clapp::value::convert_value<std::int32_t>("-2147483648"),
                 testing::Eq(std::int32_t{-2147483648}));
     ASSERT_THAT(clapp::value::convert_value<std::int32_t>("0xffab"),
-                testing::Eq(std::int32_t{0xffabu}));
+                testing::Eq(std::int32_t{0xffab}));
     ASSERT_THAT(clapp::value::convert_value<std::int32_t>("-0x3fffffff"),
                 testing::Eq(std::int32_t{-0x3fffffff}));
     ASSERT_THAT(clapp::value::convert_value<std::int32_t>("-0123456"),
-                testing::Eq(std::int32_t{-0123456ll}));
+                testing::Eq(std::int32_t{-0123456LL}));
     ASSERT_THROW(clapp::value::convert_value<std::int32_t>("2147483648"),
                  clapp::exception::out_of_range_t);
     ASSERT_THROW(clapp::value::convert_value<std::int32_t>("-2147483649"),
@@ -178,27 +178,27 @@ TEST(value, convert_value_int32_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_int64_t) {
+TEST(value, convertValueInt64T) {
     ASSERT_THAT(clapp::value::convert_value<std::int64_t>("0"),
                 testing::Eq(std::int64_t{0}));
     ASSERT_THAT(clapp::value::convert_value<std::int64_t>("10000000000"),
-                testing::Eq(std::int64_t{10000000000ll}));
+                testing::Eq(std::int64_t{10000000000LL}));
     ASSERT_THAT(
         clapp::value::convert_value<std::int64_t>("9223372036854775807"),
-        testing::Eq(std::int64_t{9223372036854775807ll}));
+        testing::Eq(std::int64_t{9223372036854775807LL}));
     ASSERT_THAT(
         clapp::value::convert_value<std::int64_t>("-9223372036854775807"),
-        testing::Eq(std::int64_t{-9223372036854775807ll}));
+        testing::Eq(std::int64_t{-9223372036854775807LL}));
     ASSERT_THAT(
         clapp::value::convert_value<std::int64_t>("-9223372036854775808"),
-        testing::Eq(std::int64_t{-9223372036854775807ll - 1ll}));
+        testing::Eq(std::int64_t{-9223372036854775807LL - 1LL}));
     ASSERT_THAT(clapp::value::convert_value<std::int64_t>("0x3fffffffffffff"),
                 testing::Eq(std::int64_t{0x3fffffffffffffLL}));
     ASSERT_THAT(
         clapp::value::convert_value<std::int64_t>("-0x3fffffffffffffff"),
         testing::Eq(std::int64_t{-0x3fffffffffffffffLL}));
     ASSERT_THAT(clapp::value::convert_value<std::int64_t>("-012345671234"),
-                testing::Eq(std::int64_t{-012345671234ll}));
+                testing::Eq(std::int64_t{-012345671234LL}));
     ASSERT_THROW(
         clapp::value::convert_value<std::int64_t>("9223372036854775808"),
         clapp::exception::out_of_range_t);
@@ -209,7 +209,7 @@ TEST(value, convert_value_int64_t) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_double) {
+TEST(value, convertValueDouble) {
     ASSERT_THAT(clapp::value::convert_value<double>("0"),
                 testing::Eq(double{0}));
     ASSERT_THAT(clapp::value::convert_value<double>("10000000000"),
@@ -230,67 +230,67 @@ TEST(value, convert_value_double) {
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_float) {
+TEST(value, convertValueFloat) {
     ASSERT_THAT(clapp::value::convert_value<float>("0"),
-                testing::Eq(float{0.f}));
+                testing::Eq(float{0.F}));
     ASSERT_THAT(clapp::value::convert_value<float>("10000000000"),
-                testing::Eq(float{10000000000.f}));
+                testing::Eq(float{10000000000.F}));
     ASSERT_THAT(clapp::value::convert_value<float>("0.125"),
-                testing::Eq(float{0.125f}));
+                testing::Eq(float{0.125F}));
     ASSERT_THAT(clapp::value::convert_value<float>("5e-1"),
-                testing::Eq(float{.5f}));
+                testing::Eq(float{.5F}));
     ASSERT_THROW(clapp::value::convert_value<float>("10e-600"),
                  clapp::exception::out_of_range_t);
     ASSERT_THROW(clapp::value::convert_value<float>("z"),
                  clapp::exception::invalid_value_t);
 }
 
-TEST(value, convert_value_chrono_nanoseconds) {
+TEST(value, convertValueChronoNanoseconds) {
     ASSERT_THAT(clapp::value::convert_value<std::chrono::nanoseconds>("0"),
-                testing::Eq(std::chrono::nanoseconds{0u}));
+                testing::Eq(std::chrono::nanoseconds{0U}));
     ASSERT_THAT(
         clapp::value::convert_value<std::chrono::nanoseconds>("1000000"),
-        testing::Eq(std::chrono::nanoseconds{1000000u}));
+        testing::Eq(std::chrono::nanoseconds{1000000U}));
 }
 
-TEST(value, convert_value_chrono_microseconds) {
+TEST(value, convertValueChronoMicroseconds) {
     ASSERT_THAT(clapp::value::convert_value<std::chrono::microseconds>("0"),
-                testing::Eq(std::chrono::microseconds{0u}));
+                testing::Eq(std::chrono::microseconds{0U}));
     ASSERT_THAT(
         clapp::value::convert_value<std::chrono::microseconds>("1000000"),
-        testing::Eq(std::chrono::microseconds{1000000u}));
+        testing::Eq(std::chrono::microseconds{1000000U}));
 }
 
-TEST(value, convert_value_chrono_milliseconds) {
+TEST(value, convertValueChronoMilliseconds) {
     ASSERT_THAT(clapp::value::convert_value<std::chrono::milliseconds>("0"),
-                testing::Eq(std::chrono::milliseconds{0u}));
+                testing::Eq(std::chrono::milliseconds{0U}));
     ASSERT_THAT(
         clapp::value::convert_value<std::chrono::milliseconds>("1000000"),
-        testing::Eq(std::chrono::milliseconds{1000000u}));
+        testing::Eq(std::chrono::milliseconds{1000000U}));
 }
 
-TEST(value, convert_value_chrono_seconds) {
+TEST(value, convertValueChronoSeconds) {
     ASSERT_THAT(clapp::value::convert_value<std::chrono::seconds>("0"),
-                testing::Eq(std::chrono::seconds{0u}));
+                testing::Eq(std::chrono::seconds{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::chrono::seconds>("1000000"),
-                testing::Eq(std::chrono::seconds{1000000u}));
+                testing::Eq(std::chrono::seconds{1000000U}));
 }
 
-TEST(value, convert_value_chrono_minutes) {
+TEST(value, convertValueChronoMinutes) {
     ASSERT_THAT(clapp::value::convert_value<std::chrono::minutes>("0"),
-                testing::Eq(std::chrono::minutes{0u}));
+                testing::Eq(std::chrono::minutes{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::chrono::minutes>("1000000"),
-                testing::Eq(std::chrono::minutes{1000000u}));
+                testing::Eq(std::chrono::minutes{1000000U}));
 }
 
-TEST(value, convert_value_chrono_hours) {
+TEST(value, convertValueChronoHours) {
     ASSERT_THAT(clapp::value::convert_value<std::chrono::hours>("0"),
-                testing::Eq(std::chrono::hours{0u}));
+                testing::Eq(std::chrono::hours{0U}));
     ASSERT_THAT(clapp::value::convert_value<std::chrono::hours>("1000000"),
-                testing::Eq(std::chrono::hours{1000000u}));
+                testing::Eq(std::chrono::hours{1000000U}));
 }
 
-TEST(value, get_chrono_postfix) {
+TEST(value, getChronoPostfix) {
     ASSERT_THAT(clapp::value::get_chrono_postfix<std::chrono::nanoseconds>(),
                 testing::StrEq("ns"));
     ASSERT_THAT(clapp::value::get_chrono_postfix<std::chrono::microseconds>(),
@@ -305,7 +305,7 @@ TEST(value, get_chrono_postfix) {
                 testing::StrEq("h"));
 }
 
-TEST(value, default_value_uint8_t) {
+TEST(value, defaultValueUint8T) {
     constexpr std::uint8_t value{10};
     clapp::value::default_value_t<std::uint8_t> dv{value};
     std::stringstream ss;
@@ -314,7 +314,7 @@ TEST(value, default_value_uint8_t) {
     ASSERT_THAT(dv.default_value(), testing::Eq(std::uint8_t{value}));
 }
 
-TEST(value, default_value_int8_t) {
+TEST(value, defaultValueInt8T) {
     constexpr std::int8_t value{-10};
     clapp::value::default_value_t<std::int8_t> dv{value};
     std::stringstream ss;
@@ -323,7 +323,7 @@ TEST(value, default_value_int8_t) {
     ASSERT_THAT(dv.default_value(), testing::Eq(std::int8_t{value}));
 }
 
-TEST(value, default_value_int32_t) {
+TEST(value, defaultValueInt32T) {
     constexpr std::int32_t value{100'000};
     clapp::value::default_value_t<std::int32_t> dv{value};
     std::stringstream ss;
@@ -332,7 +332,7 @@ TEST(value, default_value_int32_t) {
     ASSERT_THAT(dv.default_value(), testing::Eq(value));
 }
 
-TEST(value, default_value_string) {
+TEST(value, defaultValueString) {
     const std::string value{"value"};
     clapp::value::default_value_t<std::string> dv{value};
     std::stringstream ss;
@@ -341,7 +341,7 @@ TEST(value, default_value_string) {
     ASSERT_THAT(dv.default_value(), testing::Eq(value));
 }
 
-TEST(value, default_value_milliseconds) {
+TEST(value, defaultValueMilliseconds) {
     constexpr std::uint64_t value{30};
     clapp::value::default_value_t<std::chrono::milliseconds> dv{
         std::chrono::milliseconds{value}};
@@ -352,7 +352,7 @@ TEST(value, default_value_milliseconds) {
                 testing::Eq(std::chrono::milliseconds{value}));
 }
 
-TEST(value, min_max_value_uint8_t) {
+TEST(value, minMaxValueUint8T) {
     constexpr std::uint8_t min{10};
     constexpr std::uint8_t max{50};
     clapp::value::min_max_value_t<std::uint8_t> mmv{min, max};
@@ -367,7 +367,7 @@ TEST(value, min_max_value_uint8_t) {
     ASSERT_THROW(mmv.validate(55, "option"), clapp::exception::out_of_range_t);
 }
 
-TEST(value, min_max_value_int32_t) {
+TEST(value, minMaxValueInt32T) {
     constexpr std::int32_t min{-1024};
     constexpr std::int32_t max{50};
     clapp::value::min_max_value_t<std::int32_t> mmv{min, max};
@@ -382,9 +382,10 @@ TEST(value, min_max_value_int32_t) {
     ASSERT_THROW(mmv.validate(55, "option"), clapp::exception::out_of_range_t);
 }
 
-TEST(value, min_max_value_double_t) {
+TEST(value, minMaxValueDoubleT) {
     const double min{100.};
     const double max{200.5};
+    const double above{max + 0.1};
     clapp::value::min_max_value_t<double> mmv{min, max};
     std::stringstream ss;
     ss << "constraint: [" << min << "," << max << "]";
@@ -393,11 +394,11 @@ TEST(value, min_max_value_double_t) {
     EXPECT_NO_THROW(mmv.validate(max, "option"));
     EXPECT_NO_THROW(mmv.validate(130, "option"));
     ASSERT_THROW(mmv.validate(5, "option"), clapp::exception::out_of_range_t);
-    ASSERT_THROW(mmv.validate(200.6, "option"),
+    ASSERT_THROW(mmv.validate(above, "option"),
                  clapp::exception::out_of_range_t);
 }
 
-TEST(value, min_max_value_milliseconds_t) {
+TEST(value, minMaxValueMillisecondsT) {
     const std::chrono::milliseconds min{std::chrono::milliseconds{100}};
     const std::chrono::milliseconds max{std::chrono::milliseconds{200}};
     clapp::value::min_max_value_t<std::chrono::milliseconds> mmv{min, max};
@@ -413,7 +414,7 @@ TEST(value, min_max_value_milliseconds_t) {
                  clapp::exception::out_of_range_t);
 }
 
-TEST(value, path_exists_t) {
+TEST(value, pathExistsT) {
     clapp::value::path_exists_t pe;
     ASSERT_THAT(pe.append_restriction_text(), testing::StrEq("existing path"));
     EXPECT_NO_THROW(pe.validate(clapp::fs::path{"/tmp"}, "option"));
@@ -422,7 +423,7 @@ TEST(value, path_exists_t) {
         clapp::exception::path_does_not_exist_t);
 }
 
-TEST(value, found_func_t) {
+TEST(value, foundFuncT) {
     std::stringstream ss;
     clapp::value::found_func_t ff{[&ss]() { ss << "called func"; }};
     ff.found();