Merge branch 'master' of git@git.labs.intellij.net:idea/community
authorEugene Kudelevsky <Eugene.Kudelevsky@jetbrains.com>
Mon, 19 Apr 2010 12:38:11 +0000 (16:38 +0400)
committerEugene Kudelevsky <Eugene.Kudelevsky@jetbrains.com>
Mon, 19 Apr 2010 12:38:11 +0000 (16:38 +0400)
platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/WrapWithCustomTemplateAction.java
xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java
xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingTemplate.java

index d137ce89ba0331afe3f6b3e1fbf94ff3904a7f21..feaac8aded4c4c9e05e3dd3d419d7659edb8fc2c 100644 (file)
@@ -48,7 +48,7 @@ public class CustomTemplateCallback {
 
   private FileType myFileType;
 
-  private final LiveTemplateBuilder myBuilder = new LiveTemplateBuilder();
+  private LiveTemplateBuilder myBuilder = new LiveTemplateBuilder();
   private int myOffset = 0;
 
   public CustomTemplateCallback(Editor editor, PsiFile file) {
@@ -81,9 +81,15 @@ public class CustomTemplateCallback {
 
   @Nullable
   public TemplateImpl findApplicableTemplate(@NotNull String key) {
+    List<TemplateImpl> templates = findApplicableTemplates(key);
+    return templates.size() > 0 ? templates.get(0) : null;
+  }
+
+  @NotNull
+  public List<TemplateImpl> findApplicableTemplates(String key) {
     List<TemplateImpl> templates = getMatchingTemplates(key);
     templates = filterApplicableCandidates(templates);
-    return templates.size() > 0 ? templates.get(0) : null;
+    return templates;
   }
 
   private List<TemplateImpl> filterApplicableCandidates(Collection<TemplateImpl> candidates) {
@@ -101,18 +107,17 @@ public class CustomTemplateCallback {
    * @param predefinedVarValues
    * @param listener            @return returns if template invokation is finished
    */
-  public void startTemplate(@NotNull String key,
-                            Map<String, String> predefinedVarValues) {
-    List<TemplateImpl> templates = getMatchingTemplates(key);
-    templates = filterApplicableCandidates(templates);
+  public void expandTemplate(@NotNull String key,
+                             Map<String, String> predefinedVarValues) {
+    List<TemplateImpl> templates = findApplicableTemplates(key);
     if (templates.size() > 0) {
       TemplateImpl template = templates.get(0);
-      startTemplate(template, predefinedVarValues);
+      expandTemplate(template, predefinedVarValues);
     }
   }
 
-  public void startTemplate(@NotNull TemplateImpl template,
-                            Map<String, String> predefinedVarValues) {
+  public void expandTemplate(@NotNull TemplateImpl template,
+                             Map<String, String> predefinedVarValues) {
     int offset = myBuilder.insertTemplate(myOffset, template, predefinedVarValues);
     moveToOffset(offset);
   }
@@ -148,18 +153,30 @@ public class CustomTemplateCallback {
     }
   }
 
-  public void finish() {
+  public void startAllExpandedTemplates() {
     /*myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
     final CodeStyleManager style = CodeStyleManager.getInstance(myProject);
     if (myGlobalMarker != null) {
       style.reformatText(myFile, myGlobalMarker.getStartOffset(), myGlobalMarker.getEndOffset());
     }*/
+    if (myBuilder.getText().length() == 0) {
+      return;
+    }
     gotoEndOffset();
     if (myOffset < myBuilder.getText().length()) {
       myBuilder.insertVariableSegment(myOffset, TemplateImpl.END);
     }
     TemplateImpl template = myBuilder.buildTemplate();
     myTemplateManager.startTemplate(myEditor, template, false, myBuilder.getPredefinedValues(), null);
+    myBuilder = new LiveTemplateBuilder();
+    myEndOffsetMarker = null;
+    myCheckpoints.clear();
+  }
+
+  public boolean startTemplate() {
+    Map<TemplateImpl, String> template2Argument =
+      ((TemplateManagerImpl)myTemplateManager).findMatchingTemplates(myFile, myEditor, null, TemplateSettings.getInstance());
+    return ((TemplateManagerImpl)myTemplateManager).startNonCustomTemplates(template2Argument, myEditor, null);
   }
 
   private static List<TemplateImpl> getMatchingTemplates(@NotNull String templateKey) {
@@ -207,4 +224,9 @@ public class CustomTemplateCallback {
   public void insertString(int offset, String text) {
     myBuilder.insertText(offset, text);
   }
+
+  public void deleteTemplateKey(String key) {
+    int caretAt = myEditor.getCaretModel().getOffset();
+    myEditor.getDocument().deleteString(caretAt - key.length(), caretAt);
+  }
 }
index c6aac65a17825eff9122f21327f0d5cddbb25601..eec5cef1d3435f05ef374c3e16cfe504faf6a329 100644 (file)
@@ -227,7 +227,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
     for (TemplateImpl template : template2argument.keySet()) {
       String argument = template2argument.get(template);
       int templateStart = getTemplateStart(template, argument, caretOffset, text);
-      if (templateStart <= offset) {
+      if (templateStart < offset) {
         return true;
       }
     }
@@ -251,9 +251,8 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
             int offsetBeforeKey = caretOffset - key.length();
             CharSequence text = editor.getDocument().getCharsSequence();
             if (template2argument == null || !containsTemplateStartingBefore(template2argument, offsetBeforeKey, caretOffset, text)) {
-              callback.getEditor().getDocument().deleteString(offsetBeforeKey, caretOffset);
               customLiveTemplate.expand(key, callback);
-              callback.finish();
+              callback.startAllExpandedTemplates();
               return true;
             }
           }
@@ -285,9 +284,9 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
     return templateStart;
   }
 
-  private Map<TemplateImpl, String> findMatchingTemplates(final PsiFile file,
+  public Map<TemplateImpl, String> findMatchingTemplates(final PsiFile file,
                                                           Editor editor,
-                                                          char shortcutChar,
+                                                          Character shortcutChar,
                                                           TemplateSettings templateSettings) {
     final Document document = editor.getDocument();
     CharSequence text = document.getCharsSequence();
@@ -325,7 +324,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
     return candidate2Argument;
   }
 
-  private boolean startNonCustomTemplates(Map<TemplateImpl, String> template2argument,
+  public boolean startNonCustomTemplates(Map<TemplateImpl, String> template2argument,
                                           Editor editor,
                                           PairProcessor<String, String> processor) {
     final int caretOffset = editor.getCaretModel().getOffset();
@@ -353,7 +352,7 @@ public class TemplateManagerImpl extends TemplateManager implements ProjectCompo
 
   public static List<TemplateImpl> findMatchingTemplates(CharSequence text,
                                                          int caretOffset,
-                                                         char shortcutChar,
+                                                         Character shortcutChar,
                                                          TemplateSettings settings,
                                                          boolean hasArgument) {
     String key;
index a1f72df86d463ebd0f9fb66ab90a227561e08836..2d340bec8c15a09999c5d5106628e0c1c3c7d41e 100644 (file)
@@ -673,14 +673,14 @@ public class TemplateSettings implements PersistentStateComponent<Element>, Expo
     return mySchemesManager.getAllSchemes();
   }
 
-  public List<TemplateImpl> collectMatchingCandidates(String key, char shortcutChar, boolean hasArgument) {
+  public List<TemplateImpl> collectMatchingCandidates(String key, Character shortcutChar, boolean hasArgument) {
     final Collection<TemplateImpl> templates = getTemplates(key);
     List<TemplateImpl> candidates = new ArrayList<TemplateImpl>();
     for (TemplateImpl template : templates) {
       if (template.isDeactivated()) {
         continue;
       }
-      if (getShortcutChar(template) != shortcutChar) {
+      if (shortcutChar != null && getShortcutChar(template) != shortcutChar) {
         continue;
       }
       if (template.isSelectionTemplate()) {
index 937de4b5ab899070976ebbd0a04fe5c3543e841f..04603f37fd72bff56b8d04c085b0342982f9d262 100644 (file)
@@ -66,7 +66,7 @@ public class WrapWithCustomTemplateAction extends AnAction {
       final CustomTemplateCallback callback = new CustomTemplateCallback(myEditor, myFile);
       myTemplate.wrap(selection, callback, new TemplateInvokationListener() {
         public void finished() {
-          callback.finish();
+          callback.startAllExpandedTemplates();
         }
       });
     }
index 8198ee9842cd6875c880ed97c813972c0a8c0dae..42f4e112375ae0715e52e3716a13b730cf4a083d 100644 (file)
@@ -339,7 +339,7 @@ class XmlZenCodingInterpreter {
       }
       template.setToReformat(true);
       Map<String, String> predefinedValues = buildPredefinedValues(attr2value, numberInIteration);
-      callback.startTemplate(template, predefinedValues);
+      callback.expandTemplate(template, predefinedValues);
     }
   }
 
@@ -382,15 +382,15 @@ class XmlZenCodingInterpreter {
           modifiedTemplate.setString(text);
           removeVariablesWhichHasNoSegment(modifiedTemplate);
           Map<String, String> predefinedValues = buildPredefinedValues(attr2value, numberInIteration);
-          callback.startTemplate(modifiedTemplate, predefinedValues);
+          callback.expandTemplate(modifiedTemplate, predefinedValues);
           return;
         }
       }
-      callback.startTemplate(token.myTemplate, null);
+      callback.expandTemplate(token.myTemplate, null);
     }
     else {
       Map<String, String> predefinedValues = buildPredefinedValues(attr2value, numberInIteration);
-      callback.startTemplate(token.myKey, predefinedValues);
+      callback.expandTemplate(token.myKey, predefinedValues);
     }
   }
 
index f46965b3cb5c543d0d63b0507ab9b63758a1576f..445280d738596b10fa748d42cbdbe5423d16291a 100644 (file)
@@ -297,6 +297,10 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
   }
 
   public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
+    return computeKey(callback);
+  }
+
+  static String computeKey(CustomTemplateCallback callback) {
     Editor editor = callback.getEditor();
     PsiElement element = callback.getContext();
     int line = editor.getCaretModel().getLogicalPosition().line;
@@ -369,6 +373,18 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
                              String surroundedText) {
     List<Token> tokens = parse(key, callback);
     assert tokens != null;
+    if (surroundedText == null) {
+      if (tokens.size() == 2) {
+        Token token = tokens.get(0);
+        if (token instanceof TemplateToken) {
+          if (key.equals(((TemplateToken)token).myKey) && callback.findApplicableTemplates(key).size() > 1) {
+            callback.startTemplate();
+            return;
+          }
+        }
+      }
+      callback.deleteTemplateKey(key);
+    }
     XmlZenCodingInterpreter.interpret(tokens, 0, callback, State.WORD, surroundedText);
   }
 
@@ -447,7 +463,7 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
         selection = selection.trim();
         doWrap(selection, abbreviation, callback, new TemplateInvokationListener() {
           public void finished() {
-            callback.finish();
+            callback.startAllExpandedTemplates();
           }
         });
       }
@@ -455,10 +471,8 @@ public class XmlZenCodingTemplate implements CustomLiveTemplate {
         XmlZenCodingTemplate template = new XmlZenCodingTemplate();
         String key = template.computeTemplateKey(callback);
         if (key != null) {
-          int offsetBeforeKey = caretAt - key.length();
-          callback.getEditor().getDocument().deleteString(offsetBeforeKey, caretAt);
           template.expand(key, callback);
-          callback.finish();
+          callback.startAllExpandedTemplates();
           return true;
         }
         // if it is simple live template invokation, we should start it using TemplateManager because template may be ambiguous