diff --git a/TODO.FACTOR.txt b/TODO.FACTOR.txt index 1e54cf10d5..dc81053347 100644 --- a/TODO.FACTOR.txt +++ b/TODO.FACTOR.txt @@ -11,15 +11,11 @@ - handle odd base cases, with code after ifte - handle recursion with when, when* etc -+ linearizer/generator: ++ compiler: - getenv/setenv: if literal arg, compile as a load/store - -+ compiler frontend: - - assembler opcodes dispatch on operand types - save code in image -- compile word twice; no more 'cannot compile' error! + oop: @@ -36,7 +32,6 @@ + listener/plugin: -- use decl wrong - faster completion - sidekick: still parsing too much - errors don't always disappear @@ -53,10 +48,9 @@ - cat, reverse-cat primitives - first-class hashtables - rewrite accessors and mutators in Factor, with slot/set-slot primitive -- replace -export-dynamic with sundry-xt - add a socket timeout -- word, writes entire plist - do transfer-word in fixup +- move dispatch getenv setenv to kernel-internals + misc: @@ -65,7 +59,6 @@ - perhaps /i should work with all numbers - unit test weirdness: 2 lines appears at end - jedit ==> jedit-word, jedit takes a file name -- command line parsing cleanup - nicer way to combine two paths - ditch object paths - browser responder for word links in HTTPd; inspect responder for diff --git a/factor/DefaultVocabularyLookup.java b/factor/DefaultVocabularyLookup.java index 3492910c79..4e0a3d3f6b 100644 --- a/factor/DefaultVocabularyLookup.java +++ b/factor/DefaultVocabularyLookup.java @@ -207,8 +207,27 @@ public class DefaultVocabularyLookup implements VocabularyLookup } //}}} //{{{ getCompletions() method - public void getCompletions(String vocab, String word, Set completions, - boolean anywhere) + /** + * @param use A list of vocabularies. + * @param word A substring of the word name to complete + * @param anywhere If true, matches anywhere in the word name are + * returned; otherwise, only matches from beginning. + * @param completions Set to add completions to + */ + public void getCompletions(Cons use, String word, boolean anywhere, + Set completions) throws Exception + { + while(use != null) + { + String vocab = (String)use.car; + getCompletions(vocab,word,anywhere,completions); + use = use.next(); + } + } //}}} + + //{{{ getCompletions() method + public void getCompletions(String vocab, String word, boolean anywhere, + Set completions) throws Exception { Map v = (Map)vocabularies.get(vocab); if(v == null) diff --git a/factor/ExternalFactor.java b/factor/ExternalFactor.java index d6f34771a1..3c94bfffac 100644 --- a/factor/ExternalFactor.java +++ b/factor/ExternalFactor.java @@ -178,6 +178,19 @@ public class ExternalFactor extends DefaultVocabularyLookup return vocabs; } //}}} + //{{{ makeWord() method + /** + * Make a word from an info list returned by Factor. + */ + public synchronized FactorWord makeWord(Cons info) + { + FactorWord w = new FactorWord( + (String)info.car, + (String)info.next().car); + w.stackEffect = (String)info.next().next().car; + return w; + } //}}} + //{{{ searchVocabulary() method /** * Search through the given vocabulary list for the given word. @@ -197,16 +210,11 @@ public class ExternalFactor extends DefaultVocabularyLookup Cons result = parseObject(eval(FactorReader.unparseObject(name) + " " + FactorReader.unparseObject(vocabulary) - + " jedit-lookup .")); + + " search jedit-lookup .")); if(result.car == null) return null; - result = (Cons)result.car; - w = new FactorWord( - (String)result.car, - (String)result.next().car); - w.stackEffect = (String)result.next().next().car; - return w; + return makeWord((Cons)result.car); } catch(Exception e) { @@ -216,40 +224,32 @@ public class ExternalFactor extends DefaultVocabularyLookup } //}}} //{{{ getCompletions() method - public synchronized void getCompletions(String vocab, String word, Set completions, - boolean anywhere) + public synchronized void getCompletions(Cons use, String word, + boolean anywhere, Set completions) throws Exception { - super.getCompletions(vocab,word,completions,anywhere); + super.getCompletions(use,word,anywhere,completions); if(closed) return; - try - { - /* We can't send words across the socket at this point in - human history, because of USE: issues. so we send name/vocab - pairs. */ - Cons moreCompletions = (Cons)parseObject(eval( - FactorReader.unparseObject(word) - + " " - + FactorReader.unparseObject(vocab) - + " " - + (anywhere ? "vocab-apropos" : "vocab-completions") - + " [ dup word-name swap word-vocabulary 2list ] map .")).car; + /* We can't send words across the socket at this point in + human history, because of USE: issues. so we send name/vocab + pairs. */ + Cons moreCompletions = (Cons)parseObject(eval( + FactorReader.unparseObject(word) + + " " + + FactorReader.unparseObject(Boolean.valueOf(anywhere)) + + " " + + FactorReader.unparseObject(use) + + " completions .")).car; - while(moreCompletions != null) - { - Cons completion = (Cons)moreCompletions.car; - FactorWord w = searchVocabulary(completion.next(), - (String)completion.car); - if(w != null) - completions.add(w); - moreCompletions = moreCompletions.next(); - } - } - catch(Exception e) + while(moreCompletions != null) { - Log.log(Log.ERROR,this,e); + Cons completion = (Cons)moreCompletions.car; + FactorWord w = makeWord(completion); + if(w != null) + completions.add(w); + moreCompletions = moreCompletions.next(); } } //}}} diff --git a/factor/VocabularyLookup.java b/factor/VocabularyLookup.java index 60ec6ada36..31b4f85c9b 100644 --- a/factor/VocabularyLookup.java +++ b/factor/VocabularyLookup.java @@ -42,15 +42,25 @@ public interface VocabularyLookup public void forget(FactorWord word); + /** + * @param use A list of vocabularies. + * @param word A substring of the word name to complete + * @param anywhere If true, matches anywhere in the word name are + * returned; otherwise, only matches from beginning. + * @param completions Set to add completions to + */ + public void getCompletions(Cons use, String word, boolean anywhere, + Set completions) throws Exception; + /** * @param vocab The vocabulary name * @param word A substring of the word name to complete - * @param completions List to add completions to * @param anywhere If true, word name will be matched anywhere, otherwise, just at * the beginning of the name. + * @param completions Set to add completions to */ - public void getCompletions(String vocab, String word, Set completions, - boolean anywhere) throws Exception; + public void getCompletions(String vocab, String word, boolean anywhere, + Set completions) throws Exception; public Cons getVocabularies() throws Exception; } diff --git a/factor/jedit/EditWordDialog.java b/factor/jedit/EditWordDialog.java index 265999fd54..cae245698b 100644 --- a/factor/jedit/EditWordDialog.java +++ b/factor/jedit/EditWordDialog.java @@ -126,6 +126,8 @@ public class EditWordDialog extends WordListDialog list.setSelectedIndex(0); list.ensureIndexIsVisible(0); } + + updatePreview(); } //}}} //{{{ UpdateTimer class diff --git a/factor/jedit/FactorCompletion.java b/factor/jedit/FactorCompletion.java index 3ee9e50b5f..654b77dcf1 100644 --- a/factor/jedit/FactorCompletion.java +++ b/factor/jedit/FactorCompletion.java @@ -61,14 +61,23 @@ public class FactorCompletion extends SideKickCompletion public void insert(int index) { - Macros.Recorder recorder = view.getMacroRecorder(); + FactorWord selected = ((FactorWord)get(index)); + String insert = selected.name.substring(word.length()); - String insert = ((FactorWord)get(index)).name.substring( - word.length()); + Buffer buffer = textArea.getBuffer(); - if(recorder != null) - recorder.recordInput(insert,false); - textArea.setSelectedText(insert); + try + { + buffer.beginCompoundEdit(); + + textArea.setSelectedText(insert); + if(!FactorPlugin.isUsed(view,selected.vocabulary)) + FactorPlugin.insertUse(view,selected.vocabulary); + } + finally + { + buffer.endCompoundEdit(); + } } public int getTokenLength() @@ -81,13 +90,7 @@ public class FactorCompletion extends SideKickCompletion if(keyChar == '\t' || keyChar == '\n') insert(selectedIndex); else - { - Macros.Recorder recorder = view.getMacroRecorder(); - - if(recorder != null) - recorder.recordInput(1,keyChar,false); textArea.userInput(keyChar); - } boolean ws = (ReadTable.DEFAULT_READTABLE .getCharacterType(keyChar) diff --git a/factor/jedit/FactorPlugin.java b/factor/jedit/FactorPlugin.java index e556b70560..7b5b6ddb8b 100644 --- a/factor/jedit/FactorPlugin.java +++ b/factor/jedit/FactorPlugin.java @@ -73,6 +73,13 @@ public class FactorPlugin extends EditPlugin public void stop() { stopExternalInstance(); + + Buffer buffer = jEdit.getFirstBuffer(); + while(buffer != null) + { + buffer.setProperty(FactorSideKickParser.PARSED_PROPERTY,null); + buffer = buffer.getNext(); + } } //}}} //{{{ getExternalInstance() method @@ -165,9 +172,9 @@ public class FactorPlugin extends EditPlugin } //}}} //{{{ evalInWire() method - public static void evalInWire(String cmd) throws IOException + public static String evalInWire(String cmd) throws IOException { - getExternalInstance().eval(cmd); + return getExternalInstance().eval(cmd); } //}}} //{{{ lookupWord() method @@ -275,37 +282,15 @@ public class FactorPlugin extends EditPlugin * returned; otherwise, only matches from beginning. */ public static Set getCompletions(String word, boolean anywhere) - { - try - { - return getCompletions(getExternalInstance().getVocabularies(),word, - anywhere); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - } //}}} - - //{{{ getCompletions() method - /** - * @param anywhere If true, matches anywhere in the word name are - * returned; otherwise, only matches from beginning. - */ - public static Set getCompletions(Cons use, String word, boolean anywhere) { try { Set completions = new HashSet(); - - while(use != null) - { - String vocab = (String)use.car; - getExternalInstance().getCompletions( - vocab,word,completions,anywhere); - use = use.next(); - } - + getExternalInstance().getCompletions( + getExternalInstance().getVocabularies(), + word, + anywhere, + completions); return completions; } catch(Exception e) @@ -375,7 +360,7 @@ public class FactorPlugin extends EditPlugin } //}}} //{{{ isUsed() method - private static boolean isUsed(View view, String vocab) + public static boolean isUsed(View view, String vocab) { SideKickParsedData data = SideKickParsedData .getParsedData(view); diff --git a/factor/jedit/FactorPlugin.props b/factor/jedit/FactorPlugin.props index 2a35e84023..7d36660d79 100644 --- a/factor/jedit/FactorPlugin.props +++ b/factor/jedit/FactorPlugin.props @@ -2,7 +2,7 @@ plugin.factor.jedit.FactorPlugin.activate=startup plugin.factor.jedit.FactorPlugin.name=Factor -plugin.factor.jedit.FactorPlugin.version=0.70 +plugin.factor.jedit.FactorPlugin.version=0.71 plugin.factor.jedit.FactorPlugin.author=Slava Pestov plugin.factor.jedit.FactorPlugin.docs=/doc/jedit/index.html diff --git a/factor/jedit/FactorSideKickParser.java b/factor/jedit/FactorSideKickParser.java index fe7e19a1d3..cda9819c61 100644 --- a/factor/jedit/FactorSideKickParser.java +++ b/factor/jedit/FactorSideKickParser.java @@ -290,8 +290,7 @@ public class FactorSideKickParser extends SideKickParser return null; FactorWord[] completions = FactorPlugin.toWordArray( - FactorPlugin.getCompletions( - data.use,word,false)); + FactorPlugin.getCompletions(word,false)); if(completions.length == 0) return null; diff --git a/factor/jedit/WordListDialog.java b/factor/jedit/WordListDialog.java index 4b2f0f8967..7846378ce2 100644 --- a/factor/jedit/WordListDialog.java +++ b/factor/jedit/WordListDialog.java @@ -31,16 +31,19 @@ package factor.jedit; import factor.*; import javax.swing.border.*; +import javax.swing.event.*; import javax.swing.*; import java.awt.event.*; import java.awt.*; import org.gjt.sp.jedit.gui.EnhancedDialog; import org.gjt.sp.jedit.*; +import org.gjt.sp.util.Log; public abstract class WordListDialog extends EnhancedDialog { protected View view; protected JList list; + protected JTextArea preview; protected JButton ok, cancel; //{{{ WordListDialog constructor @@ -55,13 +58,47 @@ public abstract class WordListDialog extends EnhancedDialog content.setBorder(new EmptyBorder(12,12,12,12)); setContentPane(content); - content.add(BorderLayout.CENTER,new JScrollPane( - list = new JList())); + JScrollPane listScroll = new JScrollPane( + list = new JList()); list.setCellRenderer(new FactorWordRenderer(parser,true)); + list.addListSelectionListener(new ListHandler()); + + JScrollPane previewScroll = new JScrollPane( + preview = new JTextArea(12,60)); + preview.setEditable(false); + + listScroll.setPreferredSize(previewScroll.getPreferredSize()); + + JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + listScroll,previewScroll); + split.setDividerLocation(0.5); + split.setResizeWeight(0.5); + content.add(BorderLayout.CENTER,split); content.add(BorderLayout.SOUTH,createButtonPanel()); } //}}} + //{{{ updatePreview() method + protected void updatePreview() + { + FactorWord word = (FactorWord)list.getSelectedValue(); + if(word == null) + { + preview.setText(""); + return; + } + + try + { + preview.setText(FactorPlugin.evalInWire( + FactorPlugin.factorWord(word) + " see").trim()); + } + catch(Exception e) + { + Log.log(Log.ERROR,this,e); + } + } //}}} + //{{{ createButtonPanel() method private Box createButtonPanel() { @@ -91,4 +128,13 @@ public abstract class WordListDialog extends EnhancedDialog cancel(); } } //}}} + + //{{{ ListHandler class + class ListHandler implements ListSelectionListener + { + public void valueChanged(ListSelectionEvent evt) + { + updatePreview(); + } + } //}}} } diff --git a/library/tools/jedit-wire.factor b/library/tools/jedit-wire.factor index 87db36e0ef..f75c1ff8dc 100644 --- a/library/tools/jedit-wire.factor +++ b/library/tools/jedit-wire.factor @@ -95,10 +95,10 @@ C: jedit-stream ( stream -- stream ) #! Execute this in the inferior Factor. stdio [ ] change print-banner ; -: jedit-lookup ( word vocabs -- ) +: jedit-lookup ( word -- list ) #! A utility word called by the Factor plugin to get some #! required word info. - search dup [ + dup [ [ "vocabulary" "name" @@ -107,3 +107,16 @@ C: jedit-stream ( stream -- stream ) dupd word-property ] map nip ] when ; + +: completions ( str anywhere vocabs -- list ) + #! Make a list of completions. Each element of the list is + #! a name/vocabulary pair. + [ + [ + >r 2dup r> swap [ + vocab-apropos + ] [ + vocab-completions + ] ifte [ jedit-lookup , ] each + ] each + ] make-list ;