]> gitweb.factorcode.org Git - factor.git/commitdiff
working on jEdit plugin
authorSlava Pestov <slava@factorcode.org>
Thu, 17 Feb 2005 02:54:36 +0000 (02:54 +0000)
committerSlava Pestov <slava@factorcode.org>
Thu, 17 Feb 2005 02:54:36 +0000 (02:54 +0000)
14 files changed:
TODO.FACTOR.txt
factor/DefaultVocabularyLookup.java
factor/ExternalFactor.java
factor/VocabularyLookup.java
factor/jedit/AbstractCompletion.java [new file with mode: 0644]
factor/jedit/EditWordDialog.java
factor/jedit/FactorCompletion.java [deleted file]
factor/jedit/FactorPlugin.java
factor/jedit/FactorPlugin.props
factor/jedit/FactorSideKickParser.java
factor/jedit/FactorVocabCompletion.java [new file with mode: 0644]
factor/jedit/FactorWordCompletion.java [new file with mode: 0644]
factor/jedit/WordPreview.java
library/ui/labels.factor

index 3d4a59d61a3133bb1512e3ae48e047b53ea59aae..4ec2f1a8e7ae5ee098c5e7b2662d29cbc9e82508 100644 (file)
@@ -3,10 +3,7 @@
 - [ [ dup call ] dup call ] infer hangs\r
 - move tuple to generic vocab\r
 - update plugin docs\r
-- extract word keeps indent\r
 - word preview for remote words\r
-- support USING:\r
-- special completion for USE:/IN:\r
 - vectors: ensure its ok with bignum indices\r
 - code gc\r
 - type inference fails with some assembler words;\r
   not cons, and need stronger branch partial eval\r
 - print warning on null class\r
 - optimize away dispatch\r
-- alignment of gadgets inside their bounding boxes needs thought\r
 - faster completion\r
 - ppc register decls\r
 \r
+- extract word inside M:, C:, and structure browsing for these\r
+- fix checkbox alignment\r
 - begin-scan, next-object, end-scan primitives\r
 - each-object, each-slot combinators\r
 - port leak\r
index 3561609c922136b3835661557cb686b8444a611b..5035fa13544946bbe050c1387aae0cb879059cbe 100644 (file)
@@ -218,7 +218,7 @@ public class DefaultVocabularyLookup implements VocabularyLookup
                return vocabs;
        } //}}}
 
-       //{{{ getCompletions() method
+       //{{{ getWordCompletions() method
        /**
         * @param use A list of vocabularies.
         * @param word A substring of the word name to complete
@@ -226,19 +226,36 @@ public class DefaultVocabularyLookup implements VocabularyLookup
         * returned; otherwise, only matches from beginning.
         * @param completions Set to add completions to
         */
