Completion proposal support for complete jline parameter

- to allow completing single argument with multiple tab clicks,
  for example file paths.
- Backport #512
- Fixes #835
This commit is contained in:
MJ Gallego
2023-04-15 16:04:55 +02:00
committed by Janne Valkealahti
parent e2da0d0907
commit 2cb0f115c6
3 changed files with 34 additions and 14 deletions

View File

@@ -63,7 +63,7 @@ public class CompleterAutoConfiguration {
p.description(), p.description(),
null, null,
null, null,
true) p.complete())
) )
.forEach(candidates::add); .forEach(candidates::add);
} }

View File

@@ -49,6 +49,12 @@ public class CompletionProposal {
*/ */
private boolean dontQuote = false; private boolean dontQuote = false;
/**
* Whether the proposal cant be completed further. By setting complete to false then it will not append an space
* making it easier to continue tab completion
*/
private boolean complete = true;
public CompletionProposal(String value) { public CompletionProposal(String value) {
this.value = this.displayText = value; this.value = this.displayText = value;
} }
@@ -89,6 +95,16 @@ public class CompletionProposal {
return this; return this;
} }
public CompletionProposal complete(boolean complete) {
this.complete = complete;
return this;
}
public boolean complete() {
return complete;
}
public CompletionProposal dontQuote(boolean dontQuote) { public CompletionProposal dontQuote(boolean dontQuote) {
this.dontQuote = dontQuote; this.dontQuote = dontQuote;
return this; return this;

View File

@@ -41,19 +41,23 @@ public class FileValueProvider implements ValueProvider {
@Override @Override
public List<CompletionProposal> complete(CompletionContext completionContext) { public List<CompletionProposal> complete(CompletionContext completionContext) {
String input = completionContext.currentWordUpToCursor(); String input = completionContext.currentWordUpToCursor();
int lastSlash = input.lastIndexOf(File.separatorChar); int lastSlash = input.lastIndexOf(File.separatorChar);
Path dir = lastSlash > -1 ? Paths.get(input.substring(0, lastSlash+1)) : Paths.get(""); Path dir = lastSlash > -1 ? Paths.get(input.substring(0, lastSlash + 1)) : Paths.get("");
String prefix = input.substring(lastSlash + 1, input.length()); String prefix = input.substring(lastSlash + 1);
try { try {
return Files return Files
.find(dir, 1, (p, a) -> p.getFileName() != null && p.getFileName().toString().startsWith(prefix), .find(dir, 1, (p, a) -> p.getFileName() != null && p.getFileName().toString().startsWith(prefix),
FOLLOW_LINKS) FOLLOW_LINKS)
.map(p -> new CompletionProposal(p.toString())) .map(p -> {
.collect(Collectors.toList()); boolean directory = Files.isDirectory(p);
} catch (IOException e) { String value = p.toString() + (directory ? File.separatorChar : "");
throw new UncheckedIOException(e); return new CompletionProposal(value).complete(!directory);
} })
.collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} }
} }