use error_tools::{ Error, Result };
const BOOL_PARAMS : &[ &str ] = &[ "dry" ];
const VERBOSITY_ALIAS : &str = "v";
const VERBOSITY_KEY : &str = "verbosity";
const MAX_VERBOSITY : u8 = 2;
#[ inline ]
fn split_first_colons( s : &str ) -> Option< ( &str, &str ) >
{
s.find( "::" ).map( |i| ( &s[ ..i ], &s[ i + 2.. ] ) )
}
#[ inline ]
fn normalise_bool_value( key : &str, raw_val : &str ) -> Result< String >
{
match raw_val
{
"true" | "1" => Ok( "1".to_string() ),
"false" | "0" => Ok( "0".to_string() ),
other =>
{
Err( Error::msg( format!(
"invalid value for {key}::{other}: expected true, false, 1, or 0"
) ) )
}
}
}
#[ inline ]
fn parse_verbosity( raw_val : &str ) -> Result< u8 >
{
let n = raw_val.parse::< u8 >().map_err( |_| Error::msg( format!(
"verbosity must be 0, 1, or 2, got: '{raw_val}'"
) ) )?;
if n > MAX_VERBOSITY
{
return Err( Error::msg( format!(
"verbosity out of range: {n} (max {MAX_VERBOSITY})"
) ) );
}
Ok( n )
}
#[ inline ]
pub fn argv_to_unilang_tokens( argv : &[ String ] ) -> Result< ( Vec< String >, bool ) >
{
if argv.is_empty()
{
return Ok( ( vec![ ".help".to_string() ], true ) );
}
if argv.iter().any( |a| a == ".help" || a == "help" )
{
return Ok( ( vec![ ".help".to_string() ], true ) );
}
if argv[ 0 ] == "--help" || argv[ 0 ] == "-h"
{
return Ok( ( vec![ ".help".to_string() ], true ) );
}
if argv[ 0 ].starts_with( '-' )
{
return Err( Error::msg( format!(
"unexpected flag '{}': use param::value syntax (e.g., verbosity::2)",
argv[ 0 ]
) ) );
}
if argv[ 0 ].contains( "::" )
{
return Err( Error::msg( format!(
"expected command name as first argument, got '{}'",
argv[ 0 ]
) ) );
}
if argv[ 0 ] == "."
{
return Ok( ( vec![ ".help".to_string() ], true ) );
}
let command_name = argv[ 0 ].clone();
let mut pairs : Vec< ( String, String ) > = vec![];
for arg in &argv[ 1.. ]
{
if arg.starts_with( '-' )
{
return Err( Error::msg( format!(
"unexpected flag '{arg}': use param::value syntax (e.g., verbosity::2)"
) ) );
}
let ( raw_key, raw_val ) = split_first_colons( arg ).ok_or_else( || Error::msg( format!(
"expected param::value syntax, got: '{arg}'"
) ) )?;
let key : String = if raw_key == VERBOSITY_ALIAS
{
VERBOSITY_KEY.to_string()
}
else
{
raw_key.to_string()
};
if key == VERBOSITY_KEY
{
parse_verbosity( raw_val )?;
}
let val : String = if BOOL_PARAMS.contains( &key.as_str() )
{
normalise_bool_value( &key, raw_val )?
}
else
{
raw_val.to_string()
};
if let Some( entry ) = pairs.iter_mut().find( |( k, _ )| k == &key )
{
entry.1 = val;
}
else
{
pairs.push( ( key, val ) );
}
}
let mut tokens = vec![ command_name ];
for ( k, v ) in pairs
{
tokens.push( format!( "{k}::{v}" ) );
}
Ok( ( tokens, false ) )
}