package de.axone.funky.shell;
import de.axone.exception.Assert;
import de.axone.funky.Argument;
import de.axone.funky.ArgumentImpl;
import de.axone.funky.ArgumentType;
import de.axone.funky.FunctionDescription;
import de.axone.funky.FunctionDescriptionImpl;
import de.axone.funky.types.ArgumentTypes;
import de.axone.funky.types.ArgumentValidator_OneOf;
/**
* Build a function description using a shell-like syntax:
*
* <pre>
* ls [--all] [--color=none|some|full] dir
* ls [-a] [-c none|some|full] dir
* ls [-a|--all] [-c|--color=none|some|full] dir
* all: Display hidden files e.g. those starting with dots
* color: Color scheme to use
* dir: directory to look in
* </pre>
*
* Call of shell functions:
*
* ls -a -c full /etc
* or:
* ls --all --color=full /etc
* but although:
* ls /etc --all -c full
*
* @author flo
*/
public abstract class FunctionDescriptionBuilder_Shell {
public static FunctionDescription build( String description ){
String [] args = description.split( "\\s+" );
FunctionDescriptionImpl result = new FunctionDescriptionImpl( args[ 0 ] );
for( int i=1; i<args.length; i++ ){
String arg = args[ i ];
arg = arg.trim();
if( arg.length() == 0 ) continue;
result.argument( buildArgument( args[ i ] ) );
}
return result;
}
public static Argument<?,?> buildArgument( String arg ){
boolean optional = false;
if( arg.startsWith( "[" ) ){
Assert.isTrue( arg.endsWith( "]" ), "must be closed" );
arg = arg.substring( 1, arg.length()-1 );
optional = true;
}
NameValue nv = parseArg( arg );
ArgumentImpl<String,ArgumentType<String>> result = new ArgumentImpl<>(
ArgumentTypes.STRING, nv.name, null, null, null, optional, nv.positional );
if( nv.value != null ){
result.validate( new ArgumentValidator_OneOf( nv.value.split( "\\s*\\|\\s*" ) ) );
}
return result;
}
static class NameValue {
String name, value;
boolean positional;
}
static NameValue parseArg( String arg ){
NameValue result = new NameValue();
if( arg.contains( "=" ) ){
String [] split = arg.split( "=", 2 );
result.name = split[ 0 ];
result.value = split[ 1 ];
} else {
result.name = arg;
}
if( result.name.startsWith( "--" ) ){
result.name = result.name.substring( 2 );
result.positional = false;
} else if( result.name.startsWith( "-" ) ){
result.name = result.name.substring( 1 );
result.positional = false;
} else {
result.positional = true;
}
return result;
}
}