You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vk...@apache.org on 2020/12/22 01:50:09 UTC
[ignite-3] branch main updated: CLI tool: help improvements
This is an automated email from the ASF dual-hosted git repository.
vkulichenko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new cedb629 CLI tool: help improvements
cedb629 is described below
commit cedb629ecf1d680bfe07148cf955caf5969c964d
Author: Valentin Kulichenko <va...@gmail.com>
AuthorDate: Mon Dec 21 17:49:48 2020 -0800
CLI tool: help improvements
---
.../java/org/apache/ignite/cli/ErrorHandler.java | 12 +-
.../org/apache/ignite/cli/HelpFactoryImpl.java | 228 ++++++++++-----------
.../src/main/java/org/apache/ignite/cli/Table.java | 75 +++++--
...nitIgniteCommandSpec.java => CategorySpec.java} | 21 +-
.../{AbstractCommandSpec.java => CommandSpec.java} | 9 +-
.../apache/ignite/cli/spec/ConfigCommandSpec.java | 12 +-
.../org/apache/ignite/cli/spec/IgniteCliSpec.java | 13 +-
.../ignite/cli/spec/InitIgniteCommandSpec.java | 3 +-
.../apache/ignite/cli/spec/ModuleCommandSpec.java | 14 +-
.../apache/ignite/cli/spec/NodeCommandSpec.java | 15 +-
.../org/apache/ignite/cli/spec/SpecAdapter.java | 55 +++++
.../java/org/apache/ignite/app/IgniteRunner.java | 4 +-
12 files changed, 262 insertions(+), 199 deletions(-)
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/ErrorHandler.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/ErrorHandler.java
index eba44d7..ae68a02 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/ErrorHandler.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/ErrorHandler.java
@@ -19,7 +19,7 @@ package org.apache.ignite.cli;
import javax.inject.Inject;
import io.micronaut.context.ApplicationContext;
-import org.apache.ignite.cli.spec.IgniteCliSpec;
+import org.apache.ignite.cli.spec.CategorySpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
@@ -45,9 +45,15 @@ public class ErrorHandler implements CommandLine.IExecutionExceptionHandler, Com
@Override public int handleParseException(CommandLine.ParameterException ex, String[] args) {
CommandLine cli = ex.getCommandLine();
- cli.getErr().println(cli.getColorScheme().errorText("ERROR: ") + ex.getMessage() + '\n');
+ if (cli.getCommand() instanceof CategorySpec) {
+ ((Runnable)cli.getCommand()).run();
+ }
+ else {
+ cli.getErr().println(cli.getColorScheme().errorText("[ERROR] ") + ex.getMessage() +
+ ". Please see usage information below.\n");
- cli.usage(cli.getOut());
+ cli.usage(cli.getOut());
+ }
return cli.getCommandSpec().exitCodeOnInvalidInput();
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/HelpFactoryImpl.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/HelpFactoryImpl.java
index a5c40b5..e2f1583 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/HelpFactoryImpl.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/HelpFactoryImpl.java
@@ -1,167 +1,147 @@
package org.apache.ignite.cli;
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.Optional;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.ToIntFunction;
-import java.util.stream.Collectors;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.cli.spec.SpecAdapter;
import picocli.CommandLine;
+import picocli.CommandLine.Help.Ansi;
+import picocli.CommandLine.Help.ColorScheme;
+import picocli.CommandLine.Model.OptionSpec;
+import picocli.CommandLine.Model.PositionalParamSpec;
public class HelpFactoryImpl implements CommandLine.IHelpFactory {
-
public static final String SECTION_KEY_BANNER = "banner";
- public static final String SECTION_KEY_SYNOPSIS_EXTENSION = "synopsisExt";
-
- private static final String[] BANNER = new String[] {
- " ___ __",
- " / | ____ ____ _ _____ / /_ ___",
- " @|red,bold ⣠⣶⣿|@ / /| | / __ \\ / __ `// ___// __ \\ / _ \\",
- " @|red,bold ⣿⣿⣿⣿|@ / ___ | / /_/ // /_/ // /__ / / / // __/",
- " @|red,bold ⢠⣿⡏⠈⣿⣿⣿⣿⣷|@ /_/ |_|/ .___/ \\__,_/ \\___//_/ /_/ \\___/",
- " @|red,bold ⢰⣿⣿⣿⣧⠈⢿⣿⣿⣿⣿⣦|@ /_/",
- " @|red,bold ⠘⣿⣿⣿⣿⣿⣦⠈⠛⢿⣿⣿⣿⡄|@ ____ _ __ _____",
- " @|red,bold ⠈⠛⣿⣿⣿⣿⣿⣿⣦⠉⢿⣿⡟|@ / _/____ _ ____ (_)/ /_ ___ |__ /",
- " @|red,bold ⢰⣿⣶⣀⠈⠙⠿⣿⣿⣿⣿ ⠟⠁|@ / / / __ `// __ \\ / // __// _ \\ /_ <",
- " @|red,bold ⠈⠻⣿⣿⣿⣿⣷⣤⠙⢿⡟|@ _/ / / /_/ // / / // // /_ / __/ ___/ /",
- " @|red,bold ⠉⠉⠛⠏⠉|@ /___/ \\__, //_/ /_//_/ \\__/ \\___/ /____/",
- " /____/\n"};
-
- @Override public CommandLine.Help create(CommandLine.Model.CommandSpec commandSpec,
- CommandLine.Help.ColorScheme colorScheme) {
+ public static final String SECTION_KEY_PARAMETER_OPTION_TABLE = "paramsOptsTable";
+
+ @Override public CommandLine.Help create(CommandLine.Model.CommandSpec commandSpec, ColorScheme cs) {
+ boolean hasCommands = !commandSpec.subcommands().isEmpty();
+ boolean hasOptions = commandSpec.options().stream().anyMatch(o -> !o.hidden());
+ boolean hasParameters = commandSpec.positionalParameters().stream().anyMatch(o -> !o.hidden());
+
+ // Any command can have either subcommands or options/parameters, but not both.
+ assert !(hasCommands && (hasOptions || hasParameters));
+
commandSpec.usageMessage().sectionKeys(Arrays.asList(
SECTION_KEY_BANNER,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_HEADER,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_DESCRIPTION,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_SYNOPSIS_HEADING,
CommandLine.Model.UsageMessageSpec.SECTION_KEY_SYNOPSIS,
- SECTION_KEY_SYNOPSIS_EXTENSION,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_PARAMETER_LIST_HEADING,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_PARAMETER_LIST,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST_HEADING,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST_HEADING,
- CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST));
+ CommandLine.Model.UsageMessageSpec.SECTION_KEY_DESCRIPTION,
+ CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST,
+ SECTION_KEY_PARAMETER_OPTION_TABLE
+ ));
var sectionMap = new HashMap<String, CommandLine.IHelpSectionRenderer>();
- boolean hasCommands = !commandSpec.subcommands().isEmpty();
- boolean hasOptions = commandSpec.options().stream().anyMatch(o -> !o.hidden());
- boolean hasParameters = !commandSpec.positionalParameters().isEmpty();
-
- sectionMap.put(SECTION_KEY_BANNER,
- help -> Arrays
- .stream(BANNER)
- .map(CommandLine.Help.Ansi.AUTO::string)
- .collect(Collectors.joining("\n")) +
- "\n"
- );
-
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_HEADER,
- help -> CommandLine.Help.Ansi.AUTO.string(
- Arrays.stream(help.commandSpec().version())
- .collect(Collectors.joining("\n")) + "\n\n")
- );
+ if (commandSpec.commandLine().isUsageHelpRequested()) {
+ sectionMap.put(SECTION_KEY_BANNER,
+ help -> {
+ assert help.commandSpec().commandLine().getCommand() instanceof SpecAdapter;
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_DESCRIPTION,
- help -> CommandLine.Help.Ansi.AUTO.string("@|bold,green " + help.commandSpec().qualifiedName() +
- "|@\n " + help.description() + "\n"));
+ return ((SpecAdapter)help.commandSpec().commandLine().getCommand()).banner();
+ }
+ );
+ }
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_SYNOPSIS_HEADING,
- help -> CommandLine.Help.Ansi.AUTO.string("@|bold USAGE|@\n"));
+ if (!hasCommands) {
+ sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_SYNOPSIS,
+ help -> {
+ StringBuilder sb = new StringBuilder();
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_SYNOPSIS,
- help -> {
- StringBuilder sb = new StringBuilder();
+ List<Ansi.IStyle> boldCmdStyle = new ArrayList<>(cs.commandStyles());
- sb.append(" ");
- sb.append(help.colorScheme().commandText(help.commandSpec().qualifiedName()));
+ boldCmdStyle.add(Ansi.Style.bold);
+
+ sb.append(cs.apply(help.commandSpec().qualifiedName(), boldCmdStyle));
- if (hasCommands) {
- sb.append(help.colorScheme().commandText(" <COMMAND>"));
- }
- else {
if (hasOptions)
- sb.append(help.colorScheme().optionText(" [OPTIONS]"));
+ sb.append(cs.optionText(" [OPTIONS]"));
if (hasParameters) {
- for (CommandLine.Model.PositionalParamSpec parameter : commandSpec.positionalParameters())
- sb.append(' ').append(help.colorScheme().parameterText(parameter.paramLabel()));
+ for (PositionalParamSpec parameter : commandSpec.positionalParameters())
+ sb.append(' ').append(cs.parameterText(parameter.paramLabel()));
}
- }
- sb.append("\n\n");
-
- return sb.toString();
- });
+ sb.append("\n\n");
+ return sb.toString();
+ }
+ );
+ }
- Optional.ofNullable(commandSpec.usageMessage().sectionMap().get(SECTION_KEY_SYNOPSIS_EXTENSION))
- .ifPresent(v -> sectionMap.put(SECTION_KEY_SYNOPSIS_EXTENSION, v));
+ sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_DESCRIPTION,
+ help -> Ansi.AUTO.string(help.description() + '\n'));
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_PARAMETER_LIST_HEADING,
- help -> hasParameters ? CommandLine.Help.Ansi.AUTO.string("@|bold REQUIRED PARAMETERS|@\n") : "");
+ if (hasCommands) {
+ sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST, help -> {
+ Table table = new Table(0, cs);
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_PARAMETER_LIST, new TableRenderer<>(
- h -> h.commandSpec().positionalParameters(),
- p -> p.paramLabel().length(),
- (h, p) -> h.colorScheme().parameterText(p.paramLabel()),
- (h, p) -> h.colorScheme().text(p.description()[0])));
+ table.addSection("@|bold COMMANDS|@");
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST_HEADING,
- help -> hasOptions ? CommandLine.Help.Ansi.AUTO.string("@|bold OPTIONS|@\n") : "");
+ for (Map.Entry<String, CommandLine.Help> entry : help.subcommands().entrySet()) {
+ String name = entry.getKey();
+ CommandLine.Help cmd = entry.getValue();
- if (hasOptions)
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST, new TableRenderer<>(
- h -> h.commandSpec().options(),
- o -> o.shortestName().length() + o.paramLabel().length() + 1,
- (h, o) -> h.colorScheme().optionText(o.shortestName()).concat("=").concat(o.paramLabel()),
- (h, o) -> h.colorScheme().text(o.description()[0])));
+ if (cmd.subcommands().isEmpty()) {
+ table.addRow(cs.commandText(name), cmd.description().trim());
+ }
+ else {
+ for (Map.Entry<String, CommandLine.Help> subEntry : cmd.subcommands().entrySet()) {
+ String subName = subEntry.getKey();
+ CommandLine.Help subCmd = subEntry.getValue();
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST_HEADING,
- help -> hasCommands ? CommandLine.Help.Ansi.AUTO.string("@|bold COMMANDS|@\n") : "");
+ // Further hierarchy is prohibited.
+ assert subCmd.subcommands().isEmpty();
- sectionMap.put(CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST, new TableRenderer<>(
- h -> h.subcommands().values(),
- c -> c.commandSpec().name().length(),
- (h, c) -> h.colorScheme().commandText(c.commandSpec().name()),
- (h, c) -> h.colorScheme().text(c.description().stripTrailing())));
- commandSpec.usageMessage().sectionMap(sectionMap);
- return new CommandLine.Help(commandSpec, colorScheme);
- }
+ table.addRow(cs.commandText(name + " " + subName), subCmd.description().trim());
+ }
+ }
+ }
- private static class TableRenderer<T> implements CommandLine.IHelpSectionRenderer {
- private final Function<CommandLine.Help, Collection<T>> itemsFunc;
- private final ToIntFunction<T> nameLenFunc;
- private final BiFunction<CommandLine.Help, T, CommandLine.Help.Ansi.Text> nameFunc;
- private final BiFunction<CommandLine.Help, T, CommandLine.Help.Ansi.Text> descriptionFunc;
-
- TableRenderer(Function<CommandLine.Help, Collection<T>> itemsFunc, ToIntFunction<T> nameLenFunc,
- BiFunction<CommandLine.Help, T, CommandLine.Help.Ansi.Text> nameFunc, BiFunction<CommandLine.Help, T, CommandLine.Help.Ansi.Text> descriptionFunc) {
- this.itemsFunc = itemsFunc;
- this.nameLenFunc = nameLenFunc;
- this.nameFunc = nameFunc;
- this.descriptionFunc = descriptionFunc;
+ return table.toString();
+ });
}
+ else if (hasParameters || hasOptions) {
+ sectionMap.put(SECTION_KEY_PARAMETER_OPTION_TABLE, help -> {
+ Table table = new Table(0, cs);
- @Override public String render(CommandLine.Help help) {
- Collection<T> items = itemsFunc.apply(help);
+ if (hasParameters) {
+ table.addSection("@|bold REQUIRED PARAMETERS|@");
- if (items.isEmpty())
- return "";
+ for (PositionalParamSpec param : help.commandSpec().positionalParameters()) {
+ if (!param.hidden()) {
+ // TODO: Support multiple-line descriptions.
+ assert param.description().length == 1;
- int len = 2 + items.stream().mapToInt(nameLenFunc).max().getAsInt();
+ table.addRow(cs.parameterText(param.paramLabel()), param.description()[0]);
+ }
+ }
+ }
+
+ if (hasOptions) {
+ table.addSection("@|bold OPTIONS|@");
- CommandLine.Help.TextTable table = CommandLine.Help.TextTable.forColumns(help.colorScheme(),
- new CommandLine.Help.Column(len, 2, CommandLine.Help.Column.Overflow.SPAN),
- new CommandLine.Help.Column(160 - len, 4, CommandLine.Help.Column.Overflow.WRAP));
+ for (OptionSpec option : help.commandSpec().options()) {
+ if (!option.hidden()) {
+ // TODO: Support multiple names.
+ assert option.names().length == 1;
+ // TODO: Support multiple-line descriptions.
+ assert option.description().length == 1;
- for (T item : items)
- table.addRowValues(nameFunc.apply(help, item), descriptionFunc.apply(help, item));
+ table.addRow(
+ cs.optionText(option.names()[0] + '=' + option.paramLabel()),
+ option.description()[0]);
+ }
+ }
+ }
- return table.toString() + '\n';
+ return table.toString();
+ });
}
+
+ commandSpec.usageMessage().sectionMap(sectionMap);
+
+ return new CommandLine.Help(commandSpec, cs);
}
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/Table.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/Table.java
index af43004..cc4cffb 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/Table.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/Table.java
@@ -18,6 +18,7 @@
package org.apache.ignite.cli;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import picocli.CommandLine.Help.Ansi.Text;
import picocli.CommandLine.Help.ColorScheme;
@@ -30,7 +31,7 @@ public class Table {
private final ColorScheme colorScheme;
- private final Collection<Text[]> data = new ArrayList<>();
+ private final Collection<Row> data = new ArrayList<>();
private int[] lengths;
@@ -76,7 +77,18 @@ public class Table {
lengths[i] = Math.max(lengths[i], text.getCJKAdjustedLength());
}
- data.add(row);
+ data.add(new DataRow(row));
+ }
+
+ /**
+ * Adds a section. Title spans all columns in the table.
+ *
+ * @param title Section title.
+ */
+ public void addSection(Object title) {
+ Text text = title instanceof Text ? (Text)title : colorScheme.text(title.toString());
+
+ data.add(new SectionTitle(text));
}
/**
@@ -85,13 +97,12 @@ public class Table {
* @return String representation of this table.
*/
@Override public String toString() {
- String indentStr = " ".repeat(indent);
+ if (data.isEmpty())
+ return "";
StringBuilder sb = new StringBuilder();
- for (Text[] row : data) {
- sb.append(indentStr);
-
+ for (Row row : data) {
appendLine(sb);
appendRow(sb, row);
}
@@ -102,6 +113,8 @@ public class Table {
}
private void appendLine(StringBuilder sb) {
+ sb.append(" ".repeat(indent));
+
for (int length : lengths) {
sb.append('+').append("-".repeat(length + 2));
}
@@ -109,15 +122,53 @@ public class Table {
sb.append("+\n");
}
- private void appendRow(StringBuilder sb, Text[] row) {
- assert row.length == lengths.length;
+ private void appendRow(StringBuilder sb, Row row) {
+ sb.append(" ".repeat(indent))
+ .append(row.render())
+ .append('\n');
+ }
+
+ private interface Row {
+ String render();
+ }
+
+ private class DataRow implements Row {
+ private final Text[] row;
- for (int i = 0; i < row.length; i++) {
- Text item = row[i];
+ DataRow(Text[] row) {
+ this.row = row;
+ }
+
+ @Override public String render() {
+ assert row.length == lengths.length;
+
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < row.length; i++) {
+ Text item = row[i];
+
+ sb.append("| ")
+ .append(item.toString())
+ .append(" ".repeat(lengths[i] + 1 - item.getCJKAdjustedLength()));
+ }
+
+ sb.append("|");
- sb.append("| ").append(item.toString()).append(" ".repeat(lengths[i] + 1 - item.getCJKAdjustedLength()));
+ return sb.toString();
}
+ }
+
+ private class SectionTitle implements Row {
+ private final Text title;
+
+ SectionTitle(Text title) {
+ this.title = title;
+ }
+
+ @Override public String render() {
+ int totalLen = Arrays.stream(lengths).sum() + 3 * (lengths.length - 1);
- sb.append("|\n");
+ return "| " + title.toString() + " ".repeat(totalLen - title.getCJKAdjustedLength()) + " |";
+ }
}
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/CategorySpec.java
similarity index 64%
copy from modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java
copy to modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/CategorySpec.java
index af1aefd..0b42d7a 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/CategorySpec.java
@@ -17,20 +17,17 @@
package org.apache.ignite.cli.spec;
-import javax.inject.Inject;
-import io.micronaut.context.ApplicationContext;
-import org.apache.ignite.cli.common.IgniteCommand;
-import org.apache.ignite.cli.builtins.init.InitIgniteCommand;
-import picocli.CommandLine;
+import java.io.PrintWriter;
+import picocli.CommandLine.Help.ColorScheme;
-@CommandLine.Command(name = "init", description = "Install Ignite core modules locally.")
-public class InitIgniteCommandSpec extends AbstractCommandSpec implements IgniteCommand {
+public abstract class CategorySpec extends SpecAdapter {
+ @Override public void run() {
+ PrintWriter out = spec.commandLine().getOut();
+ ColorScheme cs = spec.commandLine().getColorScheme();
- @Inject
- InitIgniteCommand command;
+ out.println(cs.errorText("[ERROR] ") + "Unknown command: " +
+ cs.commandText(spec.qualifiedName()) + ". See the list of available commands below.\n");
- @Override public void run() {
- command.init(spec.commandLine().getOut());
+ spec.parent().commandLine().usage(out);
}
-
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/AbstractCommandSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/CommandSpec.java
similarity index 76%
rename from modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/AbstractCommandSpec.java
rename to modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/CommandSpec.java
index 4cc905d..50541d8 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/AbstractCommandSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/CommandSpec.java
@@ -17,12 +17,9 @@
package org.apache.ignite.cli.spec;
-import org.apache.ignite.cli.VersionProvider;
import picocli.CommandLine;
-import picocli.CommandLine.Model.CommandSpec;
-@CommandLine.Command(versionProvider = VersionProvider.class)
-public abstract class AbstractCommandSpec implements Runnable {
- @CommandLine.Spec
- protected CommandSpec spec;
+public abstract class CommandSpec extends SpecAdapter {
+ @CommandLine.Option(names = "--help", usageHelp = true, hidden = true)
+ protected boolean usageHelpRequested;
}
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ConfigCommandSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ConfigCommandSpec.java
index aa08afc..abd5bb1 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ConfigCommandSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ConfigCommandSpec.java
@@ -18,7 +18,6 @@
package org.apache.ignite.cli.spec;
import javax.inject.Inject;
-import io.micronaut.context.ApplicationContext;
import org.apache.ignite.cli.IgniteCLIException;
import org.apache.ignite.cli.builtins.config.ConfigurationClient;
import picocli.CommandLine;
@@ -31,14 +30,9 @@ import picocli.CommandLine;
ConfigCommandSpec.SetConfigCommandSpec.class
}
)
-public class ConfigCommandSpec extends AbstractCommandSpec {
-
- @Override public void run() {
- spec.commandLine().usage(spec.commandLine().getOut());
- }
-
+public class ConfigCommandSpec extends CategorySpec {
@CommandLine.Command(name = "get", description = "Get current Ignite cluster configuration values.")
- public static class GetConfigCommandSpec extends AbstractCommandSpec {
+ public static class GetConfigCommandSpec extends CommandSpec {
@Inject private ConfigurationClient configurationClient;
@@ -59,7 +53,7 @@ public class ConfigCommandSpec extends AbstractCommandSpec {
name = "set",
description = "Update Ignite cluster configuration values."
)
- public static class SetConfigCommandSpec extends AbstractCommandSpec {
+ public static class SetConfigCommandSpec extends CommandSpec {
@Inject private ConfigurationClient configurationClient;
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/IgniteCliSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/IgniteCliSpec.java
index ba25e51..657348c 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/IgniteCliSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/IgniteCliSpec.java
@@ -36,14 +36,12 @@ import org.apache.ignite.cli.builtins.module.ModuleStorage;
import org.apache.ignite.cli.common.IgniteCommand;
import picocli.CommandLine;
-import static org.apache.ignite.cli.HelpFactoryImpl.SECTION_KEY_SYNOPSIS_EXTENSION;
-
/**
*
*/
@CommandLine.Command(
name = "ignite",
- description = "Entry point.",
+ description = "Type @|green ignite <COMMAND>|@ @|yellow --help|@ to get help for any command.",
subcommands = {
InitIgniteCommandSpec.class,
ModuleCommandSpec.class,
@@ -51,18 +49,15 @@ import static org.apache.ignite.cli.HelpFactoryImpl.SECTION_KEY_SYNOPSIS_EXTENSI
ConfigCommandSpec.class,
}
)
-public class IgniteCliSpec extends AbstractCommandSpec {
-
+public class IgniteCliSpec extends CommandSpec {
@CommandLine.Option(names = "-i", hidden = true, required = false)
boolean interactive;
@Override public void run() {
- spec.usageMessage().sectionMap().put(SECTION_KEY_SYNOPSIS_EXTENSION,
- help -> " Or type " + help.colorScheme().commandText(spec.qualifiedName()) +
- ' ' + help.colorScheme().parameterText("-i") + " to enter interactive mode.\n\n");
-
CommandLine cli = spec.commandLine();
+ cli.getOut().print(banner());
+
if (interactive)
new InteractiveWrapper().run(cli);
else
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java
index af1aefd..488bd88 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/InitIgniteCommandSpec.java
@@ -18,13 +18,12 @@
package org.apache.ignite.cli.spec;
import javax.inject.Inject;
-import io.micronaut.context.ApplicationContext;
import org.apache.ignite.cli.common.IgniteCommand;
import org.apache.ignite.cli.builtins.init.InitIgniteCommand;
import picocli.CommandLine;
@CommandLine.Command(name = "init", description = "Install Ignite core modules locally.")
-public class InitIgniteCommandSpec extends AbstractCommandSpec implements IgniteCommand {
+public class InitIgniteCommandSpec extends CommandSpec implements IgniteCommand {
@Inject
InitIgniteCommand command;
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ModuleCommandSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ModuleCommandSpec.java
index ab114ff..07f608c 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ModuleCommandSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/ModuleCommandSpec.java
@@ -25,7 +25,6 @@ import javax.inject.Inject;
import com.github.freva.asciitable.AsciiTable;
import com.github.freva.asciitable.Column;
import com.github.freva.asciitable.HorizontalAlign;
-import io.micronaut.context.ApplicationContext;
import org.apache.ignite.cli.CliPathsConfigLoader;
import org.apache.ignite.cli.builtins.module.ModuleManager;
import org.apache.ignite.cli.common.IgniteCommand;
@@ -40,14 +39,9 @@ import picocli.CommandLine;
ModuleCommandSpec.RemoveModuleCommandSpec.class
}
)
-public class ModuleCommandSpec extends AbstractCommandSpec implements IgniteCommand {
-
- @Override public void run() {
- spec.commandLine().usage(spec.commandLine().getOut());
- }
-
+public class ModuleCommandSpec extends CategorySpec implements IgniteCommand {
@CommandLine.Command(name = "add", description = "Add an optional Ignite module or an external artifact.")
- public static class AddModuleCommandSpec extends AbstractCommandSpec {
+ public static class AddModuleCommandSpec extends CommandSpec {
@Inject private ModuleManager moduleManager;
@@ -72,7 +66,7 @@ public class ModuleCommandSpec extends AbstractCommandSpec implements IgniteComm
}
@CommandLine.Command(name = "remove", description = "Add an optional Ignite module or an external artifact.")
- public static class RemoveModuleCommandSpec extends AbstractCommandSpec {
+ public static class RemoveModuleCommandSpec extends CommandSpec {
@Inject private ModuleManager moduleManager;
@@ -89,7 +83,7 @@ public class ModuleCommandSpec extends AbstractCommandSpec implements IgniteComm
}
@CommandLine.Command(name = "list", description = "Show the list of available optional Ignite modules.")
- public static class ListModuleCommandSpec extends AbstractCommandSpec {
+ public static class ListModuleCommandSpec extends CommandSpec {
@Inject private ModuleManager moduleManager;
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java
index 5b761f3..00f4b21 100644
--- a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/NodeCommandSpec.java
@@ -38,14 +38,9 @@ import picocli.CommandLine;
NodeCommandSpec.ListNodesCommandSpec.class
}
)
-public class NodeCommandSpec extends AbstractCommandSpec {
-
- @Override public void run() {
- spec.commandLine().usage(spec.commandLine().getOut());
- }
-
+public class NodeCommandSpec extends CategorySpec {
@CommandLine.Command(name = "start", description = "Start an Ignite node locally.")
- public static class StartNodeCommandSpec extends AbstractCommandSpec {
+ public static class StartNodeCommandSpec extends CommandSpec {
@Inject private CliPathsConfigLoader cliPathsConfigLoader;
@@ -71,7 +66,7 @@ public class NodeCommandSpec extends AbstractCommandSpec {
}
@CommandLine.Command(name = "stop", description = "Stop a locally running Ignite node.")
- public static class StopNodeCommandSpec extends AbstractCommandSpec {
+ public static class StopNodeCommandSpec extends CommandSpec {
@Inject private NodeManager nodeManager;
@Inject private CliPathsConfigLoader cliPathsConfigLoader;
@@ -93,7 +88,7 @@ public class NodeCommandSpec extends AbstractCommandSpec {
}
@CommandLine.Command(name = "list", description = "Show the list of currently running local Ignite nodes.")
- public static class ListNodesCommandSpec extends AbstractCommandSpec {
+ public static class ListNodesCommandSpec extends CommandSpec {
@Inject private NodeManager nodeManager;
@Inject private CliPathsConfigLoader cliPathsConfigLoader;
@@ -121,7 +116,7 @@ public class NodeCommandSpec extends AbstractCommandSpec {
}
@CommandLine.Command(name = "classpath", description = "Show the current classpath used by the Ignite nodes.")
- public static class NodesClasspathCommandSpec extends AbstractCommandSpec {
+ public static class NodesClasspathCommandSpec extends CommandSpec {
@Inject private NodeManager nodeManager;
diff --git a/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/SpecAdapter.java b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/SpecAdapter.java
new file mode 100644
index 0000000..f0c8157
--- /dev/null
+++ b/modules/cli-demo/cli/src/main/java/org/apache/ignite/cli/spec/SpecAdapter.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cli.spec;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import org.apache.ignite.cli.VersionProvider;
+import picocli.CommandLine;
+import picocli.CommandLine.Help.Ansi;
+import picocli.CommandLine.Model.CommandSpec;
+
+@CommandLine.Command(versionProvider = VersionProvider.class)
+public abstract class SpecAdapter implements Runnable {
+ private static final String[] BANNER = new String[] {
+ " ___ __",
+ " / | ____ ____ _ _____ / /_ ___",
+ " @|red,bold ⣠⣶⣿|@ / /| | / __ \\ / __ `// ___// __ \\ / _ \\",
+ " @|red,bold ⣿⣿⣿⣿|@ / ___ | / /_/ // /_/ // /__ / / / // ___/",
+ " @|red,bold ⢠⣿⡏⠈⣿⣿⣿⣿⣷|@ /_/ |_|/ .___/ \\__,_/ \\___//_/ /_/ \\___/",
+ " @|red,bold ⢰⣿⣿⣿⣧⠈⢿⣿⣿⣿⣿⣦|@ /_/",
+ " @|red,bold ⠘⣿⣿⣿⣿⣿⣦⠈⠛⢿⣿⣿⣿⡄|@ ____ _ __ @|red,bold _____|@",
+ " @|red,bold ⠈⠛⣿⣿⣿⣿⣿⣿⣦⠉⢿⣿⡟|@ / _/____ _ ____ (_)/ /_ ___ @|red,bold |__ /|@",
+ " @|red,bold ⢰⣿⣶⣀⠈⠙⠿⣿⣿⣿⣿ ⠟⠁|@ / / / __ `// __ \\ / // __// _ \\ @|red,bold /_ <|@",
+ " @|red,bold ⠈⠻⣿⣿⣿⣿⣷⣤⠙⢿⡟|@ _/ / / /_/ // / / // // /_ / ___/ @|red,bold ___/ /|@",
+ " @|red,bold ⠉⠉⠛⠏⠉|@ /___/ \\__, //_/ /_//_/ \\__/ \\___/ @|red,bold /____/|@",
+ " /____/\n"
+ };
+
+ @CommandLine.Spec
+ protected CommandSpec spec;
+
+ public String banner() {
+ String banner = Arrays
+ .stream(BANNER)
+ .map(Ansi.AUTO::string)
+ .collect(Collectors.joining("\n"));
+
+ return banner + '\n' + " ".repeat(19) + spec.version()[0] + "\n\n";
+ }
+}
diff --git a/modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java b/modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
index 02d8877..061e69c 100644
--- a/modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
+++ b/modules/ignite-runner/src/main/java/org/apache/ignite/app/IgniteRunner.java
@@ -36,13 +36,13 @@ public class IgniteRunner {
" ___ __\n" +
" / | ____ ____ _ _____ / /_ ___\n" +
" ⣠⣶⣿ / /| | / __ \\ / __ `// ___// __ \\ / _ \\\n" +
- " ⣿⣿⣿⣿ / ___ | / /_/ // /_/ // /__ / / / // __/\n" +
+ " ⣿⣿⣿⣿ / ___ | / /_/ // /_/ // /__ / / / // ___/\n" +
" ⢠⣿⡏⠈⣿⣿⣿⣿⣷ /_/ |_|/ .___/ \\__,_/ \\___//_/ /_/ \\___/\n" +
" ⢰⣿⣿⣿⣧⠈⢿⣿⣿⣿⣿⣦ /_/\n" +
" ⠘⣿⣿⣿⣿⣿⣦⠈⠛⢿⣿⣿⣿⡄ ____ _ __ _____\n" +
" ⠈⠛⣿⣿⣿⣿⣿⣿⣦⠉⢿⣿⡟ / _/____ _ ____ (_)/ /_ ___ |__ /\n" +
" ⢰⣿⣶⣀⠈⠙⠿⣿⣿⣿⣿ ⠟⠁ / / / __ `// __ \\ / // __// _ \\ /_ <\n" +
- " ⠈⠻⣿⣿⣿⣿⣷⣤⠙⢿⡟ _/ / / /_/ // / / // // /_ / __/ ___/ /\n" +
+ " ⠈⠻⣿⣿⣿⣿⣷⣤⠙⢿⡟ _/ / / /_/ // / / // // /_ / ___/ ___/ /\n" +
" ⠉⠉⠛⠏⠉ /___/ \\__, //_/ /_//_/ \\__/ \\___/ /____/\n" +
" /____/\n\n";