-       public void getCompletions(Cons use, String word, boolean anywhere,
+       public void getWordCompletions(Cons use, String word, boolean anywhere,
                Set completions) throws Exception
        {
                while(use != null)
                {
                        String vocab = (String)use.car;
-                       getCompletions(vocab,word,anywhere,completions);
+                       getWordCompletions(vocab,word,anywhere,completions);
                        use = use.next();
                }
        } //}}}
 
-       //{{{ getCompletions() method
-       public void getCompletions(String vocab, String word, boolean anywhere,
+       //{{{ isCompletion() method
+       public boolean isCompletion(String match, String against, boolean anywhere)
+       {
+               if(anywhere)
+               {
+                       if(against.indexOf(match) != -1)
+                               return true;
+               }
+               else
+               {
+                       if(against.startsWith(match))
+                               return true;
+               }
+               
+               return false;
+       } //}}}
+       
+       //{{{ getWordCompletions() method
+       public void getWordCompletions(String vocab, String word, boolean anywhere,
                Set completions) throws Exception
        {
                Map v = (Map)vocabularies.get(vocab);
@@ -254,21 +271,35 @@ public class DefaultVocabularyLookup implements VocabularyLookup
                        {
                                if(!completions.contains(w))
                                {
-                                       if(anywhere)
-                                       {
-                                               if(w.name.indexOf(word) != -1)
-                                                       completions.add(w);
-                                       }
-                                       else
-                                       {
-                                               if(w.name.startsWith(word))
-                                                       completions.add(w);
-                                       }
+                                       if(isCompletion(word,w.name,anywhere))
+                                               completions.add(w);
                                }
                        }
                }
        } //}}}
 
+       //{{{ getVocabCompletions() method
+       /**
+        * @param vocab A string to complete
+        * @param anywhere If true, matches anywhere in the vocab name are
+        * returned; otherwise, only matches from beginning.
+        */
+       public String[] getVocabCompletions(String vocab, boolean anywhere)
+               throws Exception
+       {
+               List completions = new ArrayList();
+               Cons vocabs = getVocabularies();
+               while(vocabs != null)
+               {
+                       String v = (String)vocabs.car;
+                       if(isCompletion(vocab,v,anywhere))
+                               completions.add(v);
+                       vocabs = vocabs.next();
+               }
+
+               return (String[])completions.toArray(new String[completions.size()]);
+       } //}}}
+
        //{{{ parseObject() method
        public Cons parseObject(String source) throws Exception
        {
index 78b5779ae9c8572b41c73211a44717a5a1e62b35..4d825452d185a2f0591a807e9a3967d3425ba311 100644 (file)
@@ -238,11 +238,11 @@ public class ExternalFactor extends DefaultVocabularyLookup
                }
        } //}}}
 
