[med-svn] [Git][med-team/argh][upstream] New upstream version 1.3.2+ds

Étienne Mollier (@emollier) gitlab at salsa.debian.org
Sun May 15 12:50:03 BST 2022



Étienne Mollier pushed to branch upstream at Debian Med / argh


Commits:
366ab582 by Étienne Mollier at 2022-05-15T13:26:08+02:00
New upstream version 1.3.2+ds
- - - - -


4 changed files:

- CMakeLists.txt
- README.md
- argh.h
- argh_tests.cpp


Changes:

=====================================
CMakeLists.txt
=====================================
@@ -1,46 +1,54 @@
-project(argh)
 cmake_minimum_required(VERSION 3.1)
 
-set (CMAKE_CXX_STANDARD 11)
+project(argh)
+
+set(CMAKE_CXX_STANDARD 11)
 
-option(BUILD_TESTS "Build tests. Uncheck for install only runs" ON)
-option(BUILD_EXAMPLES "Build examples. Uncheck for install only runs" ON)
+# Check if argh is being used directly or via add_subdirectory
+set(ARGH_MASTER_PROJECT OFF)
+if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+  set(ARGH_MASTER_PROJECT ON)
+endif()
+
+option(BUILD_TESTS "Build tests. Uncheck for install only runs"
+       ${ARGH_MASTER_PROJECT})
+option(BUILD_EXAMPLES "Build examples. Uncheck for install only runs"
+       ${ARGH_MASTER_PROJECT})
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "(Clang|GNU)")
+	list(APPEND flags "-Wall" "-Wextra" "-Wshadow" "-Wnon-virtual-dtor" "-pedantic")
+elseif(MSVC)
+	list(APPEND flags "/W4" "/WX")
+endif()
 
 if(BUILD_EXAMPLES)
 	add_executable(argh_example example.cpp)
+	target_compile_options(argh_example PRIVATE ${flags})
 endif()
 if(BUILD_TESTS)
 	add_executable(argh_tests   argh_tests.cpp)
+	target_compile_options(argh_tests PRIVATE ${flags})
+	set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT argh_tests)
 endif()
 
 add_library(argh INTERFACE)
 target_include_directories(argh INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> $<INSTALL_INTERFACE:include>)
 
-set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT argh_tests)
+if(ARGH_MASTER_PROJECT)
+	install(TARGETS argh EXPORT arghTargets)
 
