Skip to content

Command Registries

mattirn edited this page Jan 20, 2022 · 8 revisions

JLine provides CommandRegistry interface and two abstract classes JlineCommandRegistry and AbstractCommandRegistry to help custom commands implementation and integration to JLine application. JlineCommandRegistry can be used to facilitate command registry implementation of commands that uses Options and AbstractCommandRegistry for all the other cases.

JLine CommandRegistry implementations: Builtins, GroovyCommand, ConsoleEngineImpl and SystemRegistryImpl.

GroovyCommandRegistry

Builtins

Builtins has implementation of JLine builtin commands: colors, highlighter, history, keymap, less, nano, setopt, setvar , ttop, unsetopt and widget.

SystemRegistry

SystemRegistry aggregates CommandRegisteries, compile command pipe lines and dispatch command executions to the command registeries. In addition it compiles command completer for ReadLine and provides implemention of commandDescription() method for auto suggestion widgets. SystemRegistryImpl implements commands: exit and help.

ConsoleEngine

ConsoleEngine manages console variables, console script execution and object printing. ConsoleEngineImpl have implementation of console commands: alias, del, doc, pipe, prnt, show, slurp and unalias. ConsoleEngineImpl has println() method to facilitate highlighted object printing and adds support for widget creation using command widget -N new-widget.

ConsoleEngineImpl requires an implementation of ScriptEngine interface. GroovyEngine is JLine implemention of ScriptEngine interface. GroovyEngine maven dependency

<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline-groovy</artifactId>
    <version>${jline.version}</version>
</dependency>

that depence from two groovy libraries:

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy</artifactId>
</dependency>
<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-json</artifactId>
 </dependency>

GroovyCommand

GroovyCommand implements commands classloader, console, grab and inspect. GroovyCommand requires an optional JLine maven dependency

<dependency>
    <groupId>org.jline</groupId>
    <artifactId>jline-groovy</artifactId>
    <version>${jline.version}</version>
</dependency>

In addition commands console and grab require optional maven dependencies. Command console requires

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-console</artifactId>
</dependency>

and command grab

<dependency>
    <groupId>org.apache.ivy</groupId>
    <artifactId>ivy</artifactId>
</dependency> 

Examples

JLine has two demos that uses command registries one with ConsoleEngine and Groovy dependencies: Repl and an other without Graal.

    //
    // ScriptEngine and command registeries
    //
    ConfigurationPath configPath = new ConfigurationPath(appConfig, userConfig);
    GroovyEngine scriptEngine = new GroovyEngine();
    Printer printer = new DefaultPrinter(scriptEngine, configPath);
    ConsoleEngineImpl consoleEngine = new ConsoleEngineImpl(scriptEngine
                                                          , printer
                                                          , Repl::workDir, configPath);
    Builtins builtins = new Builtins(Repl::workDir, configPath
                                  , (String fun)-> {return new ConsoleEngine.WidgetCreator(consoleEngine, fun);});
    MyCommands myCommands = new MyCommands(Repl::workDir);
    SystemRegistryImpl systemRegistry = new SystemRegistryImpl(parser, terminal, Repl::workDir, configPath);
    systemRegistry.register("groovy", new GroovyCommand(scriptEngine, consoleEngine));
    systemRegistry.setCommandRegistries(consoleEngine, builtins, myCommands);
    //
    // set scriptEngine statement completer and description method to systemRegistry (JLine version > 3.15.0)
    //
    systemRegistry.addCompleter(scriptEngine.getScriptCompleter());
    systemRegistry.setScriptDescription(scriptEngine::scriptDescription);
    //
    // LineReader
    //
    LineReader reader = LineReaderBuilder.builder()
                .terminal(terminal)
                .completer(systemRegistry.completer())
                .parser(parser)
                .variable(LineReader.SECONDARY_PROMPT_PATTERN, "%M%P > ")
                .variable(LineReader.INDENTATION, 2)
                .variable(LineReader.HISTORY_FILE, Paths.get(root, "history"))
                .option(Option.INSERT_BRACKET, true)
                .option(Option.DISABLE_EVENT_EXPANSION, true)
                .build();
    //
    // complete command registeries
    //
    consoleEngine.setLineReader(reader);
    builtins.setLineReader(reader);
    myCommands.setLineReader(reader);
    //
    // widgets and console initialization
    //
    new TailTipWidgets(reader, systemRegistry::commandDescription, 5, TipType.COMPLETER);
    KeyMap<Binding> keyMap = reader.getKeyMaps().get("main");
    keyMap.bind(new Reference(Widgets.TAILTIP_TOGGLE), KeyMap.alt("s"));
    systemRegistry.initialize(Paths.get(root, "init.jline").toFile());
    //
    // REPL-loop
    //
    consoleEngine.println(terminal.getName() + ": " + terminal.getType());
    while (true) {
        try {
            systemRegistry.cleanUp();         // delete temporary variables and reset output streams
            String line = reader.readLine("groovy-repl> ");
            Object result = systemRegistry.execute(line);
            consoleEngine.println(result);    // print command result
        }
        catch (UserInterruptException e) {
            // Ignore
        }
        catch (EndOfFileException e) {
            break;
        }
        catch (Exception e) {
            systemRegistry.trace(e);          // print exception and save it to console variable
        }
    }
    systemRegistry.close();                   // persist pipeline names for completer etc