"St"+<tab> should always work like a live template expansion

This commit is contained in:
peter.gromov
2010-11-10 21:24:14 +03:00
parent 391a9f4e2b
commit 9d4c174c66
5 changed files with 65 additions and 28 deletions
@@ -77,7 +77,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
private int myMinPrefixLength;
private int myPreferredItemsCount;
private long myShownStamp = -1;
private String myInitialPrefix;
private LookupArranger myArranger;
@@ -493,10 +492,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
}
public void finishLookup(final char completionChar) {
if (justShown()) {
return;
}
final LookupElement item = (LookupElement)myList.getSelectedValue();
doHide(false, true);
if (item == null ||
@@ -537,10 +532,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
fireItemSelected(item, completionChar);
}
public boolean justShown() {
return myShownStamp > 0 && System.currentTimeMillis() - myShownStamp < 42 && !ApplicationManager.getApplication().isUnitTestMode();
}
public int getLookupStart() {
if (myLookupStartMarker == null) {
final int start = calcLookupStart();
@@ -581,8 +572,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
hintManager.showEditorHint(this, myEditor, p, HintManagerImpl.HIDE_BY_ESCAPE | HintManagerImpl.UPDATE_BY_SCROLLING, 0, false);
getComponent().getRootPane().getLayeredPane().add(myIconPanel, 42, 0);
myShownStamp = System.currentTimeMillis();
}
private void addListeners() {
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.lookup.impl.actions;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.Editor;
@@ -33,6 +34,7 @@ public class ChooseItemAction extends EditorAction {
private static class Handler extends EditorActionHandler {
public void execute(final Editor editor, final DataContext dataContext) {
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
assert lookup != null;
lookup.finishLookup(Lookup.NORMAL_SELECT_CHAR);
}
}
@@ -41,7 +43,8 @@ public class ChooseItemAction extends EditorAction {
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup != null) {
lookup.refreshUi(); // to bring the list model up to date
presentation.setEnabled(!lookup.justShown() && (lookup.isFocused() || lookup.isCompletion() && !lookup.getItems().isEmpty()));
presentation.setEnabled(lookup.isFocused() &&
!ChooseItemReplaceAction.hasTemplatePrefix(lookup, TemplateSettings.ENTER_CHAR));
} else {
presentation.setEnabled(false);
}
@@ -17,15 +17,21 @@
package com.intellij.codeInsight.lookup.impl.actions;
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
public class ChooseItemReplaceAction extends EditorAction {
public ChooseItemReplaceAction(){
@@ -36,15 +42,28 @@ public class ChooseItemReplaceAction extends EditorAction {
public void executeWriteAction(Editor editor, DataContext dataContext) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_REPLACE);
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
assert lookup != null;
lookup.finishLookup(Lookup.REPLACE_SELECT_CHAR);
}
}
static boolean hasTemplatePrefix(LookupImpl lookup, char shortcutChar) {
final PsiFile file = lookup.getPsiFile();
final Editor editor = lookup.getEditor();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(editor.getDocument());
final int offset = editor.getCaretModel().getOffset();
final String prefix = CompletionUtil.findJavaIdentifierPrefix(file, offset);
final TemplateImpl template = LiveTemplateCompletionContributor.findApplicableTemplate(file, offset, prefix);
return template != null && shortcutChar == TemplateSettings.getInstance().getShortcutChar(template);
}
public void update(Editor editor, Presentation presentation, DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup != null) {
lookup.refreshUi(); // to bring the list model up to date
presentation.setEnabled(!lookup.justShown() && (lookup.isFocused() || lookup.isCompletion() && !lookup.getItems().isEmpty()));
presentation.setEnabled((lookup.isFocused() || lookup.isCompletion() && !lookup.getItems().isEmpty()) &&
!hasTemplatePrefix(lookup, TemplateSettings.TAB_CHAR));
} else {
presentation.setEnabled(false);
}
@@ -19,10 +19,17 @@ import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.openapi.util.Condition;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
@@ -39,23 +46,42 @@ public class LiveTemplateCompletionContributor extends CompletionContributor {
final PsiFile file = parameters.getOriginalFile();
final int offset = parameters.getOffset();
final String prefix = result.getPrefixMatcher().getPrefix();
for (final TemplateImpl template : TemplateSettings.getInstance().getTemplates()) {
final String key = template.getKey();
if (!template.isDeactivated() && !template.isSelectionTemplate() && TemplateManagerImpl.isApplicable(file, offset, template)) {
if (prefix.equals(key)) {
result.addElement(LookupElementBuilder.create(key).setTypeText(template.getDescription()).setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
context.setAddCompletionChar(false);
TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), template);
}
}));
} else {
result.restartCompletionOnPrefixChange(key);
final TemplateImpl template = findApplicableTemplate(file, offset, prefix);
if (template != null) {
result.addElement(LookupElementBuilder.create(prefix).setTypeText(template.getDescription()).setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
context.setAddCompletionChar(false);
TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), template);
}
}));
} else {
for (final TemplateImpl possible : listApplicableTemplates(file, offset)) {
result.restartCompletionOnPrefixChange(possible.getKey());
}
}
}
});
}
private static List<TemplateImpl> listApplicableTemplates(PsiFile file, int offset) {
final ArrayList<TemplateImpl> result = CollectionFactory.arrayList();
for (final TemplateImpl template : TemplateSettings.getInstance().getTemplates()) {
if (!template.isDeactivated() && !template.isSelectionTemplate() && TemplateManagerImpl.isApplicable(file, offset, template)) {
result.add(template);
}
}
return result;
}
@Nullable
public static TemplateImpl findApplicableTemplate(PsiFile file, int offset, final String key) {
return ContainerUtil.find(listApplicableTemplates(file, offset), new Condition<TemplateImpl>() {
@Override
public boolean value(TemplateImpl template) {
return key.equals(template.getKey());
}
});
}
@@ -690,7 +690,7 @@ public class TemplateSettings implements PersistentStateComponent<Element>, Expo
return candidates;
}
private char getShortcutChar(TemplateImpl template) {
public char getShortcutChar(TemplateImpl template) {
char c = template.getShortcutChar();
if (c == DEFAULT_CHAR) {
return getDefaultShortcutChar();