Skip to content

Commit

Permalink
REPL console: added Printer interface and a groovy command inspect
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Apr 24, 2020
1 parent 4179fbd commit 070d32c
Show file tree
Hide file tree
Showing 10 changed files with 430 additions and 133 deletions.
4 changes: 0 additions & 4 deletions builtins/src/main/java/org/jline/builtins/Builtins.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
*/
package org.jline.builtins;

import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Matcher;
Expand All @@ -28,7 +25,6 @@
import org.jline.reader.impl.completer.ArgumentCompleter;
import org.jline.reader.impl.completer.NullCompleter;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.terminal.Terminal;
import org.jline.utils.AttributedString;

/**
Expand Down
251 changes: 152 additions & 99 deletions builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
* @author <a href="mailto:matti.rintanikkola@gmail.com">Matti Rinta-Nikkola</a>
*/
public abstract class JlineCommandRegistry extends AbstractCommandRegistry {

public JlineCommandRegistry() {
super();
}

public List<String> commandInfo(String command) {
try {
Object[] args = {"--help"};
Expand All @@ -56,19 +56,7 @@ public List<String> commandInfo(String command) {

public CmdDesc commandDescription(String command) {
try {
if (command != null && !command.isEmpty()) {
invoke(new CommandSession(), command, new Object[] {"--help"});
} else {
List<AttributedString> main = new ArrayList<>();
Map<String, List<AttributedString>> options = new HashMap<>();
for (String c : new TreeSet<String>(commandNames())) {
for (String info : commandInfo(c)) {
main.add(HelpException.highlightSyntax(c + " - " + info, HelpException.defaultStyle(), true));
break;
}
}
return new CmdDesc(main, ArgDesc.doArgNames(Arrays.asList("")), options);
}
invoke(new CommandSession(), command, new Object[] {"--help"});
} catch (HelpException e) {
return Builtins.compileCommandDescription(e.getMessage());
} catch (Exception e) {
Expand All @@ -77,7 +65,7 @@ public CmdDesc commandDescription(String command) {
throw new IllegalArgumentException("JlineCommandRegistry.commandDescription() method must be overridden in class "
+ this.getClass().getCanonicalName());
}

public List<OptDesc> commandOptions(String command) {
try {
invoke(new CommandSession(), command, "--help");
Expand Down Expand Up @@ -106,5 +94,5 @@ public Options parseOptions(String[] usage, Object[] args) throws HelpException
}
return opt;
}

}
23 changes: 19 additions & 4 deletions builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.jline.builtins.Widgets;
import org.jline.builtins.Options.HelpException;
import org.jline.console.AbstractCommandRegistry;
import org.jline.console.ArgDesc;
import org.jline.console.CmdDesc;
import org.jline.console.CommandInput;
import org.jline.console.CommandMethods;
Expand Down Expand Up @@ -276,7 +277,7 @@ private CmdDesc localCommandDescription(String command) {
public CmdDesc commandDescription(String command) {
return commandDescription(Arrays.asList(command));
}

@Override
public CmdDesc commandDescription(List<String> args) {
CmdDesc out = new CmdDesc(false);
Expand All @@ -292,6 +293,18 @@ public CmdDesc commandDescription(List<String> args) {
return out;
}

private CmdDesc commandDescription(CommandRegistry subreg) {
List<AttributedString> main = new ArrayList<>();
Map<String, List<AttributedString>> options = new HashMap<>();
for (String sc : new TreeSet<String>(subreg.commandNames())) {
for (String info : subreg.commandInfo(sc)) {
main.add(HelpException.highlightSyntax(sc + " - " + info, HelpException.defaultStyle(), true));
break;
}
}
return new CmdDesc(main, ArgDesc.doArgNames(Arrays.asList("")), options);
}

@Override
public CmdDesc commandDescription(Widgets.CmdLine line) {
CmdDesc out = null;
Expand All @@ -305,11 +318,13 @@ public CmdDesc commandDescription(Widgets.CmdLine line) {
if (c == null || subcommands.get(cmd).hasCommand(c)) {
if (c != null && c.equals("help")) {
out = null;
} else {
} else if (c != null) {
out = subcommands.get(cmd).commandDescription(c);
} else {
out = commandDescription(subcommands.get(cmd));
}
} else {
out = subcommands.get(cmd).commandDescription("");
out = commandDescription(subcommands.get(cmd));
}
if (out != null) {
out.setSubcommand(true);
Expand Down Expand Up @@ -1407,7 +1422,7 @@ private Object exit(CommandInput input) {
, "Usage: exit [OBJECT]"
, " -? --help Displays command help"
};

try {
Options opt = parseOptions(usage, input.args());
if (!opt.args().isEmpty() && consoleId != null) {
Expand Down
2 changes: 1 addition & 1 deletion builtins/src/main/java/org/jline/builtins/Widgets.java
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ private List<AttributedString> compileMainDescription(CmdDesc cmdDesc, int descr
if (mainDesc == null) {
// do nothing
} else if (mainDesc.size() <= descriptionSize && lastArg == null) {
out = mainDesc;
out.addAll(mainDesc);
} else {
int tabs = 0;
int row = 0;
Expand Down
5 changes: 3 additions & 2 deletions demo/src/main/java/org/jline/demo/Repl.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.jline.builtins.SystemRegistryImpl;
import org.jline.builtins.Widgets.TailTipWidgets;
import org.jline.builtins.Widgets.TailTipWidgets.TipType;
import org.jline.console.AbstractCommandRegistry;
import org.jline.console.CommandInput;
import org.jline.console.CommandMethods;
import org.jline.console.CommandRegistry;
Expand All @@ -48,6 +47,7 @@
import org.jline.reader.impl.completer.ArgumentCompleter;
import org.jline.reader.impl.completer.NullCompleter;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.script.GroovyCommand;
import org.jline.script.GroovyEngine;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
Expand Down Expand Up @@ -321,11 +321,12 @@ public static void main(String[] args) {
GroovyEngine scriptEngine = new GroovyEngine();
scriptEngine.put("ROOT", root);
ConfigurationPath configPath = new ConfigurationPath(Paths.get(root), Paths.get(root));
ConsoleEngine consoleEngine = new ConsoleEngineImpl(scriptEngine, Repl::workDir, configPath);
ConsoleEngineImpl consoleEngine = new ConsoleEngineImpl(scriptEngine, 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("command", new SubCommands());
systemRegistry.register("groovy", new GroovyCommand(scriptEngine, consoleEngine));
systemRegistry.setCommandRegistries(consoleEngine, builtins, myCommands);
//
// LineReader
Expand Down
56 changes: 56 additions & 0 deletions groovy/src/main/groovy/org/jline/groovy/ObjectInspector.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2002-2020, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package org.jline.groovy

import java.lang.reflect.*

public class ObjectInspector {
public static final List<String> METHOD_COLUMNS = ['language','modifiers','this','return','name','parameters','exception','8']
def obj
def inspector

public ObjectInspector(def obj) {
this.obj = obj
this.inspector = new groovy.inspect.Inspector(obj)
}

List<Map<String, String>> methods() {
def out = []
inspector.methods.each {
def mdef = [:]
for (int i = 0; i < it.size(); i++) {
mdef.put(METHOD_COLUMNS.get(i), it.getAt(i))
}
out.add(mdef)
}
out
}

List<Map<String, String>> metaMethods() {
def out = []
inspector.metaMethods.each {
def mdef = [:]
for (int i = 0; i < it.size(); i++) {
mdef.put(METHOD_COLUMNS.get(i),it.getAt(i))
}
out.add(mdef)
}
out
}

def properties() {
def out = [:]
def props=['propertyInfo', 'publicFields', 'classProps']
props.each {
def val = inspector.properties.get(it)
out.put(it, val)
}
out
}
}
141 changes: 137 additions & 4 deletions groovy/src/main/java/org/jline/script/GroovyCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,161 @@
*/
package org.jline.script;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jline.console.CommandInput;
import org.jline.console.CommandMethods;
import org.jline.console.AbstractCommandRegistry;
import org.jline.console.CmdDesc;
import org.jline.console.CommandRegistry;
import org.jline.console.Printer;
import org.jline.groovy.ObjectInspector;
import org.jline.reader.Completer;
import org.jline.reader.impl.completer.ArgumentCompleter;
import org.jline.reader.impl.completer.NullCompleter;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.utils.AttributedString;

public class GroovyCommand extends AbstractCommandRegistry implements CommandRegistry {
public enum Command {INSPECT}
private GroovyEngine engine;
private Printer printer;
private final Map<Command,CmdDesc> commandDescs = new HashMap<>();
private final Map<Command,List<String>> commandInfos = new HashMap<>();

public GroovyCommand() {
public GroovyCommand(GroovyEngine engine, Printer printer) {
this(null, engine, printer);
}

public GroovyCommand(Set<Command> commands, GroovyEngine engine, Printer printer) {
this.engine = engine;
this.printer = printer;
Set<Command> cmds = new HashSet<>();
Map<Command,String> commandName = new HashMap<>();
Map<Command,CommandMethods> commandExecute = new HashMap<>();
if (commands == null) {
cmds = new HashSet<>(EnumSet.allOf(Command.class));
} else {
cmds = new HashSet<>(commands);
}
for (Command c: cmds) {
commandName.put(c, c.name().toLowerCase());
}
commandExecute.put(Command.INSPECT, new CommandMethods(this::inspect, this::inspectCompleter));
registerCommands(commandName, commandExecute);
commandDescs.put(Command.INSPECT, inspectCmdDesc());
}

@Override
public List<String> commandInfo(String command) {
// TODO Auto-generated method stub
return null;
Command cmd = (Command)registeredCommand(command);
return commandInfos.get(cmd);
}

@Override
public CmdDesc commandDescription(String command) {
// TODO Auto-generated method stub
Command cmd = (Command)registeredCommand(command);
return commandDescs.get(cmd);
}

public Object inspect(CommandInput input) {
if (input.xargs().length == 0) {
return null;
}
if (input.args().length > 2) {
throw new IllegalArgumentException("Wrong number of command parameters: " + input.args().length);
}
int idx = optionIdx(Command.INSPECT, input.args());
String option = idx < 0 ? "--info" : input.args()[idx];
if (option.equals("-?") || option.equals("--help")) {
printer.println(commandDescs.get(Command.INSPECT));
return null;
}
int id = 0;
if (idx >= 0) {
id = idx == 0 ? 1 : 0;
}
if (input.args().length < id + 1) {
throw new IllegalArgumentException("Wrong number of command parameters: " + input.args().length);
}
Object obj = input.xargs()[id];
ObjectInspector inspector = new ObjectInspector(obj);
Object out = option;
if (option.equals("-m") || option.equals("--methods")) {
out = inspector.methods();
} else if (option.equals("-n") || option.equals("--metaMethods")) {
out = inspector.metaMethods();
} else if (option.equals("-i") || option.equals("--info")) {
out = inspector.properties();
} else if (option.equals("-g") || option.equals("--gui")) {
// groovy.inspect.swingui.ObjectBrowser.inspect(obj);
} else {
throw new IllegalArgumentException("Unknown option: " + option);
}
Map<String,Object> options = new HashMap<>();
options.put(Printer.SKIP_DEFAULT_OPTIONS, true);
options.put(Printer.COLUMNS, ObjectInspector.METHOD_COLUMNS);
printer.println(options, out);
return null;
}

private CmdDesc inspectCmdDesc() {
Map<String,List<AttributedString>> optDescs = new HashMap<>();
optDescs.put("-? --help", doDescription ("Displays command help"));
optDescs.put("-g --gui", doDescription ("Open object browser"));
optDescs.put("-i --info", doDescription ("Object class info"));
optDescs.put("-m --methods", doDescription ("List object methods"));
optDescs.put("-n --metaMethods", doDescription ("List object metaMethads"));
CmdDesc out = new CmdDesc(new ArrayList<>(), optDescs);
List<AttributedString> mainDesc = new ArrayList<>();
List<String> info = new ArrayList<>();
info.add("Display object info on terminal");
commandInfos.put(Command.INSPECT, info);
mainDesc.add(new AttributedString("inspect - " + info.get(0)));
mainDesc.add(new AttributedString("Usage: inspect [OPTION] OBJECT"));
out.setMainDesc(mainDesc);
return out;
}

private List<AttributedString> doDescription(String description) {
List<AttributedString> out = new ArrayList<>();
out.add(new AttributedString(description));
return out;
}

private int optionIdx(Command cmd, String[] args) {
for (String a : args) {
int out = 0;
if (a.startsWith("-")) {
return out;
}
out++;
}
return -1;
}

private List<String> variables() {
List<String> out = new ArrayList<>();
for (String v : engine.find(null).keySet()) {
out.add("$" + v);
}
return out;
}

public List<Completer> inspectCompleter(String command) {
List<Completer> out = new ArrayList<>();
ArgumentCompleter ac = new ArgumentCompleter(NullCompleter.INSTANCE
, new StringsCompleter("--help", "--methods", "--metaMethods", "--gui", "--info"
,"-?", "-n", "-m", "-i", "-g")
, new StringsCompleter(this::variables)
, NullCompleter.INSTANCE);
out.add(ac);
return out;
}
}

0 comments on commit 070d32c

Please sign in to comment.