-if(BUILD_EXAMPLES OR BUILD_TESTS)
-	if(UNIX OR CMAKE_COMPILER_IS_GNUCXX)
-		add_definitions("-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic")
-	else(MSVC)
-		add_definitions("/W4 /WX")
-	endif()
-endif()
-
-install(TARGETS argh EXPORT arghTargets)
-
-if(CMAKE_SYSTEM_NAME STREQUAL Linux)
-# this might be a bit too restrictive, since for other (BSD, ...) this might apply also
-# but this can be fixed later in extra pull requests from people on the platform
 	include(GNUInstallDirs)
 	install(FILES "${CMAKE_CURRENT_LIST_DIR}/argh.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
 	install(FILES "${CMAKE_CURRENT_LIST_DIR}/LICENSE" DESTINATION ${CMAKE_INSTALL_DOCDIR})
 	install(FILES "${CMAKE_CURRENT_LIST_DIR}/README.md" DESTINATION ${CMAKE_INSTALL_DOCDIR})
-	install(FILES argh-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/argh)
-	install(EXPORT arghTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/argh)
-else()
-	install(FILES "${CMAKE_CURRENT_LIST_DIR}/argh.h" DESTINATION include)
-	install(FILES "${CMAKE_CURRENT_LIST_DIR}/LICENSE" DESTINATION license)
-	install(FILES "${CMAKE_CURRENT_LIST_DIR}/README.md" DESTINATION .)
-	install(FILES argh-config.cmake DESTINATION CMake)
-	install(EXPORT arghTargets DESTINATION CMake)
+
+	if(CMAKE_SYSTEM_NAME STREQUAL Linux)
+	# this might be a bit too restrictive, since for other (BSD, ...) this might apply also
+	# but this can be fixed later in extra pull requests from people on the platform
+		install(FILES argh-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/argh)
+		install(EXPORT arghTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/argh)
+	else()
+		install(FILES argh-config.cmake DESTINATION CMake)
+		install(EXPORT arghTargets DESTINATION CMake)
+	endif()
 endif()


=====================================
README.md
=====================================
@@ -30,6 +30,10 @@ int main(int, char* argv[])
     return EXIT_SUCCESS;
 }
 ```
+#### TL;DR Videos 
+- [Arguments over Arguments - Adi Shavit - Core C++ 2019](https://youtu.be/hCbEHzDvLno)
+- [Arguments over Arguments, but you already know this... - Adi Shavit - CppCon 2019](https://youtu.be/KkjKkGuQUqU)
+
 ## Philosophy
 
 Contrary to many alternatives, `argh` takes a minimalist *laissez-faire* approach, very suitable for fuss-less prototyping with the following rules:
@@ -151,43 +155,49 @@ for (auto& param : cmdl.params())
 By default, options are assumed to be boolean flags. 
 When this is not what you want, there are several ways to specify when an option is a parameter with an associated value.  
 
-Specify **`PREFER_PARAM_FOR_UNREG_OPTION`** mode to interpret *any* `<option> <non-option>` as `<parameter-name> <parameter-value>`:
-```cpp
-using namespace argh;
-auto cmdl = parser(argc, argv, parser::PREFER_PARAM_FOR_UNREG_OPTION);
+ 1. Specify **`PREFER_PARAM_FOR_UNREG_OPTION`** mode to interpret *any* `<option> <non-option>` as `<parameter-name> <parameter-value>`:
+    ```cpp
+    using namespace argh;
+    auto cmdl = parser(argc, argv, parser::PREFER_PARAM_FOR_UNREG_OPTION);
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-cout << cmdl("--threshold").str() << '\n';
-```
-Pre-register an expected parameter name with `add_param()` (before calling `parse()`):
-```cpp
-argh::parser cmdl;
-cmdl.add_param("threshold"); // pre-register "threshold" as a param: name + value
-cmdl.parse(argc, argv);
-cout << cmdl("threshold").str() << '\n';
-```
-You can also *batch* pre-register multiple options as parameters with `add_params({ ... })`:
-```cpp
-argh::parser cmdl;
-cmdl.add_params({ "-t", "--threshold", "-s", "--scale" }); // batch pre-register multiple params: name + value
-cmdl.parse(argc, argv);
-cout << cmdl("threshold").str() << '\n';
-```
-Since pre-registration has to be done *before* parsing, we might as well just use the ctor:
-```cpp
-argh::parser cmdl({ "-t", "--threshold", "-s", "--scale" }); // batch pre-register multiple params: name + value
-cmdl.parse(argc, argv);
-cout << cmdl("threshold").str() << '\n';
-```
-Use a `=` (with no spaces around it) within the option when *calling* the app:
-```cpp
->> my_app --threshold=42
-42
-```
-
+    cout << cmdl("--threshold").str() << '\n';
+    ```
+    
+ 2. Pre-register an expected parameter name with `add_param()` (before calling `parse()`):
+    ```cpp
+    argh::parser cmdl;
+    cmdl.add_param("threshold"); // pre-register "threshold" as a param: name + value
+    cmdl.parse(argc, argv);
+    cout << cmdl("threshold").str() << '\n';
+    ```
+    You may also *batch* pre-register multiple options as parameters with `add_params({ ... })`:
+    ```cpp
+    argh::parser cmdl;
+    cmdl.add_params({ "-t", "--threshold", "-s", "--scale" }); // batch pre-register multiple params: name + value
+    cmdl.parse(argc, argv);
+    cout << cmdl("threshold").str() << '\n';
+    ```
+    _Unregistered_ options will default to boolean flags.
+    
+ 3. Since pre-registration has to be done *before* parsing, we might as well just use the ctor:
+    ```cpp
+    argh::parser cmdl({ "-t", "--threshold", "-s", "--scale" }); // batch pre-register multiple params: name + value
+    cmdl.parse(argc, argv);
+    cout << cmdl("threshold").str() << '\n';
+    ```
+    
+ 4. Use a `=` with no spaces around it within the option when *calling* the app:
+    ```cpp
+    >> my_app --threshold=42
+    42
+    ```
+    This will automatically be interpreted as a named parameter-value pair. 
+    
+    
 ### Tips
 - By default, arguments of the form `--<name>=<value>` (with no spaces, one or more dashes), e.g. `--answer=42`, will be parsed as `<parameter-name> <parameter-value>`.
 To disable this specify the **`NO_SPLIT_ON_EQUALSIGN`** mode.
-- Specifying the **`SINGLE_DASH_IS_MULTIFLAG`** mode will split a single-hyphen argument into multiple single-character flags (as is common in various POSIX tools).
+- Specifying the **`SINGLE_DASH_IS_MULTIFLAG`** mode, a.k.a _Compound Arguments_, will split a single-hyphen argument into multiple single-character flags (as is common in various POSIX tools).
 - When using **`SINGLE_DASH_IS_MULTIFLAG`**, you can still pre-register the last character as a param with the value, such that if we pre-register `f` as a param, `>> myapp -xvf 42` will be parsed with two boolean flags `x` and `v` and a one param `f`=`42`.
 - When parsing parameter values as strings that may contain spaces (e.g. `--config="C:\Folder\With Space\Config.ini"`), prefer using `.str()` instead of `>>` to avoid the default automatic whitespace input stream tokenization:  
 `cout << cmdl({ "-c", "--config" }).str()`.
@@ -220,7 +230,7 @@ Parse the command line using either
   `parser(argv);`
 
 ### Special Parsing Modes
-Extra flexibility can be added be specifying parsing modes:
+Extra flexibility can be added by specifying parsing modes:
 - **`NO_SPLIT_ON_EQUALSIGN`**:
    By default, an option of the form `--pi=22/7` will be parsed as a *parameter* `pi` with an associated value `"22/7"`.
    By setting this mode, it will be not be broken at the `=`.
@@ -232,7 +242,7 @@ Extra flexibility can be added be specifying parsing modes:
   Interpret `<option> <non-option>` as `<parameter-name> <parameter-value>`.
   e.g. `myapp --gamma 2.2` will have `gamma` as a parameter with the value "2.2".
 - **`SINGLE_DASH_IS_MULTIFLAG`**:
-  Splits an option with a *single* dash into separate boolean flags, one for each letter.
+  Splits an option with a *single* dash into separate boolean flags, one for each letter (a.k.a _Compound Arguments_).
   e.g. in this mode, `-xvf` will be parsed as 3 separate flags: `x`, `v`, `f`.
 
 ### Argument Access
@@ -313,4 +323,6 @@ If you take `argh` as a submodule, then the visible target is `//:argh`.
 
 ## Colophon
 
