code completion filtering and text substitution by confirming
authorMartin Fousek <marfous@netbeans.org>
Fri, 11 Jun 2010 15:27:20 +0200
changeset 163287074d66bc2f1
parent 16327 c742b6c9bc54
child 16329 8ea9eb7f219b
code completion filtering and text substitution by confirming
php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/CodeCompletionUtils.java
php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionItem.java
php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionProvider.java
php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionQuery.java
php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/entries/SmartyCodeCompletionOffer.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/CodeCompletionUtils.java	Fri Jun 11 15:27:20 2010 +0200
     1.3 @@ -0,0 +1,84 @@
     1.4 +/*
     1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 + *
     1.7 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
     1.8 + *
     1.9 + * The contents of this file are subject to the terms of either the GNU
    1.10 + * General Public License Version 2 only ("GPL") or the Common
    1.11 + * Development and Distribution License("CDDL") (collectively, the
    1.12 + * "License"). You may not use this file except in compliance with the
    1.13 + * License. You can obtain a copy of the License at
    1.14 + * http://www.netbeans.org/cddl-gplv2.html
    1.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.16 + * specific language governing permissions and limitations under the
    1.17 + * License.  When distributing the software, include this License Header
    1.18 + * Notice in each file and include the License file at
    1.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    1.20 + * particular file as subject to the "Classpath" exception as provided
    1.21 + * by Sun in the GPL Version 2 section of the License file that
    1.22 + * accompanied this code. If applicable, add the following below the
    1.23 + * License Header, with the fields enclosed by brackets [] replaced by
    1.24 + * your own identifying information:
    1.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    1.26 + *
    1.27 + * If you wish your version of this file to be governed by only the CDDL
    1.28 + * or only the GPL Version 2, indicate your decision by adding
    1.29 + * "[Contributor] elects to include this software in this distribution
    1.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.31 + * single choice of license, a recipient has the option to distribute
    1.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    1.33 + * to extend the choice of license to its licensees as provided above.
    1.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    1.35 + * Version 2 license, then the option applies only if the new code is
    1.36 + * made subject to such option by the copyright holder.
    1.37 + *
    1.38 + * Contributor(s):
    1.39 + *
    1.40 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
    1.41 + */
    1.42 +
    1.43 +package org.netbeans.modules.php.smarty.editor.completion;
    1.44 +
    1.45 +import java.util.Locale;
    1.46 +import javax.swing.text.BadLocationException;
    1.47 +import javax.swing.text.Document;
    1.48 +import org.netbeans.modules.php.smarty.editor.utlis.LexerUtils;
    1.49 +import org.openide.util.Exceptions;
    1.50 +
    1.51 +/**
    1.52 + *
    1.53 + * @author Martin Fousek
    1.54 + */
    1.55 +public class CodeCompletionUtils {
    1.56 +
    1.57 +    private static final int COMPLETION_MAX_FILTER_LENGHT = 20;
    1.58 +
    1.59 +    public static String getTextPrefix(Document doc, int offset) {
    1.60 +        int readLength = (COMPLETION_MAX_FILTER_LENGHT > offset) ? offset : COMPLETION_MAX_FILTER_LENGHT;
    1.61 +        try {
    1.62 +            int lastWS = getLastWS(doc.getText(offset - readLength, readLength));
    1.63 +            return doc.getText(offset - lastWS, lastWS);
    1.64 +        } catch (BadLocationException ex) {
    1.65 +            Exceptions.printStackTrace(ex);
    1.66 +        }
    1.67 +        return "";
    1.68 +    }
    1.69 +
    1.70 +    public static int getSubstitutionLenght(Document doc, int offset) {
    1.71 +        return getTextPrefix(doc, offset).length();
    1.72 +    }
    1.73 +
    1.74 +    public static int getLastWS(String area) {
    1.75 +        for (int i = area.length()-1; i >= 0; i--) {
    1.76 +            if (LexerUtils.isWS(area.charAt(i))) {
    1.77 +                return area.length()-i-1;
    1.78 +            }
    1.79 +        }
    1.80 +        return area.length();
    1.81 +    }
    1.82 +
    1.83 +    public static boolean startsWithIgnoreCase(String text, String prefix) {
    1.84 +        return text.toLowerCase(Locale.ENGLISH).startsWith(prefix.toLowerCase(Locale.ENGLISH));
    1.85 +    }
    1.86 +
    1.87 +}
     2.1 --- a/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionItem.java	Thu Jun 10 16:12:22 2010 +0200
     2.2 +++ b/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionItem.java	Fri Jun 11 15:27:20 2010 +0200
     2.3 @@ -67,17 +67,15 @@
     2.4      protected static final int DEFAULT_SORT_PRIORITY = 22;
     2.5  
     2.6      //------------------------------------------
     2.7 -    protected int substitutionOffset;
     2.8      protected String text, help, helpUrl;
     2.9      protected boolean shift;
    2.10  
    2.11 -    protected TplCompletionItem(String text, int substituteOffset) {
    2.12 -        this.substitutionOffset = substituteOffset;
    2.13 +    protected TplCompletionItem(String text) {
    2.14          this.text = text;
    2.15      }
    2.16  
    2.17 -    protected TplCompletionItem(String text, int substituteOffset, String help, String helpUrl) {
    2.18 -        this(text, substituteOffset);
    2.19 +    protected TplCompletionItem(String text, String help, String helpUrl) {
    2.20 +        this(text);
    2.21          this.help = help;
    2.22          this.helpUrl = helpUrl;
    2.23      }
    2.24 @@ -113,7 +111,7 @@
    2.25                  Completion.get().hideCompletion();
    2.26              }
    2.27              int caretOffset = component.getSelectionEnd();
    2.28 -            substituteText(component, caretOffset - substitutionOffset);
    2.29 +            substituteText(component, CodeCompletionUtils.getSubstitutionLenght(component.getDocument(), component.getCaretPosition()));
    2.30          }
    2.31  
    2.32      }
    2.33 @@ -147,6 +145,7 @@
    2.34  
    2.35              public void run() {
    2.36                  try {
    2.37 +                    int substitutionOffset = c.getCaretPosition() - CodeCompletionUtils.getSubstitutionLenght(c.getDocument(), c.getCaretPosition());
    2.38                      //test whether we are trying to insert sg. what is already present in the text
    2.39                      String currentText = doc.getText(substitutionOffset, (doc.getLength() - substitutionOffset) < substituteText.length() ? (doc.getLength() - substitutionOffset) : substituteText.length());
    2.40                      if (!substituteText.equals(currentText)) {
    2.41 @@ -203,6 +202,7 @@
    2.42      public boolean instantSubstitution(JTextComponent component) {
    2.43          if (component != null) {
    2.44              try {
    2.45 +                int substitutionOffset = CodeCompletionUtils.getSubstitutionLenght(component.getDocument(), component.getCaretPosition());
    2.46                  int caretOffset = component.getSelectionEnd();
    2.47                  if (caretOffset > substitutionOffset) {
    2.48                      String currentText = component.getDocument().getText(substitutionOffset, caretOffset - substitutionOffset);
    2.49 @@ -275,8 +275,8 @@
    2.50  
    2.51          protected static final String BUILT_IN_FUNC_COLOR = "529854";
    2.52  
    2.53 -        public BuiltInFunctionsCompletionItem(String value, int offset, String help, String helpUrl) {
    2.54 -            super(value, offset, help, helpUrl);
    2.55 +        public BuiltInFunctionsCompletionItem(String value, String help, String helpUrl) {
    2.56 +            super(value, help, helpUrl);
    2.57          }
    2.58  
    2.59          @Override
    2.60 @@ -295,8 +295,8 @@
    2.61  
    2.62          protected static final String CUSTOM_FUNC_COLOR = "3B713B";
    2.63  
    2.64 -        public CustomFunctionsCompletionItem(String value, int offset, String help, String helpUrl) {
    2.65 -            super(value, offset, help, helpUrl);
    2.66 +        public CustomFunctionsCompletionItem(String value, String help, String helpUrl) {
    2.67 +            super(value, help, helpUrl);
    2.68          }
    2.69  
    2.70          @Override
    2.71 @@ -310,8 +310,8 @@
    2.72  
    2.73          protected static final String ATTR_NAME_COLOR = hexColorCode(Color.blue.darker());
    2.74  
    2.75 -        public VariableModifiersCompletionItem(String value, int offset, String help, String helpUrl) {
    2.76 -            super(value, offset, help, helpUrl);
    2.77 +        public VariableModifiersCompletionItem(String value, String help, String helpUrl) {
    2.78 +            super(value, help, helpUrl);
    2.79          }
    2.80  
    2.81          @Override
     3.1 --- a/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionProvider.java	Thu Jun 10 16:12:22 2010 +0200
     3.2 +++ b/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionProvider.java	Fri Jun 11 15:27:20 2010 +0200
     3.3 @@ -42,15 +42,10 @@
     3.4  
     3.5  import java.util.Collection;
     3.6  import java.util.Collections;
     3.7 -import java.util.Locale;
     3.8  import java.net.URL;
     3.9  import javax.swing.Action;
    3.10 -import javax.swing.text.BadLocationException;
    3.11  import javax.swing.text.Document;
    3.12  import javax.swing.text.JTextComponent;
    3.13 -import org.netbeans.api.editor.completion.Completion;
    3.14 -import org.netbeans.api.html.lexer.HTMLTokenId;
    3.15 -import org.netbeans.api.lexer.Token;
    3.16  import org.netbeans.api.lexer.TokenHierarchy;
    3.17  import org.netbeans.api.lexer.TokenSequence;
    3.18  import org.netbeans.editor.BaseDocument;
    3.19 @@ -63,7 +58,6 @@
    3.20  import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
    3.21  import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
    3.22  import org.openide.util.Exceptions;
    3.23 -import org.openide.util.NbBundle;
    3.24  
    3.25  /**
    3.26   * Implementation of {@link CompletionProvider} for Tpl documents.
    3.27 @@ -94,7 +88,6 @@
    3.28  
    3.29      private static class Query extends AbstractQuery {
    3.30  
    3.31 -        private int anchor;
    3.32          private volatile Collection<? extends CompletionItem> items =  Collections.<CompletionItem>emptyList();
    3.33          private JTextComponent component;
    3.34  
    3.35 @@ -121,62 +114,34 @@
    3.36  
    3.37          @Override
    3.38          protected boolean canFilter(JTextComponent component) {
    3.39 -            try {
    3.40 -                Document doc = component.getDocument();
    3.41 -                int offset = component.getCaretPosition();
    3.42 -                if(offset < anchor) {
    3.43 -                    return false;
    3.44 -                }
    3.45 +            String prefix = CodeCompletionUtils.getTextPrefix(component.getDocument(), component.getCaretPosition());
    3.46  
    3.47 -                String prefix = doc.getText(anchor, offset - anchor);
    3.48 -
    3.49 -                //check the items
    3.50 -                for(CompletionItem item : items) {
    3.51 -                    if(item instanceof TplCompletionItem) {
    3.52 -                        if(startsWithIgnoreCase( ((TplCompletionItem)item).getItemText(), prefix)) {
    3.53 -                            return true; //at least one item will remain
    3.54 -                        }
    3.55 +            //check the items
    3.56 +            for(CompletionItem item : items) {
    3.57 +                if(item instanceof TplCompletionItem) {
    3.58 +                    if(CodeCompletionUtils.startsWithIgnoreCase( ((TplCompletionItem)item).getItemText(), prefix)) {
    3.59 +                        return true; //at least one item will remain
    3.60                      }
    3.61                  }
    3.62 -
    3.63 -
    3.64 -            } catch (BadLocationException ex) {
    3.65 -                Exceptions.printStackTrace(ex);
    3.66              }
    3.67  
    3.68              return false;
    3.69 -
    3.70          }
    3.71  
    3.72          @Override
    3.73          protected void filter(CompletionResultSet resultSet) {
    3.74 -            try {
    3.75 -                Document doc = component.getDocument();
    3.76 -                int offset = component.getCaretPosition();
    3.77 -                String prefix = doc.getText(anchor, offset - anchor);
    3.78 +            String prefix = CodeCompletionUtils.getTextPrefix(component.getDocument(), component.getCaretPosition());
    3.79  
    3.80 -                //check the items
    3.81 -                for(CompletionItem item : items) {
    3.82 -                    if(item instanceof TplCompletionItem) {
    3.83 -                        if(startsWithIgnoreCase(((TplCompletionItem)item).getItemText(), prefix)) {
    3.84 -                            resultSet.addItem(item);
    3.85 -                        }
    3.86 +            //check the items
    3.87 +            for(CompletionItem item : items) {
    3.88 +                if(item instanceof TplCompletionItem) {
    3.89 +                    if(CodeCompletionUtils.startsWithIgnoreCase(((TplCompletionItem)item).getItemText(), prefix)) {
    3.90 +                        resultSet.addItem(item);
    3.91                      }
    3.92                  }
    3.93 -
    3.94 -            } catch (BadLocationException ex) {
    3.95 -                Exceptions.printStackTrace(ex);
    3.96 -            } finally {
    3.97 -                resultSet.setAnchorOffset(anchor);
    3.98 -                resultSet.finish();
    3.99              }
   3.100 -
   3.101 +            resultSet.finish();
   3.102          }
   3.103 -
   3.104 -        private static boolean startsWithIgnoreCase(String text, String prefix) {
   3.105 -            return text.toLowerCase(Locale.ENGLISH).startsWith(prefix.toLowerCase(Locale.ENGLISH));
   3.106 -        }
   3.107 -
   3.108      }
   3.109  
   3.110      public static class DocQuery extends AbstractQuery {
   3.111 @@ -409,10 +374,6 @@
   3.112  
   3.113          @Override
   3.114          public CompletionDocumentation resolveLink(String link) {
   3.115 -//            URL itemUrl = HelpManager.getDefault().getHelpURL(item.getHelpId());
   3.116 -//            return itemUrl != null ?
   3.117 -//                new LinkDocItem(HelpManager.getDefault().getRelativeURL(itemUrl, link)) :
   3.118 -//                new NoDocItem();
   3.119              return null;
   3.120          }
   3.121  
     4.1 --- a/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionQuery.java	Thu Jun 10 16:12:22 2010 +0200
     4.2 +++ b/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/TplCompletionQuery.java	Fri Jun 11 15:27:20 2010 +0200
     4.3 @@ -41,19 +41,15 @@
     4.4  package org.netbeans.modules.php.smarty.editor.completion;
     4.5  
     4.6  import java.util.*;
     4.7 -import java.util.Collections;
     4.8  import javax.swing.text.Document;
     4.9 -import org.netbeans.modules.csl.api.DataLoadersBridge;
    4.10  import org.netbeans.modules.parsing.api.ParserManager;
    4.11  import org.netbeans.modules.parsing.api.ResultIterator;
    4.12  import org.netbeans.modules.parsing.api.Snapshot;
    4.13  import org.netbeans.modules.parsing.api.Source;
    4.14  import org.netbeans.modules.parsing.api.UserTask;
    4.15  import org.netbeans.modules.parsing.spi.ParseException;
    4.16 -import org.netbeans.modules.php.smarty.editor.completion.entries.CodeCompletionEntryMetadata;
    4.17  import org.netbeans.modules.php.smarty.editor.completion.entries.SmartyCodeCompletionOffer;
    4.18  import org.netbeans.spi.editor.completion.CompletionItem;
    4.19 -import org.openide.filesystems.FileObject;
    4.20  
    4.21  /**
    4.22   *
    4.23 @@ -64,14 +60,12 @@
    4.24  public class TplCompletionQuery extends UserTask {
    4.25  
    4.26      private Document document;
    4.27 -    private FileObject file;
    4.28      private int offset;
    4.29      private CompletionResult completionResult;
    4.30  
    4.31      public TplCompletionQuery(Document document, int offset) {
    4.32          this.document = document;
    4.33          this.offset = offset;
    4.34 -        this.file = DataLoadersBridge.getDefault().getFileObject(document);
    4.35      }
    4.36  
    4.37      public CompletionResult query() throws ParseException {
    4.38 @@ -108,4 +102,3 @@
    4.39          }
    4.40      }
    4.41  }
    4.42 -
     5.1 --- a/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/entries/SmartyCodeCompletionOffer.java	Thu Jun 10 16:12:22 2010 +0200
     5.2 +++ b/php.smarty/src/org/netbeans/modules/php/smarty/editor/completion/entries/SmartyCodeCompletionOffer.java	Fri Jun 11 15:27:20 2010 +0200
     5.3 @@ -69,17 +69,17 @@
     5.4              Collection<CodeCompletionEntryMetadata> ccList = parseCCData(completionType);
     5.5              if (completionType.equals("built-in-functions") ) {
     5.6                  for (CodeCompletionEntryMetadata entryMetadata : ccList) {
     5.7 -                    completionItems.add(new BuiltInFunctionsCompletionItem(entryMetadata.getKeyword(), 0, entryMetadata.getHelp(), entryMetadata.getHelpUrl()));
     5.8 +                    completionItems.add(new BuiltInFunctionsCompletionItem(entryMetadata.getKeyword(), entryMetadata.getHelp(), entryMetadata.getHelpUrl()));
     5.9                  }
    5.10              }
    5.11              else if (completionType.equals("custom-functions")) {
    5.12                  for (CodeCompletionEntryMetadata entryMetadata : ccList) {
    5.13 -                    completionItems.add(new CustomFunctionsCompletionItem(entryMetadata.getKeyword(), 0, entryMetadata.getHelp(), entryMetadata.getHelpUrl()));
    5.14 +                    completionItems.add(new CustomFunctionsCompletionItem(entryMetadata.getKeyword(), entryMetadata.getHelp(), entryMetadata.getHelpUrl()));
    5.15                  }
    5.16              }
    5.17              else if (completionType.equals("variable-modifiers")) {
    5.18                  for (CodeCompletionEntryMetadata entryMetadata : ccList) {
    5.19 -                    completionItems.add(new VariableModifiersCompletionItem(entryMetadata.getKeyword(), 0, entryMetadata.getHelp(), entryMetadata.getHelpUrl()));
    5.20 +                    completionItems.add(new VariableModifiersCompletionItem(entryMetadata.getKeyword(), entryMetadata.getHelp(), entryMetadata.getHelpUrl()));
    5.21                  }
    5.22              }
    5.23          }