improved factor plugin

cvs
Slava Pestov 2004-12-20 00:36:10 +00:00
parent 12a09523d4
commit 8b0949dd8b
11 changed files with 167 additions and 97 deletions

View File

@ -11,15 +11,11 @@
- handle odd base cases, with code after ifte - handle odd base cases, with code after ifte
- handle recursion with when, when* etc - handle recursion with when, when* etc
+ linearizer/generator: + compiler:
- getenv/setenv: if literal arg, compile as a load/store - getenv/setenv: if literal arg, compile as a load/store
+ compiler frontend:
- assembler opcodes dispatch on operand types - assembler opcodes dispatch on operand types
- save code in image - save code in image
- compile word twice; no more 'cannot compile' error!
+ oop: + oop:
@ -36,7 +32,6 @@
+ listener/plugin: + listener/plugin:
- use decl wrong
- faster completion - faster completion
- sidekick: still parsing too much - sidekick: still parsing too much
- errors don't always disappear - errors don't always disappear
@ -53,10 +48,9 @@
- cat, reverse-cat primitives - cat, reverse-cat primitives
- first-class hashtables - first-class hashtables
- rewrite accessors and mutators in Factor, with slot/set-slot primitive - rewrite accessors and mutators in Factor, with slot/set-slot primitive
- replace -export-dynamic with sundry-xt
- add a socket timeout - add a socket timeout
- word, writes entire plist
- do transfer-word in fixup - do transfer-word in fixup
- move dispatch getenv setenv to kernel-internals
+ misc: + misc:
@ -65,7 +59,6 @@
- perhaps /i should work with all numbers - perhaps /i should work with all numbers
- unit test weirdness: 2 lines appears at end - unit test weirdness: 2 lines appears at end
- jedit ==> jedit-word, jedit takes a file name - jedit ==> jedit-word, jedit takes a file name
- command line parsing cleanup
- nicer way to combine two paths - nicer way to combine two paths
- ditch object paths - ditch object paths
- browser responder for word links in HTTPd; inspect responder for - browser responder for word links in HTTPd; inspect responder for

View File

@ -207,8 +207,27 @@ public class DefaultVocabularyLookup implements VocabularyLookup
} //}}} } //}}}
//{{{ getCompletions() method //{{{ 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); Map v = (Map)vocabularies.get(vocab);
if(v == null) if(v == null)

View File

@ -178,6 +178,19 @@ public class ExternalFactor extends DefaultVocabularyLookup
return vocabs; 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 //{{{ searchVocabulary() method
/** /**
* Search through the given vocabulary list for the given word. * 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) Cons result = parseObject(eval(FactorReader.unparseObject(name)
+ " " + " "
+ FactorReader.unparseObject(vocabulary) + FactorReader.unparseObject(vocabulary)
+ " jedit-lookup .")); + " search jedit-lookup ."));
if(result.car == null) if(result.car == null)
return null; return null;
result = (Cons)result.car; return makeWord((Cons)result.car);
w = new FactorWord(
(String)result.car,
(String)result.next().car);
w.stackEffect = (String)result.next().next().car;
return w;
} }
catch(Exception e) catch(Exception e)
{ {
@ -216,41 +224,33 @@ public class ExternalFactor extends DefaultVocabularyLookup
} //}}} } //}}}
//{{{ getCompletions() method //{{{ getCompletions() method
public synchronized void getCompletions(String vocab, String word, Set completions, public synchronized void getCompletions(Cons use, String word,
boolean anywhere) boolean anywhere, Set completions) throws Exception
{ {
super.getCompletions(vocab,word,completions,anywhere); super.getCompletions(use,word,anywhere,completions);
if(closed) if(closed)
return; return;
try
{
/* We can't send words across the socket at this point in /* We can't send words across the socket at this point in
human history, because of USE: issues. so we send name/vocab human history, because of USE: issues. so we send name/vocab
pairs. */ pairs. */
Cons moreCompletions = (Cons)parseObject(eval( Cons moreCompletions = (Cons)parseObject(eval(
FactorReader.unparseObject(word) FactorReader.unparseObject(word)
+ " " + " "
+ FactorReader.unparseObject(vocab) + FactorReader.unparseObject(Boolean.valueOf(anywhere))
+ " " + " "
+ (anywhere ? "vocab-apropos" : "vocab-completions") + FactorReader.unparseObject(use)
+ " [ dup word-name swap word-vocabulary 2list ] map .")).car; + " completions .")).car;
while(moreCompletions != null) while(moreCompletions != null)
{ {
Cons completion = (Cons)moreCompletions.car; Cons completion = (Cons)moreCompletions.car;
FactorWord w = searchVocabulary(completion.next(), FactorWord w = makeWord(completion);
(String)completion.car);
if(w != null) if(w != null)
completions.add(w); completions.add(w);
moreCompletions = moreCompletions.next(); moreCompletions = moreCompletions.next();
} }
}
catch(Exception e)
{
Log.log(Log.ERROR,this,e);
}
} //}}} } //}}}
//{{{ close() method //{{{ close() method

