From e92757e93ceffe213ef5395206da46723917e125 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 17 Feb 2005 02:54:36 +0000 Subject: [PATCH] working on jEdit plugin --- TODO.FACTOR.txt | 6 +- factor/DefaultVocabularyLookup.java | 61 +++-- factor/ExternalFactor.java | 6 +- factor/VocabularyLookup.java | 12 +- factor/jedit/AbstractCompletion.java | 81 +++++++ factor/jedit/EditWordDialog.java | 2 +- factor/jedit/FactorPlugin.java | 209 ++++++++++++++---- factor/jedit/FactorPlugin.props | 4 +- factor/jedit/FactorSideKickParser.java | 38 +++- factor/jedit/FactorVocabCompletion.java | 95 ++++++++ ...pletion.java => FactorWordCompletion.java} | 41 +--- factor/jedit/WordPreview.java | 21 +- library/ui/labels.factor | 11 +- 13 files changed, 460 insertions(+), 127 deletions(-) create mode 100644 factor/jedit/AbstractCompletion.java create mode 100644 factor/jedit/FactorVocabCompletion.java rename factor/jedit/{FactorCompletion.java => FactorWordCompletion.java} (73%) diff --git a/TODO.FACTOR.txt b/TODO.FACTOR.txt index 3d4a59d61a..4ec2f1a8e7 100644 --- a/TODO.FACTOR.txt +++ b/TODO.FACTOR.txt @@ -3,10 +3,7 @@ - [ [ dup call ] dup call ] infer hangs - move tuple to generic vocab - update plugin docs -- extract word keeps indent - word preview for remote words -- support USING: -- special completion for USE:/IN: - vectors: ensure its ok with bignum indices - code gc - type inference fails with some assembler words; @@ -14,10 +11,11 @@ not cons, and need stronger branch partial eval - print warning on null class - optimize away dispatch -- alignment of gadgets inside their bounding boxes needs thought - faster completion - ppc register decls +- extract word inside M:, C:, and structure browsing for these +- fix checkbox alignment - begin-scan, next-object, end-scan primitives - each-object, each-slot combinators - port leak diff --git a/factor/DefaultVocabularyLookup.java b/factor/DefaultVocabularyLookup.java index 3561609c92..5035fa1354 100644 --- a/factor/DefaultVocabularyLookup.java +++ b/factor/DefaultVocabularyLookup.java @@ -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 { diff --git a/factor/ExternalFactor.java b/factor/ExternalFactor.java index 78b5779ae9..4d825452d1 100644 --- a/factor/ExternalFactor.java +++ b/factor/ExternalFactor.java @@ -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; diff --git a/factor/VocabularyLookup.java b/factor/VocabularyLookup.java index 31b4f85c9b..4047cff4b2 100644 --- a/factor/VocabularyLookup.java +++ b/factor/VocabularyLookup.java @@ -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 index 0000000000..bf5eeaea39 --- /dev/null +++ b/factor/jedit/AbstractCompletion.java @@ -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; + } + } //}}} +} diff --git a/factor/jedit/EditWordDialog.java b/factor/jedit/EditWordDialog.java index cae245698b..912bc3d609 100644 --- a/factor/jedit/EditWordDialog.java +++ b/factor/jedit/EditWordDialog.java @@ -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/FactorPlugin.java b/factor/jedit/FactorPlugin.java index 67c4791adc..9d4756ef1f 100644 --- a/factor/jedit/FactorPlugin.java +++ b/factor/jedit/FactorPlugin.java @@ -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 + * word. * * @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 + * vocab. + * + * @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,6 +496,109 @@ public class FactorPlugin extends EditPlugin } } //}}} + //{{{ findUse() method + /** + * Find an existing USING: declaration. + */ + private static int findUse(Buffer buffer) + { + for(int i = 0; i < buffer.getLineCount(); i++) + { + String text = buffer.getLineText(i); + int index = text.indexOf("USING:"); + if(index != -1) + return index + "USING:".length(); + } + + return -1; + } //}}} + + //{{{ 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 trailingNewline = true; + + for(int i = 0; i < buffer.getLineCount(); i++) + { + String text = buffer.getLineText(i).trim(); + if(text.startsWith("IN:")) + { + offset = buffer.getLineEndOffset(i) - 1; + leadingNewline = true; + } + else if(text.startsWith("!")) + { + offset = buffer.getLineEndOffset(i) - 1; + leadingNewline = true; + } + else if(text.length() == 0) + { + if(i == 0) + offset = 0; + else + offset = buffer.getLineEndOffset(i - 1) - 1; + leadingNewline = true; + trailingNewline = false; + } + else + break; + } + + 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) { @@ -483,44 +609,14 @@ public class FactorPlugin extends EditPlugin } Buffer buffer = view.getBuffer(); - int lastUseOffset = 0; - boolean leadingNewline = false; - boolean seenUse = false; + int offset = findUse(buffer); - for(int i = 0; i < buffer.getLineCount(); i++) - { - String text = buffer.getLineText(i).trim(); - if(text.startsWith("IN:") || text.startsWith("USE:")) - { - lastUseOffset = buffer.getLineEndOffset(i) - 1; - leadingNewline = true; - seenUse = true; - } - else if(text.startsWith("!") && !seenUse) - { - lastUseOffset = buffer.getLineEndOffset(i) - 1; - leadingNewline = true; - } - else if(text.length() == 0 && !seenUse) - { - if(i == 0) - lastUseOffset = 0; - else - lastUseOffset = buffer.getLineEndOffset(i - 1) - 1; - } - else - { - break; - } - } + if(offset == -1) + createUse(buffer,vocab); + else + updateUse(buffer,vocab,offset); - String decl = "USE: " + vocab; - if(leadingNewline) - decl = "\n" + decl; - if(lastUseOffset == 0) - decl = decl + "\n"; - buffer.insert(lastUseOffset,decl); - showStatus(view,"inserted-use",decl); + 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(); + } //}}} } diff --git a/factor/jedit/FactorPlugin.props b/factor/jedit/FactorPlugin.props index f23e301970..19c7225f67 100644 --- a/factor/jedit/FactorPlugin.props +++ b/factor/jedit/FactorPlugin.props @@ -62,8 +62,8 @@ factor.completion.def={0} {1} 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: diff --git a/factor/jedit/FactorSideKickParser.java b/factor/jedit/FactorSideKickParser.java index 95d54fcfb6..0b48708959 100644 --- a/factor/jedit/FactorSideKickParser.java +++ b/factor/jedit/FactorSideKickParser.java @@ -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; - FactorWord[] completions = FactorPlugin.toWordArray( - FactorPlugin.getCompletions(word,false)); + 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 FactorCompletion(editPane.getView(), + 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.getWordCompletions(word,false)); + + if(completions.length == 0) + return null; + else + { + return new FactorWordCompletion(editPane.getView(), completions,word,data); } } //}}} diff --git a/factor/jedit/FactorVocabCompletion.java b/factor/jedit/FactorVocabCompletion.java new file mode 100644 index 0000000000..6ea308c0f7 --- /dev/null +++ b/factor/jedit/FactorVocabCompletion.java @@ -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/FactorCompletion.java b/factor/jedit/FactorWordCompletion.java similarity index 73% rename from factor/jedit/FactorCompletion.java rename to factor/jedit/FactorWordCompletion.java index 7807fa5224..d6f1e12ec4 100644 --- a/factor/jedit/FactorCompletion.java +++ b/factor/jedit/FactorWordCompletion.java @@ -3,7 +3,7 @@ /* * $Id$ * - * Copyright (C) 2004 Slava Pestov. + * 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: @@ -36,29 +36,18 @@ import org.gjt.sp.jedit.textarea.*; import org.gjt.sp.jedit.*; import sidekick.*; -public class FactorCompletion extends SideKickCompletion +public class FactorWordCompletion extends AbstractCompletion { - private View view; - private JEditTextArea textArea; private String word; - private FactorParsedData data; - //{{{ FactorCompletion constructor - public FactorCompletion(View view, FactorWord[] items, + //{{{ FactorWordCompletion constructor + public FactorWordCompletion(View view, FactorWord[] items, String word, FactorParsedData data) { - this.view = view; - textArea = view.getTextArea(); - this.items = Arrays.asList(items); + super(view,items,data); this.word = word; - this.data = data; } //}}} - public String getLongestPrefix() - { - return MiscUtilities.getLongestPrefix(items,false); - } - public void insert(int index) { FactorWord selected = ((FactorWord)get(index)); @@ -85,26 +74,6 @@ public class FactorCompletion extends SideKickCompletion 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); diff --git a/factor/jedit/WordPreview.java b/factor/jedit/WordPreview.java index 53ecca3e5f..8cc25b8b1c 100644 --- a/factor/jedit/WordPreview.java +++ b/factor/jedit/WordPreview.java @@ -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])) diff --git a/library/ui/labels.factor b/library/ui/labels.factor index 4befbeabe1..3163403cc0 100644 --- a/library/ui/labels.factor +++ b/library/ui/labels.factor @@ -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 ;