KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > Expansion


1 /*
2  * Expansion.java
3  *
4  * Copyright (C) 1998-2003 Peter Graves
5  * $Id: Expansion.java,v 1.4 2003/10/13 12:13:19 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26 import javax.swing.undo.CompoundEdit JavaDoc;
27
28 public class Expansion implements Constants
29 {
30     protected String JavaDoc prefix;
31     protected int prefixOffset; // Offset of prefix on current line.
32

33     protected List JavaDoc candidates;
34     protected int last = -1;
35
36     private static Expansion lastExpansion;
37
38     protected Position savedDot;
39     protected String JavaDoc savedText;
40
41     private final Mode mode;
42
43     private String JavaDoc current;
44     private boolean forceLowerCase;
45
46     // For MailAddressExpansion.
47
protected Expansion()
48     {
49         mode = Editor.getModeList().getMode(PLAIN_TEXT_MODE);
50     }
51
52     public Expansion(Position dot, Mode mode)
53     {
54         savedDot = new Position(dot);
55         this.mode = mode;
56         final Line dotLine = dot.getLine();
57         final int dotOffset = dot.getOffset();
58         savedText = dotLine.getText();
59         // Get word before caret.
60
int begin = dotOffset - 1;
61         if (begin < 0)
62             return;
63         final int end = dotOffset;
64         while (begin > 0 && mode.isIdentifierPart(dotLine.charAt(begin)))
65             --begin;
66         if (!mode.isIdentifierPart(dotLine.charAt(begin)))
67             ++begin;
68         if (begin == end)
69             return;
70         prefix = dotLine.substring(begin, end);
71         prefixOffset = begin;
72         Position pos = new Position(dotLine, begin);
73         current = pos.getIdentifier(mode);
74         int modeId = mode.getId();
75         if (modeId == LISP_MODE || modeId == LISP_SHELL_MODE)
76             if (Utilities.isLowerCase(prefix))
77                 forceLowerCase = true;
78         candidates = list(pos);
79     }
80
81     public Expansion(Buffer buffer, String JavaDoc prefix, String JavaDoc current)
82     {
83         this(buffer, prefix, current, null);
84     }
85
86     public Expansion(Buffer buffer, String JavaDoc prefix, String JavaDoc current, Position pos)
87     {
88         mode = buffer.getMode();
89         this.prefix = prefix;
90         this.current = current;
91         if (buffer.getFirstLine() == null)
92             return;
93         if (pos == null)
94             pos = new Position(buffer.getFirstLine(), 0);
95         candidates = list(pos);
96     }
97
98     private List JavaDoc list(Position pos)
99     {
100         List JavaDoc list = new ArrayList JavaDoc();
101         if (prefix != null) {
102             final boolean ignoreCase = Utilities.isLowerCase(prefix);
103             String JavaDoc s = null;
104             // Search backwards on current line.
105
Line line = pos.getLine();
106             final int begin = pos.getOffset();
107             int index = begin - 1;
108             if (index >= 0) {
109                 s = line.substring(0, begin);
110                 if (ignoreCase)
111                     s = s.toLowerCase();
112                 while ((index = s.lastIndexOf(prefix, index)) >= 0) {
113                     maybeAddCandidate(list, new Position(line, index));
114                     --index;
115                 }
116             }
117             // Search backwards to start of buffer.
118
for (line = pos.getLine().previous(); line != null; line = line.previous()) {
119                 index = line.length();
120                 s = ignoreCase ? line.getText().toLowerCase() : line.getText();
121                 while ((index = s.lastIndexOf(prefix, index)) >= 0) {
122                     maybeAddCandidate(list, new Position(line, index));
123                     --index;
124                 }
125             }
126             // Search forwards from current line to end of buffer. Search current
127
// line again to pick up possible matches to right of dot.
128
for (line = pos.getLine(); line != null; line = line.next()) {
129                 index = 0;
130                 s = ignoreCase ? line.getText().toLowerCase() : line.getText();
131                 while ((index = s.indexOf(prefix, index)) >= 0) {
132                     maybeAddCandidate(list, new Position(line, index));
133                     ++index;
134                 }
135             }
136         }
137         return list;
138     }
139
140     private void maybeAddCandidate(List JavaDoc list, Position where)
141     {
142         final Line line = where.getLine();
143         final int offset = where.getOffset();
144         if (offset == 0 || !mode.isIdentifierPart(line.charAt(offset-1))) {
145             final String JavaDoc candidate = where.getIdentifier(mode);
146             maybeAddCandidate(list, candidate);
147         }
148     }
149
150     private void maybeAddCandidate(List JavaDoc list, String JavaDoc candidate)
151     {
152         // We don't want what we started with.
153
if (candidate.equals(current))
154             return;
155         if (forceLowerCase)
156             candidate = candidate.toLowerCase();
157         for (int i = list.size(); i-- > 0;) {
158             if (candidate.equals(list.get(i))) {
159                 // It's already in the list.
160
return;
161             }
162         }
163         // Not found.
164
list.add(candidate);
165     }
166
167     public void appendCandidates(List JavaDoc list)
168     {
169         final int size = list.size();
170         for (int i = 0; i < size; i++)
171             maybeAddCandidate(candidates, (String JavaDoc)list.get(i));
172     }
173
174     public String JavaDoc getNextCandidate()
175     {
176         if (candidates == null || candidates.size() == 0)
177             return null;
178         int index = last + 1;
179         if (index == candidates.size())
180             index = 0;
181         last = index;
182         return (String JavaDoc) candidates.get(index);
183     }
184
185     private final int getPrefixOffset()
186     {
187         return prefixOffset;
188     }
189
190     public final String JavaDoc getPrefix()
191     {
192         return prefix;
193     }
194
195     public final String JavaDoc getCurrent()
196     {
197         return current;
198     }
199
200     public final List JavaDoc getCandidates()
201     {
202         return candidates;
203     }
204
205     public void undo(Editor editor)
206     {
207         final Buffer buffer = editor.getBuffer();
208         try {
209             buffer.lockWrite();
210         }
211         catch (InterruptedException JavaDoc e) {
212             Log.error(e);
213             return;
214         }
215         try {
216             editor.addUndo(SimpleEdit.LINE_EDIT);
217             editor.getDotLine().setText(savedText);
218             editor.getBuffer().modified();
219             editor.getDot().moveTo(savedDot);
220             editor.getDisplay().moveCaretToDotCol();
221             Editor.updateInAllEditors(editor.getDotLine());
222         }
223         finally {
224             buffer.unlockWrite();
225         }
226     }
227
228     public static Expansion getLastExpansion()
229     {
230         return lastExpansion;
231     }
232
233     public static void setLastExpansion(Expansion expansion)
234     {
235         lastExpansion = expansion;
236     }
237
238     public static void expand()
239     {
240         final Editor editor = Editor.currentEditor();
241         if (editor.getLastCommand() == COMMAND_EXPAND)
242             expand(editor, Expansion.getLastExpansion(), true);
243         else {
244             Expansion e = editor.getBuffer().getExpansion(editor.getDot());
245             Expansion.setLastExpansion(e);
246             expand(editor, e, false);
247         }
248     }
249
250     private static void expand(Editor editor, Expansion expansion, boolean again)
251     {
252         final Buffer buffer = editor.getBuffer();
253         final String JavaDoc candidate = expansion.getNextCandidate();
254         if (candidate == null)
255             return;
256         try {
257             buffer.lockWrite();
258         }
259         catch (InterruptedException JavaDoc e) {
260             Log.error(e);
261             return;
262         }
263         try {
264             if (again)
265                 editor.undo();
266
267             CompoundEdit JavaDoc compoundEdit = buffer.beginCompoundEdit();
268             editor.addUndo(SimpleEdit.MOVE);
269             editor.getDot().setOffset(expansion.getPrefixOffset());
270
271             // Remove prefix from line.
272
final Line line = editor.getDotLine();
273             final int offset = editor.getDotOffset();
274             String JavaDoc head = line.substring(0, offset);
275             String JavaDoc tail = line.substring(offset + expansion.getPrefix().length());
276             editor.addUndo(SimpleEdit.LINE_EDIT);
277             line.setText(head.concat(tail));
278
279             editor.addUndo(SimpleEdit.INSERT_STRING);
280             editor.insertStringInternal(candidate);
281
282             editor.moveCaretToDotCol();
283             buffer.endCompoundEdit(compoundEdit);
284             Editor.updateInAllEditors(line);
285             editor.setCurrentCommand(COMMAND_EXPAND);
286         }
287         finally {
288             buffer.unlockWrite();
289         }
290     }
291 }
292
Popular Tags