Iwakura Enterprises Documentations 1.0 Help

Ganyu

  • Ganyu logo

  • Ganyu is a Java library that allows you to create easy CLI.

    It provides a toolset of annotations and classes to create commands and subcommands.

    Contrary to normal CLI libraries, Ganyu also provides so called "named arguments", which are similar to flags.

    You may find all the documentation about Ganyu on this page.

Quick example

// Define a command @Command("echo") @Syntax("echo [-m --message text] (-t --times number)") @Description("Echoes a message a number of times") public class EchoCommand implements GanyuCommand { // Define default command method @DefaultCommand @NamedArgumentHandler public void echo( CommandInvocationContext ctx, // Define named arguments @NamedArg(value = "m", longForm = "message") String message, @NamedArg(value = "t", longForm = "times") Integer times ) { // Command execution for (int i = 0; i < times; i++) { System.out.println(message); } } } // Create Ganyu instance and register the command Ganyu ganyu = Ganyu.console(); ganyu.registerCommands(new EchoCommand()); ganyu.run(); // Now, in console: // $ echo -m "Hello, World!" -t 3 // Hello, World! // Hello, World! // Hello, World!

    Installation

    Ganyu is available on Maven Central.

    Badge

    implementation 'enterprises.iwakura:ganyu:VERSION'
    <dependency> <groupId>enterprises.iwakura</groupId> <artifactId>ganyu</artifactId> <version>VERSION</version> </dependency>

    Creating a Ganyu instance

    There are more ways to create your Ganyu instance. Ganyu has three built-in static methods that should cover the majority of use cases.

    Ganyu.console()

    Uses System.in and System.out for IO.

    Ganyu.standard(Input, Output)

    Specifies custom Input and Output implementations.

    Ganyu.standardWithExecutor(Input, Output, Executor)

    Same as standard(), but allows you to specify Executor.

    When your application is about to exit, you should call Ganyu#stop() method to properly interrupt the command reader thread.

    Input

    Ganyu uses Input interface to read user input. It has a single method, readNextInput(). This method should block a thread until a line is read, and return the line as a String.

    Output

    Ganyu uses Output interface to write output. It has two methods, info(String) and error(String, Throwable). These methods are used throughout Ganyu to write normal and error outputs respectively. The Throwable parameter in error() may be null.

    CommandArgumentParser

    Ganyu uses CommandArgumentParser interface to parse command arguments. There are two methods for two possible argument styles: parseSimple() and parseNamed(). The former is used to parse simple arguments, while the latter is used to parse named arguments (flags).

    CommandRegisterProcessor

    Ganyu uses CommandRegisterProcessor interface to parse and register commands. It has a single method, process(Ganyu, GanyuCommand).

    This method returns a List<RegisteredCommand>, which contains all commands that are registered from the given GanyuCommand instance. This is because there may be more than one method annotated with @Command annotation.

    InjectableArgumentResolver

    Ganyu uses InjectableArgumentResolver interface to resolve injectable arguments. It has two methods, register() and resolve(). The former is used to register injectable argument types with its getter, while the latter is used to resolve injectable arguments based on CommandArgumentDefinition.

    Creating commands

    A command is a class that implements GanyuCommand interface. It may contain one or more methods annotated with @DefaultCommand, @Command or @SubCommand annotation. Each method represents a command.

    You may also define methods annotated with @PreCommand, @PostCommand, and @ExceptionHandler annotations. They will be invoked before, after, and when an exception is thrown in a command method respectively.

    You may register command classes with Ganyu.registerCommands(GanyuCommand...) method.

    Example command

    @Command("users") @Description("Manages users") @Syntax("(add | delete [id])") public class UserCommand implements GanyuCommand { @DefaultCommand @Description("Lists all users") public void listUsers(CommandInvocationContext ctx) { // List users } @SubCommand("add") @Description("Adds a new user") @Syntax("[name] (age)") public void addUser( CommandInvocationContext ctx, @Description("Name of the user") String name, @OptionalArg @Description("Age of the user") Integer age ) { // Add user } @SubCommand("delete") @Description("Deletes a user") @Syntax("id") public void deleteUser( CommandInvocationContext ctx, @Description("ID of the user") int userId ) { // Delete user } }

      Command methods

      As you define a command, you must define its method signature properly.

      Return value

      Command can return void, CommandResult or CompletableFuture<CommandResult>. If the return type is void, it is treated as CommandResult.success().

      Parameters

      Commands may have unlimited number of parameters. Some of them may be optional, in which case they cannot be primitive.

      Parameters come in three forms: simple, named and injectable. Simple and named arguments are parsed from user input,

      whereas injectable arguments are resolved by InjectableArgumentResolver.

      The CommandInvocationContext parameter is injectable and is optional.

      Method body

      Preferably, you should not throw exceptions within command methods. Instead, return CommandResult.error(String) or

      CommandResult.error(String, Throwable) to indicate failure. If an exception is thrown,

      it will be caught and passed to @ExceptionHandler method if defined.

      Interesting classes

      Ganyu uses several classes to represent commands, arguments and command invocation context.

      CommandInvocationContext

      CommandInvocationContext is a class that contains information about the command invocation.

      It contains fields that may be useful in command methods, pre/post-command methods, and exception handler methods, as it holds references to Ganyu instance, RegisteredCommand instance, command arguments, nullable CommandResult instance and so on.

      RegisteredCommand

      An internal class that represents a registered command. It contains information about the command, such as its name, description, syntax, method, instance, argument definitions and so on. It also holds references to its sub-commands.

      You do not directly use this class. But it is accessible via the CommandInvocationContext instance.

      CommandArgumentDefinition

      CommandArgumentDefinition is a class that represents a command argument definition. It contains information about the argument, such as its name, type, whether it is optional, whether it is named, and so on.

      Usually you come across this class when you want to resolve injectable arguments via InjectableArgumentResolver.

      Custom command arguments

      You may define your own command argument types. Either an argument parsed from user input or a injectable argument.

      Argument parsed from user input

      For this type of argument you must define a ArgumentParser class and its method parse(String).

      This method should parse the given string and return an instance of the argument type.

      You must as well use its constructor to define the Class.

      This kind of argument may be annotated with @GreedyArgument annotation to indicate that it is a greedy argument. See @GreedyArgument annotation for more details.

      You may register your argument parser as follows:

      ganyu.registerArgumentParser(new MyArgumentParser());
      Injectable argument

      For this type of argument you must define a class and annotate it with @InjectableArgument annotation.

      Then you must register it with InjectableArgumentResolver as follows:

      ganyu.getInjectableArgumentResolver().register( MyInjectableArgument.class, (arg, ctx) -> new MyInjectableArgument(/* ... */) );

      In-built help command

      Ganyu provides an in-built command, help, which lists all registered commands and their descriptions. It is registered by default.

      Annotations

      There are several annotations provided by Ganyu to define commands and their properties.

      @Command

      Defines a command. You may annotate a class or a method with this annotation. Has one value, the command's name.

      If annotated on a class, the specified command's name will be used for @DefaultCommand and @SubCommand methods in the class.

      If annotated on a method, the method will be treated as root level command.

      @Command("users") public class UserCommand { // ... }

        @DefaultCommand

        Defines the default command in a class. Maximum of one method in a class may be annotated with this annotation.

        Is similar to other annotations: @Command and @SubCommand, but does not require a name.

        // ... public class UserCommand { // ... @DefaultCommand public void listUsers(CommandInvocationContext ctx) { // ... } }

          @SubCommand

          Defines a subcommand in a class. Annotates a method.

          As the name suggests, this command is a subcommand of the command defined by the class's @Command annotation.

          Has one value, the subcommand's name.

          // ... public class UserCommand { // ... @SubCommand("delete") public void deleteUser(CommandInvocationContext ctx /* ... */) { // ... } }

            @PreCommand

            Defines a pre-command method. Maximum of one method in a class may be annotated with this annotation.

            This method will be invoked before a command method is invoked.

            // ... public class UserCommand { // ... @PreCommand public void logUsage(CommandInvocationContext ctx) { // ... } }

              @PostCommand

              Defines a post-command method. Maximum of one method in a class may be annotated with this annotation.

              This method will be invoked after a command method is invoked and did not throw an exception.

              // ... public class UserCommand { // ... @PostCommand public void cleanUp(CommandInvocationContext ctx) { // ... } }

                @ExceptionHandler

                Defines an exception handler method. Maximum of one method in a class may be annotated with this annotation.

                This method will be invoked when a command method throws an exception.

                // ... public class UserCommand { // ... @ExceptionHandler public void handleExceptions( CommandInvocationContext ctx, Throwable exception ) { // ... } }

                  @Description

                  Defines a description for a command or argument. Annotates a class, method, or parameter.

                  Has one value, the description text.

                  @Description("Manages users") public class UserCommand { // ... @Description("Deletes a user") public void deleteUser( CommandInvocationContext ctx, @Description("ID of the user") int userId ) { // ... } }

                    @Syntax

                    Defines a syntax for a command. Annotates a class or method.

                    Has one value, the syntax text.

                    @Syntax("(add | delete [id])") public class UserCommand { // ... @Syntax("[id]") public void deleteUser(CommandInvocationContext ctx /* ... */) { // ... } }

                      @NamedArgumentHandler

                      Marks a command method as a named argument handler.

                      Named arguments (flags) will be parsed and passed to the method.

                      Must have parameters annotated with @NamedArg annotation.

                      // ... public class UserCommand { // ... @NamedArgumentHandler public void deleteUser(CommandInvocationContext ctx /* ... */) { // ... } }

                        @NamedArg

                        Defines a named argument (flag) for a command method.

                        Has two values, value and longForm, which are the short and long forms of the named argument respectively.

                        // ... public class UserCommand { // ... @NamedArgumentHandler public void deleteUser( CommandInvocationContext ctx, @NamedArg(value = "i", longForm = "id") int userId ) { // ... } }

                          @OptionalArg

                          Marks a command method parameter as optional.

                          Optional arguments may be null if not provided. Primitive types are not supported.

                          In case of simple arguments, you must mark parameters as optional from right to left with no gaps.

                          // ... public class UserCommand { // ... public void deleteUser( CommandInvocationContext ctx, @OptionalArg Integer userId ) { // ... } }

                            @GreedyArgument

                            Annotates a class that may be used as a greedy argument.

                            Greedy arguments will consume all remaining input as a single argument.

                            A command method may have at most one greedy argument, and it must be the last parameter.

                            String is a built-in greedy argument type.

                            @GreedyArgument public class MyGreedyArgument { // ... }

                              @InjectableArgument

                              Annotates a class that may be used as an injectable argument.

                              Injectable arguments will be resolved by InjectableArgumentResolver.

                              A command method may have any number of injectable arguments.

                              CommandInvocationContext is a built-in injectable argument type.

                              @InjectableArgument public class MyInjectableArgument { // ... }
                                01 September 2025