001: /*
002: * FindTagTextFieldHandler.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: */
020:
021: package org.armedbear.j;
022:
023: import java.util.ArrayList;
024: import java.util.Iterator;
025: import java.util.List;
026:
027: public final class FindTagTextFieldHandler extends
028: DefaultTextFieldHandler {
029: public FindTagTextFieldHandler(Editor editor,
030: HistoryTextField textField) {
031: super (editor, textField);
032: }
033:
034: public boolean wantTab() {
035: return true;
036: }
037:
038: public void enter() {
039: String pattern = textField.getText();
040: if (pattern == null)
041: return;
042: pattern = pattern.trim();
043: if (pattern.length() == 0)
044: return;
045: // Save history.
046: History history = textField.getHistory();
047: if (history != null) {
048: history.append(pattern);
049: history.save();
050: }
051: editor.ensureActive();
052: editor.setFocusToDisplay();
053: editor.updateLocation();
054: findTag(pattern);
055: editor.getDispatcher().eventHandled();
056: }
057:
058: private void findTag(String pattern) {
059: final Buffer buffer = editor.getBuffer();
060: List tags = findMatchingTags(buffer, pattern);
061: if (tags != null) {
062: if (tags.size() > 1) {
063: // Can we get a unique match if we just consider defuns etc.
064: // and explicit tags?
065: ArrayList shortList = new ArrayList();
066: for (Iterator it = tags.iterator(); it.hasNext();) {
067: Tag tag = (Tag) it.next();
068: if (tag instanceof LocalTag) {
069: int type = ((LocalTag) tag).getType();
070: // Java etc.
071: if (type == TAG_METHOD || type == TAG_EXPLICIT)
072: shortList.add(tag);
073: // Lisp.
074: if (type == TAG_DEFUN
075: || type == TAG_GENERIC_FUNCTION
076: || type == TAG_MACRO)
077: shortList.add(tag);
078: }
079: }
080: if (shortList.size() == 1)
081: tags = shortList;
082: }
083: if (tags.size() > 1) {
084: editor.setDefaultCursor();
085: ListTagsBuffer buf = new ListTagsBuffer(editor,
086: "findTag", pattern, tags);
087: editor.makeNext(buf);
088: Editor ed = editor.activateInOtherWindow(buf);
089: ed.setDot(buf.getInitialDotPos());
090: ed.moveCaretToDotCol();
091: ed.updateDisplay();
092: } else if (tags.size() == 1) {
093: // Exactly one match.
094: Tag tag = (Tag) tags.get(0);
095: editor.pushPosition();
096: if (tag instanceof LocalTag)
097: TagCommands.gotoLocalTag(editor, (LocalTag) tag,
098: false);
099: else if (tag instanceof GlobalTag)
100: TagCommands.gotoGlobalTag(editor, (GlobalTag) tag,
101: false);
102: else
103: Debug.bug();
104: }
105: } else
106: editor.status("Tag \"".concat(pattern).concat(
107: "\" not found"));
108: }
109:
110: private static List findMatchingTags(Buffer buffer, String pattern) {
111: boolean ignoreCase = Utilities.isLowerCase(pattern);
112: final Mode mode = buffer.getMode();
113: // We'll start by looking in the current buffer. If we find an exact
114: // match there, we're done.
115: List list = findMatchingTagsInBuffer(buffer, pattern,
116: ignoreCase);
117: if (list == null) {
118: // No exact match in the current buffer. Look in the current
119: // directory.
120: list = TagCommands.findMatchingTagsInDirectory(pattern,
121: buffer.getCurrentDirectory(), mode, -1, ignoreCase);
122: if (list == null) {
123: // Look at all the directories in the buffer's tag path.
124: List dirs = TagCommands.getDirectoriesInTagPath(buffer);
125: if (dirs != null) {
126: for (int i = 0; i < dirs.size(); i++) {
127: String dir = (String) dirs.get(i);
128: File directory = File.getInstance(dir);
129: if (directory.equals(buffer
130: .getCurrentDirectory()))
131: continue;
132: List tagsInDir = TagCommands
133: .findMatchingTagsInDirectory(pattern,
134: directory, mode, -1, ignoreCase);
135: if (tagsInDir != null) {
136: if (list == null)
137: list = new ArrayList();
138: list.addAll(tagsInDir);
139: }
140: }
141: }
142: }
143: }
144: return (list != null && list.size() > 0) ? list : null;
145: }
146:
147: private static List findMatchingTagsInBuffer(Buffer buffer,
148: String pattern, boolean ignoreCase) {
149: if (buffer.getTags() == null) {
150: Tagger tagger = buffer.getMode().getTagger(buffer);
151: if (tagger != null)
152: tagger.run();
153: }
154: boolean isQualified = buffer.getMode().isQualifiedName(pattern);
155: List list = new ArrayList();
156: final List localTags = buffer.getTags();
157: if (localTags != null) {
158: // Look through all the local tags.
159: Iterator iter = localTags.iterator();
160: while (iter.hasNext()) {
161: LocalTag localTag = (LocalTag) iter.next();
162: if (isQualified) {
163: String tagName = localTag.getName();
164: if ((ignoreCase && tagName
165: .equalsIgnoreCase(pattern))
166: || tagName.equals(pattern)) {
167: list.add(localTag);
168: }
169: } else {
170: // Not qualified.
171: String methodName = localTag.getMethodName();
172: if (methodName != null) {
173: if ((ignoreCase && methodName
174: .equalsIgnoreCase(pattern))
175: || methodName.equals(pattern)) {
176: list.add(localTag);
177: }
178: }
179: }
180: }
181: }
182: return (list != null && list.size() > 0) ? list : null;
183: }
184:
185: public List getCompletions(final String prefix) {
186: List list = getCompletionsInCurrentBuffer(prefix);
187: Mode mode = editor.getMode();
188: List tags = Editor.getTagFileManager().getTags(
189: editor.getCurrentDirectory(), mode);
190: if (tags != null) {
191: boolean prefixIsQualified = mode.isQualifiedName(prefix);
192: boolean ignoreCase = Utilities.isLowerCase(prefix);
193: int prefixLength = prefix.length();
194: for (int i = 0; i < tags.size(); i++) {
195: GlobalTag tag = (GlobalTag) tags.get(i);
196: if (tag.getName().regionMatches(ignoreCase, 0, prefix,
197: 0, prefixLength)) {
198: String toBeAdded;
199: if (prefixIsQualified)
200: toBeAdded = tag.getName();
201: else {
202: toBeAdded = tag.getClassName();
203: if (toBeAdded == null)
204: toBeAdded = tag.getName();
205: }
206: maybeAdd(list, toBeAdded);
207: continue;
208: }
209: if (!prefixIsQualified && mode.hasQualifiedNames()) {
210: // The name we're looking for does not have a class prefix.
211: // Look for a match on the method name of the tag.
212: String methodName = tag.getMethodName();
213: if (methodName != null) {
214: if (methodName.regionMatches(ignoreCase, 0,
215: prefix, 0, prefixLength))
216: maybeAdd(list, tag.getMethodName());
217: }
218: }
219: }
220: }
221: return list;
222: }
223:
224: private List getCompletionsInCurrentBuffer(String prefix) {
225: List list = new ArrayList();
226: List tags = editor.getBuffer().getTags();
227: if (tags != null) {
228: boolean ignoreCase = Utilities.isLowerCase(prefix);
229: int prefixLength = prefix.length();
230: for (int i = 0; i < tags.size(); i++) {
231: Tag tag = (Tag) tags.get(i);
232: if (tag.getMethodName().regionMatches(ignoreCase, 0,
233: prefix, 0, prefixLength))
234: maybeAdd(list, tag.getMethodName());
235: }
236: }
237: return list;
238: }
239:
240: // Add name if it's not already in the list.
241: private void maybeAdd(List list, String name) {
242: if (name != null) {
243: for (int i = list.size(); i-- > 0;)
244: if (name.equals(list.get(i)))
245: return; // It's already there.
246: list.add(name);
247: }
248: }
249: }
|