-I ❤ your feedback. If you found Argh! useful - do Tweet about it to let [me](https://twitter.com/AdiShavit) know. If you found it lacking, please post an [issue](https://github.com/adishavit/argh/issues).
+I ❤ your feedback.  
+If you found Argh! useful - do Tweet about it to let [me](https://twitter.com/AdiShavit) know.  
+If you found it lacking, please post an [issue](https://github.com/adishavit/argh/issues).


=====================================
argh.h
=====================================
@@ -2,6 +2,7 @@
 
 #include <algorithm>
 #include <sstream>
+#include <limits>
 #include <string>
 #include <vector>
 #include <set>
@@ -57,9 +58,9 @@ namespace argh
 
       std::stringbuf* rdbuf() const { return stream_.rdbuf(); }
 
-      // Check the state of the stream. 
+      // Check the state of the stream.
       // False when the most recent stream operation failed
-      operator bool() const { return !!stream_; }
+      explicit operator bool() const { return !!stream_; }
 
       ~stringstream_proxy() = default;
    private:
@@ -172,8 +173,13 @@ namespace argh
 
    inline void parser::parse(int argc, const char* const argv[], int mode /*= PREFER_FLAG_FOR_UNREG_OPTION*/)
    {
+      // clear out possible previous parsing remnants
+      flags_.clear();
+      params_.clear();
+      pos_args_.clear();
+
       // convert to strings
-      args_.resize(argc);
+      args_.resize(static_cast<decltype(args_)::size_type>(argc));
       std::transform(argv, argv + argc, args_.begin(), [](const char* const arg) { return arg;  });
 
       // parse line
@@ -202,8 +208,8 @@ namespace argh
             argh::parser::SINGLE_DASH_IS_MULTIFLAG & mode && // multi-flag mode
             !is_param(name))                                  // unregistered
          {
-            std::string keep_param; 
-            
+            std::string keep_param;
+
             if (!name.empty() && is_param(std::string(1ul, name.back()))) // last char is param
             {
                keep_param += name.back();
@@ -235,7 +241,7 @@ namespace argh
 
          // if 'name' is a pre-registered option, then the next arg cannot be a free parameter to it is skipped
          // otherwise we have 2 modes:
-         // PREFER_FLAG_FOR_UNREG_OPTION: a non-registered 'name' is determined a flag. 
+         // PREFER_FLAG_FOR_UNREG_OPTION: a non-registered 'name' is determined a flag.
          //                               The following value (the next arg) will be a free parameter.
          //
          // PREFER_PARAM_FOR_UNREG_OPTION: a non-registered 'name' is determined a parameter, the next arg
@@ -256,7 +262,7 @@ namespace argh
          {
             flags_.emplace(name);
          }
-      };
+      }
    }
 
    //////////////////////////////////////////////////////////////////////////
@@ -367,6 +373,7 @@ namespace argh
          return string_stream(optIt->second);
 
       std::ostringstream ostr;
+      ostr.precision(std::numeric_limits<long double>::max_digits10);
       ostr << def_val;
       return string_stream(ostr.str()); // use default
    }
@@ -382,8 +389,9 @@ namespace argh
          auto optIt = params_.find(trim_leading_dashes(name));
          if (params_.end() != optIt)
             return string_stream(optIt->second);
-      }      
+      }
       std::ostringstream ostr;