View File

@ -42,15 +42,25 @@ public interface VocabularyLookup
public void forget(FactorWord word); 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 vocab The vocabulary name
* @param word A substring of the word name to complete * @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 * @param anywhere If true, word name will be matched anywhere, otherwise, just at
* the beginning of the name. * the beginning of the name.
* @param completions Set to add completions to
*/ */
public void getCompletions(String vocab, String word, Set completions, public void getCompletions(String vocab, String word, boolean anywhere,
boolean anywhere) throws Exception; Set completions) throws Exception;
public Cons getVocabularies() throws Exception; public Cons getVocabularies() throws Exception;
} }

View File

@ -126,6 +126,8 @@ public class EditWordDialog extends WordListDialog
list.setSelectedIndex(0); list.setSelectedIndex(0);
list.ensureIndexIsVisible(0); list.ensureIndexIsVisible(0);
} }
updatePreview();
} //}}} } //}}}
//{{{ UpdateTimer class //{{{ UpdateTimer class

View File

@ -61,14 +61,23 @@ public class FactorCompletion extends SideKickCompletion
public void insert(int index) 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( Buffer buffer = textArea.getBuffer();
word.length());
try
{
buffer.beginCompoundEdit();
if(recorder != null)
recorder.recordInput(insert,false);
textArea.setSelectedText(insert); textArea.setSelectedText(insert);
if(!FactorPlugin.isUsed(view,selected.vocabulary))
FactorPlugin.insertUse(view,selected.vocabulary);
}
finally
{
buffer.endCompoundEdit();
}
} }
public int getTokenLength() public int getTokenLength()
@ -81,13 +90,7 @@ public class FactorCompletion extends SideKickCompletion
if(keyChar == '\t' || keyChar == '\n') if(keyChar == '\t' || keyChar == '\n')
insert(selectedIndex); insert(selectedIndex);
else else
{
Macros.Recorder recorder = view.getMacroRecorder();
if(recorder != null)
recorder.recordInput(1,keyChar,false);
textArea.userInput(keyChar); textArea.userInput(keyChar);
}
boolean ws = (ReadTable.DEFAULT_READTABLE boolean ws = (ReadTable.DEFAULT_READTABLE
.getCharacterType(keyChar) .getCharacterType(keyChar)

View File

@ -73,6 +73,13 @@ public class FactorPlugin extends EditPlugin
public void stop() public void stop()
{ {
stopExternalInstance(); stopExternalInstance();
Buffer buffer = jEdit.getFirstBuffer();
while(buffer != null)
{
buffer.setProperty(FactorSideKickParser.PARSED_PROPERTY,null);
buffer = buffer.getNext();
}
} //}}} } //}}}
//{{{ getExternalInstance() method //{{{ getExternalInstance() method
@ -165,9 +172,9 @@ public class FactorPlugin extends EditPlugin
} //}}} } //}}}
//{{{ evalInWire() method //{{{ 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 //{{{ lookupWord() method
@ -275,37 +282,15 @@ public class FactorPlugin extends EditPlugin
* returned; otherwise, only matches from beginning. * returned; otherwise, only matches from beginning.
*/ */
public static Set getCompletions(String word, boolean anywhere) 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 try
{ {
Set completions = new HashSet(); Set completions = new HashSet();
while(use != null)
{
String vocab = (String)use.car;
getExternalInstance().getCompletions( getExternalInstance().getCompletions(
vocab,word,completions,anywhere); getExternalInstance().getVocabularies(),
use = use.next(); word,
} anywhere,
completions);
return completions; return completions;
} }
catch(Exception e) catch(Exception e)
@ -375,7 +360,7 @@ public class FactorPlugin extends EditPlugin
} //}}} } //}}}
//{{{ isUsed() method //{{{ isUsed() method
private static boolean isUsed(View view, String vocab) public static boolean isUsed(View view, String vocab)
{ {
SideKickParsedData data = SideKickParsedData SideKickParsedData data = SideKickParsedData
.getParsedData(view); .getParsedData(view);

View File

@ -2,7 +2,7 @@
plugin.factor.jedit.FactorPlugin.activate=startup plugin.factor.jedit.FactorPlugin.activate=startup
plugin.factor.jedit.FactorPlugin.name=Factor 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.author=Slava Pestov
plugin.factor.jedit.FactorPlugin.docs=/doc/jedit/index.html plugin.factor.jedit.FactorPlugin.docs=/doc/jedit/index.html

View File

@ -290,8 +290,7 @@ public class FactorSideKickParser extends SideKickParser
return null; return null;
FactorWord[] completions = FactorPlugin.toWordArray( FactorWord[] completions = FactorPlugin.toWordArray(
FactorPlugin.getCompletions( FactorPlugin.getCompletions(word,false));
data.use,word,false));
if(completions.length == 0) if(completions.length == 0)
return null; return null;

View File

@ -31,16 +31,19 @@ package factor.jedit;
import factor.*; import factor.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.*; import javax.swing.*;
import java.awt.event.*; import java.awt.event.*;
import java.awt.*; import java.awt.*;
import org.gjt.sp.jedit.gui.EnhancedDialog; import org.gjt.sp.jedit.gui.EnhancedDialog;
import org.gjt.sp.jedit.*; import org.gjt.sp.jedit.*;
import org.gjt.sp.util.Log;
public abstract class WordListDialog extends EnhancedDialog public abstract class WordListDialog extends EnhancedDialog
{ {
protected View view; protected View view;
protected JList list; protected JList list;
protected JTextArea preview;
protected JButton ok, cancel; protected JButton ok, cancel;
//{{{ WordListDialog constructor //{{{ WordListDialog constructor
@ -55,13 +58,47 @@ public abstract class WordListDialog extends EnhancedDialog
content.setBorder(new EmptyBorder(12,12,12,12)); content.setBorder(new EmptyBorder(12,12,12,12));
setContentPane(content); setContentPane(content);
content.add(BorderLayout.CENTER,new JScrollPane( JScrollPane listScroll = new JScrollPane(
list = new JList())); list = new JList());
list.setCellRenderer(new FactorWordRenderer(parser,true)); 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()); 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 //{{{ createButtonPanel() method
private Box createButtonPanel() private Box createButtonPanel()
{ {
@ -91,4 +128,13 @@ public abstract class WordListDialog extends EnhancedDialog
cancel(); cancel();
} }
} //}}} } //}}}
//{{{ ListHandler class
class ListHandler implements ListSelectionListener
{
public void valueChanged(ListSelectionEvent evt)
{
updatePreview();
}
} //}}}
} }

View File

@ -95,10 +95,10 @@ C: jedit-stream ( stream -- stream )
#! Execute this in the inferior Factor. #! Execute this in the inferior Factor.
stdio [ <jedit-stream> ] change print-banner ; stdio [ <jedit-stream> ] change print-banner ;
: jedit-lookup ( word vocabs -- ) : jedit-lookup ( word -- list )
#! A utility word called by the Factor plugin to get some #! A utility word called by the Factor plugin to get some
#! required word info. #! required word info.
search dup [ dup [
[ [
"vocabulary" "vocabulary"
"name" "name"
@ -107,3 +107,16 @@ C: jedit-stream ( stream -- stream )
dupd word-property dupd word-property
] map nip ] map nip
] when ; ] 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 ;