mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-18 01:14:42 -04:00
merged cli implementation, closes #473
This commit is contained in:
commit
3ed5dd8f8c
@ -14,6 +14,9 @@ Head, planned as v0.25
|
||||
- The layout shape uses a slightly different algorithm to determine
|
||||
the pin positions. You may need to adjust usages of embedded circuits
|
||||
that use the layout shape.
|
||||
- The CommandLineTester has moved! Tests are now executed like
|
||||
java -cp Digital.jar CLI test [file to test]
|
||||
[-tests [optional file with test cases]]
|
||||
|
||||
v0.24, released on 1. Feb. 2020
|
||||
- Improved SVG export
|
||||
|
27
src/main/java/CLI.java
Normal file
27
src/main/java/CLI.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.Main;
|
||||
|
||||
/**
|
||||
* Entry point for the CLI interface.
|
||||
* Used to allow a more compact command line.
|
||||
* All work is delegated to {@link Main}.
|
||||
*/
|
||||
public final class CLI {
|
||||
|
||||
private CLI() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for the CLI interface
|
||||
*
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
new Main().main(args);
|
||||
}
|
||||
}
|
64
src/main/java/de/neemann/digital/cli/CSVWriter.java
Normal file
64
src/main/java/de/neemann/digital/cli/CSVWriter.java
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 javax.swing.table.TableModel;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Helper to write a {@link TableModel} to a csv file
|
||||
*/
|
||||
public class CSVWriter {
|
||||
private final TableModel tableModel;
|
||||
private boolean newLine = true;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param tableModel the table model to be written to a csv file
|
||||
*/
|
||||
public CSVWriter(TableModel tableModel) {
|
||||
this.tableModel = tableModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the {@link TableModel} to the given writer
|
||||
*
|
||||
* @param w the writer to use
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public void writeTo(BufferedWriter w) throws IOException {
|
||||
for (int c = 0; c < tableModel.getColumnCount(); c++)
|
||||
writeCell(w, tableModel.getColumnName(c));
|
||||
newLine(w);
|
||||
|
||||
for (int r = 0; r < tableModel.getRowCount(); r++) {
|
||||
for (int c = 0; c < tableModel.getColumnCount(); c++)
|
||||
writeCell(w, tableModel.getValueAt(r, c));
|
||||
newLine(w);
|
||||
}
|
||||
w.close();
|
||||
}
|
||||
|
||||
private void newLine(BufferedWriter w) throws IOException {
|
||||
w.newLine();
|
||||
newLine = true;
|
||||
}
|
||||
|
||||
private void writeCell(BufferedWriter w, Object value) throws IOException {
|
||||
if (!newLine)
|
||||
w.write(',');
|
||||
if (value != null) {
|
||||
String v = value.toString();
|
||||
boolean quotes = v.contains(",") || v.contains(";") || v.contains("\t") || v.contains("\n");
|
||||
if (quotes) w.write('"');
|
||||
w.write(v);
|
||||
if (quotes) w.write('"');
|
||||
}
|
||||
newLine = false;
|
||||
}
|
||||
}
|
105
src/main/java/de/neemann/digital/cli/CircuitLoader.java
Normal file
105
src/main/java/de/neemann/digital/cli/CircuitLoader.java
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.core.Model;
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.draw.elements.Circuit;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.library.ElementLibrary;
|
||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||
import de.neemann.digital.draw.model.ModelCreator;
|
||||
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Helper to make it easier to load a circuit.
|
||||
*/
|
||||
public final class CircuitLoader {
|
||||
private final Circuit circuit;
|
||||
private final ElementLibrary library;
|
||||
private final ShapeFactory shapeFactory;
|
||||
|
||||
/**
|
||||
* Loads a circuit.
|
||||
*
|
||||
* @param filename filename
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CircuitLoader(String filename) throws IOException {
|
||||
this(new File(filename), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a circuit.
|
||||
*
|
||||
* @param filename filename
|
||||
* @param ieeeShapes if true ieee shapes are used
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CircuitLoader(String filename, boolean ieeeShapes) throws IOException {
|
||||
this(new File(filename), ieeeShapes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a circuit.
|
||||
*
|
||||
* @param file filename
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CircuitLoader(File file) throws IOException {
|
||||
this(file, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a circuit.
|
||||
*
|
||||
* @param file filename
|
||||
* @param ieeeShapes if true ieee shapes are used
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CircuitLoader(File file, boolean ieeeShapes) throws IOException {
|
||||
library = new ElementLibrary();
|
||||
library.setRootFilePath(file.getAbsoluteFile().getParentFile());
|
||||
shapeFactory = new ShapeFactory(library, ieeeShapes);
|
||||
circuit = Circuit.loadCircuit(file, shapeFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the circuit
|
||||
*/
|
||||
public Circuit getCircuit() {
|
||||
return circuit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the created library
|
||||
*/
|
||||
public ElementLibrary getLibrary() {
|
||||
return library;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the created shape factory
|
||||
*/
|
||||
public ShapeFactory getShapeFactory() {
|
||||
return shapeFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mode from the loaded circuit.
|
||||
*
|
||||
* @return the model
|
||||
* @throws ElementNotFoundException ElementNotFoundException
|
||||
* @throws PinException PinException
|
||||
* @throws NodeException NodeException
|
||||
*/
|
||||
public Model createModel() throws ElementNotFoundException, PinException, NodeException {
|
||||
return new ModelCreator(circuit, library).createModel(false);
|
||||
}
|
||||
}
|
@ -3,17 +3,22 @@
|
||||
* Use of this source code is governed by the GPL v3 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
package de.neemann.digital.testing;
|
||||
package de.neemann.digital.cli;
|
||||
|
||||
import de.neemann.digital.cli.cli.Argument;
|
||||
import de.neemann.digital.cli.cli.BasicCommand;
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
import de.neemann.digital.core.Model;
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.draw.elements.Circuit;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.elements.VisualElement;
|
||||
import de.neemann.digital.draw.library.ElementLibrary;
|
||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||
import de.neemann.digital.draw.model.ModelCreator;
|
||||
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
import de.neemann.digital.testing.TestCaseDescription;
|
||||
import de.neemann.digital.testing.TestCaseElement;
|
||||
import de.neemann.digital.testing.TestExecutor;
|
||||
import de.neemann.digital.testing.TestingDataException;
|
||||
import de.neemann.digital.testing.parser.ParserException;
|
||||
|
||||
import java.io.File;
|
||||
@ -26,10 +31,7 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class CommandLineTester {
|
||||
|
||||
private final ElementLibrary library;
|
||||
private final ShapeFactory shapeFactory;
|
||||
private Circuit circuit;
|
||||
private PrintStream out = System.out;
|
||||
private final CircuitLoader circuitLoader;
|
||||
private ArrayList<TestCase> testCases;
|
||||
private int testsPassed;
|
||||
|
||||
@ -40,20 +42,7 @@ public class CommandLineTester {
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CommandLineTester(File file) throws IOException {
|
||||
library = new ElementLibrary();
|
||||
shapeFactory = new ShapeFactory(library);
|
||||
circuit = Circuit.loadCircuit(file, shapeFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the printer to use
|
||||
*
|
||||
* @param out the {@link PrintStream}
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public CommandLineTester setOutputs(PrintStream out) {
|
||||
this.out = out;
|
||||
return this;
|
||||
circuitLoader = new CircuitLoader(file);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +53,7 @@ public class CommandLineTester {
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public CommandLineTester useTestCasesFrom(File file) throws IOException {
|
||||
Circuit c = Circuit.loadCircuit(file, shapeFactory);
|
||||
Circuit c = Circuit.loadCircuit(file, circuitLoader.getShapeFactory());
|
||||
testCases = getTestCasesFrom(c);
|
||||
return this;
|
||||
}
|
||||
@ -82,11 +71,12 @@ public class CommandLineTester {
|
||||
/**
|
||||
* Executes test test
|
||||
*
|
||||
* @param out Stream to output messages
|
||||
* @return the number of failed test cases
|
||||
*/
|
||||
public int execute() {
|
||||
public int execute(PrintStream out) {
|
||||
if (testCases == null)
|
||||
testCases = getTestCasesFrom(circuit);
|
||||
testCases = getTestCasesFrom(circuitLoader.getCircuit());
|
||||
|
||||
int errorCount = 0;
|
||||
|
||||
@ -100,7 +90,7 @@ public class CommandLineTester {
|
||||
label = "unnamed";
|
||||
|
||||
try {
|
||||
Model model = new ModelCreator(circuit, library).createModel(false);
|
||||
Model model = circuitLoader.createModel();
|
||||
TestExecutor te = new TestExecutor(t.getTestCaseDescription()).create(model);
|
||||
|
||||
if (te.allPassed()) {
|
||||
@ -145,23 +135,42 @@ public class CommandLineTester {
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point of the command line tester.
|
||||
*
|
||||
* @param args the program arguments
|
||||
* @throws IOException IOException
|
||||
* The test command
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length == 0) {
|
||||
System.err.println("no command line arguments given!\n");
|
||||
System.err.println("usage:\n");
|
||||
System.err.println("java -cp Digital.jar " + CommandLineTester.class.getName() + " [dig file to test] [[optional dig file with test cases]]");
|
||||
System.exit(1);
|
||||
public static class TestCommand extends BasicCommand {
|
||||
private final Argument<String> circ;
|
||||
private final Argument<String> tests;
|
||||
private int testsPassed;
|
||||
|
||||
/**
|
||||
* Creates a new CLI command
|
||||
*/
|
||||
public TestCommand() {
|
||||
super("test");
|
||||
circ = addArgument(new Argument<>("circ", "", false));
|
||||
tests = addArgument(new Argument<>("tests", "", true));
|
||||
}
|
||||
|
||||
CommandLineTester clt = new CommandLineTester(new File(args[0]));
|
||||
if (args.length > 1)
|
||||
clt.useTestCasesFrom(new File(args[1]));
|
||||
int errors = clt.execute();
|
||||
System.exit(errors);
|
||||
@Override
|
||||
protected void execute() throws CLIException {
|
||||
try {
|
||||
CommandLineTester clt = new CommandLineTester(new File(circ.get()));
|
||||
if (tests.isSet())
|
||||
clt.useTestCasesFrom(new File(tests.get()));
|
||||
int errors = clt.execute(System.out);
|
||||
testsPassed = clt.getTestsPassed();
|
||||
if (errors > 0)
|
||||
throw new CLIException(Lang.get("cli_thereAreTestFailures"), errors).hideHelp();
|
||||
} catch (IOException e) {
|
||||
throw new CLIException(Lang.get("cli_errorExecutingTests"), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of tests passed
|
||||
*/
|
||||
public int getTestsPassed() {
|
||||
return testsPassed;
|
||||
}
|
||||
}
|
||||
}
|
42
src/main/java/de/neemann/digital/cli/Main.java
Normal file
42
src/main/java/de/neemann/digital/cli/Main.java
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.cli.cli.CLIException;
|
||||
import de.neemann.digital.cli.cli.Muxer;
|
||||
|
||||
/**
|
||||
* Entry point for the command line interface
|
||||
*/
|
||||
public class Main extends Muxer {
|
||||
/**
|
||||
* Creates a new CLI main
|
||||
*/
|
||||
public Main() {
|
||||
super("java -cp Digital.jar CLI");
|
||||
addCommand(new CommandLineTester.TestCommand());
|
||||
addCommand(new SVGExport());
|
||||
addCommand(new StatsExport());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the command line arguments
|
||||
*
|
||||
* @param args the cli arguments
|
||||
*/
|
||||
public void main(String[] args) {
|
||||
try {
|
||||
execute(args);
|
||||
} catch (CLIException e) {
|
||||
e.printMessage(System.out);
|
||||
if (e.showHelp()) {
|
||||
System.out.println();
|
||||
printDescription(System.out, "");
|
||||
}
|
||||
System.exit(e.getExitCode());
|
||||
}
|
||||
}
|
||||
}
|
65
src/main/java/de/neemann/digital/cli/SVGExport.java
Normal file
65
src/main/java/de/neemann/digital/cli/SVGExport.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.cli.cli.Argument;
|
||||
import de.neemann.digital.cli.cli.ArgumentKey;
|
||||
import de.neemann.digital.cli.cli.BasicCommand;
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.Key;
|
||||
import de.neemann.digital.draw.elements.Circuit;
|
||||
import de.neemann.digital.draw.graphics.Export;
|
||||
import de.neemann.digital.draw.graphics.GraphicSVG;
|
||||
import de.neemann.digital.draw.graphics.SVGSettings;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* CLI svg exporter
|
||||
*/
|
||||
public class SVGExport extends BasicCommand {
|
||||
private final ElementAttributes attr;
|
||||
private final Argument<String> digFile;
|
||||
private final Argument<String> svgFile;
|
||||
private final Argument<Boolean> ieeeShapes;
|
||||
|
||||
/**
|
||||
* Creates the SVG export command
|
||||
*/
|
||||
public SVGExport() {
|
||||
super("svg");
|
||||
|
||||
digFile = addArgument(new Argument<>("dig", "", false));
|
||||
svgFile = addArgument(new Argument<>("svg", "", true));
|
||||
ieeeShapes = addArgument(new Argument<>("ieee", false, true));
|
||||
|
||||
attr = new ElementAttributes();
|
||||
for (Key<?> k : SVGSettings.createKeyList())
|
||||
addArgument(new ArgumentKey<>(k, attr, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute() throws CLIException {
|
||||
try {
|
||||
Circuit circuit = new CircuitLoader(digFile.get(), ieeeShapes.get()).getCircuit();
|
||||
|
||||
String outName;
|
||||
if (svgFile.isSet())
|
||||
outName = svgFile.get();
|
||||
else
|
||||
outName = digFile.get() + ".svg";
|
||||
|
||||
OutputStream out = new FileOutputStream(outName);
|
||||
new Export(circuit, o -> new GraphicSVG(o, attr)).export(out);
|
||||
} catch (IOException e) {
|
||||
throw new CLIException(Lang.get("cli_errorCreatingSVG"), e);
|
||||
}
|
||||
}
|
||||
}
|
57
src/main/java/de/neemann/digital/cli/StatsExport.java
Normal file
57
src/main/java/de/neemann/digital/cli/StatsExport.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.cli.cli.Argument;
|
||||
import de.neemann.digital.cli.cli.BasicCommand;
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
import de.neemann.digital.core.Model;
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.core.stats.Statistics;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
/**
|
||||
* CLI stats exporter
|
||||
*/
|
||||
public class StatsExport extends BasicCommand {
|
||||
private final Argument<String> digFile;
|
||||
private final Argument<String> csvFile;
|
||||
|
||||
/**
|
||||
* Creates the stats export command
|
||||
*/
|
||||
public StatsExport() {
|
||||
super("stats");
|
||||
digFile = addArgument(new Argument<>("dig", "", false));
|
||||
csvFile = addArgument(new Argument<>("csv", "", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute() throws CLIException {
|
||||
try {
|
||||
Model model = new CircuitLoader(digFile.get()).createModel();
|
||||
Statistics stats = new Statistics(model);
|
||||
|
||||
BufferedWriter writer;
|
||||
if (csvFile.isSet())
|
||||
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile.get())));
|
||||
else
|
||||
writer = new BufferedWriter(new OutputStreamWriter(System.out));
|
||||
|
||||
new CSVWriter(stats.getTableModel()).writeTo(writer);
|
||||
|
||||
} catch (IOException | ElementNotFoundException | PinException | NodeException e) {
|
||||
throw new CLIException(Lang.get("cli_errorCreatingStats"), e);
|
||||
}
|
||||
}
|
||||
}
|
100
src/main/java/de/neemann/digital/cli/cli/Argument.java
Normal file
100
src/main/java/de/neemann/digital/cli/cli/Argument.java
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
/**
|
||||
* A command cline argument
|
||||
*
|
||||
* @param <T> the type of the argument
|
||||
*/
|
||||
public class Argument<T> extends ArgumentBase<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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setString(String val) throws CLIException {
|
||||
value = (T) fromString(val, value);
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a value from a string
|
||||
*
|
||||
* @param val the value as a string
|
||||
* @param defValue the default value
|
||||
* @return the value converted to the type of the default value
|
||||
* @throws CLIException CLIException
|
||||
*/
|
||||
public static Object fromString(String val, Object defValue) throws CLIException {
|
||||
if (defValue instanceof String)
|
||||
return val;
|
||||
else if (defValue instanceof Boolean)
|
||||
switch (val.toLowerCase()) {
|
||||
case "yes":
|
||||
case "1":
|
||||
case "true":
|
||||
return true;
|
||||
case "no":
|
||||
case "0":
|
||||
case "false":
|
||||
return false;
|
||||
default:
|
||||
throw new CLIException(Lang.get("cli_notABool_N", val), 106);
|
||||
}
|
||||
else if (defValue instanceof Integer) {
|
||||
try {
|
||||
return 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", defValue.getClass().getSimpleName()), 203);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSet() {
|
||||
return isSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String command) {
|
||||
return Lang.get("cli_help_" + command + "_" + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
}
|
109
src/main/java/de/neemann/digital/cli/cli/ArgumentBase.java
Normal file
109
src/main/java/de/neemann/digital/cli/cli/ArgumentBase.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
/**
|
||||
* The base class of all arguments
|
||||
*
|
||||
* @param <T> the type of the argument
|
||||
*/
|
||||
public abstract class ArgumentBase<T> {
|
||||
|
||||
/**
|
||||
* @return the name of this argument
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/**
|
||||
* @return true if this argument is optional
|
||||
*/
|
||||
public abstract boolean isOptional();
|
||||
|
||||
/**
|
||||
* Sets a string value
|
||||
*
|
||||
* @param val the value to set
|
||||
* @throws CLIException CLIException
|
||||
*/
|
||||
public abstract void setString(String val) throws CLIException;
|
||||
|
||||
/**
|
||||
* @return if this argument was set
|
||||
*/
|
||||
public abstract boolean isSet();
|
||||
|
||||
/**
|
||||
* Returns the description of the argument
|
||||
*
|
||||
* @param command the name of the command this argument belongs to.
|
||||
* @return the description
|
||||
*/
|
||||
public abstract String getDescription(String command);
|
||||
|
||||
/**
|
||||
* @return the value of the option
|
||||
*/
|
||||
public abstract T get();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String s;
|
||||
if (isBool())
|
||||
s = "-" + getName();
|
||||
else
|
||||
s = "-" + getName()
|
||||
+ " ["
|
||||
+ get().getClass().getSimpleName()
|
||||
+ "]";
|
||||
return optionalBrace(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representation containing the default value
|
||||
*/
|
||||
public String toStringDef() {
|
||||
String s;
|
||||
if (isBool())
|
||||
s = "-" + getName()
|
||||
+ "(def: "
|
||||
+ get()
|
||||
+ ")";
|
||||
else
|
||||
s = "-" + getName()
|
||||
+ " ["
|
||||
+ get().getClass().getSimpleName()
|
||||
+ "(def: "
|
||||
+ get()
|
||||
+ ")]";
|
||||
|
||||
return optionalBrace(s);
|
||||
}
|
||||
|
||||
private String optionalBrace(String s) {
|
||||
if (isOptional())
|
||||
return "[" + s + "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this is a bool flag
|
||||
*/
|
||||
public boolean isBool() {
|
||||
return get() instanceof Boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a bool value
|
||||
*
|
||||
* @throws CLIException CLIException
|
||||
*/
|
||||
public void toggle() throws CLIException {
|
||||
if (isBool()) {
|
||||
boolean b = (Boolean) get();
|
||||
setString(Boolean.toString(!b));
|
||||
}
|
||||
}
|
||||
}
|
77
src/main/java/de/neemann/digital/cli/cli/ArgumentKey.java
Normal file
77
src/main/java/de/neemann/digital/cli/cli/ArgumentKey.java
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.Key;
|
||||
|
||||
/**
|
||||
* A cli argument based on a Key instance.
|
||||
*
|
||||
* @param <T> the type of the argument.
|
||||
*/
|
||||
public class ArgumentKey<T> extends ArgumentBase<T> {
|
||||
|
||||
private final Key<T> key;
|
||||
private final ElementAttributes attr;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param key the key
|
||||
* @param attr the attribute to store the values
|
||||
*/
|
||||
public ArgumentKey(Key<T> key, ElementAttributes attr) {
|
||||
this(key, attr, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param key the key
|
||||
* @param attr the attribute to store the values
|
||||
* @param stripFromKey number of characters to strip from the key name
|
||||
*/
|
||||
public ArgumentKey(Key<T> key, ElementAttributes attr, int stripFromKey) {
|
||||
this.key = key;
|
||||
this.attr = attr;
|
||||
if (stripFromKey > 0)
|
||||
name = this.key.getKey().substring(stripFromKey);
|
||||
else
|
||||
name = this.key.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setString(String val) throws CLIException {
|
||||
attr.set(key, (T) Argument.fromString(val, key.getDefault()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSet() {
|
||||
return attr.contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String command) {
|
||||
return key.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return attr.get(key);
|
||||
}
|
||||
}
|
174
src/main/java/de/neemann/digital/cli/cli/BasicCommand.java
Normal file
174
src/main/java/de/neemann/digital/cli/cli/BasicCommand.java
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A simple executable command
|
||||
*/
|
||||
public abstract class BasicCommand extends NamedCommand {
|
||||
private final ArrayList<ArgumentBase<?>> arguments;
|
||||
|
||||
/**
|
||||
* Creates a new command
|
||||
*
|
||||
* @param name the name of the command
|
||||
*/
|
||||
public BasicCommand(String name) {
|
||||
super(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 ArgumentBase<T>> A addArgument(A argument) {
|
||||
arguments.add(argument);
|
||||
return argument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDescription(PrintStream out, String prefix) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName());
|
||||
for (ArgumentBase<?> a : arguments) {
|
||||
sb.append(" ");
|
||||
sb.append(a);
|
||||
}
|
||||
sb.append(":");
|
||||
out.print(prefix);
|
||||
printString(out, prefix + " ", sb.toString());
|
||||
|
||||
prefix += " ";
|
||||
out.print(prefix + " ");
|
||||
printString(out, prefix + " ", Lang.get("cli_help_" + getName()));
|
||||
out.print(prefix);
|
||||
out.println(Lang.get("cli_options"));
|
||||
|
||||
|
||||
for (ArgumentBase<?> a : arguments) {
|
||||
out.println(prefix + " " + a.toStringDef());
|
||||
out.print(prefix + " ");
|
||||
printString(out, prefix + " ", a.getDescription(getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printXMLDescription(Writer w) throws IOException {
|
||||
w.write("<indent>\n");
|
||||
w.append(getName());
|
||||
for (ArgumentBase<?> a : arguments) {
|
||||
w.append(" ");
|
||||
w.append(a.toString());
|
||||
}
|
||||
w.append(":");
|
||||
w.write("<indent>\n");
|
||||
w.write(Lang.get("cli_help_" + getName()));
|
||||
w.write("</indent>\n");
|
||||
w.write("<indent>\n");
|
||||
w.write(Lang.get("cli_options"));
|
||||
for (ArgumentBase<?> a : arguments) {
|
||||
w.write("<indent>\n");
|
||||
w.write(a.toStringDef());
|
||||
w.write("<indent>\n");
|
||||
w.write(a.getDescription(getName()));
|
||||
w.write("</indent>\n");
|
||||
w.write("</indent>\n");
|
||||
}
|
||||
w.write("</indent>\n");
|
||||
w.write("</indent>\n");
|
||||
}
|
||||
|
||||
void printString(PrintStream out, String prefix, String message) {
|
||||
boolean lastWasSpace = false;
|
||||
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();
|
||||
}
|
||||
|
||||
private void set(String arg, Iterator<String> args) throws CLIException {
|
||||
for (ArgumentBase<?> a : arguments)
|
||||
if (arg.equals(a.getName())) {
|
||||
if (a.isBool())
|
||||
a.toggle();
|
||||
else {
|
||||
if (!args.hasNext())
|
||||
throw new CLIException(Lang.get("cli_notEnoughArgumentsGiven"), 100);
|
||||
a.setString(args.next());
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new CLIException(Lang.get("cli_noArgument_N_available", arg), 104);
|
||||
}
|
||||
|
||||
@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("-")) {
|
||||
set(n.substring(1), it);
|
||||
} 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 (ArgumentBase<?> 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;
|
||||
|
||||
}
|
42
src/main/java/de/neemann/digital/cli/cli/CLICommand.java
Normal file
42
src/main/java/de/neemann/digital/cli/cli/CLICommand.java
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* A cli command
|
||||
*/
|
||||
public interface CLICommand {
|
||||
|
||||
/**
|
||||
* Executes the command
|
||||
*
|
||||
* @param args the arguments
|
||||
* @throws CLIException CLIException
|
||||
*/
|
||||
void execute(String[] args) throws CLIException;
|
||||
|
||||
/**
|
||||
* Prints the description
|
||||
*
|
||||
* @param out the print stream
|
||||
* @param prefix the prefex string which should
|
||||
* printed at the beginning of each line
|
||||
*/
|
||||
void printDescription(PrintStream out, String prefix);
|
||||
|
||||
/**
|
||||
* Prints the description in xml format
|
||||
*
|
||||
* @param w the writer to write to
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
void printXMLDescription(Writer w) throws IOException;
|
||||
|
||||
}
|
78
src/main/java/de/neemann/digital/cli/cli/CLIException.java
Normal file
78
src/main/java/de/neemann/digital/cli/cli/CLIException.java
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* he command line exception
|
||||
*/
|
||||
public class CLIException extends Exception {
|
||||
private final int exitCode;
|
||||
private boolean showHelp = true;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints 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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the help text
|
||||
*
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public CLIException hideHelp() {
|
||||
showHelp = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if help has to be shown
|
||||
*/
|
||||
public boolean showHelp() {
|
||||
return showHelp;
|
||||
}
|
||||
}
|
84
src/main/java/de/neemann/digital/cli/cli/Muxer.java
Normal file
84
src/main/java/de/neemann/digital/cli/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.cli;
|
||||
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* The command muxer
|
||||
*/
|
||||
public class Muxer extends NamedCommand {
|
||||
private final HashMap<String, CLICommand> commands;
|
||||
|
||||
/**
|
||||
* Creates a new muxer
|
||||
*
|
||||
* @param name the name of the muxer
|
||||
*/
|
||||
public Muxer(String name) {
|
||||
super(name);
|
||||
this.commands = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a command to the muxer
|
||||
*
|
||||
* @param command the command
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public Muxer addCommand(NamedCommand 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(getName());
|
||||
out.println();
|
||||
for (CLICommand c : commands.values())
|
||||
c.printDescription(out, prefix + " ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printXMLDescription(Writer w) throws IOException {
|
||||
w.write("<indent>\n");
|
||||
w.write(getName());
|
||||
for (CLICommand c : commands.values())
|
||||
c.printXMLDescription(w);
|
||||
w.write("</indent>\n");
|
||||
}
|
||||
|
||||
@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", getName(), args[0]), 101);
|
||||
|
||||
command.execute(Arrays.copyOfRange(args, 1, args.length));
|
||||
}
|
||||
|
||||
}
|
29
src/main/java/de/neemann/digital/cli/cli/NamedCommand.java
Normal file
29
src/main/java/de/neemann/digital/cli/cli/NamedCommand.java
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
/**
|
||||
* The base class of all named commands
|
||||
*/
|
||||
public abstract class NamedCommand implements CLICommand {
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param name the name of the command
|
||||
*/
|
||||
public NamedCommand(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the command
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
10
src/main/java/de/neemann/digital/cli/cli/package-info.java
Normal file
10
src/main/java/de/neemann/digital/cli/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 classes needed to implement the command line interface
|
||||
*/
|
||||
package de.neemann.digital.cli.cli;
|
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;
|
@ -52,7 +52,10 @@ public final class SVGSettings extends SettingsBase {
|
||||
super(createKeyList(), ".svgStyle.cfg");
|
||||
}
|
||||
|
||||
private static List<Key> createKeyList() {
|
||||
/**
|
||||
* @return a list of available SVG export keys
|
||||
*/
|
||||
public static List<Key> createKeyList() {
|
||||
ArrayList<Key> list = new ArrayList<>();
|
||||
list.add(LATEX);
|
||||
list.add(PINS_IN_MATH_MODE);
|
||||
|
@ -69,7 +69,7 @@ public final class InfoDialog implements Iterable<InfoDialog.Manifest> {
|
||||
*/
|
||||
private String createMessage(String message) {
|
||||
StringBuilder sb = new StringBuilder("<html>");
|
||||
sb.append(message.replace("\n", "<br/>"));
|
||||
sb.append(message.replace("\n\n", "<br/><br/>"));
|
||||
sb.append("\n\n");
|
||||
for (Manifest m : infos) {
|
||||
m.createInfoString(sb);
|
||||
@ -93,6 +93,9 @@ public final class InfoDialog implements Iterable<InfoDialog.Manifest> {
|
||||
ta.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true);
|
||||
ta.setEditable(false);
|
||||
ta.setBackground(new JLabel().getBackground());
|
||||
ta.setSize(new Dimension(400, 800));
|
||||
ta.setPreferredSize(new Dimension(400, ta.getPreferredSize().height + 30));
|
||||
|
||||
Font font = ta.getFont().deriveFont(Font.BOLD);
|
||||
ta.setFont(font);
|
||||
int border = font.getSize();
|
||||
|
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,43 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="lib_ram">RAM</string>
|
||||
<string name="lib_eeprom">EEPROM</string>
|
||||
|
||||
<string name="cli_cli">Steuerung per Kommandozeile</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_options">Optionen:</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_tests">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="cli_help_svg">Kann verwendet werden, um aus einer Schaltung
|
||||
eine SVG-Datei zu erzeugen.
|
||||
</string>
|
||||
<string name="cli_help_svg_dig">Der Dateiname der Schaltung.</string>
|
||||
<string name="cli_help_svg_svg">Der Name der zu schreibenden SVG-Datei.</string>
|
||||
<string name="cli_help_svg_ieee">Verwendung der IEEE Symbole.</string>
|
||||
<string name="cli_errorCreatingSVG">Fehler bei der Erzeugung der SVG Datei!</string>
|
||||
|
||||
<string name="cli_help_stats">Erzeugt eine CSV Datei welche die Schaltungsstatistik enthält.
|
||||
Aufgeführt sind alle verwendeten Komponenten.
|
||||
</string>
|
||||
<string name="cli_help_stats_dig">Name der Schaltung.</string>
|
||||
<string name="cli_help_stats_csv">Name der Ausgabedatei.
|
||||
Wenn diese Option fehlt, erfolgt eine Ausgabe auf die Konsole.
|
||||
</string>
|
||||
<string name="cli_errorCreatingStats">Fehler bei der Erzeugung der CSV Datei!</string>
|
||||
|
||||
<string name="menu_window">Fenster</string>
|
||||
<string name="menu_about">Über Digital</string>
|
||||
<string name="menu_analyse">Analyse</string>
|
||||
|
@ -1505,6 +1505,41 @@
|
||||
<string name="lib_ram">RAM</string>
|
||||
<string name="lib_eeprom">EEPROM</string>
|
||||
|
||||
<string name="cli_cli">Command Line Interface</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_options">Options:</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_tests">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="cli_help_svg">Can be used to create an SVG file from a circuit.</string>
|
||||
<string name="cli_help_svg_dig">The file name of the circuit.</string>
|
||||
<string name="cli_help_svg_svg">The name of the SVG file to be written.</string>
|
||||
<string name="cli_help_svg_ieee">Use of the IEEE symbols.</string>
|
||||
<string name="cli_errorCreatingSVG">Error while creating the SVG file!</string>
|
||||
|
||||
<string name="cli_help_stats">Creates a CSV file which contains the circuit statistics.
|
||||
All components used are listed in the CSV file.
|
||||
</string>
|
||||
<string name="cli_help_stats_dig">File name of the circuit.</string>
|
||||
<string name="cli_help_stats_csv">Name of the csv file to be created.
|
||||
If this option is missing, the table is written to stdout.
|
||||
</string>
|
||||
<string name="cli_errorCreatingStats">Error while creating the stats file!</string>
|
||||
|
||||
<string name="menu_window">Windows</string>
|
||||
<string name="menu_about">About</string>
|
||||
<string name="menu_analyse">Analysis</string>
|
||||
|
65
src/test/java/de/neemann/digital/cli/ArgumentTest.java
Normal file
65
src/test/java/de/neemann/digital/cli/ArgumentTest.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.cli.cli.Argument;
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
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 testToggle() throws CLIException {
|
||||
Argument<Boolean> a = new Argument<>("flag", false, false);
|
||||
assertTrue(a.isBool());
|
||||
assertFalse(a.get());
|
||||
a.toggle();
|
||||
assertTrue(a.get());
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
106
src/test/java/de/neemann/digital/cli/BasicCommandTest.java
Normal file
106
src/test/java/de/neemann/digital/cli/BasicCommandTest.java
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.cli.cli.Argument;
|
||||
import de.neemann.digital.cli.cli.BasicCommand;
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class BasicCommandTest extends TestCase {
|
||||
|
||||
private static class TestCommand extends BasicCommand {
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -3,8 +3,9 @@
|
||||
* Use of this source code is governed by the GPL v3 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
package de.neemann.digital.testing;
|
||||
package de.neemann.digital.cli;
|
||||
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
import de.neemann.digital.integration.Resources;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@ -16,7 +17,7 @@ public class CommandLineTesterTest extends TestCase {
|
||||
public void test74181() throws IOException {
|
||||
File source = new File(Resources.getRoot(), "../../main/dig/lib/DIL Chips/74xx/arithmetic/74181.dig");
|
||||
CommandLineTester tester = new CommandLineTester(source);
|
||||
int errors = tester.execute();
|
||||
int errors = tester.execute(System.out);
|
||||
assertEquals(0, errors);
|
||||
assertEquals(32, tester.getTestsPassed());
|
||||
}
|
||||
@ -24,7 +25,7 @@ public class CommandLineTesterTest extends TestCase {
|
||||
public void testFailing() throws IOException {
|
||||
File source = new File(Resources.getRoot(), "dig/failingTest.dig");
|
||||
CommandLineTester tester = new CommandLineTester(source);
|
||||
int errors = tester.execute();
|
||||
int errors = tester.execute(System.out);
|
||||
assertEquals(1, errors);
|
||||
assertEquals(0, tester.getTestsPassed());
|
||||
}
|
||||
@ -34,9 +35,28 @@ public class CommandLineTesterTest extends TestCase {
|
||||
CommandLineTester tester = new CommandLineTester(source)
|
||||
.useTestCasesFrom(new File(Resources.getRoot(), "../../main/dig/sequential/Counter-D.dig"));
|
||||
|
||||
int errors = tester.execute();
|
||||
int errors = tester.execute(System.out);
|
||||
assertEquals(0, errors);
|
||||
assertEquals(1, tester.getTestsPassed());
|
||||
}
|
||||
|
||||
public void testCommand() throws CLIException {
|
||||
File source = new File(Resources.getRoot(), "dig/failingTest.dig");
|
||||
File tests = new File(Resources.getRoot(), "../../main/dig/sequential/Counter-D.dig");
|
||||
CommandLineTester.TestCommand tc = new CommandLineTester.TestCommand();
|
||||
tc.execute(new String[]{source.getPath(), "-tests", tests.getPath()});
|
||||
assertEquals(1, tc.getTestsPassed());
|
||||
}
|
||||
|
||||
public void testCommandTestFail() {
|
||||
try {
|
||||
File source = new File(Resources.getRoot(), "dig/failingTest.dig");
|
||||
CommandLineTester.TestCommand tc = new CommandLineTester.TestCommand();
|
||||
tc.execute(new String[]{source.getPath()});
|
||||
fail();
|
||||
} catch (CLIException e) {
|
||||
assertEquals(1, e.getExitCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
96
src/test/java/de/neemann/digital/cli/MuxerTest.java
Normal file
96
src/test/java/de/neemann/digital/cli/MuxerTest.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.cli.cli.Argument;
|
||||
import de.neemann.digital.cli.cli.BasicCommand;
|
||||
import de.neemann.digital.cli.cli.CLIException;
|
||||
import de.neemann.digital.cli.cli.Muxer;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class MuxerTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Creates the documentation.
|
||||
* Used to make the maven build fail, if a language key is missing.
|
||||
*/
|
||||
public void testDocu() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
new Main().printDescription(new PrintStream(baos), "");
|
||||
assertTrue(baos.toByteArray().length > 100);
|
||||
}
|
||||
|
||||
public void testErrors() throws CLIException {
|
||||
TestCommand tc = new TestCommand();
|
||||
Muxer m = new Muxer("test").addCommand(tc);
|
||||
|
||||
try {
|
||||
m.execute(new String[]{"add"});
|
||||
fail();
|
||||
} catch (CLIException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
m.execute(new String[]{"add", "-arg", "zz"});
|
||||
assertEquals("zz", tc.arg.get());
|
||||
|
||||
try {
|
||||
m.execute(new String[]{"add", "-foo", "zz"});
|
||||
fail();
|
||||
} catch (CLIException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
m.execute(new String[]{"sub"});
|
||||
fail();
|
||||
} catch (CLIException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try {
|
||||
m.execute(new String[]{});
|
||||
fail();
|
||||
} catch (CLIException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNesting() throws CLIException {
|
||||
TestCommand tc = new TestCommand();
|
||||
Muxer m = new Muxer("main")
|
||||
.addCommand(new Muxer("arith")
|
||||
.addCommand(tc));
|
||||
|
||||
m.execute(new String[]{"arith", "add", "-arg", "tt"});
|
||||
|
||||
assertTrue(tc.wasExecuted);
|
||||
}
|
||||
|
||||
private static class TestCommand extends BasicCommand {
|
||||
private final Argument<String> arg;
|
||||
private boolean wasExecuted = false;
|
||||
|
||||
public TestCommand() {
|
||||
super("add");
|
||||
arg = addArgument(new Argument<>("arg", "def", false));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void printDescription(PrintStream out, String prefix) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute() {
|
||||
wasExecuted = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
34
src/test/java/de/neemann/digital/cli/StatsExportTest.java
Normal file
34
src/test/java/de/neemann/digital/cli/StatsExportTest.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.cli.cli.CLIException;
|
||||
import de.neemann.digital.integration.Resources;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class StatsExportTest extends TestCase {
|
||||
|
||||
public void testStats() throws CLIException {
|
||||
File source = new File(Resources.getRoot(), "../../main/dig/sequential/Counter-T.dig");
|
||||
PrintStream old = System.out;
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (PrintStream out = new PrintStream(baos)) {
|
||||
System.setOut(out);
|
||||
new StatsExport().execute(new String[]{source.getPath()});
|
||||
}
|
||||
String outStr = baos.toString();
|
||||
assertTrue(outStr.contains("FlipflopT,,,,4"));
|
||||
} finally {
|
||||
System.setOut(old);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package de.neemann.digital.docu;
|
||||
|
||||
import de.neemann.digital.cli.Main;
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.core.element.*;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
@ -89,6 +90,8 @@ public class DocuTest extends TestCase {
|
||||
w.append(" </circuit>\n");
|
||||
w.append(" </settings>\n");
|
||||
|
||||
writeCLIDescription(w);
|
||||
|
||||
ElementLibrary library = new ElementLibrary();
|
||||
ShapeFactory shapeFactory = new ShapeFactory(library, !language.equals("de"));
|
||||
String actPath = null;
|
||||
@ -139,6 +142,12 @@ public class DocuTest extends TestCase {
|
||||
w.append("</root>");
|
||||
}
|
||||
|
||||
private void writeCLIDescription(Writer w) throws IOException {
|
||||
w.append(" <cli heading=\"").append(Lang.get("cli_cli")).append("\">\n");
|
||||
new Main().printXMLDescription(w);
|
||||
w.append(" </cli>\n");
|
||||
}
|
||||
|
||||
private void writeAttributes(Writer w, List<Key> keyList) throws IOException {
|
||||
w.append(" <attributes name=\"").append(Lang.get("elem_Help_attributes")).append("\">\n");
|
||||
for (Key k : keyList) {
|
||||
|
@ -68,7 +68,7 @@ public class TestLang extends TestCase {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String key : map.keySet()) {
|
||||
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)
|
||||
sb.append(", ");
|
||||
sb.append('"').append(key).append('"');
|
||||
|
@ -78,43 +78,86 @@
|
||||
<fo:block page-break-before="always" margin-bottom="5mm" font-size="18pt" font-weight="bold">
|
||||
<xsl:value-of select="@toc"/>
|
||||
</fo:block>
|
||||
<!-- table of contents -->
|
||||
<!-- table of contents -->
|
||||
<fo:block margin-bottom="2mm" font-weight="bold">
|
||||
A <fo:inline padding-left="1mm"><xsl:value-of select="@general"/></fo:inline>
|
||||
A
|
||||
<fo:inline padding-left="1mm">
|
||||
<xsl:value-of select="@general"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="document(@static)/*" mode="toc"/>
|
||||
<fo:block margin-top="2mm" margin-bottom="2mm" font-weight="bold">
|
||||
<fo:basic-link show-destination="replace" internal-destination="chap_settings">
|
||||
B <fo:inline padding-left="2mm"><xsl:value-of select="settings/@name"/></fo:inline>
|
||||
B
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="settings/@name"/>
|
||||
</fo:inline>
|
||||
</fo:basic-link>
|
||||
</fo:block>
|
||||
<fo:block margin-top="2mm" margin-bottom="2mm" font-weight="bold">
|
||||
C <fo:inline padding-left="2mm"><xsl:value-of select="@components"/></fo:inline>
|
||||
<fo:basic-link show-destination="replace" internal-destination="chap_cli">
|
||||
C
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="cli/@heading"/>
|
||||
</fo:inline>
|
||||
</fo:basic-link>
|
||||
</fo:block>
|
||||
<fo:block margin-top="2mm" margin-bottom="2mm" font-weight="bold">
|
||||
D
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="@components"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="lib" mode="toc"/>
|
||||
<fo:block margin-top="2mm" margin-bottom="2mm" font-weight="bold">
|
||||
<fo:basic-link show-destination="replace" internal-destination="chap_library">
|
||||
D <fo:inline padding-left="2mm"><xsl:value-of select="@lib"/></fo:inline>
|
||||
E
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="@lib"/>
|
||||
</fo:inline>
|
||||
</fo:basic-link>
|
||||
</fo:block>
|
||||
<fo:block page-break-before="always"/>
|
||||
<!-- the content -->
|
||||
<fo:block margin-top="4mm" margin-bottom="4mm" font-size="16pt" font-weight="bold">
|
||||
A <fo:inline padding-left="2mm"><xsl:value-of select="@general"/></fo:inline>
|
||||
A
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="@general"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="document(@static)/*" mode="full"/>
|
||||
|
||||
<fo:block page-break-before="always" margin-top="4mm" margin-bottom="4mm" font-size="16pt" font-weight="bold" id="chap_settings">
|
||||
B <fo:inline padding-left="2mm"><xsl:value-of select="settings/@name"/></fo:inline>
|
||||
<fo:block page-break-before="always" margin-top="4mm" margin-bottom="4mm" font-size="16pt"
|
||||
font-weight="bold" id="chap_settings">
|
||||
B
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="settings/@name"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="settings" mode="full"/>
|
||||
|
||||
<fo:block page-break-before="always" margin-top="4mm" margin-bottom="4mm" font-size="16pt"
|
||||
font-weight="bold" id="chap_cli">
|
||||
C
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="cli/@heading"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="cli" mode="full"/>
|
||||
|
||||
<fo:block page-break-before="always" margin-bottom="4mm" font-size="16pt" font-weight="bold">
|
||||
C <fo:inline padding-left="2mm"><xsl:value-of select="@components"/></fo:inline>
|
||||
D
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="@components"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="lib" mode="full"/>
|
||||
<fo:block page-break-before="always" margin-bottom="4mm" font-size="16pt" font-weight="bold" id="chap_library">
|
||||
D <fo:inline padding-left="2mm"><xsl:value-of select="@lib"/></fo:inline>
|
||||
<fo:block page-break-before="always" margin-bottom="4mm" font-size="16pt" font-weight="bold"
|
||||
id="chap_library">
|
||||
E
|
||||
<fo:inline padding-left="2mm">
|
||||
<xsl:value-of select="@lib"/>
|
||||
</fo:inline>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="document(@library)/*"/>
|
||||
<fo:block id="LastPage"/>
|
||||
@ -294,14 +337,25 @@
|
||||
<xsl:apply-templates select="circuit/attributes"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cli" mode="full">
|
||||
<xsl:apply-templates select="indent"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="indent">
|
||||
<fo:block margin-left="4mm" start-indent="2mm" margin-top="2mm" margin-bottom="2mm">
|
||||
<xsl:apply-templates/>
|
||||
</fo:block>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="lib" mode="full">
|
||||
<fo:block page-break-after="avoid" margin-top="4mm" margin-bottom="4mm" font-size="16pt" font-weight="bold">
|
||||
<xsl:value-of select="position()"/>. <xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="position()"/>.
|
||||
<xsl:value-of select="@name"/>
|
||||
</fo:block>
|
||||
<xsl:apply-templates select="element" mode="full">
|
||||
<xsl:with-param name="number" select="position()"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="element" mode="full">
|
||||
<xsl:param name="number" />
|
||||
|
@ -515,7 +515,7 @@
|
||||
</par>
|
||||
<par>
|
||||
<code>
|
||||
java -cp Digital.jar de.neemann.digital.testing.CommandLineTester [zu testende Datei] [[optionale Datei
|
||||
java -cp Digital.jar CLI test [zu testende Datei] [-tests [optionale Datei
|
||||
mit Testfällen]]
|
||||
</code>
|
||||
</par>
|
||||
|
@ -484,7 +484,7 @@
|
||||
</par>
|
||||
<par>
|
||||
<code>
|
||||
java -cp Digital.jar de.neemann.digital.testing.CommandLineTester [file to test] [[optional file with
|
||||
java -cp Digital.jar CLI test [file to test] [-tests [optional file with
|
||||
test cases]]
|
||||
</code>
|
||||
</par>
|
||||
|
@ -310,7 +310,7 @@
|
||||
</par>
|
||||
<par>
|
||||
<code>
|
||||
java -cp Digital.jar de.neemann.digital.testing.CommandLineTester [file to test] [[optional file with
|
||||
java -cp Digital.jar CLI test [file to test] [-tests [optional file with
|
||||
test cases]]
|
||||
</code>
|
||||
</par>
|
||||
|
@ -556,7 +556,7 @@
|
||||
</par>
|
||||
<par>
|
||||
<code>
|
||||
java -cp Digital.jar de.neemann.digital.testing.CommandLineTester [file to test] [[optional file with
|
||||
java -cp Digital.jar CLI test [file to test] [-tests [optional file with
|
||||
test cases]]
|
||||
</code>
|
||||
</par>
|
||||
|
Loading…
x
Reference in New Issue
Block a user