1 21 22 package org.armedbear.j; 23 24 import java.util.ArrayList ; 25 import java.util.List ; 26 import javax.swing.undo.CompoundEdit ; 27 28 public class Expansion implements Constants 29 { 30 protected String prefix; 31 protected int prefixOffset; 33 protected List candidates; 34 protected int last = -1; 35 36 private static Expansion lastExpansion; 37 38 protected Position savedDot; 39 protected String savedText; 40 41 private final Mode mode; 42 43 private String current; 44 private boolean forceLowerCase; 45 46 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 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 prefix, String current) 82 { 83 this(buffer, prefix, current, null); 84 } 85 86 public Expansion(Buffer buffer, String prefix, String 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 list(Position pos) 99 { 100 List list = new ArrayList (); 101 if (prefix != null) { 102 final boolean ignoreCase = Utilities.isLowerCase(prefix); 103 String s = null; 104 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 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 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 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 candidate = where.getIdentifier(mode); 146 maybeAddCandidate(list, candidate); 147 } 148 } 149 150 private void maybeAddCandidate(List list, String candidate) 151 { 152 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 return; 161 } 162 } 163 list.add(candidate); 165 } 166 167 public void appendCandidates(List list) 168 { 169 final int size = list.size(); 170 for (int i = 0; i < size; i++) 171 maybeAddCandidate(candidates, (String )list.get(i)); 172 } 173 174 public String 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 ) candidates.get(index); 183 } 184 185 private final int getPrefixOffset() 186 { 187 return prefixOffset; 188 } 189 190 public final String getPrefix() 191 { 192 return prefix; 193 } 194 195 public final String getCurrent() 196 { 197 return current; 198 } 199 200 public final List 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 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 candidate = expansion.getNextCandidate(); 254 if (candidate == null) 255 return; 256 try { 257 buffer.lockWrite(); 258 } 259 catch (InterruptedException e) { 260 Log.error(e); 261 return; 262 } 263 try { 264 if (again) 265 editor.undo(); 266 267 CompoundEdit compoundEdit = buffer.beginCompoundEdit(); 268 editor.addUndo(SimpleEdit.MOVE); 269 editor.getDot().setOffset(expansion.getPrefixOffset()); 270 271 final Line line = editor.getDotLine(); 273 final int offset = editor.getDotOffset(); 274 String head = line.substring(0, offset); 275 String 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 |