diff --git a/builtins/src/main/java/org/jline/builtins/CommandRegistry.java b/builtins/src/main/java/org/jline/builtins/CommandRegistry.java index 6b1c0da2d..ca14ed8b3 100644 --- a/builtins/src/main/java/org/jline/builtins/CommandRegistry.java +++ b/builtins/src/main/java/org/jline/builtins/CommandRegistry.java @@ -10,14 +10,13 @@ import org.jline.builtins.Completers; import org.jline.builtins.Widgets; -import org.jline.reader.*; import java.util.List; import java.util.Map; import java.util.Set; public interface CommandRegistry { - + /** * Aggregate SystemCompleters of commandRegisteries * @return uncompiled SystemCompleter @@ -51,7 +50,7 @@ static Completers.SystemCompleter compileCompleters(CommandRegistry ... commandR * @return a map with alias keys and command name values */ Map commandAliases(); - + /** * Returns a short info about command known by this registry. * @return a short info about command @@ -68,24 +67,28 @@ static Completers.SystemCompleter compileCompleters(CommandRegistry ... commandR /** * Returns a {@code SystemCompleter} that can provide detailed completion * information for all registered commands. - * + * * @return a SystemCompleter that can provide command completion for all registered commands */ Completers.SystemCompleter compileCompleters(); /** * Returns a command description for use in the JLine Widgets framework. - * @param command name of the command whose description to return + * @param command name of the command whose description to return * @return command description for JLine TailTipWidgets to be displayed * in the terminal status bar. */ Widgets.CmdDesc commandDescription(String command); - + default Object execute(String command, String[] args) throws Exception { - throw new IllegalArgumentException("CommandRegistry has no implementation: execute(String command, String[] args)"); + throw new IllegalArgumentException("CommandRegistry method execute(String command, String[] args) is not implemented!"); } default Object invoke(String command, Object... args) throws Exception { - throw new IllegalArgumentException("CommandRegistry has no implementation: invoke(String command, Object... args)"); + String[] _args = new String[args.length]; + for (int i = 0; i < args.length; i++) { + _args[i] = args[i].toString(); + } + return execute(command, _args); } } \ No newline at end of file diff --git a/builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java b/builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java index 8a263a7e8..84f797b95 100644 --- a/builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java +++ b/builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java @@ -59,6 +59,7 @@ public ConsoleEngineImpl(ScriptEngine engine, Parser parser, Terminal terminal) commandExecute.put(Command.SHOW, new CommandMethods(this::show, this::defaultCompleter)); } + @Override public void setSystemRegistry(SystemRegistry systemRegistry) { this.systemRegistry = systemRegistry; } @@ -68,6 +69,7 @@ public ConsoleEngineImpl scriptExtension(String extension) { return this; } + @Override public Set commandNames() { return nameCommand.keySet(); } @@ -76,6 +78,7 @@ public Map commandAliases() { return aliasCommand; } + @Override public boolean hasCommand(String name) { if (nameCommand.containsKey(name) || aliasCommand.containsKey(name)) { return true; @@ -122,10 +125,12 @@ public void alias(String alias, String command) { aliasCommand.put(alias, command); } + @Override public List commandInfo(String command) { return new ArrayList<>(); } + @Override public Completers.SystemCompleter compileCompleters() { SystemCompleter out = new SystemCompleter(); for (Map.Entry entry: commandName.entrySet()) { @@ -135,6 +140,7 @@ public Completers.SystemCompleter compileCompleters() { return out; } + @Override public Widgets.CmdDesc commandDescription(String command) { return null; } @@ -181,12 +187,13 @@ private String quote(String var) { || (var.startsWith("'") && var.endsWith("'"))) { return var; } - if (var.contains("\\\"")) { + if (!var.contains("\\\"")) { return "'" + var + "'"; } return "\\\"" + var + "\\\""; } + @Override public Object execute(ParsedLine pl) throws Exception { if (pl.line().trim().startsWith("#")) { return null; @@ -239,20 +246,31 @@ public Object execute(ParsedLine pl) throws Exception { String line = pl.line(); if (isCodeBlock(line)) { StringBuilder sb = new StringBuilder(); - boolean copyRegistry = false; - String registry = "_systemRegistry"; for (String s: line.split("\n|\n\r")) { if (isCommandLine(s)) { - copyRegistry = true; List ws = parser.parse(s, 0, ParseContext.COMPLETE).words(); int idx = ws.get(0).lastIndexOf(":"); if (idx > 0) { - sb.append(ws.get(0).substring(0, idx - 1)); + sb.append(ws.get(0).substring(0, idx)); } - sb.append(registry + ".invoke('" + ws.get(0).substring(idx + 1) + "'"); + String[] argv = new String[ws.size()]; for (int i = 1; i < ws.size(); i++) { + argv[i] = ws.get(i); + if (argv[i].startsWith("${")) { + Matcher argvMatcher = Pattern.compile("\\$\\{(.*)}").matcher(argv[i]); + if (argvMatcher.find()) { + argv[i] = argv[i].replace(argv[i], argvMatcher.group(1)); + } + } else if (argv[i].startsWith("$")) { + argv[i] = argv[i].substring(1); + } else { + argv[i] = quote(argv[i]); + } + } + sb.append("org.jline.builtins.SystemRegistry.get().invoke('" + ws.get(0).substring(idx + 1) + "'"); + for (int i = 1; i < argv.length; i++) { sb.append(", "); - sb.append(ws.get(i)); + sb.append(argv[i]); } sb.append(")"); } else { @@ -261,9 +279,6 @@ public Object execute(ParsedLine pl) throws Exception { sb.append("\n"); } line = sb.toString(); - if (copyRegistry && !engine.hasVariable(registry)) { - engine.put(registry, systemRegistry); - } } if (engine.hasVariable(line)) { out = engine.get(line); @@ -276,6 +291,7 @@ public Object execute(ParsedLine pl) throws Exception { return out; } + @Override public Object postProcess(String line, Object result) { Object out = result; if (Parser.getVariable(line) != null) { @@ -285,6 +301,7 @@ public Object postProcess(String line, Object result) { return out; } + @Override public Object execute(String command, String[] args) throws Exception { exception = null; Object out = commandExecute.get(command(command)).executeFunction().apply(new Builtins.CommandInput(args)); @@ -294,6 +311,7 @@ public Object execute(String command, String[] args) throws Exception { return out; } + @Override public void println(Map options, Object object) { options.putIfAbsent("width", terminal.getSize().getColumns()); for (AttributedString as : engine.format(options, object)) { diff --git a/builtins/src/main/java/org/jline/builtins/SystemRegistry.java b/builtins/src/main/java/org/jline/builtins/SystemRegistry.java index beedcfb6b..b937a44a7 100644 --- a/builtins/src/main/java/org/jline/builtins/SystemRegistry.java +++ b/builtins/src/main/java/org/jline/builtins/SystemRegistry.java @@ -8,9 +8,41 @@ */ package org.jline.builtins; +import java.util.HashMap; +import java.util.Map; + import org.jline.reader.ParsedLine; public interface SystemRegistry extends CommandRegistry { Object execute(ParsedLine parsedLine) throws Exception; + + static SystemRegistry get() { + return Registeries.getInstance().getSystemRegistry(); + } + + static void put(SystemRegistry systemRegistry) { + Registeries.getInstance().addRegistry(systemRegistry); + } + + public class Registeries { + private static Registeries instance = new Registeries(); + private Map systemRegisteries = new HashMap<>(); + + private Registeries () {} + + public static Registeries getInstance() { + return instance; + } + + public void addRegistry(SystemRegistry systemRegistry) { + systemRegisteries.put(Thread.currentThread().getId(), systemRegistry); + } + + public SystemRegistry getSystemRegistry() { + return systemRegisteries.getOrDefault(Thread.currentThread().getId(), null); + } + + } + } diff --git a/builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java b/builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java index 2b6b3aead..b7a756626 100644 --- a/builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java +++ b/builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java @@ -39,6 +39,7 @@ public SystemRegistryImpl(CommandRegistry... commandRegistries) { throw new IllegalArgumentException(); } } + SystemRegistry.put(this); } public Set commandNames() { @@ -75,6 +76,19 @@ public Widgets.CmdDesc commandDescription(String command) { return id > -1 ? commandRegistries[id].commandDescription(command) : new Widgets.CmdDesc(false); } + public Object execute(String command, String[] args) throws Exception { + return null; + } + + public Object invoke(String command, Object... args) throws Exception { + Object out = null; + int id = registryId(command); + if (id > -1) { + out = commandRegistries[id].invoke(command, args); + } + return out; + } + public Object execute(ParsedLine pl) throws Exception { String[] argv = pl.words().subList(1, pl.words().size()).toArray(new String[0]); String cmd = Parser.getCommand(pl.word()); diff --git a/reader/src/main/java/org/jline/reader/Parser.java b/reader/src/main/java/org/jline/reader/Parser.java index b347ae926..13407c7d6 100644 --- a/reader/src/main/java/org/jline/reader/Parser.java +++ b/reader/src/main/java/org/jline/reader/Parser.java @@ -13,7 +13,7 @@ public interface Parser { static final String REGEX_VARIABLE = "[a-zA-Z]{1,}[a-zA-Z0-9_-]*"; - static final String REGEX_COMMAND = REGEX_VARIABLE; + static final String REGEX_COMMAND = "[:]{0,1}" + REGEX_VARIABLE; ParsedLine parse(String line, int cursor, ParseContext context) throws SyntaxError;