Skip to content

Quick Start

JohnnyJayJay edited this page Mar 28, 2020 · 7 revisions

After having added the necessary dependencies you're ready to use mela-command.

As explained in the project structure, you can write commands in two different ways. This page has a quick start for both of them.

Core Commands

Core Framework Guide

To write commands using the core framework, your classes must implement the CommandCallable interface. In most cases, it is convenient to extend the CommandCallableAdapter class, as it already implements the various getter methods of CommandCallable.

As an example, here is a command that takes one argument and "greets" it on the console:

import io.github.mela.command.core.*;
import java.util.Arrays;

public class GreetCommand extends CommandCallableAdapter {

  public GreetCommand() {
    super(
      Arrays.asList("greet", "g"),     // labels (to identify the command)
      "Greets someone or something",   // Description   
      "Try \"greet Johnny\"!",         // Help message  
       "[greet|g] <subject>"           // Usage
    );
  }

  @Override 
  public void call(CommandArguments arguments, CommandContext context) {
    System.out.printf("Hello, %s.%n", arguments.hasNext() ? arguments.nextString() : "world");
  }
}

Now, you need to create a CommandGroup. This can be done with an ImmutableGroupBuilder.

CommandGroup root = ImmutableGroup.builder()
    .add(new GreetCommand())
    .build();        .

Finally, to actually execute commands, you need an instance of a CommandDispatcher. The core module provides a default implementation called DefaultDispatcher.

CommandDispatcher dispatcher = DefaultDispatcher.create(root);

Now you can dispatch commands using dispatcher.dispatch(String, CommandContext). The command context holds any data related to the context in which the command was executed, e.g. who executed it, where it was executed etc. In our case, there is no relevant information to provide for that matter, so we can just dispatch commands with an empty context.

The dispatch method throws an UnknownCommandException if the input could not be resolved to a command.

This is our final programme:

import io.github.mela.command.core.*;

public class Main {

  private static CommandDispatcher dispatcher;

  public static void main(String[] args) {
    CommandGroup root = ImmutableGroup.builder()
        .add(new GreetCommand())
        .build();
    dispatcher = DefaultDispatcher.create(root);
    // Irrelevant whitespace is ignored
    dispatch("g    user    ");
    // Command labels are case insensitive
    dispatch("grEEt");
    // Even mela can't fix your typos
    dispatch("freet mela");
  }

  private static void dispatch(String input) {
    System.out.printf("Dispatching \"%s\"...%n", input);
    try {
      dispatcher.dispatch(input, CommandContext.create());
    } catch (UnknownCommandException e) {
      System.out.println("Unknown command.")
    }    
  }
}

Output:

Dispatching "g    user    "...
Hello, user.

Dispatching "grEEt"...
Hello, world.

Dispatching "freet mela"...
Unknown command.

Bind Commands

Bind Framework Guide

As a quick start for the bind framework and its standard library, let's create an equivalent of the quick start above.

To create commands, no inheritance or interface implementation is needed; just an annotated instance method.

import io.github.mela.command.provided.interceptors.Default;

public class GreetCommand {

  // This annotation takes the same data as the constructor of CommandCallableAdapter
  @Command(
    labels = {"greet", "g"},
    desc = "Greets someone or something",
    help = "Try \"greet Johnny\"!",
    usage = "[greet|g] <subject>"
  )
  // Command methods need to be public
  public void greet(
    @Default("world") String subject // One String argument - default to "world" if not present
  ) { 
    System.out.printf("Hello, %s.%n", subject);
  }
}

To create a CommandGroup, an extra step is required, since we now need to use the compile API explicitely:

CommandBindings bindings = ProvidedBindings.get(); // std lib (provided) bindings
CommandCompiler compiler = MethodHandleCompiler.withBindings(bindings); 
CommandGroup root = ImmutableGroup.builder()
    .add(new GreetCommand())
    .compile(compiler);

The ProvidedBindings contain bindings for String and @Default and is therefore everything we need.

Apart from that, everything remains the same:

import io.github.mela.command.core.*;
import io.github.mela.command.bind.*;
import io.github.mela.command.provided.ProvidedBindings;

public class Main {

  private static CommandDispatcher dispatcher;

  public static void main(String[] args) {
    CommandBindings bindings = ProvidedBindings.get(); // std lib (provided) bindings
    CommandCompiler compiler = MethodHandleCompiler.withBindings(bindings);
    CommandGroup root = ImmutableGroup.builder()
        .add(new GreetCommand())
        .compile(compiler);
    dispatcher = DefaultDispatcher.create(root);
    // Irrelevant whitespace is ignored
    dispatch("g    user    ");
    // Command labels are case insensitive
    dispatch("grEEt");
    // Even mela can't fix your typos
    dispatch("freet mela");
  }

  private static void dispatch(String input) {
    System.out.printf("Dispatching \"%s\"...%n", input);
    try {
      dispatcher.dispatch(input, CommandContext.create());
    } catch (UnknownCommandException e) {
      System.out.println("Unknown command.")
    }
  }
}

Output:

Dispatching "g    user    "...
Hello, user.

Dispatching "grEEt"...
Hello, world.

Dispatching "freet mela"...
Unknown command.