Skip to content

Commit

Permalink
Variables and scripts tab completion
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Jan 25, 2020
1 parent 4b040eb commit 5320ef3
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 24 deletions.
16 changes: 15 additions & 1 deletion builtins/src/main/java/org/jline/builtins/ConsoleEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
package org.jline.builtins;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.jline.builtins.CommandRegistry;
import org.jline.reader.Completer;
import org.jline.reader.ParsedLine;

/**
Expand All @@ -34,7 +36,19 @@ public interface ConsoleEngine extends CommandRegistry {
* @throws Exception
*/
Object[] expandParameters(String[] args) throws Exception;


/**
* Returns all scripts found from PATH
* @return script names
*/
List<String> scripts();

/**
* Returns script and variable completers
* @return completers
*/
List<Completer> scriptCompleters();

/**
* Executes parsed line that does not contain known command by the system registry.
* If parsed line is neither JLine or ScriptEngine script it will be evaluated
Expand Down
87 changes: 69 additions & 18 deletions builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
import java.io.FileReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.*;
import java.util.*;
import java.util.function.Supplier;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -54,7 +52,7 @@ public enum Command {SHOW
private static final String VAR_PRNT_OPTIONS = "PRNT_OPTIONS";
private static final String VAR_PATH = "PATH";
private static final String VAR_NANORC = "NANORC";
private static final String OPTION_HELP = "-?";
private static final String[] OPTION_HELP = {"-?", "--help"};
private static final String OPTION_VERBOSE = "-v";
private static final String HELP_END = "HELP_END";
private static final int HELP_MAX_SIZE = 30;
Expand Down Expand Up @@ -164,6 +162,48 @@ public Completers.SystemCompleter compileCompleters() {
out.addAliases(aliasCommand);
return out;
}

private Set<String> variables() {
return engine.find().keySet();
}

@Override
public List<Completer> scriptCompleters() {
List<Completer> out = new ArrayList<>();
out.add(new ArgumentCompleter(new StringsCompleter(this::variables), NullCompleter.INSTANCE));
out.add(new ArgumentCompleter(new StringsCompleter(this::scripts)
, new OptionCompleter(NullCompleter.INSTANCE
, this::commandOptions
, 1)
));
return out;
}

@SuppressWarnings("unchecked")
@Override
public List<String> scripts() {
List<String> out = new ArrayList<>();
try {
List<Path> scripts = new ArrayList<>();
if (engine.hasVariable(VAR_PATH)) {
for (String pp : (List<String>) engine.get(VAR_PATH)) {
for (String e : scriptExtensions()) {
String regex = pp + "/*." + e;
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + regex);
Files.find(Paths.get(new File(regex).getParent()), Integer.MAX_VALUE,
(path, f) -> pathMatcher.matches(path)).forEach(p -> scripts.add(p));
}
}
}
for (Path p : scripts) {
String name = p.toFile().getName();
out.add(name.substring(0, name.lastIndexOf(".")));
}
} catch (Exception e) {
println(e);
}
return out;
}

@Override
public Object[] expandParameters(String[] args) throws Exception {
Expand Down Expand Up @@ -227,6 +267,13 @@ private String quote(String var) {
return "\"" + var + "\"";
}

private List<String> scriptExtensions() {
List<String> extensions = new ArrayList<>();
extensions.addAll(engine.getExtensions());
extensions.add(scriptExtension);
return extensions;
}

private class ScriptFile {
private File script;
private String extension = "";
Expand All @@ -242,12 +289,9 @@ public ScriptFile(String command, String cmdLine, String[] args) {
if (script.exists()) {
scriptExtension(command);
} else if (engine.hasVariable(VAR_PATH)) {
List<String> extensions = new ArrayList<>();
extensions.addAll(engine.getExtensions());
extensions.add(scriptExtension);
boolean found = false;
for (String p: (List<String>)engine.get(VAR_PATH)) {
for (String e : extensions) {
for (String e : scriptExtensions()) {
String file = command + "." + e;
Path path = Paths.get(p, file);
if (path.toFile().exists()) {
Expand Down Expand Up @@ -319,26 +363,31 @@ public boolean execute() throws Exception {
return false;
}
result = null;
if (Arrays.asList(args).contains(OPTION_HELP)) {
if (Arrays.asList(args).contains(OPTION_HELP[0]) || Arrays.asList(args).contains(OPTION_HELP[1])) {
try(BufferedReader br = new BufferedReader(new FileReader(script))) {
int size = 0;
StringBuilder usage = new StringBuilder();
boolean helpEnd = false;
for(String l; (l = br.readLine()) != null; ) {
size++;
l = l.replaceAll("\\s+$", "");
String line = l;
if (size > HELP_MAX_SIZE || line.endsWith(HELP_END)) {
helpEnd = line.endsWith(HELP_END);
break;
}
if (l.trim().startsWith("*") || l.trim().startsWith("#")) {
line = l.trim().substring(1);
} else if (l.trim().startsWith("/*") || l.trim().startsWith("//")) {
line = l.trim().substring(2);
} else if (l.trim().startsWith("/*") || l.trim().startsWith("//")) {
line = l.trim().substring(3);
}
usage.append(line).append('\n');
}
if (usage.length() > 0) {
usage.append("\n");
if (!helpEnd) {
usage.insert(0, "\n");
}
throw new HelpException(usage.toString());
} else {
internalExecute();
Expand Down Expand Up @@ -726,9 +775,10 @@ private List<OptDesc> commandOptions(String command) {
private List<Completer> slurpCompleter(String command) {
List<Completer> completers = new ArrayList<>();
completers.add(new ArgumentCompleter(NullCompleter.INSTANCE
, new OptionCompleter(new FilesCompleter(workDir)
, this::commandOptions
, 1)
, new OptionCompleter(new ArgumentCompleter(new FilesCompleter(workDir)
, NullCompleter.INSTANCE)
, this::commandOptions
, 1)
));
return completers;
}
Expand Down Expand Up @@ -756,10 +806,11 @@ private List<Completer> echoCompleter(String command) {
private List<Completer> prntCompleter(String command) {
List<Completer> completers = new ArrayList<>();
completers.add(new ArgumentCompleter(NullCompleter.INSTANCE
, new OptionCompleter(new StringsCompleter(this::variableReferences)
, this::commandOptions
, 1)
));
, new OptionCompleter(new ArgumentCompleter(new StringsCompleter(this::variableReferences)
, NullCompleter.INSTANCE)
, this::commandOptions
, 1)
));
return completers;
}

Expand Down
7 changes: 7 additions & 0 deletions builtins/src/main/java/org/jline/builtins/SystemRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.HashMap;
import java.util.Map;

import org.jline.reader.Completer;
import org.jline.reader.ParsedLine;
import org.jline.terminal.Terminal;

Expand All @@ -34,6 +35,12 @@ public interface SystemRegistry extends CommandRegistry {
*/
void initialize(File script);

