001: /*
002: * Completion.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: * $Id: Completion.java,v 1.5 2003/09/16 00:29:43 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.util.List;
025: import java.util.ArrayList;
026:
027: public final class Completion {
028: private String input;
029: private String toBeCompleted;
030: private boolean ignoreCase;
031: private boolean cygnify;
032:
033: private ArrayList list = new ArrayList();
034:
035: public Completion(File dir, String input, String shellCommand) {
036: if (Platform.isPlatformWindows()) {
037: if (shellCommand != null
038: && shellCommand.toLowerCase().indexOf("cmd.exe") < 0)
039: cygnify = true;
040: }
041: final char separatorChar = getSeparatorChar();
042: this .input = input;
043: toBeCompleted = input;
044: if (Platform.isPlatformWindows()) {
045: if (cygnify) {
046: if (toBeCompleted.startsWith("~/")) {
047: String home = Utilities.getUserHome();
048: if (!home.startsWith("/"))
049: home = Utilities.cygnify(home);
050: toBeCompleted = Utilities.uncygnify(home
051: + toBeCompleted.substring(1));
052: } else if (toBeCompleted.startsWith("../"))
053: toBeCompleted = File.normalize(toBeCompleted);
054: else
055: toBeCompleted = Utilities.uncygnify(toBeCompleted);
056: } else {
057: if (toBeCompleted.startsWith("~/")) {
058: String home = Utilities.getUserHome();
059: toBeCompleted = home + toBeCompleted.substring(1);
060: } else
061: toBeCompleted = File.normalize(toBeCompleted);
062: }
063: ignoreCase = true;
064: }
065: FilenameCompletion c = new FilenameCompletion(dir,
066: toBeCompleted, null, ignoreCase);
067: List files = c.listFiles();
068: if (files != null) {
069: String home = Utilities.getUserHome() + "/";
070: String prefix = dir.canonicalPath()
071: + LocalFile.getSeparator();
072: int skip = prefix.length();
073: String toBeAdded;
074: int limit = files.size();
075: for (int i = 0; i < limit; i++) {
076: File file = (File) files.get(i);
077: toBeAdded = file.getAbsolutePath();
078: if (!Utilities.isFilenameAbsolute(toBeCompleted)) {
079: if (toBeAdded.startsWith(prefix)) {
080: toBeAdded = toBeAdded.substring(skip);
081: if (input.startsWith("./"))
082: toBeAdded = "./" + toBeAdded;
083: }
084: }
085: if (cygnify)
086: toBeAdded = Utilities.cygnify(toBeAdded);
087: if (input.startsWith("~/")) {
088: if (toBeAdded.startsWith(home)) {
089: toBeAdded = "~/"
090: + toBeAdded.substring(home.length());
091: }
092: } else if (input.startsWith("..")) {
093: String remaining = input;
094: File parentDir = dir;
095: String parentPrefix = "";
096: while (remaining.startsWith("../")) {
097: parentDir = parentDir.getParentFile();
098: parentPrefix += "../";
099: remaining = remaining.substring(3);
100: }
101: String parentDirName = parentDir.canonicalPath();
102: if (cygnify)
103: parentDirName = Utilities
104: .cygnify(parentDirName);
105: if (!parentDirName.endsWith("/"))
106: parentDirName += "/";
107: if (toBeAdded.startsWith(parentDirName))
108: toBeAdded = parentPrefix
109: + toBeAdded.substring(parentDirName
110: .length());
111: }
112: toBeAdded = escapeSpaces(toBeAdded);
113: if (file.isDirectory())
114: toBeAdded += separatorChar;
115: list.add(toBeAdded);
116: }
117: }
118: }
119:
120: // Converts "this is a test" into "this\ is\ a\ test".
121: private static final String escapeSpaces(String s) {
122: final int length = s.length();
123: FastStringBuffer sb = new FastStringBuffer(length * 2);
124: for (int i = 0; i < length; i++) {
125: char c = s.charAt(i);
126: if (c == ' ')
127: sb.append('\\');
128: sb.append(c);
129: }
130: return sb.toString();
131: }
132:
133: private final char getSeparatorChar() {
134: if (Platform.isPlatformWindows() && !cygnify)
135: return '\\';
136: return '/';
137: }
138:
139: public final List getCompletions() {
140: return list;
141: }
142:
143: private boolean isUnique() {
144: return list.size() == 1;
145: }
146:
147: private String getLongestCommonPrefix() {
148: String s = input;
149: if (list.size() != 0) {
150: if (list.size() == 1) {
151: s = (String) list.get(0);
152: } else {
153: String first = (String) list.get(0);
154: int length = toBeCompleted.length() + 1;
155: while (true) {
156: if (length > first.length())
157: return s;
158: String maybe = first.substring(0, length);
159: for (int i = 1; i < list.size(); i++) {
160: String toBeChecked = (String) list.get(i);
161: if (!maybe.regionMatches(ignoreCase, 0,
162: toBeChecked, 0, length)) {
163: if (cygnify)
164: s = Utilities.cygnify(s);
165: return s;
166: }
167: }
168: s = maybe;
169: ++length;
170: }
171: }
172: }
173: if (cygnify)
174: s = Utilities.cygnify(s);
175: return s;
176: }
177:
178: public String toString() {
179: if (isUnique()) {
180: String s = (String) list.get(0);
181: // Directories have file separator already appended.
182: if (!s.endsWith("/") && !s.endsWith("\\"))
183: s += ' ';
184: return s;
185: }
186: return getLongestCommonPrefix();
187: }
188: }
|