-       //{{{ getCompletions() method
-       public synchronized void getCompletions(Cons use, String word,
+       //{{{ getWordCompletions() method
+       public synchronized void getWordCompletions(Cons use, String word,
                boolean anywhere, Set completions) throws Exception
        {
-               super.getCompletions(use,word,anywhere,completions);
+               super.getWordCompletions(use,word,anywhere,completions);
 
                if(closed)
                        return;
index 31b4f85c9b1a6b9efcb19db758369bdf40807298..4047cff4b27aec942062d61328e174c8aab0b549 100644 (file)
@@ -49,9 +49,17 @@ public interface VocabularyLookup
         * returned; otherwise, only matches from beginning.
         * @param completions Set to add completions to
         */
-       public void getCompletions(Cons use, String word, boolean anywhere,
+       public void getWordCompletions(Cons use, String word, boolean anywhere,
                Set completions) throws Exception;
 
+       /**
+        * @param vocab A string to complete
+        * @param anywhere If true, matches anywhere in the vocab name are
+        * returned; otherwise, only matches from beginning.
+        */
+       public String[] getVocabCompletions(String vocab, boolean anywhere)
+               throws Exception;
+
        /**
         * @param vocab The vocabulary name
         * @param word A substring of the word name to complete
@@ -59,7 +67,7 @@ public interface VocabularyLookup
         * the beginning of the name.
         * @param completions Set to add completions to
         */
-       public void getCompletions(String vocab, String word, boolean anywhere,
+       public void getWordCompletions(String vocab, String word, boolean anywhere,
                Set completions) throws Exception;
 
        public Cons getVocabularies() throws Exception;
diff --git a/factor/jedit/AbstractCompletion.java b/factor/jedit/AbstractCompletion.java
new file mode 100644 (file)
index 0000000..bf5eeae
--- /dev/null
@@ -0,0 +1,81 @@
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004, 2005 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.*;
+import java.util.*;
+import javax.swing.ListCellRenderer;
+import org.gjt.sp.jedit.textarea.*;
+import org.gjt.sp.jedit.*;
+import sidekick.*;
+
+public abstract class AbstractCompletion extends SideKickCompletion
+{
+       protected View view;
+       protected JEditTextArea textArea;
+       protected FactorParsedData data;
+       
+       //{{{ AbstractCompletion constructor
+       public AbstractCompletion(View view, Object[] items,
+               FactorParsedData data)
+       {
+               this.view = view;
+               textArea = view.getTextArea();
+               this.items = Arrays.asList(items);
+               this.data = data;
+       } //}}}
+
+       //{{{ getLongestPrefix() method
+       public String getLongestPrefix()
+       {
+               return MiscUtilities.getLongestPrefix(items,false);
+       } //}}}
+
+       //{{{ handleKeystroke() method
+       public boolean handleKeystroke(int selectedIndex, char keyChar)
+       {
+               if(keyChar == '\t' || keyChar == '\n')
+               {
+                       insert(selectedIndex);
+                       return false;
+               }
+               else if(keyChar == ' ')
+               {
+                       insert(selectedIndex);
+                       textArea.userInput(' ');
+                       return false;
+               }
+               else
+               {
+                       textArea.userInput(keyChar);
+                       return true;
+               }
+       } //}}}
+}
index cae245698b9f48fb6562b0253ac184821f54a4b5..912bc3d609a0757f4f0785a97e733351dc4e70ca 100644 (file)
@@ -118,7 +118,7 @@ public class EditWordDialog extends WordListDialog
        private void updateList()
        {
                FactorWord[] completions = FactorPlugin.toWordArray(
-                       FactorPlugin.getCompletions(
+                       FactorPlugin.getWordCompletions(
                        field.getText(),true));
                list.setListData(completions);
                if(completions.length != 0)
diff --git a/factor/jedit/FactorCompletion.java b/factor/jedit/FactorCompletion.java
deleted file mode 100644 (file)
index 7807fa5..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.jedit;
-
-import factor.*;
-import java.util.*;
-import javax.swing.ListCellRenderer;
-import org.gjt.sp.jedit.textarea.*;
-import org.gjt.sp.jedit.*;
-import sidekick.*;
-
-public class FactorCompletion extends SideKickCompletion
-{
-       private View view;
-       private JEditTextArea textArea;
-       private String word;
-       private FactorParsedData data;
-
-       //{{{ FactorCompletion constructor
-       public FactorCompletion(View view, FactorWord[] items,
-               String word, FactorParsedData data)
-       {
-               this.view = view;
-               textArea = view.getTextArea();
-               this.items = Arrays.asList(items);
-               this.word = word;
-               this.data = data;
-       } //}}}
-
-       public String getLongestPrefix()
-       {
-               return MiscUtilities.getLongestPrefix(items,false);
-       }
-
-       public void insert(int index)
-       {
-               FactorWord selected = ((FactorWord)get(index));
-               String insert = selected.name.substring(word.length());
-
-               Buffer buffer = textArea.getBuffer();
-
-               try
-               {
-                       buffer.beginCompoundEdit();
-                       
-                       textArea.setSelectedText(insert);
-                       if(!FactorPlugin.isUsed(view,selected.vocabulary))
-                               FactorPlugin.insertUse(view,selected.vocabulary);
-               }
-               finally
-               {
-                       buffer.endCompoundEdit();
-               }
-       }
-
-       public int getTokenLength()
-       {
-               return word.length();
-       }
-
-       public boolean handleKeystroke(int selectedIndex, char keyChar)
-       {
-               if(keyChar == '\t' || keyChar == '\n')
-               {
-                       insert(selectedIndex);
-                       return false;
-               }
-               else if(keyChar == ' ')
-               {
-                       insert(selectedIndex);
-                       textArea.userInput(' ');
-                       return false;
-               }
-               else
-               {
-                       textArea.userInput(keyChar);
-                       return true;
-               }
-       }
-
-       public ListCellRenderer getRenderer()
-       {
-               return new FactorWordRenderer(data.parser,false);
-       }
-}
index 67c4791adc3ada681af775c5d1d58709ce8ded5a..9d4756ef1ff0f54ecd1ffb24e0e5ae9d9fb7e5fd 100644 (file)
@@ -33,6 +33,7 @@ import factor.*;
 import java.io.*;
 import java.util.*;
 import org.gjt.sp.jedit.gui.*;
+import org.gjt.sp.jedit.syntax.*;
 import org.gjt.sp.jedit.textarea.*;
 import org.gjt.sp.jedit.*;
 import org.gjt.sp.util.Log;
@@ -325,19 +326,20 @@ public class FactorPlugin extends EditPlugin
                return w;
        } //}}}
        
-       //{{{ getCompletions() method
+       //{{{ getWordCompletions() method
        /**
-        * Returns all words in all vocabularies.
+        * Returns all words in all vocabularies whose name starts with
+        * <code>word</code>.
         *
         * @param anywhere If true, matches anywhere in the word name are
         * returned; otherwise, only matches from beginning.
         */
-       public static Set getCompletions(String word, boolean anywhere)
+       public static Set getWordCompletions(String word, boolean anywhere)
        {
                try
                {
                        Set completions = new HashSet();
-                       getExternalInstance().getCompletions(
+                       getExternalInstance().getWordCompletions(
                                getExternalInstance().getVocabularies(),
                                word,
                                anywhere,
@@ -350,6 +352,27 @@ public class FactorPlugin extends EditPlugin
                }
        } //}}}
        
+       //{{{ getVocabCompletions() method
+       /**
+        * Returns all vocabularies whose name starts with
+        * <code>vocab</code>.
+        *
+        * @param anywhere If true, matches anywhere in the word name are
+        * returned; otherwise, only matches from beginning.
+        */
+       public static String[] getVocabCompletions(String vocab, boolean anywhere)
+       {
+               try
+               {
+                       return getExternalInstance().getVocabCompletions(
+                               vocab,anywhere);
+               }
+               catch(Exception e)
+               {
+                       throw new RuntimeException(e);
+               }
+       } //}}}
+       
        //{{{ getWordStartIndex() method
        public static int getWordStartOffset(String line, int caret)
        {
@@ -473,54 +496,127 @@ public class FactorPlugin extends EditPlugin
                }
        } //}}}
 
-       //{{{ insertUse() method
-       public static void insertUse(View view, String vocab)
+       //{{{ findUse() method
+       /**
+        * Find an existing USING: declaration.
+        */
+       private static int findUse(Buffer buffer)
        {
-               if(isUsed(view,vocab))
+               for(int i = 0; i < buffer.getLineCount(); i++)
                {
-                       showStatus(view,"already-used",vocab);
-                       return;
+                       String text = buffer.getLineText(i);
+                       int index = text.indexOf("USING:");
+                       if(index != -1)
+                               return index + "USING:".length();
                }
+               
+               return -1;
+       } //}}}
 
-               Buffer buffer = view.getBuffer();
-               int lastUseOffset = 0;
+       //{{{ createUse() method
+       /**
+        * No USING: declaration exists, so add a new one.
+        */
+       private static void createUse(Buffer buffer, String vocab)
+       {
+               String decl = "USING: " + vocab + " ;";
+
+               int offset = 0;
                boolean leadingNewline = false;
-               boolean seenUse = false;
+               boolean trailingNewline = true;
 
                for(int i = 0; i < buffer.getLineCount(); i++)
                {
                        String text = buffer.getLineText(i).trim();
-                       if(text.startsWith("IN:") || text.startsWith("USE:"))
+                       if(text.startsWith("IN:"))
                        {
-                               lastUseOffset = buffer.getLineEndOffset(i) - 1;
+                               offset = buffer.getLineEndOffset(i) - 1;
                                leadingNewline = true;
-                               seenUse = true;
                        }
-                       else if(text.startsWith("!") && !seenUse)
+                       else if(text.startsWith("!"))
                        {
-                               lastUseOffset = buffer.getLineEndOffset(i) - 1;
+                               offset = buffer.getLineEndOffset(i) - 1;
                                leadingNewline = true;
                        }
-                       else if(text.length() == 0 && !seenUse)
+                       else if(text.length() == 0)
                        {
                                if(i == 0)
-                                       lastUseOffset = 0;
+                                       offset = 0;
                                else
-                                       lastUseOffset  = buffer.getLineEndOffset(i - 1) - 1;
+                                       offset = buffer.getLineEndOffset(i - 1) - 1;
+                               leadingNewline = true;
+                               trailingNewline = false;
                        }
                        else
-                       {
                                break;
-                       }
                }
 
-               String decl = "USE: " + vocab;
-               if(leadingNewline)
-                       decl = "\n" + decl;
-               if(lastUseOffset == 0)
-                       decl = decl + "\n";
-               buffer.insert(lastUseOffset,decl);
-               showStatus(view,"inserted-use",decl);
+               decl = (leadingNewline ? "\n" : "") + decl
+                       + (trailingNewline ? "\n" : "");
+               
+               buffer.insert(offset,decl);
+       } //}}}
+
+       //{{{ updateUse() method
+       private static void updateUse(Buffer buffer, String vocab, int offset)
+       {
+               String text = buffer.getText(0,buffer.getLength());
+               int end = text.indexOf(";",offset);
+               if(end == -1)
+                       end = buffer.getLength();
+
+               String decl = text.substring(offset,end);
+               
+               List declList = new ArrayList();
+               StringTokenizer st = new StringTokenizer(decl);
+               while(st.hasMoreTokens())
+                       declList.add(st.nextToken());
+               declList.add(vocab);
+               Collections.sort(declList);
+               
+               StringBuffer buf = new StringBuffer(" ");
+               Iterator iter = declList.iterator();
+               while(iter.hasNext())
+               {
+                       buf.append(iter.next());
+                       buf.append(' ');
+               }
+
+               /* format() strips trailing whitespace */
+               decl = TextUtilities.format(buf.toString(),
+                       buffer.getIntegerProperty("maxLineLen",64),
+                       buffer.getTabSize()) + " ";
+
+               try
+               {
+                       buffer.beginCompoundEdit();
+                       buffer.remove(offset,end - offset);
+                       buffer.insert(offset,decl);
+               }
+               finally
+               {
+                       buffer.endCompoundEdit();
+               }
+       } //}}}
+       
+       //{{{ insertUse() method
+       public static void insertUse(View view, String vocab)
+       {
+               if(isUsed(view,vocab))
+               {
+                       showStatus(view,"already-used",vocab);
+                       return;
+               }
+
+               Buffer buffer = view.getBuffer();
+               int offset = findUse(buffer);
+
+               if(offset == -1)
+                       createUse(buffer,vocab);
+               else
+                       updateUse(buffer,vocab,offset);
+
+               showStatus(view,"inserted-use",vocab);
        } //}}}
 
        //{{{ extractWord() method
@@ -569,8 +665,16 @@ public class FactorPlugin extends EditPlugin
                try
                {
                        buffer.beginCompoundEdit();
-                       
+
+                       int firstLine = buffer.getLineOfOffset(start);
+
                        buffer.insert(start,newDef);
+                       
+                       int lastLine = buffer.getLineOfOffset(start
+                               + newDef.length());
+                       
+                       buffer.indentLines(firstLine,lastLine);
+                       
                        textArea.setSelectedText(newWord);
                }
                finally
@@ -578,4 +682,27 @@ public class FactorPlugin extends EditPlugin
                        buffer.endCompoundEdit();
                }
        } //}}}
+
+       //{{{ getRulesetAtOffset() method
+       public static String getRulesetAtOffset(JEditTextArea textArea, int caret)
+       {
+               int line = textArea.getLineOfOffset(caret);
+
+               DefaultTokenHandler h = new DefaultTokenHandler();
+               textArea.getBuffer().markTokens(line,h);
+               Token tokens = h.getTokens();
+
+               int offset = caret - textArea.getLineStartOffset(line);
+
+               int len = textArea.getLineLength(line);
+               if(len == 0)
+                       return null;
+
+               if(offset == len)
+                       offset--;
+
+               Token token = TextUtilities.getTokenAtOffset(tokens,offset);
+               
+               return token.rules.getName();
+       } //}}}
 }
index f23e30197081d358e38dc9676a6260b746abcad6..19c7225f67a31a97045173992a862ba87ae002c4 100644 (file)
@@ -62,8 +62,8 @@ factor.completion.def={0} <b>{1}</b>
 factor.completion.stack={0} ( {1})
 
 # Dialog boxes
-factor.status.inserted-use=Inserted {0}
-factor.status.already-used=Already used {0}
+factor.status.inserted-use=Using {0}
+factor.status.already-used=Already using {0}
 
 factor.insert-use.title=Insert USE: Declaration
 factor.insert-use.caption=There are multiple words named "{0}". Select the one to use:
index 95d54fcfb6ed1a730c4c7b585a8f9847c5fa49e5..0b487089595dcfc10249fb51aad3c32a07026ce5 100644 (file)
@@ -250,6 +250,12 @@ public class FactorSideKickParser extends SideKickParser
                if(data == null)
                        return null;
 
+               String ruleset = FactorPlugin.getRulesetAtOffset(
+                       editPane.getTextArea(),caret);
+
+               if(ruleset == null)
+                       return null;
+
                Buffer buffer = editPane.getBuffer();
 
                // first, we get the word before the caret
@@ -283,14 +289,40 @@ public class FactorSideKickParser extends SideKickParser
                if(word.length() == 0)
                        return null;
 
+               if(ruleset.equals("factor::USING"))
+                       return vocabComplete(editPane,data,word,caret);
+               else
+                       return wordComplete(editPane,data,word,caret);
+       } //}}}
+       
+       //{{{ vocabComplete() method
+       private SideKickCompletion vocabComplete(EditPane editPane,
+               FactorParsedData data, String vocab, int caret)
+       {
+               String[] completions = FactorPlugin.getVocabCompletions(
+                       vocab,false);
+
+               if(completions.length == 0)
+                       return null;
+               else
+               {
+                       return new FactorVocabCompletion(editPane.getView(),
+                               completions,vocab,data);
+               }
+       } //}}}
+       
+       //{{{ wordComplete() method
+       private SideKickCompletion wordComplete(EditPane editPane,
+               FactorParsedData data, String word, int caret)
+       {
                FactorWord[] completions = FactorPlugin.toWordArray(
-                       FactorPlugin.getCompletions(word,false));
+                       FactorPlugin.getWordCompletions(word,false));
 
                if(completions.length == 0)
                        return null;
                else
                {
-                       return new FactorCompletion(editPane.getView(),
+                       return new FactorWordCompletion(editPane.getView(),
                                completions,word,data);
                }
        } //}}}
diff --git a/factor/jedit/FactorVocabCompletion.java b/factor/jedit/FactorVocabCompletion.java
new file mode 100644 (file)
index 0000000..6ea308c
--- /dev/null
@@ -0,0 +1,95 @@
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004, 2005 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.*;
+import java.util.*;
+import javax.swing.*;
+import org.gjt.sp.jedit.textarea.*;
+import org.gjt.sp.jedit.*;
+import sidekick.*;
+
+public class FactorVocabCompletion extends AbstractCompletion
+{
+       private String vocab;
+
+       //{{{ FactorVocabCompletion constructor
+       public FactorVocabCompletion(View view, String[] items,
+               String vocab, FactorParsedData data)
+       {
+               super(view,items,data);
+               this.vocab = vocab;
+       } //}}}
+
+       public String getLongestPrefix()
+       {
+               return MiscUtilities.getLongestPrefix(items,false);
+       }
+
+       public void insert(int index)
+       {
+               String selected = ((String)get(index));
+               String insert = selected.substring(vocab.length());
+
+               Buffer buffer = textArea.getBuffer();
+
+               textArea.setSelectedText(insert);
+       }
+
+       public int getTokenLength()
+       {
+               return vocab.length();
+       }
+
+       public boolean handleKeystroke(int selectedIndex, char keyChar)
+       {
+               if(keyChar == '\t' || keyChar == '\n')
+               {
+                       insert(selectedIndex);
+                       return false;
+               }
+               else if(keyChar == ' ')
+               {
+                       insert(selectedIndex);
+                       textArea.userInput(' ');
+                       return false;
+               }
+               else
+               {
+                       textArea.userInput(keyChar);
+                       return true;
+               }
+       }
+
+       public ListCellRenderer getRenderer()
+       {
+               return new DefaultListCellRenderer();
+       }
+}
diff --git a/factor/jedit/FactorWordCompletion.java b/factor/jedit/FactorWordCompletion.java
new file mode 100644 (file)
index 0000000..d6f1e12
--- /dev/null
@@ -0,0 +1,81 @@
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004, 2005 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.*;
+import java.util.*;
+import javax.swing.ListCellRenderer;
+import org.gjt.sp.jedit.textarea.*;
+import org.gjt.sp.jedit.*;
+import sidekick.*;
+
+public class FactorWordCompletion extends AbstractCompletion
+{
+       private String word;
+
+       //{{{ FactorWordCompletion constructor
+       public FactorWordCompletion(View view, FactorWord[] items,
+               String word, FactorParsedData data)
+       {
+               super(view,items,data);
+               this.word = word;
+       } //}}}
+
+       public void insert(int index)
+       {
+               FactorWord selected = ((FactorWord)get(index));
+               String insert = selected.name.substring(word.length());
+
+               Buffer buffer = textArea.getBuffer();
+
+               try
+               {
+                       buffer.beginCompoundEdit();
+                       
+                       textArea.setSelectedText(insert);
+                       if(!FactorPlugin.isUsed(view,selected.vocabulary))
+                               FactorPlugin.insertUse(view,selected.vocabulary);
+               }
+               finally
+               {
+                       buffer.endCompoundEdit();
+               }
+       }
+
+       public int getTokenLength()
+       {
+               return word.length();
+       }
+
+       public ListCellRenderer getRenderer()
+       {
+               return new FactorWordRenderer(data.parser,false);
+       }
+}
index 53ecca3e5f1f0bce7e18288207a60bfe9cbcd6a8..8cc25b8b1c39ee34da4a1d08d74414f65619124d 100644 (file)
@@ -91,26 +91,11 @@ public class WordPreview implements ActionListener, CaretListener
        private FactorWord getWordAtCaret(FactorParsedData fdata)
                throws IOException
        {
-               int line = textArea.getCaretLine();
-               int caret = textArea.getCaretPosition();
-
-               DefaultTokenHandler h = new DefaultTokenHandler();
-               textArea.getBuffer().markTokens(line,h);
-               Token tokens = h.getTokens();
-
-               int offset = caret - textArea.getLineStartOffset(line);
-
-               int len = textArea.getLineLength(line);
-               if(len == 0)
+               String name = FactorPlugin.getRulesetAtOffset(textArea,
+                       textArea.getCaretPosition());
+               if(name == null)
                        return null;
 
-               if(offset == len)
-                       offset--;
-
-               Token token = TextUtilities.getTokenAtOffset(tokens,offset);
-
-               String name = token.rules.getName();
-
                for(int i = 0; i < IGNORED_RULESETS.length; i++)
                {
                        if(name.equals(IGNORED_RULESETS[i]))
index 4befbeabe1351b13140746c5c38e4175d5df5fff..3163403cc0bd3c9f3a9eb78d6e344e927584496f 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005 Slava Pestov.
 ! See http://factor.sf.net/license.txt for BSD license.
 IN: gadgets
-USING: generic kernel lists math namespaces sdl ;
+USING: generic kernel lists math namespaces sdl sdl-ttf ;
 
 ! A label draws a text label, centered on the gadget's bounding
 ! box.
@@ -14,5 +14,12 @@ C: label ( text -- )
 M: label layout* ( label -- )
     [ label-text dup shape-w swap shape-h ] keep resize-gadget ;
 
+: label-x ( label -- x )
+    dup shape-w swap label-text shape-w - 2 /i ;
+
+: label-y ( label -- y )
+    shape-h font get lookup-font TTF_FontHeight - 2 /i ;
+
 M: label draw-shape ( label -- )
-    dup [ label-text draw-shape ] with-translation ;
+    dup label-x over label-y rect> over shape-pos +
+    [ label-text draw-shape ] with-translation ;