/**
* Returns command completer that includes also console variable and script completion.
* @return complater
*/
Completer completer();

/**
* Returns a command, method or syntax description for use in the JLine Widgets framework.
* @param command line whose description to return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
import org.jline.builtins.CommandRegistry;
import org.jline.builtins.Widgets;
import org.jline.builtins.Options.HelpException;
import org.jline.reader.Completer;
import org.jline.reader.ConfigurationPath;
import org.jline.reader.EndOfFileException;
import org.jline.reader.ParsedLine;
import org.jline.reader.Parser;
import org.jline.reader.Parser.ParseContext;
import org.jline.reader.impl.completer.AggregateCompleter;
import org.jline.terminal.Terminal;
import org.jline.utils.AttributedStringBuilder;

Expand Down Expand Up @@ -98,6 +100,8 @@ public List<String> commandInfo(String command) {
commandInfos.put(command, commandRegistries[id].commandInfo(command));
}
out = commandInfos.get(command);
} else if (consoleId > -1 && consoleEngine().scripts().contains(command)) {
out = consoleEngine().commandInfo(command);
}
return out;
}
Expand All @@ -111,11 +115,27 @@ public boolean hasCommand(String command) {
public Completers.SystemCompleter compileCompleters() {
return CommandRegistry.compileCompleters(commandRegistries);
}

@Override
public Completer completer() {
List<Completer> completers = new ArrayList<>();
completers.add(compileCompleters());
if (consoleId > -1) {
completers.addAll(consoleEngine().scriptCompleters());
}
return new AggregateCompleter(completers);
}

@Override
public Widgets.CmdDesc commandDescription(String command) {
Widgets.CmdDesc out = new Widgets.CmdDesc(false);
int id = registryId(command);
return id > -1 ? commandRegistries[id].commandDescription(command) : new Widgets.CmdDesc(false);
if (id > -1) {
out = commandRegistries[id].commandDescription(command);
} else if (consoleId > -1 && consoleEngine().scripts().contains(command)) {
out = consoleEngine().commandDescription(command);
}
return out;
}

@Override
Expand Down Expand Up @@ -249,6 +269,9 @@ private String doCommandInfo(List<String> info) {

private void help() {
Set<String> commands = commandNames();
if (consoleId > -1) {
commands.addAll(consoleEngine().scripts());
}
boolean withInfo = commands.size() < terminal.getHeight() ? true : false;
int max = Collections.max(commands, Comparator.comparing(String::length)).length() + 1;
TreeMap<String,String> builtinCommands = new TreeMap<>();
Expand Down Expand Up @@ -281,6 +304,16 @@ private void help() {
printCommands(cmds, max);
}
}
if (consoleId > -1) {
printHeader("Scripts");
if (withInfo) {
for (String c: consoleEngine().scripts()) {
printCommandInfo(c, doCommandInfo(commandInfo(c)), max);
}
} else {
printCommands(consoleEngine().scripts(), max);
}
}
}

private int registryId(String command) {
Expand Down
2 changes: 1 addition & 1 deletion demo/src/main/java/org/jline/demo/Repl.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ public static void main(String[] args) {
//
LineReader reader = LineReaderBuilder.builder()
.terminal(terminal)
.completer(systemRegistry.compileCompleters())
.completer(systemRegistry.completer())
.parser(parser)
.variable(LineReader.SECONDARY_PROMPT_PATTERN, "%M%P > ")
.variable(LineReader.INDENTATION, 2)
Expand Down
21 changes: 18 additions & 3 deletions demo/src/main/scripts/hello.groovy
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
// HELP_END
import org.jline.builtins.SystemRegistry
import org.jline.builtins.Options;

class HelloWorld {
static void hello(def who) {
println "hello $who!"
static void hello(def args) {
String[] usage = [
"hello - test groovy script",
"Usage: hello [NAME]",
" -? --help Displays command help",
" --hi Says hello",
]
Options opt = Options.compile(usage).parse(args)
if (opt.isSet("help")) {
throw new Options.HelpException(opt.usage())
}
if (opt.isSet('hi')) {
def who = opt.args().getAt(0) == null ? 'world' : opt.args().getAt(0)
println "hello $who!"
}
def map = [user:'pippo',age:10]
SystemRegistry.get().invoke('prnt', '-s', 'JSON', map)
}
}

def static main(def _args){
HelloWorld.hello(!_args ? 'world' : _args[0])
HelloWorld.hello(_args)
return 'just testing...'
}
2 changes: 2 additions & 0 deletions demo/src/main/scripts/hello2.jline
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# test console script
# HELP_END
import org.jline.utils.*

println "Is Windows: " + OSUtils.IS_WINDOWS
Expand Down

0 comments on commit 5320ef3

Please sign in to comment.