1 /* :folding=explicit:collapseFolds=1: */
6 * Copyright (C) 2004 Slava Pestov.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 import org.gjt.sp.jedit.gui.*;
36 import org.gjt.sp.jedit.textarea.*;
37 import org.gjt.sp.jedit.*;
38 import org.gjt.sp.util.Log;
42 public class FactorPlugin extends EditPlugin
44 private static ExternalFactor external;
45 private static Process process;
46 private static int PORT = 9999;
48 //{{{ getPluginPath() method
49 private String getPluginPath()
51 return MiscUtilities.getParentOfPath(
52 jEdit.getPlugin("factor.jedit.FactorPlugin")
53 .getPluginJAR().getPath())
60 BeanShell.eval(null,BeanShell.getNameSpace(),
61 "import factor.*;\nimport factor.jedit.*;\n");
62 String program = jEdit.getProperty("factor.external.program");
63 String image = jEdit.getProperty("factor.external.image");
64 if(program == null || image == null
65 || program.length() == 0 || image.length() == 0)
67 jEdit.setProperty("factor.external.program",
68 MiscUtilities.constructPath(getPluginPath(),"f"));
69 jEdit.setProperty("factor.external.image",
70 MiscUtilities.constructPath(getPluginPath(),"factor.image"));
77 stopExternalInstance();
79 Buffer buffer = jEdit.getFirstBuffer();
82 buffer.setProperty(FactorSideKickParser.WORDS_PROPERTY,null);
83 buffer = buffer.getNext();
87 //{{{ addNonEmpty() method
88 private static void addNonEmpty(String[] input, List output)
90 for(int i = 0; i < input.length; i++)
92 if(input[i].length() != 0)
97 //{{{ getExternalInstance() method
99 * Returns the object representing a connection to an external Factor instance.
100 * It will start the interpreter if it's not already running.
102 public synchronized static ExternalFactor getExternalInstance()
106 InputStream in = null;
107 OutputStream out = null;
111 String exePath = jEdit.getProperty(
112 "factor.external.program");
113 String imagePath = jEdit.getProperty(
114 "factor.external.image");
115 List args = new ArrayList();
118 args.add("-shell=telnet");
119 args.add("-telnetd-port=" + PORT);
120 String[] extraArgs = jEdit.getProperty(
121 "factor.external.args")
123 addNonEmpty(extraArgs,args);
124 process = Runtime.getRuntime().exec(
125 (String[])args.toArray(
126 new String[args.size()]),
128 new File(MiscUtilities
129 .getParentOfPath(imagePath)));
131 external = new ExternalFactor(PORT);
135 Log.log(Log.ERROR,FactorPlugin.class,
136 "Cannot start external Factor:");
137 Log.log(Log.ERROR,FactorPlugin.class,e);
145 //{{{ getFactorShell() method
146 public static FactorShell getFactorShell()
148 return ((FactorShell)ServiceManager.getService("console.Shell","Factor"));
151 //{{{ stopExternalInstance() method
153 * Stops the external interpreter.
155 public static void stopExternalInstance()
157 getFactorShell().closeStreams();
164 process.getErrorStream().close();
165 process.getInputStream().close();
166 process.getOutputStream().close();
171 Log.log(Log.DEBUG,FactorPlugin.class,e);
178 //{{{ restartExternalInstance() method
180 * Restart the external interpreter.
182 public static void restartExternalInstance()
184 stopExternalInstance();
185 getExternalInstance();
186 FactorPlugin.getFactorShell().openStreams();
189 //{{{ getSideKickParser() method
190 public static FactorSideKickParser getSideKickParser()
192 return (FactorSideKickParser)ServiceManager.getService(
193 "sidekick.SideKickParser","factor");
196 //{{{ evalInListener() method
197 public static void evalInListener(View view, String cmd)
199 DockableWindowManager wm = view.getDockableWindowManager();
200 wm.addDockableWindow("console");
201 Console console = (Console)wm.getDockableWindow("console");
202 console.run(Shell.getShell("Factor"),console,cmd);
205 //{{{ evalInWire() method
206 public static String evalInWire(String cmd) throws IOException
208 return getExternalInstance().eval(cmd);
211 //{{{ lookupWord() method
213 * Look up the given Factor word in the vocabularies USE:d in the given view.
215 public static FactorWord lookupWord(View view, String word)
217 SideKickParsedData data = SideKickParsedData.getParsedData(view);
218 if(data instanceof FactorParsedData)
220 FactorParsedData fdata = (FactorParsedData)data;
221 return getExternalInstance().searchVocabulary(fdata.use,word);
227 //{{{ factorWord() method
229 * Look up the given Factor word in the vocabularies USE:d in the given view.
231 public static String factorWord(View view, String word)
233 SideKickParsedData data = SideKickParsedData
234 .getParsedData(view);
235 if(data instanceof FactorParsedData)
237 FactorParsedData fdata = (FactorParsedData)data;
239 + FactorReader.charsToEscapes(word)
240 + "\" " + FactorReader.unparseObject(fdata.use)
247 //{{{ factorWord() method
249 * Build a Factor expression for pushing the selected word on the stack
251 public static String factorWord(View view)
253 JEditTextArea textArea = view.getTextArea();
254 String word = FactorPlugin.getWordAtCaret(textArea);
258 return factorWord(view,word);
261 //{{{ factorWord() method
263 * Build a Factor expression for pushing the selected word on the stack
265 public static String factorWord(FactorWord word)
267 return FactorReader.unparseObject(word.name)
268 + " [ " + FactorReader.unparseObject(word.vocabulary)
272 //{{{ factorWordOutputOp() method
274 * Apply a Factor word to the selected word.
276 public static void factorWordOutputOp(View view, String op)
278 String word = factorWord(view);
280 view.getToolkit().beep();
282 evalInListener(view,word + " " + op);
285 //{{{ factorWordWireOp() method
287 * Apply a Factor word to the selected word.
289 public static void factorWordWireOp(View view, String op) throws IOException
291 String word = factorWord(view);
293 view.getToolkit().beep();
295 evalInWire(word + " " + op);
298 //{{{ toWordArray() method
299 public static FactorWord[] toWordArray(Set completions)
301 FactorWord[] w = (FactorWord[])completions.toArray(new FactorWord[
302 completions.size()]);
303 Arrays.sort(w,new MiscUtilities.StringICaseCompare());
308 //{{{ getCompletions() method
310 * Returns all words in all vocabularies.
312 * @param anywhere If true, matches anywhere in the word name are
313 * returned; otherwise, only matches from beginning.
315 public static Set getCompletions(String word, boolean anywhere)
319 Set completions = new HashSet();
320 getExternalInstance().getCompletions(
321 getExternalInstance().getVocabularies(),
329 throw new RuntimeException(e);
333 //{{{ getWordStartIndex() method
334 public static int getWordStartOffset(String line, int caret)
336 ReadTable readtable = ReadTable.DEFAULT_READTABLE;
341 if(readtable.getCharacterType(line.charAt(start - 1))
342 == ReadTable.WHITESPACE)
353 //{{{ getWordAtCaret() method
354 public static String getWordAtCaret(JEditTextArea textArea)
356 if(textArea.getSelectionCount() != 0)
357 return textArea.getSelectedText();
359 String line = textArea.getLineText(textArea.getCaretLine());
360 if(line.length() == 0)
363 int caret = textArea.getCaretPosition()
364 - textArea.getLineStartOffset(
365 textArea.getCaretLine());
366 if(caret == line.length())
369 ReadTable readtable = ReadTable.DEFAULT_READTABLE;
371 if(readtable.getCharacterType(line.charAt(caret))
372 == ReadTable.WHITESPACE)
377 int start = getWordStartOffset(line,caret);
382 if(readtable.getCharacterType(line.charAt(end))
383 == ReadTable.WHITESPACE)
390 while(end < line.length());
392 return line.substring(start,end);
395 //{{{ showStatus() method
396 public static void showStatus(View view, String msg, String arg)
398 view.getStatus().setMessage(
399 jEdit.getProperty("factor.status." + msg,
400 new String[] { arg }));
403 //{{{ isUsed() method
404 public static boolean isUsed(View view, String vocab)
406 SideKickParsedData data = SideKickParsedData
407 .getParsedData(view);
408 if(data instanceof FactorParsedData)
410 FactorParsedData fdata = (FactorParsedData)data;
411 Cons use = fdata.use;
412 return Cons.contains(use,vocab);
418 //{{{ findAllWordsNamed() method
419 private static FactorWord[] findAllWordsNamed(View view, String word)
422 ExternalFactor external = getExternalInstance();
424 ArrayList words = new ArrayList();
426 Cons vocabs = external.getVocabularies();
427 while(vocabs != null)
429 String vocab = (String)vocabs.car;
430 FactorWord w = (FactorWord)external.searchVocabulary(
431 new Cons(vocab,null),word);
434 vocabs = vocabs.next();
436 return (FactorWord[])words.toArray(new FactorWord[words.size()]);
439 //{{{ insertUseDialog() method
440 public static void insertUseDialog(View view, String word)
444 FactorWord[] words = findAllWordsNamed(view,word);
445 if(words.length == 0)
446 view.getToolkit().beep();
447 else if(words.length == 1)
448 insertUse(view,words[0].vocabulary);
450 new InsertUseDialog(view,getSideKickParser(),words);
454 throw new RuntimeException(e);
458 //{{{ insertUse() method
459 public static void insertUse(View view, String vocab)
461 if(isUsed(view,vocab))
463 showStatus(view,"already-used",vocab);
467 Buffer buffer = view.getBuffer();
468 int lastUseOffset = 0;
469 boolean leadingNewline = false;
470 boolean seenUse = false;
472 for(int i = 0; i < buffer.getLineCount(); i++)
474 String text = buffer.getLineText(i).trim();
475 if(text.startsWith("IN:") || text.startsWith("USE:"))
477 lastUseOffset = buffer.getLineEndOffset(i) - 1;
478 leadingNewline = true;
481 else if(text.startsWith("!") && !seenUse)
483 lastUseOffset = buffer.getLineEndOffset(i) - 1;
484 leadingNewline = true;
486 else if(text.length() == 0 && !seenUse)
491 lastUseOffset = buffer.getLineEndOffset(i - 1) - 1;
499 String decl = "USE: " + vocab;
502 if(lastUseOffset == 0)
504 buffer.insert(lastUseOffset,decl);
505 showStatus(view,"inserted-use",decl);
508 //{{{ extractWord() method
509 public static void extractWord(View view)
511 JEditTextArea textArea = view.getTextArea();
512 Buffer buffer = textArea.getBuffer();
513 String selection = textArea.getSelectedText();
514 if(selection == null)
517 SideKickParsedData data = SideKickParsedData
518 .getParsedData(view);
519 if(!(data instanceof FactorParsedData))
521 view.getToolkit().beep();
525 Asset asset = data.getAssetAtPosition(
526 textArea.getCaretPosition());
530 GUIUtilities.error(view,"factor.extract-word-where",null);
534 String newWord = GUIUtilities.input(view,
535 "factor.extract-word",null);
539 int start = asset.start.getOffset();
541 start = buffer.getLineStartOffset(
542 buffer.getLineOfOffset(start));
544 String indent = MiscUtilities.createWhiteSpace(
545 buffer.getIndentSize(),
546 (buffer.getBooleanProperty("noTabs") ? 0
547 : buffer.getTabSize()));
549 String newDef = ": " + newWord + "\n" + indent
550 + selection.trim() + " ;\n\n" ;
554 buffer.beginCompoundEdit();
556 buffer.insert(start,newDef);
557 textArea.setSelectedText(newWord);
561 buffer.endCompoundEdit();