--- /dev/null 2015-04-26 06:51:08.003313989 -0700
+++ new/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java 2015-06-25 08:33:10.728369063 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import jdk.internal.jline.internal.Configuration;
+
+import java.io.File;
+import java.util.List;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * 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
+ checkNotNull(candidates);
+
+ 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 (!(new File(translated).isAbsolute())) {
+ 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) {
+ return name;
+ }
+}