kicad-cli: Preprocess vector args
argparse required long-form functions to use an equal sign to process a
string like --rotate='-45,0,45' but would accept long-form args that
didn't have a negative like --output test.png without the equal sign.
Since this is an intrinsic limitation of our library, we work around it
by detecting these vector forms and changing them into an equality under
the hood.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20191
(cherry picked from commit a9ce9da551)
This commit is contained in:
+75
-1
@@ -36,6 +36,8 @@
|
||||
#include <systemdirsappend.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "pgm_kicad.h"
|
||||
@@ -297,6 +299,74 @@ static void printHelp( argparse::ArgumentParser& argParser )
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a string looks like a numeric vector value that happens to start with a minus sign.
|
||||
*
|
||||
* This handles values like "-45,0,45" or "-3.5,0,1.2" which are valid vector arguments
|
||||
* but get misinterpreted by argparse as unknown options because they start with '-'.
|
||||
*/
|
||||
static bool looksLikeNegativeVectorValue( const std::string& aValue )
|
||||
{
|
||||
if( aValue.empty() || aValue[0] != '-' )
|
||||
return false;
|
||||
|
||||
if( aValue.find( ',' ) == std::string::npos )
|
||||
return false;
|
||||
|
||||
for( size_t i = 1; i < aValue.size(); ++i )
|
||||
{
|
||||
char c = aValue[i];
|
||||
|
||||
if( !std::isdigit( c ) && c != '.' && c != ',' && c != '-' && c != '+' )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pre-process command line arguments to handle negative numeric values.
|
||||
*
|
||||
* The argparse library interprets values starting with '-' as option flags.
|
||||
* For arguments that accept vector values (like --rotate, --pan, --pivot),
|
||||
* we wrap negative values in single quotes to prevent argparse from treating
|
||||
* them as options. The parsing code in command_pcb_render.cpp already strips
|
||||
* these quotes via getToVector3().
|
||||
*
|
||||
* Example: "--rotate -45,0,45" becomes "--rotate='-45,0,45'"
|
||||
*/
|
||||
static std::vector<std::string> preprocessArgs( int argc, char** argv )
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
static const std::set<std::string> vectorArgs = {
|
||||
"--rotate", "--pan", "--pivot"
|
||||
};
|
||||
|
||||
for( int i = 0; i < argc; ++i )
|
||||
{
|
||||
std::string current( argv[i] );
|
||||
|
||||
if( vectorArgs.count( current ) && i + 1 < argc )
|
||||
{
|
||||
std::string next( argv[i + 1] );
|
||||
|
||||
if( looksLikeNegativeVectorValue( next ) )
|
||||
{
|
||||
result.push_back( current + "='" + next + "'" );
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.push_back( current );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool PGM_KICAD::OnPgmInit()
|
||||
{
|
||||
PGM_BASE::BuildArgvUtf8();
|
||||
@@ -349,7 +419,11 @@ int PGM_KICAD::OnPgmRun()
|
||||
// Use the C locale to parse arguments
|
||||
// Otherwise the decimal separator for the locale will be applied
|
||||
LOCALE_IO dummy;
|
||||
argParser.parse_args( m_argcUtf8, m_argvUtf8 );
|
||||
|
||||
// Pre-process arguments to handle negative vector values (e.g., --rotate -45,0,45)
|
||||
// which argparse would otherwise interpret as unknown options
|
||||
std::vector<std::string> args = preprocessArgs( m_argcUtf8, m_argvUtf8 );
|
||||
argParser.parse_args( args );
|
||||
}
|
||||
// std::runtime_error doesn't seem to be enough for the scan<>()
|
||||
catch( const std::exception& err )
|
||||
|
||||
Reference in New Issue
Block a user