diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java b/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java index 394e64050c71..d6cbd4e4cb17 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java @@ -20,12 +20,16 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.Language; import com.intellij.lang.LanguageUtil; import com.intellij.lang.StdLanguages; -import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.LanguageFileType; -import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; @@ -35,8 +39,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.LanguageSubstitutors; -import com.intellij.psi.PsiFile; +import com.intellij.psi.*; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; @@ -52,7 +55,7 @@ import java.util.List; /** * @author ignatov */ -public class NewScratchFileAction extends AnAction implements DumbAware { +public class NewScratchFileAction extends DumbAwareAction { public static final int MAX_VISIBLE_SIZE = 20; public NewScratchFileAction() { @@ -61,9 +64,14 @@ public class NewScratchFileAction extends AnAction implements DumbAware { @Override public void update(@NotNull AnActionEvent e) { - e.getPresentation().setEnabledAndVisible(e.getProject() != null && Registry.is("ide.scratch.enabled")); + e.getPresentation().setEnabledAndVisible(isEnabled(e)); } - + + public static boolean isEnabled(@NotNull AnActionEvent e) { + return e.getProject() != null && Registry.is("ide.scratch.enabled"); + } + + @NotNull public static List getLastUsedLanguagesIds(Project project) { String[] values = PropertiesComponent.getInstance(project).getValues(ScratchpadManager.class.getName()); return values == null ? ContainerUtil.emptyList() : ContainerUtil.list(values); @@ -75,26 +83,67 @@ public class NewScratchFileAction extends AnAction implements DumbAware { if (project == null) return; PsiFile file = e.getData(CommonDataKeys.PSI_FILE); - Language context = file != null ? file.getLanguage() : null; + Editor editor = e.getData(CommonDataKeys.EDITOR); + + Language language = getLanguageFromCaret(project, editor, file); + String text = getSelectionText(editor); + if (language != null && text != null) { + openNewFile(project, language, text); + return; + } - ListPopup popup = buildLanguagePopup(project, context, new Consumer() { + ListPopup popup = buildLanguagePopup(project, language, new Consumer() { @Override - public void consume(Language language) { - FeatureUsageTracker.getInstance().triggerFeatureUsed("scratch"); - VirtualFile file = ScratchpadManager.getInstance(project).createScratchFile(substitute(project, language)); - FileEditorManager.getInstance(project).openFile(file, true); + public void consume(@NotNull Language language) { + openNewFile(project, language, ""); } }); popup.showCenteredInCurrentWindow(project); } + @Nullable + public String getSelectionText(@Nullable Editor editor) { + if (editor == null) return null; + return editor.getSelectionModel().getSelectedText(); + } + + @Nullable + public Language getLanguageFromCaret(@NotNull Project project, + @Nullable Editor editor, + @Nullable PsiFile psiFile) { + if (editor == null) return null; + if (psiFile == null) return null; + Caret caret = editor.getCaretModel().getPrimaryCaret(); + int offset = caret.getOffset(); + PsiElement element = InjectedLanguageManager.getInstance(project).findInjectedElementAt(psiFile, offset); + element = element == null ? psiFile.findElementAt(offset) : element; + Language language = element != null ? element.getLanguage() : psiFile.getLanguage(); + return substitute(project, language); + } + + public static void openNewFile(@NotNull Project project, @NotNull Language language, @NotNull final String text) { + FeatureUsageTracker.getInstance().triggerFeatureUsed("scratch"); + VirtualFile file = ScratchpadManager.getInstance(project).createScratchFile(substitute(project, language)); + PsiFile psiFile = PsiManager.getInstance(project).findFile(file); + final Document document = psiFile == null ? null : PsiDocumentManager.getInstance(project).getDocument(psiFile); + if (document != null && StringUtil.isNotEmpty(text)) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + document.setText(text); + } + }); + } + FileEditorManager.getInstance(project).openFile(file, true); + } + @NotNull public static Language substitute(@NotNull Project project, @NotNull Language language) { return LanguageSubstitutors.INSTANCE.substituteLanguage(language, new LightVirtualFile(), project); } @NotNull - static ListPopup buildLanguagePopup(@NotNull Project project, @Nullable Language context, final Consumer onChoosen) { + static ListPopup buildLanguagePopup(@NotNull Project project, @Nullable Language context, @NotNull final Consumer onChoosen) { List languages = LanguageUtil.getFileLanguages(); final List ids = ContainerUtil.newArrayList(getLastUsedLanguagesIds(project)); if (context != null) { @@ -118,7 +167,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware { new BaseListPopupStep("Choose Language", languages) { @NotNull @Override - public String getTextFor(Language value) { + public String getTextFor(@NotNull Language value) { return value.getDisplayName(); } @@ -134,7 +183,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware { } @Override - public Icon getIconFor(Language language) { + public Icon getIconFor(@NotNull Language language) { LanguageFileType associatedLanguage = language.getAssociatedFileType(); return associatedLanguage != null ? associatedLanguage.getIcon() : null; } @@ -150,6 +199,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware { ListPopupStep step = popup.getListStep(); List values = step.getValues(); for (Object v : values) { + //noinspection unchecked nameLen = Math.max(nameLen, step.getTextFor(v).length()); } if (values.size() > MAX_VISIBLE_SIZE) {