mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-14 15:26:52 -04:00
first working cli interface implementation
This commit is contained in:
parent
39c21d1eac
commit
3c70b3a3bd
32
src/main/java/CLI.java
Normal file
32
src/main/java/CLI.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import de.neemann.digital.cli.CLIException;
|
||||||
|
import de.neemann.digital.cli.Muxer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for the CLI interface
|
||||||
|
*/
|
||||||
|
public final class CLI {
|
||||||
|
|
||||||
|
private CLI() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for the CLI interface
|
||||||
|
*
|
||||||
|
* @param args the command line arguments
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
Muxer.MAIN_MUXER.execute(args);
|
||||||
|
} catch (CLIException e) {
|
||||||
|
e.printMessage(System.out);
|
||||||
|
Muxer.MAIN_MUXER.printDescription(System.out, "");
|
||||||
|
System.exit(e.getExitCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
src/main/java/de/neemann/digital/cli/Argument.java
Normal file
103
src/main/java/de/neemann/digital/cli/Argument.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command cline argument
|
||||||
|
*
|
||||||
|
* @param <T> the type of the argument
|
||||||
|
*/
|
||||||
|
public class Argument<T> {
|
||||||
|
private final String name;
|
||||||
|
private final boolean optional;
|
||||||
|
private T value;
|
||||||
|
private boolean isSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new argument
|
||||||
|
*
|
||||||
|
* @param name the name of the argument
|
||||||
|
* @param def the default value
|
||||||
|
* @param optional true if argument is optional
|
||||||
|
*/
|
||||||
|
public Argument(String name, T def, boolean optional) {
|
||||||
|
this.name = name;
|
||||||
|
this.optional = optional;
|
||||||
|
if (def == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
value = def;
|
||||||
|
}
|
||||||
|
|
||||||
|
T get() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (optional)
|
||||||
|
return "[[" + name + "]]";
|
||||||
|
else
|
||||||
|
return "[" + name + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a string value
|
||||||
|
*
|
||||||
|
* @param val the value to set
|
||||||
|
* @throws CLIException CLIException
|
||||||
|
*/
|
||||||
|
public void setString(String val) throws CLIException {
|
||||||
|
if (value instanceof String)
|
||||||
|
value = (T) val;
|
||||||
|
else if (value instanceof Boolean)
|
||||||
|
switch (val.toLowerCase()) {
|
||||||
|
case "yes":
|
||||||
|
case "1":
|
||||||
|
case "true":
|
||||||
|
value = (T) (Boolean) true;
|
||||||
|
break;
|
||||||
|
case "no":
|
||||||
|
case "0":
|
||||||
|
case "false":
|
||||||
|
value = (T) (Boolean) false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new CLIException(Lang.get("cli_notABool_N", val), 106);
|
||||||
|
}
|
||||||
|
else if (value instanceof Integer) {
|
||||||
|
try {
|
||||||
|
value = (T) (Integer) Integer.parseInt(val);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new CLIException(Lang.get("cli_notANumber_N", val), e);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
throw new CLIException(Lang.get("cli_invalidType_N", value.getClass().getSimpleName()), 203);
|
||||||
|
isSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if this argument was set
|
||||||
|
*/
|
||||||
|
public boolean isSet() {
|
||||||
|
return isSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name of this argument
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this argument is optional
|
||||||
|
*/
|
||||||
|
public boolean isOptional() {
|
||||||
|
return optional;
|
||||||
|
}
|
||||||
|
}
|
31
src/main/java/de/neemann/digital/cli/CLICommand.java
Normal file
31
src/main/java/de/neemann/digital/cli/CLICommand.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cli command
|
||||||
|
*/
|
||||||
|
public interface CLICommand {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the description
|
||||||
|
*
|
||||||
|
* @param out the pront stream
|
||||||
|
* @param prefix the prefex string which should
|
||||||
|
* printed at the beginning of each line
|
||||||
|
*/
|
||||||
|
void printDescription(PrintStream out, String prefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Esecuted the command
|
||||||
|
*
|
||||||
|
* @param args the arguments
|
||||||
|
* @throws CLIException CLIException
|
||||||
|
*/
|
||||||
|
void execute(String[] args) throws CLIException;
|
||||||
|
}
|
60
src/main/java/de/neemann/digital/cli/CLIException.java
Normal file
60
src/main/java/de/neemann/digital/cli/CLIException.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* he command line exception
|
||||||
|
*/
|
||||||
|
public class CLIException extends Exception {
|
||||||
|
private final int exitCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param message the message
|
||||||
|
* @param exitCode the exit code
|
||||||
|
*/
|
||||||
|
public CLIException(String message, int exitCode) {
|
||||||
|
super(message);
|
||||||
|
this.exitCode = exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param message the message
|
||||||
|
* @param cause the cause
|
||||||
|
*/
|
||||||
|
public CLIException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
exitCode = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the exit code
|
||||||
|
*/
|
||||||
|
public int getExitCode() {
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pronts a error message to the stream
|
||||||
|
*
|
||||||
|
* @param out the print stream
|
||||||
|
*/
|
||||||
|
public void printMessage(PrintStream out) {
|
||||||
|
out.println(getMessage());
|
||||||
|
Throwable c = getCause();
|
||||||
|
if (c != null) {
|
||||||
|
if (c instanceof CLIException)
|
||||||
|
((CLIException) c).printMessage(out);
|
||||||
|
else
|
||||||
|
out.println(c.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
src/main/java/de/neemann/digital/cli/CLITester.java
Normal file
43
src/main/java/de/neemann/digital/cli/CLITester.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
import de.neemann.digital.testing.CommandLineTester;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to test circuits
|
||||||
|
*/
|
||||||
|
public class CLITester extends SimpleCommand {
|
||||||
|
private final Argument<String> circ;
|
||||||
|
private final Argument<String> test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new CLI command
|
||||||
|
*/
|
||||||
|
public CLITester() {
|
||||||
|
super("test");
|
||||||
|
circ = addArgument(new Argument<>("circ", "", false));
|
||||||
|
test = addArgument(new Argument<>("test", "", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void execute() throws CLIException {
|
||||||
|
try {
|
||||||
|
CommandLineTester clt = new CommandLineTester(new File(circ.get()));
|
||||||
|
if (test.isSet())
|
||||||
|
clt.useTestCasesFrom(new File(test.get()));
|
||||||
|
int errors = clt.execute();
|
||||||
|
if (errors > 0)
|
||||||
|
throw new CLIException(Lang.get("cli_thereAreTestFailures"), errors);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CLIException(Lang.get("cli_errorExecutingTests"), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
src/main/java/de/neemann/digital/cli/Muxer.java
Normal file
84
src/main/java/de/neemann/digital/cli/Muxer.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command muxer
|
||||||
|
*/
|
||||||
|
public class Muxer implements CLICommand {
|
||||||
|
/**
|
||||||
|
* The main muxer
|
||||||
|
*/
|
||||||
|
public static final Muxer MAIN_MUXER = new Muxer()
|
||||||
|
.addCommand(new CLITester());
|
||||||
|
|
||||||
|
private final HashMap<String, CLICommand> commands;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private Muxer() {
|
||||||
|
this("java -jar Digital.jar CLI");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new muxer
|
||||||
|
*
|
||||||
|
* @param name the name of the muxer
|
||||||
|
*/
|
||||||
|
public Muxer(String name) {
|
||||||
|
this.name = name;
|
||||||
|
this.commands = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a command to the muxer
|
||||||
|
*
|
||||||
|
* @param command the command
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public Muxer addCommand(SimpleCommand command) {
|
||||||
|
return addCommand(command.getName(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a command to the muxer
|
||||||
|
*
|
||||||
|
* @param name the name of the command
|
||||||
|
* @param command the command
|
||||||
|
* @return this for chained calls
|
||||||
|
*/
|
||||||
|
public Muxer addCommand(String name, CLICommand command) {
|
||||||
|
commands.put(name, command);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printDescription(PrintStream out, String prefix) {
|
||||||
|
out.print(prefix);
|
||||||
|
out.print(name);
|
||||||
|
out.println();
|
||||||
|
for (CLICommand c : commands.values())
|
||||||
|
c.printDescription(out, prefix + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String[] args) throws CLIException {
|
||||||
|
if (args.length == 0)
|
||||||
|
throw new CLIException(Lang.get("cli_notEnoughArgumentsGiven"), 100);
|
||||||
|
|
||||||
|
CLICommand command = commands.get(args[0]);
|
||||||
|
if (command == null)
|
||||||
|
throw new CLIException(Lang.get("cli_command_N_hasNoSubCommand_N", name, args[0]), 101);
|
||||||
|
|
||||||
|
command.execute(Arrays.copyOfRange(args, 1, args.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
142
src/main/java/de/neemann/digital/cli/SimpleCommand.java
Normal file
142
src/main/java/de/neemann/digital/cli/SimpleCommand.java
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import de.neemann.digital.lang.Lang;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* E simple executable command
|
||||||
|
*/
|
||||||
|
public abstract class SimpleCommand implements CLICommand {
|
||||||
|
private final String name;
|
||||||
|
private final ArrayList<Argument<?>> arguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new command
|
||||||
|
*
|
||||||
|
* @param name the name of the command
|
||||||
|
*/
|
||||||
|
public SimpleCommand(String name) {
|
||||||
|
this.name = name;
|
||||||
|
arguments = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an argument to the command
|
||||||
|
*
|
||||||
|
* @param argument the argument
|
||||||
|
* @param <T> the type of the arguments value
|
||||||
|
* @param <A> the type of the argument
|
||||||
|
* @return the argument itself
|
||||||
|
*/
|
||||||
|
public <T, A extends Argument<T>> A addArgument(A argument) {
|
||||||
|
arguments.add(argument);
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name of the argument
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printDescription(PrintStream out, String prefix) {
|
||||||
|
String message = Lang.get("cli_help_" + name);
|
||||||
|
out.print(prefix);
|
||||||
|
out.print(name);
|
||||||
|
for (Argument<?> a : arguments) {
|
||||||
|
out.print(" ");
|
||||||
|
out.print(a);
|
||||||
|
}
|
||||||
|
out.println(":");
|
||||||
|
|
||||||
|
for (Argument<?> a : arguments)
|
||||||
|
printString(out, prefix + " ", a + ":\t" + Lang.get("cli_help_" + name + "_" + a.getName()));
|
||||||
|
|
||||||
|
printString(out, prefix + " ", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printString(PrintStream out, String prefix, String message) {
|
||||||
|
boolean lastWasSpace = false;
|
||||||
|
out.print(prefix);
|
||||||
|
int col = prefix.length();
|
||||||
|
for (int i = 0; i < message.length(); i++) {
|
||||||
|
char c = message.charAt(i);
|
||||||
|
if (c == '\n')
|
||||||
|
c = ' ';
|
||||||
|
if (c != ' ' || !lastWasSpace) {
|
||||||
|
if (c == ' ') {
|
||||||
|
if (col > 70) {
|
||||||
|
out.print('\n');
|
||||||
|
out.print(prefix);
|
||||||
|
col = prefix.length();
|
||||||
|
} else {
|
||||||
|
out.print(c);
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.print(c);
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastWasSpace = c == ' ';
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String[] args) throws CLIException {
|
||||||
|
int nonOptional = 0;
|
||||||
|
Iterator<String> it = Arrays.asList(args).iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
String n = it.next();
|
||||||
|
if (n.startsWith("-")) {
|
||||||
|
if (!it.hasNext())
|
||||||
|
throw new CLIException(Lang.get("cli_notEnoughArgumentsGiven"), 100);
|
||||||
|
set(n.substring(1), it.next());
|
||||||
|
} else {
|
||||||
|
while (nonOptional < arguments.size() && arguments.get(nonOptional).isOptional()) {
|
||||||
|
nonOptional++;
|
||||||
|
}
|
||||||
|
if (nonOptional == arguments.size())
|
||||||
|
throw new CLIException(Lang.get("cli_toMuchArguments"), 105);
|
||||||
|
|
||||||
|
arguments.get(nonOptional).setString(n);
|
||||||
|
nonOptional++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Argument<?> a : arguments)
|
||||||
|
if (!a.isOptional() && !a.isSet())
|
||||||
|
throw new CLIException(Lang.get("cli_nonOptionalArgumentMissing_N", a), 105);
|
||||||
|
|
||||||
|
execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the command
|
||||||
|
*
|
||||||
|
* @throws CLIException CLIException
|
||||||
|
*/
|
||||||
|
protected abstract void execute() throws CLIException;
|
||||||
|
|
||||||
|
private void set(String arg, String value) throws CLIException {
|
||||||
|
for (Argument<?> a : arguments)
|
||||||
|
if (arg.equals(a.getName())) {
|
||||||
|
a.setString(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new CLIException(Lang.get("cli_noArgument_N_available", arg), 104);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/main/java/de/neemann/digital/cli/package-info.java
Normal file
10
src/main/java/de/neemann/digital/cli/package-info.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command line interface
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
9
src/main/java/package-info.java
Normal file
9
src/main/java/package-info.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The command line interface
|
||||||
|
*/
|
@ -1541,6 +1541,24 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
|||||||
<string name="lib_ram">RAM</string>
|
<string name="lib_ram">RAM</string>
|
||||||
<string name="lib_eeprom">EEPROM</string>
|
<string name="lib_eeprom">EEPROM</string>
|
||||||
|
|
||||||
|
<string name="cli_nonOptionalArgumentMissing_N">Es fehlt das nicht optionale Argument {0}.</string>
|
||||||
|
<string name="cli_notABool_N">Der Wert {0} ist kein bool.</string>
|
||||||
|
<string name="cli_notANumber_N">Der Wert {0} ist keine Zahl.</string>
|
||||||
|
<string name="cli_noArgument_N_available">Das Argument {0} fehlt.</string>
|
||||||
|
<string name="cli_notEnoughArgumentsGiven">Es sind nicht genug Argumente vorhanden.</string>
|
||||||
|
<string name="cli_toMuchArguments">Es gibt zu viele Argumente.</string>
|
||||||
|
<string name="cli_invalidType_N">Ungültiger Typ.</string>
|
||||||
|
<string name="cli_command_N_hasNoSubCommand_N">Der Befehl {0} hat keinen Subbefehl {1}.</string>
|
||||||
|
|
||||||
|
<string name="cli_help_test">Der erste Dateiname gibt die zu testende Schaltung an.
|
||||||
|
Wenn ein zweiter Dateiname angegeben wird, werden die Testfälle aus dieser Datei ausgeführt.
|
||||||
|
Wird kein zweiter Dateiname angegeben, werden die Tests aus der ersten Datei ausgeführt.
|
||||||
|
</string>
|
||||||
|
<string name="cli_help_test_circ">Name der zu testenden Datei.</string>
|
||||||
|
<string name="cli_help_test_test">Name einer Datei mit Testfällen.</string>
|
||||||
|
<string name="cli_thereAreTestFailures">Es sind Tests fehlgeschlagen.</string>
|
||||||
|
<string name="cli_errorExecutingTests">Es ist ein Fehler bei der Ausführung der Tests aufgetreten.</string>
|
||||||
|
|
||||||
<string name="menu_window">Fenster</string>
|
<string name="menu_window">Fenster</string>
|
||||||
<string name="menu_about">Über Digital</string>
|
<string name="menu_about">Über Digital</string>
|
||||||
<string name="menu_analyse">Analyse</string>
|
<string name="menu_analyse">Analyse</string>
|
||||||
|
@ -1505,6 +1505,25 @@
|
|||||||
<string name="lib_ram">RAM</string>
|
<string name="lib_ram">RAM</string>
|
||||||
<string name="lib_eeprom">EEPROM</string>
|
<string name="lib_eeprom">EEPROM</string>
|
||||||
|
|
||||||
|
<string name="cli_nonOptionalArgumentMissing_N">The non-optional argument {0} is missing.</string>
|
||||||
|
<string name="cli_notABool_N">The value {0} is no bool.</string>
|
||||||
|
<string name="cli_notANumber_N">The value {0} is not a number.</string>
|
||||||
|
<string name="cli_noArgument_N_available">The argument {0} is missing.</string>
|
||||||
|
<string name="cli_notEnoughArgumentsGiven">There are not enough arguments.</string>
|
||||||
|
<string name="cli_toMuchArguments">There are too many arguments.</string>
|
||||||
|
<string name="cli_invalidType_N">Invalid type.</string>
|
||||||
|
<string name="cli_command_N_hasNoSubCommand_N">The command {0} has no sub-command {1}.</string>
|
||||||
|
|
||||||
|
<string name="cli_help_test">The first file name specifies the circuit to be tested.
|
||||||
|
If a second file name is specified, the test cases are executed from this file.
|
||||||
|
If no second file name is specified, the tests are executed from the first file.
|
||||||
|
</string>
|
||||||
|
<string name="cli_help_test_circ">Name of the file to be tested.</string>
|
||||||
|
<string name="cli_help_test_test">Name of a file with test cases.</string>
|
||||||
|
<string name="cli_thereAreTestFailures">Tests have failed.</string>
|
||||||
|
<string name="cli_errorExecutingTests">An error has occurred during the execution of the tests.</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="menu_window">Windows</string>
|
<string name="menu_window">Windows</string>
|
||||||
<string name="menu_about">About</string>
|
<string name="menu_about">About</string>
|
||||||
<string name="menu_analyse">Analysis</string>
|
<string name="menu_analyse">Analysis</string>
|
||||||
|
55
src/test/java/de/neemann/digital/cli/ArgumentTest.java
Normal file
55
src/test/java/de/neemann/digital/cli/ArgumentTest.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class ArgumentTest extends TestCase {
|
||||||
|
|
||||||
|
public void testString() throws CLIException {
|
||||||
|
Argument<String> a = new Argument<>("n", "a", false);
|
||||||
|
assertEquals("a", a.get());
|
||||||
|
a.setString("hello");
|
||||||
|
assertEquals("hello", a.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBool() throws CLIException {
|
||||||
|
Argument<Boolean> a = new Argument<>("n", true, false);
|
||||||
|
assertTrue(a.get());
|
||||||
|
a.setString("false");
|
||||||
|
assertFalse(a.get());
|
||||||
|
a.setString("true");
|
||||||
|
assertTrue(a.get());
|
||||||
|
a.setString("0");
|
||||||
|
assertFalse(a.get());
|
||||||
|
a.setString("1");
|
||||||
|
assertTrue(a.get());
|
||||||
|
a.setString("no");
|
||||||
|
assertFalse(a.get());
|
||||||
|
a.setString("yes");
|
||||||
|
assertTrue(a.get());
|
||||||
|
|
||||||
|
try {
|
||||||
|
a.setString("foo");
|
||||||
|
fail();
|
||||||
|
} catch (CLIException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInteger() throws CLIException {
|
||||||
|
Argument<Integer> a = new Argument<>("n", 2, false);
|
||||||
|
assertEquals(2, (int) a.get());
|
||||||
|
a.setString("5");
|
||||||
|
assertEquals(5, (int) a.get());
|
||||||
|
|
||||||
|
try {
|
||||||
|
a.setString("foo");
|
||||||
|
fail();
|
||||||
|
} catch (CLIException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
103
src/test/java/de/neemann/digital/cli/SimpleCommandTest.java
Normal file
103
src/test/java/de/neemann/digital/cli/SimpleCommandTest.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Helmut Neemann.
|
||||||
|
* Use of this source code is governed by the GPL v3 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package de.neemann.digital.cli;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class SimpleCommandTest extends TestCase {
|
||||||
|
|
||||||
|
private static class TestCommand extends SimpleCommand {
|
||||||
|
private boolean wasExecuted;
|
||||||
|
|
||||||
|
private TestCommand() {
|
||||||
|
super("test");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void execute() {
|
||||||
|
wasExecuted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExecutes(boolean shouldBeExecuted) {
|
||||||
|
assertEquals(shouldBeExecuted, wasExecuted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOptional() throws CLIException {
|
||||||
|
TestCommand tc = new TestCommand();
|
||||||
|
Argument<String> n1 = tc.addArgument(new Argument<>("n1", "", false));
|
||||||
|
Argument<String> n2 = tc.addArgument(new Argument<>("n2", "", false));
|
||||||
|
|
||||||
|
tc.execute(new String[]{"name1", "name2"});
|
||||||
|
|
||||||
|
assertEquals("name1", n1.get());
|
||||||
|
assertEquals("name2", n2.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOptional2() throws CLIException {
|
||||||
|
TestCommand tc = new TestCommand();
|
||||||
|
Argument<String> n1 = tc.addArgument(new Argument<>("n1", "", false));
|
||||||
|
Argument<String> n2 = tc.addArgument(new Argument<>("n2", "", false));
|
||||||
|
|
||||||
|
tc.execute(new String[]{"-n1", "name1", "-n2", "name2"});
|
||||||
|
|
||||||
|
assertEquals("name1", n1.get());
|
||||||
|
assertEquals("name2", n2.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOptional3() {
|
||||||
|
TestCommand tc = new TestCommand();
|
||||||
|
Argument<String> n1 = tc.addArgument(new Argument<>("n1", "", false));
|
||||||
|
Argument<String> n2 = tc.addArgument(new Argument<>("n2", "", false));
|
||||||
|
|
||||||
|
try {
|
||||||
|
tc.execute(new String[]{"name1"});
|
||||||
|
fail();
|
||||||
|
} catch (CLIException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOptional4() throws CLIException {
|
||||||
|
TestCommand tc = new TestCommand();
|
||||||
|
Argument<String> n1 = tc.addArgument(new Argument<>("n1", "n1", true));
|
||||||
|
Argument<String> n2 = tc.addArgument(new Argument<>("n2", "n2", true));
|
||||||
|
|
||||||
|
tc.execute(new String[]{});
|
||||||
|
assertEquals("n1", n1.get());
|
||||||
|
assertEquals("n2", n2.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOptional5() throws CLIException {
|
||||||
|
TestCommand tc = new TestCommand();
|
||||||
|
Argument<String> n1 = tc.addArgument(new Argument<>("n1", "n1", true));
|
||||||
|
Argument<String> n2 = tc.addArgument(new Argument<>("n2", "n2", true));
|
||||||
|
|
||||||
|
try {
|
||||||
|
tc.execute(new String[]{"test"});
|
||||||
|
fail();
|
||||||
|
} catch (CLIException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWrongArgument() {
|
||||||
|
TestCommand tc = new TestCommand();
|
||||||
|
Argument<String> n1 = tc.addArgument(new Argument<>("n1", "", true));
|
||||||
|
Argument<String> n2 = tc.addArgument(new Argument<>("n2", "", true));
|
||||||
|
|
||||||
|
try {
|
||||||
|
tc.execute(new String[]{"-n3", "test"});
|
||||||
|
fail();
|
||||||
|
} catch (CLIException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
tc.execute(new String[]{"-n1"});
|
||||||
|
fail();
|
||||||
|
} catch (CLIException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -68,7 +68,7 @@ public class TestLang extends TestCase {
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (String key : map.keySet()) {
|
for (String key : map.keySet()) {
|
||||||
if (!keys.contains(key)) {
|
if (!keys.contains(key)) {
|
||||||
if (!(key.startsWith("key_") || key.startsWith("elem_") || key.startsWith("attr_panel_") || key.startsWith("tutorial"))) {
|
if (!(key.startsWith("key_") || key.startsWith("elem_") || key.startsWith("attr_panel_") || key.startsWith("tutorial") || key.startsWith("cli_help_"))) {
|
||||||
if (sb.length() > 0)
|
if (sb.length() > 0)
|
||||||
sb.append(", ");
|
sb.append(", ");
|
||||||
sb.append('"').append(key).append('"');
|
sb.append('"').append(key).append('"');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user