diff --git a/java.editor/src/org/netbeans/modules/editor/java/Utilities.java b/java.editor/src/org/netbeans/modules/editor/java/Utilities.java --- a/java.editor/src/org/netbeans/modules/editor/java/Utilities.java +++ b/java.editor/src/org/netbeans/modules/editor/java/Utilities.java @@ -60,6 +60,7 @@ import com.sun.source.util.TreePath; import com.sun.source.util.TreePathScanner; import com.sun.source.util.Trees; +import java.text.*; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -113,6 +114,7 @@ private static boolean guessMethodArguments = true; private static boolean autoPopupOnJavaIdentifierPart = true; private static boolean javaCompletionExcluderMethods; + private static boolean javaCompletionSubwords=CodeCompletionPanel.JAVA_AUTO_COMPLETION_SUBWORDS_DEFAULT; private static String javaCompletionAutoPopupTriggers = null; private static String javaCompletionSelectors = null; private static String javadocCompletionAutoPopupTriggers = null; @@ -155,6 +157,9 @@ if (settingName == null || CodeCompletionPanel.JAVA_COMPLETION_EXCLUDER_METHODS.equals(settingName)) { javaCompletionExcluderMethods = preferences.getBoolean(CodeCompletionPanel.JAVA_COMPLETION_EXCLUDER_METHODS, CodeCompletionPanel.JAVA_COMPLETION_EXCLUDER_METHODS_DEFAULT); } + if (settingName == null || CodeCompletionPanel.JAVA_AUTO_COMPLETION_SUBWORDS.equals(settingName)) { + javaCompletionSubwords = preferences.getBoolean(CodeCompletionPanel.JAVA_AUTO_COMPLETION_SUBWORDS, CodeCompletionPanel.JAVA_AUTO_COMPLETION_SUBWORDS_DEFAULT); + } } }; @@ -166,6 +171,43 @@ return false; if (prefix == null || prefix.length() == 0) return true; + + // sub word completion + if (javaCompletionSubwords) + { + // example: + // 'out' produces '.*?[o|O].*?[u|U].*?[t|T].*?' + // org.openide.util.Utilities.acoh -> actionsForPath + // java.lang.System.out -> setOut + // argex -> IllegalArgumentException + // java.util.Collections.que -> asLifoQueue + // java.lang.System.sin -> setIn, getSecurityManager, setSecurityManager + + // check whether user input matches the regex + StringBuilder sb = new StringBuilder(3+8*prefix.length()); + sb.append(".*?"); + for (int i = 0; i < prefix.length(); i++) { + char charAt = prefix.charAt(i); + if (Character.isLowerCase(charAt)) { + sb.append("["); + sb.append(charAt); + sb.append(Character.toUpperCase(charAt)); + sb.append("]"); + } else { + //keep uppercase characters as beacons + // for example: java.lang.System.sIn -> setIn + sb.append(charAt); + } + sb.append(".*?"); + } + + // System.out.println(sb); + // FIXME regex matches are expensive + if (Pattern.compile(sb.toString()).matcher(theString).matches()) { + return true; + }; + } + return isCaseSensitive() ? theString.startsWith(prefix) : theString.toLowerCase(Locale.ENGLISH).startsWith(prefix.toLowerCase(Locale.ENGLISH)); } diff --git a/java.editor/src/org/netbeans/modules/java/editor/options/Bundle.properties b/java.editor/src/org/netbeans/modules/java/editor/options/Bundle.properties --- a/java.editor/src/org/netbeans/modules/java/editor/options/Bundle.properties +++ b/java.editor/src/org/netbeans/modules/java/editor/options/Bundle.properties @@ -170,3 +170,4 @@ ACSD_CancelButton=Cancels dialog ACSD_OKButton=Confirms dialog ExcluderDialogTitle=Add/Edit excluded pattern +CodeCompletionPanel.javaAutoCompletionSubwords.text=Subword completion diff --git a/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.form b/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.form --- a/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.form +++ b/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.form @@ -164,9 +164,10 @@ - + + @@ -220,7 +221,9 @@ - + + + @@ -247,7 +250,7 @@ - + @@ -552,6 +555,16 @@ + + + + + + + + + + diff --git a/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.java b/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.java --- a/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.java +++ b/java.editor/src/org/netbeans/modules/java/editor/options/CodeCompletionPanel.java @@ -78,6 +78,8 @@ public static final String JAVA_COMPLETION_BLACKLIST_DEFAULT = ""; //NOI18N public static final String JAVA_COMPLETION_EXCLUDER_METHODS = "javaCompletionExcluderMethods"; //NOI18N public static final boolean JAVA_COMPLETION_EXCLUDER_METHODS_DEFAULT = false; + public static final String JAVA_AUTO_COMPLETION_SUBWORDS = "javaCompletionSubwords"; //NOI18N + public static final boolean JAVA_AUTO_COMPLETION_SUBWORDS_DEFAULT = false; private static final String JAVA_FQN_REGEX = "[$\\p{L}\\p{Digit}._]*"; //NOI18N @@ -94,6 +96,7 @@ javaAutoPopupOnIdentifierPart.setSelected(preferences.getBoolean(JAVA_AUTO_POPUP_ON_IDENTIFIER_PART, JAVA_AUTO_POPUP_ON_IDENTIFIER_PART_DEFAULT)); javaAutoCompletionTriggersField.setText(preferences.get(JAVA_AUTO_COMPLETION_TRIGGERS, JAVA_AUTO_COMPLETION_TRIGGERS_DEFAULT)); javaCompletionSelectorsField.setText(preferences.get(JAVA_COMPLETION_SELECTORS, JAVA_COMPLETION_SELECTORS_DEFAULT)); + javaAutoCompletionSubwords.setSelected(preferences.getBoolean(JAVA_AUTO_COMPLETION_SUBWORDS, JAVA_AUTO_COMPLETION_SUBWORDS_DEFAULT)); javadocAutoCompletionTriggersField.setText(preferences.get(JAVADOC_AUTO_COMPLETION_TRIGGERS, JAVADOC_AUTO_COMPLETION_TRIGGERS_DEFAULT)); String blacklist = preferences.get(JAVA_COMPLETION_BLACKLIST, JAVA_COMPLETION_BLACKLIST_DEFAULT); initExcluderList(javaCompletionExcludeJlist, blacklist); @@ -182,6 +185,7 @@ jSeparator1 = new javax.swing.JSeparator(); javaCompletionExcluderLabel = new javax.swing.JLabel(); jSeparator2 = new javax.swing.JSeparator(); + javaAutoCompletionSubwords = new javax.swing.JCheckBox(); javaCompletionExcluderDialog2.setTitle(org.openide.util.NbBundle.getMessage(CodeCompletionPanel.class, "ExcluderDialogTitle")); // NOI18N javaCompletionExcluderDialog2.setModal(true); @@ -216,8 +220,8 @@ .addGroup(javaCompletionExcluderDialog2Layout.createSequentialGroup() .addContainerGap() .addGroup(javaCompletionExcluderDialog2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent( javaCompletionExcluderDialogLabel, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE) - .addComponent( javaCompletionExcluderDialogTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)) + .addComponent(javaCompletionExcluderDialogLabel, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE) + .addComponent(javaCompletionExcluderDialogTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(javaCompletionExcluderDialog2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(javaCompletionExcluderDialogOkButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) @@ -230,7 +234,7 @@ .addGroup(javaCompletionExcluderDialog2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javaCompletionExcluderDialog2Layout.createSequentialGroup() .addContainerGap() - .addComponent(javaCompletionExcluderDialogLabel) + .addComponent(javaCompletionExcluderDialogLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(javaCompletionExcluderDialog2Layout.createSequentialGroup() .addContainerGap() @@ -328,6 +332,13 @@ javaCompletionExcluderLabel.setLabelFor(javaCompletionExcluderTab); org.openide.awt.Mnemonics.setLocalizedText(javaCompletionExcluderLabel, org.openide.util.NbBundle.getMessage(CodeCompletionPanel.class, "CodeCompletionPanel.javaCompletionExcluderLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(javaAutoCompletionSubwords, org.openide.util.NbBundle.getMessage(CodeCompletionPanel.class, "CodeCompletionPanel.javaAutoCompletionSubwords.text")); // NOI18N + javaAutoCompletionSubwords.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + javaAutoCompletionSubwordsActionPerformed(evt); + } + }); + javax.swing.GroupLayout javaCompletionPaneLayout = new javax.swing.GroupLayout(javaCompletionPane); javaCompletionPane.setLayout(javaCompletionPaneLayout); javaCompletionPaneLayout.setHorizontalGroup( @@ -335,9 +346,10 @@ .addGroup(javaCompletionPaneLayout.createSequentialGroup() .addContainerGap() .addGroup(javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(javaAutoCompletionSubwords) .addGroup(javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent( javaCompletionExcluderLabel, javax.swing.GroupLayout.Alignment.LEADING) - .addComponent( jSeparator2, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(javaCompletionExcluderLabel, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, javaCompletionPaneLayout.createSequentialGroup() .addGap(6, 6, 6) .addGroup(javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -372,12 +384,14 @@ .addGap(213, 213, 213))) ); - javaCompletionPaneLayout.linkSize( javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[]{javaCompletionExcluderAddButton, javaCompletionExcluderEditButton, javaCompletionExcluderRemoveButton}); + javaCompletionPaneLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {javaCompletionExcluderAddButton, javaCompletionExcluderEditButton, javaCompletionExcluderRemoveButton}); javaCompletionPaneLayout.setVerticalGroup( javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javaCompletionPaneLayout.createSequentialGroup() - .addGap(132, 132, 132) + .addGap(102, 102, 102) + .addComponent(javaAutoCompletionSubwords) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -400,7 +414,7 @@ .addGroup(javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(javadocAutoCompletionTriggersLabel) .addComponent(javadocAutoCompletionTriggersField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(20, Short.MAX_VALUE)) .addGroup(javaCompletionPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javaCompletionPaneLayout.createSequentialGroup() .addContainerGap() @@ -534,6 +548,10 @@ } }//GEN-LAST:event_javaCompletionExcluderDialogTextFieldKeyTyped + private void javaAutoCompletionSubwordsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_javaAutoCompletionSubwordsActionPerformed + preferences.putBoolean(JAVA_AUTO_COMPLETION_SUBWORDS, javaAutoCompletionSubwords.isSelected()); + }//GEN-LAST:event_javaAutoCompletionSubwordsActionPerformed + private void update(DocumentEvent e) { if (e.getDocument() == javaAutoCompletionTriggersField.getDocument()) preferences.put(JAVA_AUTO_COMPLETION_TRIGGERS, javaAutoCompletionTriggersField.getText()); @@ -580,6 +598,7 @@ private javax.swing.JCheckBox guessMethodArguments; private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator2; + private javax.swing.JCheckBox javaAutoCompletionSubwords; private javax.swing.JTextField javaAutoCompletionTriggersField; private javax.swing.JLabel javaAutoCompletionTriggersLabel; private javax.swing.JCheckBox javaAutoPopupOnIdentifierPart;