From 7386d74c8cf39a01a91e8b8fb25807ffaee42cef Mon Sep 17 00:00:00 2001 From: Aivars Kalvans Date: Tue, 6 Mar 2018 01:21:08 +0200 Subject: [PATCH 1/4] Opt values can start with a dash (-) now --- include/clara.hpp | 16 +++++++++++++++- single_include/clara.hpp | 24 ++++++++++++++++++++---- src/ClaraTests.cpp | 14 ++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/include/clara.hpp b/include/clara.hpp index 13a7981..ded156b 100644 --- a/include/clara.hpp +++ b/include/clara.hpp @@ -157,6 +157,20 @@ namespace detail { } return *this; } + + void fetchArgument() { + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); + } else { + if( it != itEnd ) + ++it; + + m_tokenBuffer.resize( 0 ); + + if( it != itEnd ) + m_tokenBuffer.push_back( { TokenType::Argument, *it } ); + } + } }; @@ -663,7 +677,7 @@ namespace detail { if( result.value() == ParseResultType::ShortCircuitAll ) return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { - ++remainingTokens; + remainingTokens.fetchArgument(); if( !remainingTokens ) return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; diff --git a/single_include/clara.hpp b/single_include/clara.hpp index aa429e7..bdf62ce 100644 --- a/single_include/clara.hpp +++ b/single_include/clara.hpp @@ -370,7 +370,7 @@ namespace detail { template struct UnaryLambdaTraits { static const bool isValid = true; - using ArgType = typename std::remove_const::type>::type;; + using ArgType = typename std::remove_const::type>::type; using ReturnType = ReturnT; }; @@ -488,6 +488,20 @@ namespace detail { } return *this; } + + void fetchArgument() { + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); + } else { + if( it != itEnd ) + ++it; + + m_tokenBuffer.resize( 0 ); + + if( it != itEnd ) + m_tokenBuffer.push_back( { TokenType::Argument, *it } ); + } + } }; @@ -535,7 +549,7 @@ namespace detail { return *this; } - ~ResultValueBase() { + ~ResultValueBase() override { if( m_type == Ok ) m_value.~T(); } @@ -573,7 +587,7 @@ namespace detail { auto errorMessage() const -> std::string { return m_errorMessage; } protected: - virtual void enforceOk() const { + void enforceOk() const override { // !TBD: If no exceptions, std::terminate here or something switch( m_type ) { case ResultBase::LogicError: @@ -994,7 +1008,7 @@ namespace detail { if( result.value() == ParseResultType::ShortCircuitAll ) return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { - ++remainingTokens; + remainingTokens.fetchArgument(); if( !remainingTokens ) return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; @@ -1116,6 +1130,8 @@ namespace detail { for( auto const &cols : rows ) optWidth = (std::max)(optWidth, cols.left.size() + 2); + optWidth = (std::min)(optWidth, consoleWidth/2); + for( auto const &cols : rows ) { auto row = TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + diff --git a/src/ClaraTests.cpp b/src/ClaraTests.cpp index f0f1af7..e10e956 100644 --- a/src/ClaraTests.cpp +++ b/src/ClaraTests.cpp @@ -330,6 +330,20 @@ std::string toString( Opt const& opt ) { return oss.str(); } +TEST_CASE( "Opt value can start with a dash" ) { + std::string name; + bool showHelp = false; + auto parser + = Help( showHelp ) + | Opt( name, "name" ) + ["-n"]["--name"] + ( "the name to use" ); + + auto result = parser.parse( Args{ "TestApp", "-n", "-foobar" } ); + CHECK( result ); + REQUIRE( name == "-foobar" ); +} + TEST_CASE( "different widths" ) { std::string s; From ebb01a0838db39eb8a0a5fb151b2373f7c8f8e22 Mon Sep 17 00:00:00 2001 From: Aivars Kalvans Date: Tue, 6 Mar 2018 01:27:50 +0200 Subject: [PATCH 2/4] Test arg separated by = as well --- src/ClaraTests.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ClaraTests.cpp b/src/ClaraTests.cpp index e10e956..76c3140 100644 --- a/src/ClaraTests.cpp +++ b/src/ClaraTests.cpp @@ -339,9 +339,16 @@ TEST_CASE( "Opt value can start with a dash" ) { ["-n"]["--name"] ( "the name to use" ); - auto result = parser.parse( Args{ "TestApp", "-n", "-foobar" } ); - CHECK( result ); - REQUIRE( name == "-foobar" ); + SECTION( "args" ) { + auto result = parser.parse( Args{ "TestApp", "-n", "-foo" } ); + CHECK( result ); + REQUIRE( name == "-foo" ); + } + SECTION( "arg separated by =" ) { + auto result = parser.parse( Args{ "TestApp", "-n=-bar" } ); + CHECK( result ); + REQUIRE( name == "-bar" ); + } } TEST_CASE( "different widths" ) { From 977b24f6fa521466ff561e3ceae5717cfc2cfeca Mon Sep 17 00:00:00 2001 From: Aivars Kalvans Date: Tue, 6 Mar 2018 01:31:19 +0200 Subject: [PATCH 3/4] And test empty argument --- src/ClaraTests.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ClaraTests.cpp b/src/ClaraTests.cpp index 76c3140..d1d5a1d 100644 --- a/src/ClaraTests.cpp +++ b/src/ClaraTests.cpp @@ -349,6 +349,11 @@ TEST_CASE( "Opt value can start with a dash" ) { CHECK( result ); REQUIRE( name == "-bar" ); } + SECTION( "empty args" ) { + auto result = parser.parse( Args{ "TestApp", "-n", "" } ); + CHECK( result ); + REQUIRE( name == "" ); + } } TEST_CASE( "different widths" ) { From 6588b4cfba42e435b19f0dc9eb6b894e507639e4 Mon Sep 17 00:00:00 2001 From: Aivars Kalvans Date: Tue, 6 Mar 2018 12:56:54 +0200 Subject: [PATCH 4/4] Interpret a single dash or slash as positional argument --- include/clara.hpp | 2 +- single_include/clara.hpp | 2 +- src/ClaraTests.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/clara.hpp b/include/clara.hpp index ded156b..63baf75 100644 --- a/include/clara.hpp +++ b/include/clara.hpp @@ -102,7 +102,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( isOptPrefix( next[0] ) ) { + if( isOptPrefix( next[0] ) && next.size() > 1 ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); diff --git a/single_include/clara.hpp b/single_include/clara.hpp index bdf62ce..593a6db 100644 --- a/single_include/clara.hpp +++ b/single_include/clara.hpp @@ -433,7 +433,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( isOptPrefix( next[0] ) ) { + if( isOptPrefix( next[0] ) && next.size() > 1 ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); diff --git a/src/ClaraTests.cpp b/src/ClaraTests.cpp index d1d5a1d..27600b2 100644 --- a/src/ClaraTests.cpp +++ b/src/ClaraTests.cpp @@ -356,6 +356,31 @@ TEST_CASE( "Opt value can start with a dash" ) { } } +TEST_CASE( "dash as positional argument" ) { + std::string name; + bool showHelp = false; + auto parser + = Help( showHelp ) + | Arg( name, "input file" ) + ( "Input file" ); + + SECTION( "args" ) { + auto result = parser.parse( Args{ "cat", "filename" } ); + CHECK( result ); + REQUIRE( name == "filename" ); + } + SECTION( "dash arg" ) { + auto result = parser.parse( Args{ "cat", "-" } ); + CHECK( result ); + REQUIRE( name == "-" ); + } + SECTION( "slash arg" ) { + auto result = parser.parse( Args{ "cat", "/" } ); + CHECK( result ); + REQUIRE( name == "/" ); + } +} + TEST_CASE( "different widths" ) { std::string s;