kandi background
Explore Kits

picocli | modern framework for building powerful | Parser library

 by   remkop Java Version: v4.6.3 License: Apache-2.0

 by   remkop Java Version: v4.6.3 License: Apache-2.0

Download this library from

kandi X-RAY | picocli Summary

picocli is a Java library typically used in Utilities, Parser applications. picocli has no bugs, it has no vulnerabilities, it has build file available, it has a Permissive License and it has high support. You can download it from GitHub, Maven.
Picocli aims to be the easiest-to-use way to create rich command line applications that can run on and off the JVM. Considering picocli? Check what happy users say about picocli. Picocli is a modern library and framework, written in Java, that contains both an annotations API and a programmatic API. It features usage help with ANSI colors and styles, TAB autocompletion and nested subcommands. In a single file, so you can include it in source form. This lets users run picocli-based applications without requiring picocli as an external dependency. Picocli-based applications can be ahead-of-time compiled to a native image, with extremely fast startup time and lower memory requirements, which can be distributed as a single executable file. Picocli comes with an annotation processor that automatically Graal-enables your jar during compilation. Picocli applications can be very compact with no boilerplate code: your command (or subcommand) can be executed with a single line of code. Simply implement Runnable or Callable, or put the business logic of your command in a @Command-annotated method. Picocli makes it easy to follow Command Line Interface Guidelines. How it works: annotate your class and picocli initializes it from the command line arguments, converting the input to strongly typed data. Supports git-like subcommands (and nested sub-subcommands), any option prefix style, POSIX-style grouped short options, custom type converters, password options and more. Picocli distinguishes between named options and positional parameters and allows both to be strongly typed. Multi-valued fields can specify an exact number of parameters or a range (e.g., 0..*, 1..2). Supports Map options like -Dkey1=val1 -Dkey2=val2, where both key and value can be strongly typed. Parser tracing facilitates troubleshooting. Command-line argument files (@-files) allow applications to handle very long command lines. Generates polished and easily tailored usage help and version help, using ANSI colors where possible. Requires at minimum Java 5, but is designed to facilitate the use of Java 8 lambdas. Tested on all Java versions between 5 and 18-ea (inclusive). Picocli-based command line applications can have TAB autocompletion, interactively showing users what options and subcommands are available. When an option has completionCandidates or has an enum type, autocompletion can also suggest option values. Picocli can generate completion scripts for bash and zsh, and offers picocli-shell-jline2 and picocli-shell-jline3 modules with JLine Completer implementations for building interactive shell applications. Unique features in picocli include support for negatable options, advanced quoted values, and argument groups. Argument groups can be used to create mutually exclusive options, mutually dependent options, option sections in the usage help message and repeating composite arguments like ([-a=<a> -b=<b> -c=<c>] (-x | -y | -z)).... For advanced use cases, applications can access the picocli command object model with the @Spec annotation, and implement custom parameter processing for option parameters if the built-in logic is insufficient. Picocli-based applications can easily integrate with Dependency Injection containers. The Micronaut microservices framework has built-in support for picocli. Picocli ships with a picocli-spring-boot-starter module that includes a PicocliSpringFactory and Spring Boot auto-configuration to use Spring dependency injection in your picocli command line application. The user manual has examples of integrating with Guice, Spring Boot, Micronaut, Quarkus and with containers that comply to CDI 2.0 specification (JSR 365).
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • picocli has a highly active ecosystem.
  • It has 3486 star(s) with 313 fork(s). There are 49 watchers for this library.
  • There were 1 major release(s) in the last 6 months.
  • There are 88 open issues and 1199 have been closed. On average issues are closed in 78 days. There are 6 open pull requests and 0 closed requests.
  • It has a positive sentiment in the developer community.
  • The latest version of picocli is v4.6.3
picocli Support
Best in #Parser
Average in #Parser
picocli Support
Best in #Parser
Average in #Parser

quality kandi Quality

  • picocli has 0 bugs and 0 code smells.
picocli Quality
Best in #Parser
Average in #Parser
picocli Quality
Best in #Parser
Average in #Parser

securitySecurity

  • picocli has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
  • picocli code analysis shows 0 unresolved vulnerabilities.
  • There are 0 security hotspots that need review.
picocli Security
Best in #Parser
Average in #Parser
picocli Security
Best in #Parser
Average in #Parser

license License

  • picocli is licensed under the Apache-2.0 License. This license is Permissive.
  • Permissive licenses have the least restrictions, and you can use them in most projects.
picocli License
Best in #Parser
Average in #Parser
picocli License
Best in #Parser
Average in #Parser