+      ostr.precision(std::numeric_limits<long double>::max_digits10);
       ostr << def_val;
       return string_stream(ostr.str()); // use default
    }
@@ -406,6 +414,7 @@ namespace argh
       if (pos_args_.size() <= ind)
       {
          std::ostringstream ostr;
+         ostr.precision(std::numeric_limits<long double>::max_digits10);
          ostr << def_val;
          return string_stream(ostr.str());
       }
@@ -428,5 +437,3 @@ namespace argh
          registeredParams_.insert(trim_leading_dashes(name));
    }
 }
-
-


=====================================
argh_tests.cpp
=====================================
@@ -220,6 +220,19 @@ TEST_CASE("Test default value")
     val = -1;
     CHECK(!(cmdl("c", "bad-default") >> val));
     CHECK((-1 == val || 0 == val));
+
+    double pi     = 3.1415926535897932384626433832795028841971693993751058209749445;
+    double pi_val = 0;
+    CHECK((cmdl({"-pi, --archimedes-constant"}, pi) >> pi_val));
+    CHECK(pi == pi_val);
+
+    pi_val = 0;
+    CHECK((cmdl("-pi", pi) >> pi_val));
+    CHECK(pi == pi_val);
+
+    pi_val = 0;
+    CHECK((cmdl(argc + 1, pi) >> pi_val));
+    CHECK(pi == pi_val);
 }
 
 TEST_CASE("Leading dashed are stripped")
@@ -412,21 +425,21 @@ TEST_CASE("Handles const char versions as expected")
       CHECK(2 == cmdl.flags().size());
    }
    {    
-      char* argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
+      const char* argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
       int argc = sizeof(argv) / sizeof(argv[0]);
       auto cmdl = parser(argc, argv);
       CHECK(5 == cmdl.pos_args().size());
       CHECK(2 == cmdl.flags().size());
    }
    {
-      char * const argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
+      const char* const argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
       int argc = sizeof(argv) / sizeof(argv[0]);
       auto cmdl = parser(argc, argv);
       CHECK(5 == cmdl.pos_args().size());
       CHECK(2 == cmdl.flags().size());
    }
    {
-      char const* const argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
+      const char* const argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
       int argc = sizeof(argv) / sizeof(argv[0]);
       auto cmdl = parser(argc, argv);
       CHECK(5 == cmdl.pos_args().size());
@@ -441,22 +454,22 @@ void test(int argc, T&& argv)
    auto cmdl = parser(argc, argv);
    CHECK(5 == cmdl.pos_args().size());
    CHECK(2 == cmdl.flags().size());
-};
+}
 
 
 TEST_CASE("Handles char** const versions as expected")
 {
-   char* argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
+   const char* argv[] = { "0", "-a", "1", "-b", "2", "3", "4" };
    int argc = sizeof(argv) / sizeof(argv[0]);
 
    char const * const * const argvp_ccc = argv;
 
    char const * const *       argvp_cc0 = argv;
-   char       * const * const argvp_cc1 = argv;
+   char const * const * const argvp_cc1 = argv;
 // char const *       * const argvp_cc2 = argv;
 // const char *       *       argvp_c0  = argv;
-   char       * const *       argvp_c1  = argv;
-   char       *       * const argvp_c2  = argv;
+   char const * const *       argvp_c1  = argv;
+   char const *       * const argvp_c2  = argv;
 
    test(argc, argvp_ccc);
 
@@ -764,3 +777,18 @@ TEST_CASE("Test size() member function")
       CHECK(cmdl.flags().size() == cmdl.size());
    }
 }
+
+TEST_CASE("Test parse(...) idempotence") {
+    const char* argv_1[] = { "-a", "b", "-c=10", "d", "-f"};
+    const char* argv_2[] = { "-a", "b", "-d=c" };
+    int argc_1 = sizeof(argv_1) / sizeof(argv_1[0]);
+    int argc_2 = sizeof(argv_2) / sizeof(argv_2[0]);
+
+    parser cmdl(argc_1, argv_1);
+    cmdl.parse(argc_2, argv_2);
+
+    CHECK(std::multiset<std::string>{ "a" } == cmdl.flags());
+    CHECK(std::vector<std::string>{ "b" } == cmdl.pos_args());
+    CHECK(std::map<std::string, std::string>{ { "d", "c" } } == cmdl.params());
+}
+



View it on GitLab: https://salsa.debian.org/med-team/argh/-/commit/366ab5825ba4f7e39e57a48700542aef581e0145

-- 
View it on GitLab: https://salsa.debian.org/med-team/argh/-/commit/366ab5825ba4f7e39e57a48700542aef581e0145
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20220515/4fd1b148/attachment-0001.htm>


More information about the debian-med-commit mailing list