JavaでCUIによる対話型のツール(REPL)を作りたいときは、
以下のJLineを使うと簡単に実装する事が出来ます。
# ちなみにREPLというのは、Read-Eval-Print Loopの略で、
# コマンド受付→評価→表示を繰り返す、対話型処理のことです。

JLine | GitHub
https://github.com/jline/jline3

このエントリでは、JLineによる基本的なCUIの作り方と、
複数行コマンド受付の対応方法を示します。

JLineによるCUIの実装

まず、JLineによるCUIを実装します。
以下のbuild.gradleCuiSample.javaを作成します。

build.gradle

plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '4.0.3'
}

repositories {
    jcenter()
}
dependencies {
    compile 'org.jline:jline:3.9.0'
}

jar {
    manifest {
        attributes 'Main-Class': 'CuiSample'
    }
}
artifacts {
    archives shadowJar
}

src/main/java/CuiSample.java

import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.Parser;
import org.jline.reader.impl.DefaultParser;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

public class CuiSample {

  public static void main(String[] args) throws Exception {
    // JLine terminal の準備
    Terminal terminal = TerminalBuilder.builder()
        .system(true)
        .build();

    // Parser の準備
    Parser p = new DefaultParser();
    LineReader lineReader = LineReaderBuilder.builder()
        .terminal(terminal)
        .parser(p)
        .build();

    // REPL
    while (true) {
      String line = lineReader.readLine("input > ");

      String[] exitCommands = {":exit"};
      for (String cmd : exitCommands) {
        if (line.contains(cmd)) {
          return;
        }
      }

      System.out.println(line);
    }
  }

}

ビルドします。

$ gradle build

実行すると、以下のようになります。
この実装では、入力されたコマンドをそのまま表示、
:exitでループを抜けるようにしています。

$ java -jar build/libs/jline-sample-all.jar
input > hello
hello
input > :exit

複数行コマンド受付の対応

上記で作成したCUIでは、改行が入力されるとコマンドの評価に入ります。
複数行のコマンドを受け付けたい場合は、以下のように、
「EofOnEscapedNewLine」を有効にすると、
複数行コマンドを入力できるようになります。

src/main/java/CuiSample.java の変更

    // Parser の準備
    DefaultParser p = new DefaultParser();
    p.setEofOnEscapedNewLine(true);
    LineReader lineReader = LineReaderBuilder.builder()
        .terminal(terminal)
        .parser(p)
        .build();

実行すると、以下のようになります。

$ gradle build
$ java -jar build/libs/jline-sample-all.jar
input > hello \
> world
hello world
input > :exit

改行をESCAPEするのではなく、
SQLのCUIのように、「;」が入力された時にコマンドを確定させる。
ということをやりたい場合は、
標準のorg.jline.reader.impl.DefaultParserでは無く、
以下のように自前のParserを作って対応します。

src/main/java/MultilineParser.java

import org.jline.reader.EOFError;
import org.jline.reader.ParsedLine;
import org.jline.reader.impl.DefaultParser;

public class MultilineParser extends DefaultParser {

  @Override
  public ParsedLine parse(final String line, final int cursor, ParseContext context) {
    ParsedLine pl = super.parse(line, cursor, context);

    if (!line.trim().endsWith(";") && !line.startsWith(":")) {
      throw new EOFError(-1, -1, "Without semicolon", "");
    }
    return pl;
  }

}

src/main/java/CuiSample.java の変更

    // Parser の準備
    MultilineParser p = new MultilineParser();
    LineReader lineReader = LineReaderBuilder.builder()
        .terminal(terminal)
        .parser(p)
        .build();

MultilineParserでは、
;で終わる or :で始まる時に、コマンドを確定させています。
parseメソッドで、EOFErrorを投げればコマンドは未確定と扱われます。

実行すると、以下のようになります。

$ gradle build
$ java -jar build/libs/jline-sample-all.jar
input > hello
> world;
hello
world;
input > :exit

以上。