scala.tools.jline.console.completer.FileNameCompleter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jline Show documentation
Show all versions of jline Show documentation
Like readline, but better
/*
* Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*/
package scala.tools.jline.console.completer;
import scala.tools.jline.internal.Configuration;
import java.io.File;
import java.util.List;
/**
* A file name completer takes the buffer and issues a list of
* potential completions.
*
* This completer tries to behave as similar as possible to
* bash's file name completion (using GNU readline)
* with the following exceptions:
*
*
* - Candidates that are directories will end with "/"
* - Wildcard regular expressions are not evaluated or replaced
* - The "~" character can be used to represent the user's home,
* but it cannot complete to other users' homes, since java does
* not provide any way of determining that easily
*
*
* @author Marc Prud'hommeaux
* @author Jason Dillon
* @since 2.3
*/
public class FileNameCompleter
implements Completer
{
// TODO: Handle files with spaces in them
private static final boolean OS_IS_WINDOWS;
static {
String os = Configuration.getOsName();
OS_IS_WINDOWS = os.contains("windows");
}
public int complete(String buffer, final int cursor, final List candidates) {
// buffer can be null
assert candidates != null;
if (buffer == null) {
buffer = "";
}
if (OS_IS_WINDOWS) {
buffer = buffer.replace('/', '\\');
}
String translated = buffer;
File homeDir = getUserHome();
// Special character: ~ maps to the user's home directory
if (translated.startsWith("~" + separator())) {
translated = homeDir.getPath() + translated.substring(1);
}
else if (translated.startsWith("~")) {
translated = homeDir.getParentFile().getAbsolutePath();
}
else if (!(translated.startsWith(separator()))) {
String cwd = getUserDir().getAbsolutePath();
translated = cwd + separator() + translated;
}
File file = new File(translated);
final File dir;
if (translated.endsWith(separator())) {
dir = file;
}
else {
dir = file.getParentFile();
}
File[] entries = dir == null ? new File[0] : dir.listFiles();
return matchFiles(buffer, translated, entries, candidates);
}
protected String separator() {
return File.separator;
}
protected File getUserHome() {
return Configuration.getUserHome();
}
protected File getUserDir() {
return new File(".");
}
protected int matchFiles(final String buffer, final String translated, final File[] files, final List candidates) {
if (files == null) {
return -1;
}
int matches = 0;
// first pass: just count the matches
for (File file : files) {
if (file.getAbsolutePath().startsWith(translated)) {
matches++;
}
}
for (File file : files) {
if (file.getAbsolutePath().startsWith(translated)) {
CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? separator() : " ");
candidates.add(render(file, name).toString());
}
}
final int index = buffer.lastIndexOf(separator());
return index + separator().length();
}
protected CharSequence render(final File file, final CharSequence name) {
assert file != null;
assert name != null;
return name;
}
}