buildReuse

  • picocli releases are available to install and integrate.
  • Deployable package is available in Maven.
  • Build file is available. You can build the component from source.
  • Installation instructions, examples and code snippets are available.
  • picocli saves you 283359 person hours of effort in developing the same functionality from scratch.
  • It has 276796 lines of code, 6056 functions and 720 files.
  • It has low code complexity. Code complexity directly impacts maintainability of the code.
picocli Reuse
Best in #Parser
Average in #Parser
picocli Reuse
Best in #Parser
Average in #Parser
Top functions reviewed by kandi - BETA

kandi has reviewed picocli and discovered the below as its top functions. This is intended to give you an instant insight into picocli implemented functionality, and help decide if they suit your requirements.

  • This method applies a value to a single valued field .
  • Generate a function for the given command and command line .
  • Executes user object
  • Create the custom usage help factory .
  • Generates the options .
  • Modify base script type .
  • Build options and positions from method parameters .
  • Create the synopsis text for the options .
  • Split a string into chunks .
  • Returns an array of textual descriptions for the given option .

picocli Key Features

Picocli is a modern framework for building powerful, user-friendly, GraalVM-enabled command line apps with ease. It supports colors, autocompletion, subcommands, and more. In 1 source file so apps can include as source & avoid adding a dependency. Written in Java, usable from Groovy, Kotlin, Scala, etc.

Help to promote picocli

