diff --git a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/ToolKitCommand.java b/toolkit-app/src/main/java/iot/technology/client/toolkit/app/ToolKitCommand.java index 8bf3f8aa..c9d60d36 100644 --- a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/ToolKitCommand.java +++ b/toolkit-app/src/main/java/iot/technology/client/toolkit/app/ToolKitCommand.java @@ -15,23 +15,25 @@ */ package iot.technology.client.toolkit.app; -import iot.technology.client.toolkit.app.config.CommandLineConfig; -import iot.technology.client.toolkit.app.config.LogLevelConfig; import iot.technology.client.toolkit.app.settings.ConfigCommand; import iot.technology.client.toolkit.app.settings.info.MainInfo; import iot.technology.client.toolkit.app.settings.lang.LangService; import iot.technology.client.toolkit.coap.command.CoapCommand; +import iot.technology.client.toolkit.common.commandline.CommandErrorMessageHandler; +import iot.technology.client.toolkit.common.commandline.CommandLineConfig; +import iot.technology.client.toolkit.common.commandline.ExceptionMessageHandler; +import iot.technology.client.toolkit.common.config.LogLevelConfig; import iot.technology.client.toolkit.common.constants.ExitCodeEnum; import iot.technology.client.toolkit.common.constants.HelpVersionGroup; import iot.technology.client.toolkit.common.constants.StorageConstants; import iot.technology.client.toolkit.common.constants.VersionInfo; -import iot.technology.client.toolkit.common.exception.ExceptionMessageHandler; import iot.technology.client.toolkit.mqtt.command.MqttCommand; import iot.technology.client.toolkit.nb.command.NbCommand; import org.fusesource.jansi.AnsiConsole; import picocli.AutoComplete; import picocli.CommandLine; +import java.security.Security; import java.util.Locale; import java.util.ResourceBundle; import java.util.concurrent.Callable; @@ -69,6 +71,8 @@ public class ToolKitCommand implements Callable { public static void main(String[] args) { + Security.setProperty("crypto.policy", "unlimited"); + LogLevelConfig.setLogLevel(); AnsiConsole.systemInstall(); try { @@ -79,6 +83,7 @@ public static void main(String[] args) { .setResourceBundle(bundle) .setColorScheme(CommandLineConfig.getColorScheme()) .setUsageHelpWidth(CommandLineConfig.getCliWidth()) + .setParameterExceptionHandler(new CommandErrorMessageHandler()) .setExecutionExceptionHandler(new ExceptionMessageHandler()) .setAdjustLineBreaksForWideCJKCharacters(true) .setCaseInsensitiveEnumValuesAllowed(true); diff --git a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/settings/ConfigCommand.java b/toolkit-app/src/main/java/iot/technology/client/toolkit/app/settings/ConfigCommand.java index 86172a5e..c5c0323c 100644 --- a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/settings/ConfigCommand.java +++ b/toolkit-app/src/main/java/iot/technology/client/toolkit/app/settings/ConfigCommand.java @@ -32,9 +32,12 @@ @CommandLine.Command( name = "config", requiredOptionMarker = '*', + header = "@|bold ${bundle:config.header}|@", + description = "@|fg(red),bold ${bundle:config.description}|@", optionListHeading = "%n${bundle:general.option}:%n", - header = "@|fg(Cyan),bold ${bundle:config.header}|@", - description = "@|fg(Cyan),italic ${bundle:config.description}|@", + synopsisHeading = "%n@|bold ${bundle:general.usage}|@%n", + commandListHeading = "%n@|bold ${bundle:general.commands}|@%n", + descriptionHeading = "%n", footerHeading = "%nCopyright (c) 2019-2023, ${bundle:general.copyright}", footer = "%nDeveloped by mushuwei", versionProvider = iot.technology.client.toolkit.common.constants.VersionInfo.class diff --git a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java index fd1ac247..c10ab632 100644 --- a/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java +++ b/toolkit-coap/src/main/java/iot/technology/client/toolkit/coap/command/CoapCommand.java @@ -32,9 +32,12 @@ @CommandLine.Command( name = "coap", requiredOptionMarker = '*', - header = "@|fg(Cyan),bold ${bundle:coap.header}|@", - description = "@|fg(Cyan),italic ${bundle:coap.description}|@", - optionListHeading = "%n${bundle:general.option}:%n", + header = "@|bold ${bundle:coap.header}|@", + description = "@|fg(red),bold ${bundle:coap.description}|@", + synopsisHeading = "%n@|bold ${bundle:general.usage}|@%n", + commandListHeading = "%n@|bold ${bundle:general.commands}|@%n", + optionListHeading = "%n@|bold ${bundle:general.option}|@%n", + descriptionHeading = "%n", subcommands = { CoapDescribeCommand.class, CoapMediaTypesCommand.class, @@ -53,24 +56,12 @@ public class CoapCommand implements Callable { @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "${bundle:general.help.description}") boolean usageHelpRequested; + @CommandLine.Spec + private CommandLine.Model.CommandSpec spec; + @Override public Integer call() { - StringBuilder sb = new StringBuilder(); - sb.append("describe, desc: ").append(colorItalic(bundle.getString("coap.desc.description"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("media-type, mt: ").append(colorItalic(bundle.getString("coap.media.types.description"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("discover, disc: ").append(colorItalic(bundle.getString("coap.disc.description"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("get: ").append(colorItalic(bundle.getString("coap.get.description"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("post: ").append(colorItalic(bundle.getString("coap.post.description"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("put: ").append(colorItalic(bundle.getString("coap.put.description"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("delete, del: ").append(colorItalic(bundle.getString("coap.del.description"), "cyan")) - .append(StringUtils.lineSeparator()); - System.out.println(sb); + System.out.println(spec.commandLine().getUsageMessage()); return ExitCodeEnum.SUCCESS.getValue(); } diff --git a/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommandErrorMessageHandler.java b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommandErrorMessageHandler.java new file mode 100644 index 00000000..69748a83 --- /dev/null +++ b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommandErrorMessageHandler.java @@ -0,0 +1,22 @@ +package iot.technology.client.toolkit.common.commandline; + +import picocli.CommandLine; + +import java.io.PrintWriter; + +/** + * @author mushuwei + */ +public class CommandErrorMessageHandler extends CommonErrorMessageHandler + implements CommandLine.IParameterExceptionHandler { + + @Override + public int handleParseException(CommandLine.ParameterException ex, String[] args) throws Exception { + final int exitCode = super.handleParseException(ex, args); + final CommandLine cmd = ex.getCommandLine(); + final PrintWriter writer = cmd.getErr(); + final CommandLine.Model.CommandSpec spec = cmd.getCommandSpec(); + writer.printf("Try '%s --help' for more information.%n", spec.qualifiedName()); + return exitCode; + } +} diff --git a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/config/CommandLineConfig.java b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommandLineConfig.java similarity index 84% rename from toolkit-app/src/main/java/iot/technology/client/toolkit/app/config/CommandLineConfig.java rename to toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommandLineConfig.java index 2ed0751c..42b64dc6 100644 --- a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/config/CommandLineConfig.java +++ b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommandLineConfig.java @@ -1,4 +1,4 @@ -package iot.technology.client.toolkit.app.config; +package iot.technology.client.toolkit.common.commandline; import picocli.CommandLine; @@ -13,6 +13,7 @@ public class CommandLineConfig { .options(CommandLine.Help.Ansi.Style.italic, CommandLine.Help.Ansi.Style.fg_yellow) .parameters(CommandLine.Help.Ansi.Style.fg_yellow) .optionParams(CommandLine.Help.Ansi.Style.italic) + .errors(CommandLine.Help.Ansi.Style.bold, CommandLine.Help.Ansi.Style.fg_red) .build(); private static final int CLI_WIDTH = 160; diff --git a/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommonErrorMessageHandler.java b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommonErrorMessageHandler.java new file mode 100644 index 00000000..baa06593 --- /dev/null +++ b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/CommonErrorMessageHandler.java @@ -0,0 +1,37 @@ +package iot.technology.client.toolkit.common.commandline; + +import picocli.CommandLine; + +import java.io.PrintWriter; + +/** + * @author mushuwei + */ +public abstract class CommonErrorMessageHandler implements CommandLine.IParameterExceptionHandler { + + @Override + public int handleParseException(CommandLine.ParameterException ex, String[] args) throws Exception { + printErrorMessage(ex); + + return generateExitCode(ex); + } + + private void printErrorMessage(final CommandLine.ParameterException parameterException) { + final PrintWriter writer = parameterException.getCommandLine().getErr(); + + if (parameterException.getCause() != null) { + writer.println(parameterException.getMessage() + .replace(parameterException.getCause().toString(), parameterException.getCause().getMessage())); + } else { + writer.println(parameterException.getMessage()); + } + } + + private int generateExitCode(final CommandLine.ParameterException parameterException) { + final CommandLine cmd = parameterException.getCommandLine(); + final CommandLine.Model.CommandSpec spec = cmd.getCommandSpec(); + return cmd.getExitCodeExceptionMapper() != null ? + cmd.getExitCodeExceptionMapper().getExitCode(parameterException) : + spec.exitCodeOnInvalidInput(); + } +} diff --git a/toolkit-common/src/main/java/iot/technology/client/toolkit/common/exception/ExceptionMessageHandler.java b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/ExceptionMessageHandler.java similarity index 95% rename from toolkit-common/src/main/java/iot/technology/client/toolkit/common/exception/ExceptionMessageHandler.java rename to toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/ExceptionMessageHandler.java index e26772f3..ca5e8c52 100644 --- a/toolkit-common/src/main/java/iot/technology/client/toolkit/common/exception/ExceptionMessageHandler.java +++ b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/commandline/ExceptionMessageHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package iot.technology.client.toolkit.common.exception; +package iot.technology.client.toolkit.common.commandline; import picocli.CommandLine; diff --git a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/config/LogLevelConfig.java b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/config/LogLevelConfig.java similarity index 94% rename from toolkit-app/src/main/java/iot/technology/client/toolkit/app/config/LogLevelConfig.java rename to toolkit-common/src/main/java/iot/technology/client/toolkit/common/config/LogLevelConfig.java index babdb756..9605110c 100644 --- a/toolkit-app/src/main/java/iot/technology/client/toolkit/app/config/LogLevelConfig.java +++ b/toolkit-common/src/main/java/iot/technology/client/toolkit/common/config/LogLevelConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package iot.technology.client.toolkit.app.config; +package iot.technology.client.toolkit.common.config; /** * @author mushuwei diff --git a/toolkit-mqtt/src/main/java/iot/technology/client/toolkit/mqtt/command/MqttCommand.java b/toolkit-mqtt/src/main/java/iot/technology/client/toolkit/mqtt/command/MqttCommand.java index 4c47f207..495b3976 100644 --- a/toolkit-mqtt/src/main/java/iot/technology/client/toolkit/mqtt/command/MqttCommand.java +++ b/toolkit-mqtt/src/main/java/iot/technology/client/toolkit/mqtt/command/MqttCommand.java @@ -21,6 +21,7 @@ import iot.technology.client.toolkit.mqtt.command.sub.MqttPublishCommand; import iot.technology.client.toolkit.mqtt.command.sub.MqttSettingsCommand; import iot.technology.client.toolkit.mqtt.command.sub.MqttSubscribeCommand; +import org.jetbrains.annotations.NotNull; import picocli.CommandLine; import java.util.ResourceBundle; @@ -34,9 +35,12 @@ @CommandLine.Command( name = "mqtt", requiredOptionMarker = '*', - header = "@|fg(Cyan),bold ${bundle:mqtt.header}|@", - description = "@|fg(Cyan),italic ${bundle:mqtt.description}|@", - optionListHeading = "%n${bundle:general.option}:%n", + header = "@|bold ${bundle:mqtt.header}|@", + description = "@|fg(red),bold ${bundle:mqtt.description}|@", + synopsisHeading = "%n@|bold ${bundle:general.usage}|@%n", + commandListHeading = "%n@|bold ${bundle:general.commands}|@%n", + optionListHeading = "%n@|bold ${bundle:general.option}|@%n", + descriptionHeading = "%n", subcommands = { MqttDescribeCommand.class, MqttSettingsCommand.class, @@ -52,12 +56,12 @@ public class MqttCommand implements Callable { @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "${bundle:general.help.description}") boolean usageHelpRequested; + @CommandLine.Spec + private CommandLine.Model.CommandSpec spec; + @Override public Integer call() { - System.out.format("describe, desc: " + colorItalic(bundle.getString("mqtt.desc.description"), "cyan") + "%n"); - System.out.format("settings, set: " + colorItalic(bundle.getString("mqtt.settings.desc"), "cyan") + "%n"); - System.out.format("publish, pub: " + colorItalic(bundle.getString("mqtt.pub.description"), "cyan") + "%n"); - System.out.format("subscribe, sub: " + colorItalic(bundle.getString("mqtt.sub.description"), "cyan") + "%n"); + System.out.println(spec.commandLine().getUsageMessage()); return ExitCodeEnum.SUCCESS.getValue(); } } diff --git a/toolkit-nbiot/src/main/java/iot/technology/client/toolkit/nb/command/NbCommand.java b/toolkit-nbiot/src/main/java/iot/technology/client/toolkit/nb/command/NbCommand.java index 9548c8a6..71ca69ad 100644 --- a/toolkit-nbiot/src/main/java/iot/technology/client/toolkit/nb/command/NbCommand.java +++ b/toolkit-nbiot/src/main/java/iot/technology/client/toolkit/nb/command/NbCommand.java @@ -34,9 +34,12 @@ @CommandLine.Command( name = "nb", requiredOptionMarker = '*', - header = "@|fg(Cyan),bold ${bundle:nb.header}|@", - description = "@|fg(Cyan),italic ${bundle:nb.description}|@", - optionListHeading = "%n${bundle:general.option}:%n", + header = "@|bold ${bundle:nb.header}|@", + description = "@|fg(red),bold ${bundle:nb.description}|@", + synopsisHeading = "%n@|bold ${bundle:general.usage}|@%n", + commandListHeading = "%n@|bold ${bundle:general.commands}|@%n", + optionListHeading = "%n@|bold ${bundle:general.option}|@%n", + descriptionHeading = "%n", subcommands = { NbCallCommand.class, NbSettingsCommand.class, @@ -50,16 +53,12 @@ public class NbCommand implements Callable { @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "${bundle:general.help.description}") boolean usageHelpRequested; + @CommandLine.Spec + private CommandLine.Model.CommandSpec spec; + @Override public Integer call() throws Exception { - StringBuilder sb = new StringBuilder(); - sb.append("call: ").append(colorItalic(bundle.getString("nb.call.desc"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("settings, set: ").append(colorItalic(bundle.getString("nb.call.desc"), "cyan")) - .append(StringUtils.lineSeparator()); - sb.append("describe, desc: ").append(colorItalic(bundle.getString("nb.desc.desc"), "cyan")) - .append(StringUtils.lineSeparator()); - System.out.println(sb); + System.out.println(spec.commandLine().getUsageMessage()); return ExitCodeEnum.SUCCESS.getValue(); }