Source Code Cross Referenced for HippieCompletionEngine.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » internal » texteditor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui workbench » org.eclipse.ui.internal.texteditor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2000, 2006 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     Genady Beryozkin, me@genady.org - initial API and implementation
010:         *******************************************************************************/package org.eclipse.ui.internal.texteditor;
011:
012:        import java.util.ArrayList;
013:        import java.util.Collections;
014:        import java.util.HashSet;
015:        import java.util.Iterator;
016:        import java.util.List;
017:        import java.util.regex.Matcher;
018:        import java.util.regex.Pattern;
019:
020:        import org.eclipse.jface.text.BadLocationException;
021:        import org.eclipse.jface.text.FindReplaceDocumentAdapter;
022:        import org.eclipse.jface.text.IDocument;
023:        import org.eclipse.jface.text.IRegion;
024:
025:        /**
026:         * This class contains the hippie completion engine methods that actually
027:         * compute the possible completions.
028:         * <p>
029:         * This engine is used by the <code>org.eclipse.ui.texteditor.HippieCompleteAction</code>.
030:         * </p>
031:         *
032:         * TODO: Sort by editor type
033:         * TODO: Provide history option
034:         *
035:         * @since 3.1
036:         * @author Genady Beryozkin, me@genady.org
037:         */
038:        public final class HippieCompletionEngine {
039:
040:            /**
041:             * Regular expression that is used to find words.
042:             */
043:            // unicode identifier part
044:            //	private static final String COMPLETION_WORD_REGEX= "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}]]]]]+"; //$NON-NLS-1$
045:            // java identifier part (unicode id part + currency symbols)
046:            private static final String COMPLETION_WORD_REGEX = "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}[\\p{Sc}]]]]]]+"; //$NON-NLS-1$
047:            /**
048:             * The pre-compiled word pattern.
049:             * 
050:             * @since 3.2
051:             */
052:            private static final Pattern COMPLETION_WORD_PATTERN = Pattern
053:                    .compile(COMPLETION_WORD_REGEX);
054:
055:            /**
056:             * Word boundary pattern that does not allow searching at the beginning of the document.
057:             * 
058:             * @since 3.2
059:             */
060:            private static final String NON_EMPTY_COMPLETION_BOUNDARY = "[\\s\\p{Z}[\\p{P}&&[\\P{Pc}]][\\p{S}&&[\\P{Sc}]]]+"; //$NON-NLS-1$
061:
062:            /**
063:             * The word boundary pattern string.
064:             * 
065:             * @since 3.2
066:             */
067:            private static final String COMPLETION_BOUNDARY = "(^|" + NON_EMPTY_COMPLETION_BOUNDARY + ")"; //$NON-NLS-1$ //$NON-NLS-2$
068:            // with a 1.5 JRE, you can do this:
069:            //	private static final String COMPLETION_WORD_REGEX= "\\p{javaUnicodeIdentifierPart}+"; //$NON-NLS-1$
070:            //	private static final String COMPLETION_WORD_REGEX= "\\p{javaJavaIdentifierPart}+"; //$NON-NLS-1$
071:
072:            /**
073:             * Is completion case sensitive? Even if set to <code>false</code>, the
074:             * case of the prefix won't be changed.
075:             */
076:            private static final boolean CASE_SENSITIVE = true;
077:
078:            /**
079:             * Creates a new engine.
080:             */
081:            public HippieCompletionEngine() {
082:            }
083:
084:            /*
085:             * Copied from {@link FindReplaceDocumentAdapter#asRegPattern(java.lang.String)}.
086:             */
087:            /**
088:             * Converts a non-regex string to a pattern that can be used with the regex
089:             * search engine.
090:             *
091:             * @param string the non-regex pattern
092:             * @return the string converted to a regex pattern
093:             */
094:            private String asRegPattern(CharSequence string) {
095:                StringBuffer out = new StringBuffer(string.length());
096:                boolean quoting = false;
097:
098:                for (int i = 0, length = string.length(); i < length; i++) {
099:                    char ch = string.charAt(i);
100:                    if (ch == '\\') {
101:                        if (quoting) {
102:                            out.append("\\E"); //$NON-NLS-1$
103:                            quoting = false;
104:                        }
105:                        out.append("\\\\"); //$NON-NLS-1$
106:                        continue;
107:                    }
108:                    if (!quoting) {
109:                        out.append("\\Q"); //$NON-NLS-1$
110:                        quoting = true;
111:                    }
112:                    out.append(ch);
113:                }
114:                if (quoting)
115:                    out.append("\\E"); //$NON-NLS-1$
116:
117:                return out.toString();
118:            }
119:
120:            /**
121:             * Return the list of completion suggestions that correspond to the
122:             * provided prefix.
123:             * 
124:             * @param document the document to be scanned
125:             * @param prefix the prefix to search for
126:             * @param firstPosition the initial position in the document that
127:             *        the search will start from. In order to search from the
128:             *        beginning of the document use <code>firstPosition=0</code>.
129:             * @param currentWordLast if <code>true</code> the word at caret position
130:             * 		  should be that last completion. <code>true</code> is good
131:             * 		  for searching in the currently open document and <code>false</code>
132:             * 		  is good for searching in other documents. 
133:             * @return a {@link List} of possible completions (as {@link String}s),
134:             *         excluding the common prefix
135:             * @throws BadLocationException if there is some error scanning the
136:             *         document.
137:             */
138:            public List getCompletionsForward(IDocument document,
139:                    CharSequence prefix, int firstPosition,
140:                    boolean currentWordLast) throws BadLocationException {
141:                ArrayList res = new ArrayList();
142:                String currentWordCompletion = null; // fix bug 132533
143:
144:                if (firstPosition == document.getLength()) {
145:                    return res;
146:                }
147:
148:                FindReplaceDocumentAdapter searcher = new FindReplaceDocumentAdapter(
149:                        document);
150:
151:                // search only at word boundaries
152:                String searchPattern;
153:
154:                // unless we are at the beginning of the document, the completion boundary
155:                // matches one character. It is enough to move just one character backwards
156:                // because the boundary pattern has the (....)+ form.
157:                // see HippieCompletionTest#testForwardSearch().
158:                if (firstPosition > 0) {
159:                    firstPosition--;
160:                    // empty spacing is not permitted now.
161:                    searchPattern = NON_EMPTY_COMPLETION_BOUNDARY
162:                            + asRegPattern(prefix);
163:                } else {
164:                    searchPattern = COMPLETION_BOUNDARY + asRegPattern(prefix);
165:                }
166:
167:                IRegion reg = searcher.find(firstPosition, searchPattern, true,
168:                        CASE_SENSITIVE, false, true);
169:                while (reg != null) {
170:                    // since the boundary may be of nonzero length
171:                    int wordSearchPos = reg.getOffset() + reg.getLength()
172:                            - prefix.length();
173:                    // try to complete to a word. case is irrelevant here.
174:                    IRegion word = searcher.find(wordSearchPos,
175:                            COMPLETION_WORD_REGEX, true, true, false, true);
176:                    if (word.getLength() > prefix.length()) { // empty suggestion will be added later
177:                        String wholeWord = document.get(word.getOffset(), word
178:                                .getLength());
179:                        String completion = wholeWord
180:                                .substring(prefix.length());
181:                        if (currentWordLast && reg.getOffset() == firstPosition) { // we got the word at caret as completion
182:                            currentWordCompletion = completion; // add it as the last word.
183:                        } else {
184:                            res.add(completion);
185:                        }
186:                    }
187:                    int nextPos = word.getOffset() + word.getLength();
188:                    if (nextPos >= document.getLength()) {
189:                        break;
190:                    }
191:                    reg = searcher.find(nextPos, searchPattern, true,
192:                            CASE_SENSITIVE, false, true);
193:                }
194:
195:                // the word at caret position goes last (bug 132533).
196:                if (currentWordCompletion != null) {
197:                    res.add(currentWordCompletion);
198:                }
199:
200:                return res;
201:            }
202:
203:            /**
204:             * Search for possible completions in the backward direction. If there
205:             * is a possible completion that begins before <code>firstPosition</code>
206:             * but ends after that position, it will not be included in the results.
207:             *
208:             * @param document the document to be scanned
209:             * @param prefix the completion prefix
210:             * @param firstPosition the caret position
211:             * @return a {@link List} of possible completions ({@link String}s)
212:             *         from the caret position to the beginning of the document.
213:             *         The empty suggestion is not included in the results.
214:             * @throws BadLocationException if any error occurs
215:             */
216:            public List getCompletionsBackwards(IDocument document,
217:                    CharSequence prefix, int firstPosition)
218:                    throws BadLocationException {
219:                ArrayList res = new ArrayList();
220:
221:                // FindReplaceDocumentAdapter expects the start offset to be before the
222:                // actual caret position, probably for compatibility with forward search.
223:                if (firstPosition == 0) {
224:                    return res;
225:                }
226:
227:                FindReplaceDocumentAdapter searcher = new FindReplaceDocumentAdapter(
228:                        document);
229:
230:                // search only at word boundaries
231:                String searchPattern = COMPLETION_BOUNDARY
232:                        + asRegPattern(prefix);
233:
234:                IRegion reg = searcher.find(0, searchPattern, true,
235:                        CASE_SENSITIVE, false, true);
236:                while (reg != null) {
237:                    // since the boundary may be of nonzero length
238:                    int wordSearchPos = reg.getOffset() + reg.getLength()
239:                            - prefix.length();
240:                    // try to complete to a word. case is of no matter here
241:                    IRegion word = searcher.find(wordSearchPos,
242:                            COMPLETION_WORD_REGEX, true, true, false, true);
243:                    if (word.getOffset() + word.getLength() > firstPosition) {
244:                        break;
245:                    }
246:                    if (word.getLength() > prefix.length()) { // empty suggestion will be added later
247:                        String found = document.get(word.getOffset(), word
248:                                .getLength());
249:                        res.add(found.substring(prefix.length()));
250:                    }
251:                    int nextPos = word.getOffset() + word.getLength();
252:                    if (nextPos >= firstPosition) { // for efficiency only
253:                        break;
254:                    }
255:                    reg = searcher.find(nextPos, searchPattern, true,
256:                            CASE_SENSITIVE, false, true);
257:                }
258:                Collections.reverse(res);
259:
260:                return res;
261:            }
262:
263:            /**
264:             * Returns the text between the provided position and the preceding word boundary.
265:             * 
266:             * @param doc the document that will be scanned.
267:             * @param pos the caret position.
268:             * @return the text if found, or null.
269:             * @throws BadLocationException if an error occurs.
270:             * @since 3.2
271:             */
272:            public String getPrefixString(IDocument doc, int pos)
273:                    throws BadLocationException {
274:                Matcher m = COMPLETION_WORD_PATTERN.matcher(""); //$NON-NLS-1$
275:                int prevNonAlpha = pos;
276:                while (prevNonAlpha > 0) {
277:                    m.reset(doc.get(prevNonAlpha - 1, pos - prevNonAlpha + 1));
278:                    if (!m.matches()) {
279:                        break;
280:                    }
281:                    prevNonAlpha--;
282:                }
283:                if (prevNonAlpha != pos) {
284:                    return doc.get(prevNonAlpha, pos - prevNonAlpha);
285:                }
286:                return null;
287:            }
288:
289:            /**
290:             * Remove duplicate suggestions (excluding the prefix), leaving the closest
291:             * to list head.
292:             *
293:             * @param suggestions a list of suggestions ({@link String}).
294:             * @return a list of unique completion suggestions.
295:             */
296:            public List makeUnique(List suggestions) {
297:                HashSet seenAlready = new HashSet();
298:                ArrayList uniqueSuggestions = new ArrayList();
299:
300:                for (Iterator i = suggestions.iterator(); i.hasNext();) {
301:                    String suggestion = (String) i.next();
302:                    if (!seenAlready.contains(suggestion)) {
303:                        seenAlready.add(suggestion);
304:                        uniqueSuggestions.add(suggestion);
305:                    }
306:                }
307:                return uniqueSuggestions;
308:            }
309:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.