diff --git a/builtins/src/main/java/org/jline/builtins/Builtins.java b/builtins/src/main/java/org/jline/builtins/Builtins.java index 83eab41e8..abcbd80e4 100644 --- a/builtins/src/main/java/org/jline/builtins/Builtins.java +++ b/builtins/src/main/java/org/jline/builtins/Builtins.java @@ -26,6 +26,7 @@ import org.jline.builtins.Commands; import org.jline.builtins.Completers.FilesCompleter; +import org.jline.builtins.Completers.OptionCompleter; import org.jline.builtins.Completers.SystemCompleter; import org.jline.builtins.TTop; import org.jline.builtins.Options.HelpException; @@ -327,26 +328,45 @@ private Set allWidgets() { private List nanoCompleter(String name) { List completers = new ArrayList<>(); - completers.add(new ArgumentCompleter(new StringsCompleter(name), new FilesCompleter(workDir.get(), true))); + completers.add(new ArgumentCompleter(new StringsCompleter(name) + , new OptionCompleter(new FilesCompleter(workDir.get(), true) + , new HashMap>() + , new ArrayList() + , 1) + )); return completers; } private List lessCompleter(String name) { List completers = new ArrayList<>(); - completers.add(new ArgumentCompleter(new StringsCompleter(name), new FilesCompleter(workDir.get(), true))); + completers.add(new ArgumentCompleter(new StringsCompleter(name) + , new OptionCompleter(new FilesCompleter(workDir.get(), true) + , new HashMap>() + , new ArrayList() + , 1) + )); return completers; } private List historyCompleter(String name) { List completers = new ArrayList<>(); - completers.add(new ArgumentCompleter(new StringsCompleter(name), new NullCompleter())); completers.add(new ArgumentCompleter(new StringsCompleter(name) - , new StringsCompleter(Arrays.asList("-A", "-W", "-R")), new FilesCompleter(workDir.get(), true), new NullCompleter())); + , new OptionCompleter(new NullCompleter() + , new HashMap>() + , new ArrayList() + , 1) + )); + completers.add(new ArgumentCompleter(new StringsCompleter(name) + , new StringsCompleter(Arrays.asList("-A", "-W", "-R", "-AI", "-RI", "-WI")), new FilesCompleter(workDir.get(), true), new NullCompleter())); return completers; } private List widgetCompleter(String name) { List completers = new ArrayList<>(); + completers.add(new ArgumentCompleter(new StringsCompleter(name) + , new StringsCompleter("-l", "-la", "-N", "-U") + , new NullCompleter() + )); completers.add(new ArgumentCompleter(new StringsCompleter(name) , new StringsCompleter("-A"), new StringsCompleter(() -> allWidgets()) , new StringsCompleter(() -> reader.getWidgets().keySet()), new NullCompleter())); diff --git a/builtins/src/main/java/org/jline/builtins/Completers.java b/builtins/src/main/java/org/jline/builtins/Completers.java index 2a5716116..8dcaa05e9 100644 --- a/builtins/src/main/java/org/jline/builtins/Completers.java +++ b/builtins/src/main/java/org/jline/builtins/Completers.java @@ -678,4 +678,101 @@ public Map> getCompleters() { } } + public static class OptionCompleter implements org.jline.reader.Completer { + private Map> optionValues = new HashMap<>(); + private List options = new ArrayList(); + + private List argsCompleters = new ArrayList<>(); + private int startPos; + + public OptionCompleter(List completers, Map> optionValues, Collection options, int startPos){ + this(optionValues, options, startPos); + this.argsCompleters = new ArrayList<>(completers); + } + + public OptionCompleter(org.jline.reader.Completer completer, Map> optionValues, Collection options, int startPos){ + this(optionValues, options, startPos); + this.argsCompleters.add(completer); + } + + private OptionCompleter(Map> optionValues, Collection options, int startPos) { + this.optionValues = new HashMap<>(optionValues); + this.options.addAll(options); + this.startPos = startPos; + } + + @Override + public void complete(LineReader reader, final ParsedLine commandLine, List candidates) { + assert commandLine != null; + assert candidates != null; + List words = commandLine.words(); + String buffer = commandLine.word().substring(0, commandLine.wordCursor()); + if (buffer.startsWith("-")) { + boolean addbuff = true; + boolean valueCandidates = false; + int eq = buffer.indexOf('='); + if (eq < 0) { + List usedOptions = new ArrayList<>(); + for (int i = startPos; i < words.size(); i++) { + if (words.get(i).startsWith("-")) { + String w = words.get(i); + int ind = w.indexOf('='); + if (ind < 0) { + usedOptions.add(w); + } else { + usedOptions.add(w.substring(0,ind)); + } + } + } + for (String o: optionValues.keySet()) { + if (usedOptions.contains(o)) { + continue; + } + if (o.startsWith(buffer)) { + addbuff = false; + } + candidates.add(new Candidate(o+"=", o, null, null, null, null, false)); + } + for (String o: options) { + if (usedOptions.contains(o)) { + continue; + } + if (o.startsWith(buffer)) { + addbuff = false; + } + candidates.add(new Candidate(o, o, null, null, null, null, true)); + } + } else { + String value = buffer.substring(eq + 1); + String curBuf = buffer.substring(0, eq + 1); + String opt = buffer.substring(0, eq); + if (optionValues.containsKey(opt) && !optionValues.get(opt).isEmpty()) { + for (String v: optionValues.get(opt)) { + if (v.startsWith(value)) { + valueCandidates = true; + addbuff = false; + } + candidates.add(new Candidate(curBuf+v, v, null, null, null, null, true)); + } + } + } + if ((buffer.contains("=") && !buffer.endsWith("=") && !valueCandidates) || addbuff) { + candidates.add(new Candidate(buffer, buffer, null, null, null, null, true)); + } + } else if (argsCompleters.size() > 1){ + int args = 0; + for (int i = startPos; i < words.size(); i++) { + if (!words.get(i).startsWith("-")) { + args++; + } + } + if (args < argsCompleters.size()) { + argsCompleters.get(args).complete(reader, commandLine, candidates); + } + } else { + argsCompleters.get(0).complete(reader, commandLine, candidates); + } + } + } + }