Can scripts take an optional input?

Is it possible to have a script optionally accept an argument?

i.e. something like

Code:
void main(string input) {
[INDENT]if (input != "") {
[INDENT]print(input);[/INDENT]
} else {
[INDENT]print("No input parameter given.");[/INDENT]}
[/INDENT]
}
 

xKiv

Active member
I *think* you can have multiple main functions (with different signatures)
And then call them likde
script # no argument - main()
script bla bla bla # one argument main(string) or main(int) or ...
script (bla, bla, bla) # three arguments main(string,string,string) or ....; note the space between "script" and "("
 

fronobulax

Developer
Staff member
I *think* you can have multiple main functions (with different signatures)
And then call them likde
script # no argument - main()
script bla bla bla # one argument main(string) or main(int) or ...
script (bla, bla, bla) # three arguments main(string,string,string) or ....; note the space between "script" and "("

I thought that too but wasn't certain enough to say so and not ready to look at code or try it. ;-)
 

Veracity

Developer
Staff member
tl;dr answer:

We have no mechanism for that, currently: If you declare your main like this:

void main(string input) {...}

if you "call script my string here"

input will be "my string here"

and if you "call script"

KoLmafia will pop up a modal dialog to prompt you for "input". You are welcome to respond with no string, in which case, input will be "".

But you cannot avoid getting the dialog which prompts you for an argument, if you failed to supply one on the command line that invoked your script.

----------------------------------

That said, I explored the idea in multiple main functions in a script. We do not currently support that.

Interpreter.executeScope:

Code:
		if ( functionName.equals( "main" ) )
		{
			main = this.parser.getMainMethod();
		}
...
		if ( main != null )
		{
			// push to interpreter stack
			this.pushFrame( "main" );

			Object[] values = new Object[ main.getVariableReferences().size() + 1];
			values[ 0 ] = this;
			
			if ( !this.requestUserParams( main, parameters, values ) )
			{
				return null;
			}

			result = main.execute( this, values );
			this.popFrame();
		}
It looks for whatever the Parser thinks is the "mainMethod", gets the variable references associated with it, and prompts you for values for each of them.
The Parser will allow you to overload "main", just like any other function.

Parser.parseScope:

Code:
			Function f = this.parseFunction( t, result );
			if ( f != null )
			{
				if ( f.getName().equalsIgnoreCase( "main" ) )
				{
					if ( parentScope.getParentScope() != null )
					{
						throw this.parseException( "main method must appear at top level" );
					}
					this.mainMethod = f;
				}

				continue;
			}
However, "the" mainMethod is the last one in your script.

We could set things up so that "main" is not treated so differently:

void main()
void main( string arg1 )
void main( int arg1 )
void main( string arg1, int arg2 )

would be overloaded. When you invoke the script in the gCLI:

call script
call script ("abcd")
call script (12)
call script ("str",15)

could find the appropriate "main" method.

The issue is that, as it has worked since the beginning of ASH, you don't need to specify all the parameters.

void main( string, int, location )

can be called in any of the following ways:

call script
call script (abcd)
call script (abcd, 12)
call script (abcd, 12, The Spooky Forest)

The parameters will be split at "," and made into an array of strings. That means that a "string" parameter cannot have a "," in it.
For each parameter you did not specify, you will be prompted for.
Every parameter will be coerced from string into the expected type.

And then "main" will be executed with the expected values.

Another wrinkle:

void main( string parameters )

call script

Will prompt for a string - "parameters" - which is the single argument

call script anything you want here ...

will pass "anything you want here ..." as the argument, and the script can parse that however it wishes. For example, VeracitySpacegate has a complicated command syntax:

vsg visit complex animals, exotic plants (A-L)

will call "main" with "visit complex animals, exotic plants (A-L)" as the command and it do what you asked for.

If we were to allow overloading with multiple "main" methods, I'd want to be very careful that scripts that do NOT do such overloading will prompt for arguments, just as they do now.
I see ambiguity if we allowed

void main( int )
void main( string )

Since the gCLI collects parameters as strings and coerces them into the required data type after it has determined which function to call - "the" mainMethod.

call script (1234)

Is 1234 an integer or the string "1234"?
 
That's a very comprehensive answer; thank you. I'll work round it—it just seemed a nice idea that if you didn't add a parameter, the script would immediately return a help text giving options.

Thanks!
 
Top