copy iconCopydownload iconDownload
[![picocli](https://img.shields.io/badge/picocli-4.6.3-green.svg)](https://github.com/remkop/picocli)

Example

copy iconCopydownload iconDownload
import picocli.CommandLine;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
import java.io.File;

@Command(name = "example", mixinStandardHelpOptions = true, version = "Picocli example 4.0")
public class Example implements Runnable {

    @Option(names = { "-v", "--verbose" },
      description = "Verbose mode. Helpful for troubleshooting. Multiple -v options increase the verbosity.")
    private boolean[] verbose = new boolean[0];

    @Parameters(arity = "1..*", paramLabel = "FILE", description = "File(s) to process.")
    private File[] inputFiles;

    public void run() {
        if (verbose.length &gt; 0) {
            System.out.println(inputFiles.length + " files to process...");
        }
        if (verbose.length &gt; 1) {
            for (File f : inputFiles) {
                System.out.println(f.getAbsolutePath());
            }
        }
    }

    public static void main(String[] args) {
        // By implementing Runnable or Callable, parsing, error handling and handling user
        // requests for usage help or version help can be done with one line of code.

        int exitCode = new CommandLine(new Example()).execute(args);
        System.exit(exitCode);
    }
}

Gradle

copy iconCopydownload iconDownload
implementation 'info.picocli:picocli:4.6.3'

Maven

copy iconCopydownload iconDownload
&lt;dependency&gt;
  &lt;groupId&gt;info.picocli&lt;/groupId&gt;
  &lt;artifactId&gt;picocli&lt;/artifactId&gt;
  &lt;version&gt;4.6.3&lt;/version&gt;
&lt;/dependency&gt;

Scala SBT

copy iconCopydownload iconDownload
libraryDependencies += "info.picocli" % "picocli" % "4.6.3"

Ivy

copy iconCopydownload iconDownload
&lt;dependency org="info.picocli" name="picocli" rev="4.6.3" /&gt;

Grape

copy iconCopydownload iconDownload
@Grapes(
    @Grab(group='info.picocli', module='picocli', version='4.6.3')
)

Leiningen

copy iconCopydownload iconDownload
[info.picocli/picocli "4.6.3"]

Buildr

copy iconCopydownload iconDownload
'info.picocli:picocli:jar:4.6.3'

JBang

copy iconCopydownload iconDownload
//DEPS info.picocli:picocli:4.6.3

How can I construct the help functionality to divide subcommands into groups with separate descriptive headers?

copy iconCopydownload iconDownload
@Command(name = "help", helpCommand = true)
class Help implements Runnable {
    public static Map<String, String[]> commandGroups;
    static {
        commandGroups = new HashMap<>();
        commandGroups.put("group1", new String[]{
            "function1", "function2", "function3"});
        commandGroups.put("group2", new String[]{
            "function3", "function4", "function5"});
}

@Override
public void run() {
    CommandLine cmd = new CommandLine(new Tool());

    cmd.getHelpSectionMap().remove(SECTION_KEY_COMMAND_LIST_HEADING);
    cmd.getHelpSectionMap().remove(SECTION_KEY_COMMAND_LIST);
    List<String> keys = new ArrayList<>(cmd.getHelpSectionKeys());

    for (String group : commandGroups.keySet()) {
        String headerSection = "SECTION_KEY_" + group + "_HEADING";
        String commandSection = "SECTION_KEY_" + group;
        cmd.getHelpSectionMap().put(headerSection,
                help -> help.createHeading("%n" + group + ":%n"));
        cmd.getHelpSectionMap().put(commandSection,
                new CommandListRenderer(commandGroups.get(group)));
        keys.add(headerSection);
        keys.add(commandSection);
    }

    cmd.setHelpSectionKeys(keys);
    cmd.usage(System.out);

    }
}

class CommandListRenderer implements IHelpSectionRenderer {
    String[] functions;


    public CommandListRenderer(String[] f) {
        functions = f;
    }

    //@Override
    public String render(Help help) {
        CommandSpec spec = help.commandSpec();
        if (spec.subcommands().isEmpty()) { return ""; }

        // prepare layout: two columns
        // the left column overflows, the right column wraps if text is too long
        Help.TextTable textTable = 
        Help.TextTable.forColumns(help.colorScheme(),
            new Help.Column(30, 2, Help.Column.Overflow.SPAN),
            new Help.Column(spec.usageMessage().width() - 30, 2, 
        Help.Column.Overflow.TRUNCATE));

        for (String f : functions) {
            CommandLine subcommand = spec.subcommands().get(f);
            if (subcommand == null) {
                throw new NotFoundException("Function not found: " + f);
            }
            addCommand(subcommand, textTable);
        }
        return textTable.toString();
    }

public void addCommand(CommandLine cmd, Help.TextTable textTable) {
    // create comma-separated list of command name and aliases
    String names = cmd.getCommandSpec().names().toString();
    names = names.substring(1, names.length() - 1); // remove leading '[' and trailing ']'

    // command description is taken from header or description
    String description = description(cmd.getCommandSpec().usageMessage());

    // add a line for this command to the layout
    textTable.addRowValues(names, description);
}

private String description(Model.UsageMessageSpec usageMessage) {
    if (usageMessage.header().length > 0) {
        return usageMessage.header()[0];
    }
    if (usageMessage.description().length > 0) {
        return usageMessage.description()[0];
    }
    return "";
}

Micronaut application built with Launch4J not launching

copy iconCopydownload iconDownload
task createExe(type: Launch4jLibraryTask) {
    jarTask = shadowJar
    dontWrapJar true // <<<< THIS IS THE ADDED LINE
    icon = "${projectDir}/src/main/installer/nsis/Icon.ico"
    outfile = "${appName}.exe"
    copyConfigurable = files {}
    stayAlive = 'true'
    bundledJrePath = 'jre'
    bundledJre64Bit = true
    jvmOptions = [
            '-Xmx1024m',
            '-Dsun.java2d.d3d=false'
    ]
    fileDescription = appName + ' Application'
    productName = appName
    internalName = appName
    copyright = 'My Company'
    companyName = 'My Company'
}

arggroup with default value in picocli

copy iconCopydownload iconDownload
@Command
public class CMD implements Runnable {

    @Parameters
    private String x;
    
    @ArgGroup(exclusive = false)
    private Group group = new Group();

    static class Group {
        @Option(names = "-a", required = true, defaultValue = "aa")
        public static String a = "aa";

        @Option(names = "-b", required = true, defaultValue = "bb")
        public static String b = "bb";

        @Option(names = "-c", required = false, defaultValue = "cc")
        public static String c = "cc";
    }
@Command
static class CMD implements Runnable {

    @Parameters
    private String x;

    @ArgGroup(exclusive = false)
    private Group group = new Group();

    static class Group {
        @ArgGroup(exclusive = false)
        private InnerGroup inner = new InnerGroup("aa", "bb"); // default values

        @Option(names = "-c", required = false, defaultValue = "cc")
        public String c = "cc";
    }

    static class InnerGroup {
        // default constructor, used by picocli when
        // one or more options in this group are 
        // matched on the command line
        public InnerGroup() {}

        // this constructor assigns default values,
        // used only when *both* options are missing
        public InnerGroup(String a, String b) {
            this.a = a;
            this.b = b;
        }

        @Option(names = "-a", required = true)
        public String a;

        @Option(names = "-b", required = true)
        public String b;
    }

    @Override
    public void run() {
        System.out.printf("a=%s, b=%s, c=%s, x=%s%n", 
                group.inner.a, group.inner.b, group.c, x);
    }
}
-----------------------
@Command
public class CMD implements Runnable {

    @Parameters
    private String x;
    
    @ArgGroup(exclusive = false)
    private Group group = new Group();

    static class Group {
        @Option(names = "-a", required = true, defaultValue = "aa")
        public static String a = "aa";

        @Option(names = "-b", required = true, defaultValue = "bb")
        public static String b = "bb";

        @Option(names = "-c", required = false, defaultValue = "cc")
        public static String c = "cc";
    }
@Command
static class CMD implements Runnable {

    @Parameters
    private String x;

    @ArgGroup(exclusive = false)
    private Group group = new Group();

    static class Group {
        @ArgGroup(exclusive = false)
        private InnerGroup inner = new InnerGroup("aa", "bb"); // default values

        @Option(names = "-c", required = false, defaultValue = "cc")
        public String c = "cc";
    }

    static class InnerGroup {
        // default constructor, used by picocli when
        // one or more options in this group are 
        // matched on the command line
        public InnerGroup() {}

        // this constructor assigns default values,
        // used only when *both* options are missing
        public InnerGroup(String a, String b) {
            this.a = a;
            this.b = b;
        }

        @Option(names = "-a", required = true)
        public String a;

        @Option(names = "-b", required = true)
        public String b;
    }

    @Override
    public void run() {
        System.out.printf("a=%s, b=%s, c=%s, x=%s%n", 
                group.inner.a, group.inner.b, group.c, x);
    }
}

In picocli how do you make options on the command line to override the same option in an @-file

copy iconCopydownload iconDownload
import picocli.CommandLine.PropertiesDefaultProvider;

@Command(name = "myapp", defaultValueProvider = PropertiesDefaultProvider.class)
class MyApp { }
class MyApp { 
    @Option(names = "-D")
    void setSystemProperty(Map<String, String> properties) {
        System.getProperties().putAll(properties);
    }
}
myapp --sourceDatabaseType=MySQL -Dpicocli.defaults.myapp.path=.\myapp.options
myapp --sourceDatabaseType=MySQL -@.\myapp.options
class MyApp { 
    @Spec CommandSpec spec; // injected by picocli

    @Option(names = "-@")
    void setDefaultProviderPath(File path) {
        // you could do some validation here:
        if (!path.canRead()) {
            String msg = String.format("ERROR: file not found: %s", path);
            throw new ParameterException(spec.commandLine(), msg);
        }
        // only set the system property if the file exists
        System.setProperty("picocli.defaults.myapp.path", path.toString());
    }
}
-----------------------
import picocli.CommandLine.PropertiesDefaultProvider;

@Command(name = "myapp", defaultValueProvider = PropertiesDefaultProvider.class)
class MyApp { }
class MyApp { 
    @Option(names = "-D")
    void setSystemProperty(Map<String, String> properties) {
        System.getProperties().putAll(properties);
    }
}
myapp --sourceDatabaseType=MySQL -Dpicocli.defaults.myapp.path=.\myapp.options
myapp --sourceDatabaseType=MySQL -@.\myapp.options
class MyApp { 
    @Spec CommandSpec spec; // injected by picocli

    @Option(names = "-@")
    void setDefaultProviderPath(File path) {
        // you could do some validation here:
        if (!path.canRead()) {
            String msg = String.format("ERROR: file not found: %s", path);
            throw new ParameterException(spec.commandLine(), msg);
        }
        // only set the system property if the file exists
        System.setProperty("picocli.defaults.myapp.path", path.toString());
    }
}
-----------------------
import picocli.CommandLine.PropertiesDefaultProvider;

@Command(name = "myapp", defaultValueProvider = PropertiesDefaultProvider.class)
class MyApp { }
class MyApp { 
    @Option(names = "-D")
    void setSystemProperty(Map<String, String> properties) {
        System.getProperties().putAll(properties);
    }
}
myapp --sourceDatabaseType=MySQL -Dpicocli.defaults.myapp.path=.\myapp.options
myapp --sourceDatabaseType=MySQL -@.\myapp.options
class MyApp { 
    @Spec CommandSpec spec; // injected by picocli

    @Option(names = "-@")
    void setDefaultProviderPath(File path) {
        // you could do some validation here:
        if (!path.canRead()) {
            String msg = String.format("ERROR: file not found: %s", path);
            throw new ParameterException(spec.commandLine(), msg);
        }
        // only set the system property if the file exists
        System.setProperty("picocli.defaults.myapp.path", path.toString());
    }
}
-----------------------
import picocli.CommandLine.PropertiesDefaultProvider;

@Command(name = "myapp", defaultValueProvider = PropertiesDefaultProvider.class)
class MyApp { }
class MyApp { 
    @Option(names = "-D")
    void setSystemProperty(Map<String, String> properties) {
        System.getProperties().putAll(properties);
    }
}
myapp --sourceDatabaseType=MySQL -Dpicocli.defaults.myapp.path=.\myapp.options
myapp --sourceDatabaseType=MySQL -@.\myapp.options
class MyApp { 
    @Spec CommandSpec spec; // injected by picocli

    @Option(names = "-@")
    void setDefaultProviderPath(File path) {
        // you could do some validation here:
        if (!path.canRead()) {
            String msg = String.format("ERROR: file not found: %s", path);
            throw new ParameterException(spec.commandLine(), msg);
        }
        // only set the system property if the file exists
        System.setProperty("picocli.defaults.myapp.path", path.toString());
    }
}
-----------------------
import picocli.CommandLine.PropertiesDefaultProvider;

@Command(name = "myapp", defaultValueProvider = PropertiesDefaultProvider.class)
class MyApp { }
class MyApp { 
    @Option(names = "-D")
    void setSystemProperty(Map<String, String> properties) {
        System.getProperties().putAll(properties);
    }
}
myapp --sourceDatabaseType=MySQL -Dpicocli.defaults.myapp.path=.\myapp.options
myapp --sourceDatabaseType=MySQL -@.\myapp.options
class MyApp { 
    @Spec CommandSpec spec; // injected by picocli

    @Option(names = "-@")
    void setDefaultProviderPath(File path) {
        // you could do some validation here:
        if (!path.canRead()) {
            String msg = String.format("ERROR: file not found: %s", path);
            throw new ParameterException(spec.commandLine(), msg);
        }
        // only set the system property if the file exists
        System.setProperty("picocli.defaults.myapp.path", path.toString());
    }
}

Bridging CLI argument parsing with application setup

copy iconCopydownload iconDownload
@Command(subcommands = {Sub1.class, Sub2.class, Sub3.class})
class MyApp implements Runnable {

    Channel channel; // initialized in executionStrategy method

    // A reference to this method can be used as a custom execution strategy
    // that first calls the init() method,
    // and then delegates to the default execution strategy.
    private int executionStrategy(ParseResult parseResult) {

        // custom initialization to be done before executing any command or subcommand
        try (this.channel = _establishChannel(generalConfiguration)) {

            // default execution strategy
            return new CommandLine.RunLast().execute(parseResult); 
        }
    }

    public static void main(String[] args) {
        MyApp app = new MyApp();
        new CommandLine(app)
                // wire in the custom execution strategy
                .setExecutionStrategy(app::executionStrategy) // Java 8 method reference syntax
                .execute(args);
    }

    // ...
}
@Command(name = "country", description = "Resolve ISO country code (ISO-3166-1, Alpha-2 code)")
static class Subcommand1 implements Runnable {

    @ParentCommand
    private MyApp parent; // picocli injects reference to parent command

    @Parameters(arity = "1..*", paramLabel = "<country code>", description = "country code(s) to be resolved")
    private String[] countryCodes;

    @Override
    public void run() {
        Channel channel = parent.channel;
        doSomethingWith(channel);
        // ...
    }
}
-----------------------
@Command(subcommands = {Sub1.class, Sub2.class, Sub3.class})
class MyApp implements Runnable {

    Channel channel; // initialized in executionStrategy method

    // A reference to this method can be used as a custom execution strategy
    // that first calls the init() method,
    // and then delegates to the default execution strategy.
    private int executionStrategy(ParseResult parseResult) {

        // custom initialization to be done before executing any command or subcommand
        try (this.channel = _establishChannel(generalConfiguration)) {

            // default execution strategy
            return new CommandLine.RunLast().execute(parseResult); 
        }
    }

    public static void main(String[] args) {
        MyApp app = new MyApp();
        new CommandLine(app)
                // wire in the custom execution strategy
                .setExecutionStrategy(app::executionStrategy) // Java 8 method reference syntax
                .execute(args);
    }

    // ...
}
@Command(name = "country", description = "Resolve ISO country code (ISO-3166-1, Alpha-2 code)")
static class Subcommand1 implements Runnable {

    @ParentCommand
    private MyApp parent; // picocli injects reference to parent command

    @Parameters(arity = "1..*", paramLabel = "<country code>", description = "country code(s) to be resolved")
    private String[] countryCodes;

    @Override
    public void run() {
        Channel channel = parent.channel;
        doSomethingWith(channel);
        // ...
    }
}

How to decide Quarkus application arguments in Kubernetes at run-time?

copy iconCopydownload iconDownload
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3

ARG JAVA_PACKAGE=java-11-openjdk-headless
ARG RUN_JAVA_VERSION=1.3.8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
# Install java and the run-java script
# Also set up permissions for user `1001`
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
    && microdnf update \
    && microdnf clean all \
    && mkdir /deployments \
    && chown 1001 /deployments \
    && chmod "g+rwX" /deployments \
    && chown 1001:root /deployments \
    && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
    && chown 1001 /deployments/run-java.sh \
    && chmod 540 /deployments/run-java.sh \
    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security

# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
# We make four distinct layers so if there are application changes the library layers can be re-used
COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=1001 target/quarkus-app/*.jar /deployments/
COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/

EXPOSE 8080
USER 1001

# [== BEFORE ==]
# ENTRYPOINT [ "/deployments/run-java.sh" ]
# [== AFTER ==]
ENTRYPOINT "/deployments/run-java.sh" $CLI_ARGUMENTS

How do I transfer my parsed array data from one class to another?

copy iconCopydownload iconDownload
class getArrayElements extends SourceSentences {

    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        SourceSentences.translate();
        System.out.println(SourceSentences.sourceArray);
    }
}

Should EntityManagerFactory be closed at application shutdown?

copy iconCopydownload iconDownload
public interface DBInitializer {
    public void startDbConnection();
    public void closeDbConnection();
}
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class MySQLInitializer implements DBInitializer {
    private EntityManagerFactory emf;
    private EntityManager entityManager;
    private final Logger logger = LogManager.getLogger(MySQLInitializer.class);

    @Override
    public void startDbConnection() {
        try {
            emf = Persistence.createEntityManagerFactory("name");
            entityManager = emf.createEntityManager();
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "MySQL Exception", e);
        }
    }
    
    @Override
    public void closeDbConnection() {
        if (emf != null) {
            entityManager.close();
            emf.close();
        }
    }
}
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;

public class MongoInitializer implements DBInitializer {
    
    private MongoClient client;
    private final Logger logger = LogManager.getLogger(MongoInitializer.class);
    
    @Override
    public void startDbConnection() {
        try {
            client = new MongoClient(new ServerAddress("localhost", 27017));
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "Mongo Exception", e);
        }
    }

    @Override
    public void closeDbConnection() {
        client.close();
    }
}
import java.awt.EventQueue;
import java.util.concurrent.Callable;

import DBInitializer;
import MongoInitializer;
import MySQLInitializer;
import View;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(mixinStandardHelpOptions = true)
public class App implements Callable<Void> {

    private static final Logger LOGGER = LogManager.getLogger(App.class);

    @Option(names = { "--database" }, description = "Either 'mongo' or 'mysql'")
    private String databaseType = "mysql";

    public static void main(String[] args) {
        new CommandLine(new App()).execute(args);
    }

    DBInitializer dBInitializer;

    @Override
    public Void call() throws Exception {
        EventQueue.invokeLater(() -> {
            try {
                switch (databaseType) {
                case "mysql":
                    dBInitializer = new MySQLInitializer();
                    break;
                case "mongo":
                    dBInitializer = new MongoInitializer();
                    break;
                default:
                    LOGGER.log(Level.ERROR, "--database must be either 'mysql' or 'mongo'");
                    System.exit(1);
                }
                dBInitializer.startDbConnection();
                // other stuff
                View view = new View();
                view.setVisible(true);
                
            } catch (Exception e) {
                LOGGER.log(Level.ERROR, "Exception", e);
            }
        });

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                dBInitializer.closeDbConnection();
            }
        });
        return null;
    }
}
-----------------------
public interface DBInitializer {
    public void startDbConnection();
    public void closeDbConnection();
}
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class MySQLInitializer implements DBInitializer {
    private EntityManagerFactory emf;
    private EntityManager entityManager;
    private final Logger logger = LogManager.getLogger(MySQLInitializer.class);

    @Override
    public void startDbConnection() {
        try {
            emf = Persistence.createEntityManagerFactory("name");
            entityManager = emf.createEntityManager();
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "MySQL Exception", e);
        }
    }
    
    @Override
    public void closeDbConnection() {
        if (emf != null) {
            entityManager.close();
            emf.close();
        }
    }
}
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;

public class MongoInitializer implements DBInitializer {
    
    private MongoClient client;
    private final Logger logger = LogManager.getLogger(MongoInitializer.class);
    
    @Override
    public void startDbConnection() {
        try {
            client = new MongoClient(new ServerAddress("localhost", 27017));
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "Mongo Exception", e);
        }
    }

    @Override
    public void closeDbConnection() {
        client.close();
    }
}
import java.awt.EventQueue;
import java.util.concurrent.Callable;

import DBInitializer;
import MongoInitializer;
import MySQLInitializer;
import View;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(mixinStandardHelpOptions = true)
public class App implements Callable<Void> {

    private static final Logger LOGGER = LogManager.getLogger(App.class);

    @Option(names = { "--database" }, description = "Either 'mongo' or 'mysql'")
    private String databaseType = "mysql";

    public static void main(String[] args) {
        new CommandLine(new App()).execute(args);
    }

    DBInitializer dBInitializer;

    @Override
    public Void call() throws Exception {
        EventQueue.invokeLater(() -> {
            try {
                switch (databaseType) {
                case "mysql":
                    dBInitializer = new MySQLInitializer();
                    break;
                case "mongo":
                    dBInitializer = new MongoInitializer();
                    break;
                default:
                    LOGGER.log(Level.ERROR, "--database must be either 'mysql' or 'mongo'");
                    System.exit(1);
                }
                dBInitializer.startDbConnection();
                // other stuff
                View view = new View();
                view.setVisible(true);
                
            } catch (Exception e) {
                LOGGER.log(Level.ERROR, "Exception", e);
            }
        });

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                dBInitializer.closeDbConnection();
            }
        });
        return null;
    }
}
-----------------------
public interface DBInitializer {
    public void startDbConnection();
    public void closeDbConnection();
}
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class MySQLInitializer implements DBInitializer {
    private EntityManagerFactory emf;
    private EntityManager entityManager;
    private final Logger logger = LogManager.getLogger(MySQLInitializer.class);

    @Override
    public void startDbConnection() {
        try {
            emf = Persistence.createEntityManagerFactory("name");
            entityManager = emf.createEntityManager();
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "MySQL Exception", e);
        }
    }
    
    @Override
    public void closeDbConnection() {
        if (emf != null) {
            entityManager.close();
            emf.close();
        }
    }
}
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;

public class MongoInitializer implements DBInitializer {
    
    private MongoClient client;
    private final Logger logger = LogManager.getLogger(MongoInitializer.class);
    
    @Override
    public void startDbConnection() {
        try {
            client = new MongoClient(new ServerAddress("localhost", 27017));
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "Mongo Exception", e);
        }
    }

    @Override
    public void closeDbConnection() {
        client.close();
    }
}
import java.awt.EventQueue;
import java.util.concurrent.Callable;

import DBInitializer;
import MongoInitializer;
import MySQLInitializer;
import View;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(mixinStandardHelpOptions = true)
public class App implements Callable<Void> {

    private static final Logger LOGGER = LogManager.getLogger(App.class);

    @Option(names = { "--database" }, description = "Either 'mongo' or 'mysql'")
    private String databaseType = "mysql";

    public static void main(String[] args) {
        new CommandLine(new App()).execute(args);
    }

    DBInitializer dBInitializer;

    @Override
    public Void call() throws Exception {
        EventQueue.invokeLater(() -> {
            try {
                switch (databaseType) {
                case "mysql":
                    dBInitializer = new MySQLInitializer();
                    break;
                case "mongo":
                    dBInitializer = new MongoInitializer();
                    break;
                default:
                    LOGGER.log(Level.ERROR, "--database must be either 'mysql' or 'mongo'");
                    System.exit(1);
                }
                dBInitializer.startDbConnection();
                // other stuff
                View view = new View();
                view.setVisible(true);
                
            } catch (Exception e) {
                LOGGER.log(Level.ERROR, "Exception", e);
            }
        });

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                dBInitializer.closeDbConnection();
            }
        });
        return null;
    }
}
-----------------------
public interface DBInitializer {
    public void startDbConnection();
    public void closeDbConnection();
}
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class MySQLInitializer implements DBInitializer {
    private EntityManagerFactory emf;
    private EntityManager entityManager;
    private final Logger logger = LogManager.getLogger(MySQLInitializer.class);

    @Override
    public void startDbConnection() {
        try {
            emf = Persistence.createEntityManagerFactory("name");
            entityManager = emf.createEntityManager();
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "MySQL Exception", e);
        }
    }
    
    @Override
    public void closeDbConnection() {
        if (emf != null) {
            entityManager.close();
            emf.close();
        }
    }
}
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;

public class MongoInitializer implements DBInitializer {
    
    private MongoClient client;
    private final Logger logger = LogManager.getLogger(MongoInitializer.class);
    
    @Override
    public void startDbConnection() {
        try {
            client = new MongoClient(new ServerAddress("localhost", 27017));
            // other stuff
        } catch (Exception e) {
            logger.log(Level.ERROR, "Mongo Exception", e);
        }
    }

    @Override
    public void closeDbConnection() {
        client.close();
    }
}
import java.awt.EventQueue;
import java.util.concurrent.Callable;

import DBInitializer;
import MongoInitializer;
import MySQLInitializer;
import View;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(mixinStandardHelpOptions = true)
public class App implements Callable<Void> {

    private static final Logger LOGGER = LogManager.getLogger(App.class);

    @Option(names = { "--database" }, description = "Either 'mongo' or 'mysql'")
    private String databaseType = "mysql";

    public static void main(String[] args) {
        new CommandLine(new App()).execute(args);
    }

    DBInitializer dBInitializer;

    @Override
    public Void call() throws Exception {
        EventQueue.invokeLater(() -> {
            try {
                switch (databaseType) {
                case "mysql":
                    dBInitializer = new MySQLInitializer();
                    break;
                case "mongo":
                    dBInitializer = new MongoInitializer();
                    break;
                default:
                    LOGGER.log(Level.ERROR, "--database must be either 'mysql' or 'mongo'");
                    System.exit(1);
                }
                dBInitializer.startDbConnection();
                // other stuff
                View view = new View();
                view.setVisible(true);
                
            } catch (Exception e) {
                LOGGER.log(Level.ERROR, "Exception", e);
            }
        });

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                dBInitializer.closeDbConnection();
            }
        });
        return null;
    }
}

Groovy 4, JDK 11: Caught: Assertion failed

copy iconCopydownload iconDownload
-Dgroovy.attach.runtime.groovydoc=true

@Option with enum List does not accept candidates that ${COMPLETION-CANDIDATES} shows

copy iconCopydownload iconDownload
public class HeaderConverter implements CommandLine.ITypeConverter<List<Header>> {

    @Override
    public List<Header> convert(String s) throws Exception {
        List<Header> headers = new ArrayList<>();
        var params = s.split(",");
        Arrays.stream(params).forEach(x -> headers.add(Header.valueOf(x.trim())));
        return headers;
    }
}

Community Discussions

Trending Discussions on picocli
  • How can I construct the help functionality to divide subcommands into groups with separate descriptive headers?
  • Micronaut application built with Launch4J not launching
  • arggroup with default value in picocli
  • In picocli how do you make options on the command line to override the same option in an @-file
  • Bridging CLI argument parsing with application setup
  • How to decide Quarkus application arguments in Kubernetes at run-time?
  • How do I transfer my parsed array data from one class to another?
  • Should EntityManagerFactory be closed at application shutdown?
  • Groovy 4, JDK 11: Caught: Assertion failed
  • How to get ApplicationContext in Micronaut CLI application into Httpclient class?
Trending Discussions on picocli

QUESTION

How can I construct the help functionality to divide subcommands into groups with separate descriptive headers?

Asked 2022-Apr-08 at 12:48

A tool I am currently working on has a lot of subcommands which makes picocli's help output unclear. My code looks like this:

@Command(name = "toolName",
    version = "version",
    sortOptions = false,
    parameterListHeading = "%nParameters:%n",
    optionListHeading = "%nOptions:%n",
    commandListHeading = "%nThese are common commands:%n%n",
    subcommands = {
    command1.class,
    command2.class,
    command3.class,
    etc.class }

With help as:

@Option(names = {"-h", "--help"}, scope = ScopeType.INHERIT, usageHelp = true,
        description = "Display this help message.")
boolean usageHelpRequested;

I want the help output to look similar to git's:

git bash --help output

Here subcommands are divided into different functionalities (like start a working area) with a description. Is this possible using picocli?

ANSWER

Answered 2022-Apr-08 at 02:49

Yes that is possible by diving under the hood of picocli's Help API.

One idea is to have a custom IHelpSectionRenderer, see this example: https://github.com/remkop/picocli/blob/main/picocli-examples/src/main/java/picocli/examples/customhelp/GroupingDemo.java

Source https://stackoverflow.com/questions/71778823

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install picocli

You can add picocli as an external dependency to your project, or you can include it as source. See the source code. Copy and paste it into a file called CommandLine.java, add it to your project, and enjoy!.

Support

4.x User manual: https://picocli.info4.x Quick Guide4.x API JavadocCommand line autocompletionProgrammatic APIFAQGraalVM AOT Compilation to Native Image

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.