diff options
Diffstat (limited to 'python/edu/src')
5 files changed, 207 insertions, 7 deletions
diff --git a/python/edu/src/META-INF/PyCharmEduPlugin.xml b/python/edu/src/META-INF/PyCharmEduPlugin.xml index d5b2fdfe8c28..87739a948968 100644 --- a/python/edu/src/META-INF/PyCharmEduPlugin.xml +++ b/python/edu/src/META-INF/PyCharmEduPlugin.xml @@ -19,6 +19,10 @@ </component> </application-components> + <extensions defaultExtensionNs="com.intellij"> + <codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.python.edu.PyExecuteFileLineMarkerProvider"/> + </extensions> + <actions> <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="ToolsMenu"/> @@ -38,5 +42,11 @@ <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="NewHtmlFile"/> + <group id="PyRunMenu"> + <action id="runCurrentFile" class="com.jetbrains.python.edu.PyRunCurrentFileAction"/> + <add-to-group group-id="RunMenu" anchor="first"/> + </group> + + </actions> </idea-plugin> diff --git a/python/edu/src/com/intellij/openapi/application/PyCharmEduConfigImportSettings.java b/python/edu/src/com/intellij/openapi/application/PyCharmEduConfigImportSettings.java new file mode 100644 index 000000000000..989c750681f3 --- /dev/null +++ b/python/edu/src/com/intellij/openapi/application/PyCharmEduConfigImportSettings.java @@ -0,0 +1,12 @@ +package com.intellij.openapi.application; + +import com.intellij.ide.plugins.PluginManagerCore; + +// see com.intellij.openapi.application.ConfigImportHelper.getConfigImportSettings +@SuppressWarnings("UnusedDeclaration") +public class PyCharmEduConfigImportSettings extends ConfigImportSettings { + public PyCharmEduConfigImportSettings() { + PluginManagerCore.disablePlugin("org.jetbrains.plugins.coursecreator"); + } + +} diff --git a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java index ecf3d79a6424..2954f7c5b706 100644 --- a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java +++ b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java @@ -35,14 +35,15 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.ex.KeymapManagerEx; import com.intellij.openapi.keymap.impl.KeymapImpl; +import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.project.ex.ProjectManagerEx; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.wm.ToolWindowEP; -import com.intellij.openapi.wm.ToolWindowId; -import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.wm.*; import com.intellij.platform.DirectoryProjectConfigurator; import com.intellij.platform.PlatformProjectViewOpener; import com.intellij.psi.codeStyle.CodeStyleSettings; @@ -62,9 +63,9 @@ import java.util.Set; */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "UtilityClassWithPublicConstructor"}) public class PyCharmEduInitialConfigurator { - @NonNls private static final String DISPLAYED_PROPERTY = "PyCharm.initialConfigurationShown"; + @NonNls private static final String DISPLAYED_PROPERTY = "PyCharmEDU.initialConfigurationShown"; - @NonNls private static final String CONFIGURED = "PyCharm.InitialConfiguration"; + @NonNls private static final String CONFIGURED = "PyCharmEDU.InitialConfiguration"; public static class First { @@ -93,6 +94,8 @@ public class PyCharmEduInitialConfigurator { uiSettings.SHOW_MAIN_TOOLBAR = false; codeInsightSettings.REFORMAT_ON_PASTE = CodeInsightSettings.NO_REFORMAT; + Registry.get("ide.new.settings.dialog").setValue(true); + GeneralSettings.getInstance().setShowTipsOnStartup(false); EditorSettingsExternalizable.getInstance().setVirtualSpace(false); @@ -113,7 +116,7 @@ public class PyCharmEduInitialConfigurator { }); } }); - PyCodeInsightSettings.getInstance().SHOW_IMPORT_POPUP = true; + PyCodeInsightSettings.getInstance().SHOW_IMPORT_POPUP = false; } if (!propertiesComponent.isValueSet(DISPLAYED_PROPERTY)) { @@ -147,6 +150,29 @@ public class PyCharmEduInitialConfigurator { } patchProjectAreaExtensions(project); + + StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() { + @Override + public void run() { + if (project.isDisposed()) return; + + ToolWindowManager.getInstance(project).invokeLater(new Runnable() { + int count = 0; + + public void run() { + if (project.isDisposed()) return; + if (count++ < 3) { // we need to call this after ToolWindowManagerImpl.registerToolWindowsFromBeans + ToolWindowManager.getInstance(project).invokeLater(this); + return; + } + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project"); + if (toolWindow.getType() != ToolWindowType.SLIDING) { + toolWindow.activate(null); + } + } + }); + } + }); } }); } @@ -205,6 +231,11 @@ public class PyCharmEduInitialConfigurator { private static void showInitialConfigurationDialog() { final JFrame frame = WindowManager.getInstance().findVisibleFrame(); - new InitialConfigurationDialog(frame, "Python").show(); + new InitialConfigurationDialog(frame, "Python") { + @Override + protected boolean canCreateLauncherScript() { + return false; + } + }.show(); } } diff --git a/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java b/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java new file mode 100644 index 000000000000..03522bb8cf8a --- /dev/null +++ b/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java @@ -0,0 +1,91 @@ +package com.jetbrains.python.edu; + +import com.intellij.codeHighlighting.Pass; +import com.intellij.codeInsight.daemon.GutterIconNavigationHandler; +import com.intellij.codeInsight.daemon.LineMarkerInfo; +import com.intellij.codeInsight.daemon.LineMarkerProvider; +import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.icons.AllIcons; +import com.intellij.ide.DataManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.markup.GutterIconRenderer; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.util.PsiUtilBase; +import com.intellij.util.Function; +import com.jetbrains.python.psi.PyFile; +import com.jetbrains.python.psi.PyImportStatement; +import com.jetbrains.python.psi.PyStatement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.event.MouseEvent; +import java.util.Collection; +import java.util.List; + +/** + * @author traff + */ +public class PyExecuteFileLineMarkerProvider implements LineMarkerProvider { + @Nullable + @Override + public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { + return null; + } + + @Override + public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) { + for (PsiElement element : elements) { + if (isFirstCodeLine(element)) { + result.add(new LineMarkerInfo<PsiElement>( + element, element.getTextRange(), AllIcons.Actions.Execute, Pass.UPDATE_OVERRIDEN_MARKERS, + new Function<PsiElement, String>() { + @Override + public String fun(PsiElement e) { + return "Execute '" + e.getContainingFile().getName() + "'"; + } + }, + new GutterIconNavigationHandler<PsiElement>() { + @Override + public void navigate(MouseEvent e, PsiElement elt) { + executeCurrentScript(elt); + } + }, + GutterIconRenderer.Alignment.RIGHT)); + } + } + } + + private static void executeCurrentScript(PsiElement elt) { + Editor editor = PsiUtilBase.findEditor(elt); + assert editor != null; + + final ConfigurationContext context = + ConfigurationContext.getFromContext(DataManager.getInstance().getDataContext(editor.getComponent())); + PyRunCurrentFileAction.run(context); + } + + private static boolean isFirstCodeLine(PsiElement element) { + return element instanceof PyStatement && + element.getParent() instanceof PyFile && + !isNothing(element) && + nothingBefore(element); + } + + private static boolean nothingBefore(PsiElement element) { + element = element.getPrevSibling(); + while (element != null) { + if (!isNothing(element)) { + return false; + } + element = element.getPrevSibling(); + } + + return true; + } + + private static boolean isNothing(PsiElement element) { + return (element instanceof PsiComment) || (element instanceof PyImportStatement) || (element instanceof PsiWhiteSpace); + } +} diff --git a/python/edu/src/com/jetbrains/python/edu/PyRunCurrentFileAction.java b/python/edu/src/com/jetbrains/python/edu/PyRunCurrentFileAction.java new file mode 100644 index 000000000000..4d30fa29a3b3 --- /dev/null +++ b/python/edu/src/com/jetbrains/python/edu/PyRunCurrentFileAction.java @@ -0,0 +1,56 @@ +package com.jetbrains.python.edu; + +import com.intellij.execution.Location; +import com.intellij.execution.RunManagerEx; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.runners.ExecutionUtil; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.Presentation; +import com.jetbrains.python.PythonFileType; +import org.jetbrains.annotations.NotNull; + +/** + * @author traff + */ +public class PyRunCurrentFileAction extends AnAction { + public PyRunCurrentFileAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.Execute); + } + + @Override + public void update(AnActionEvent e) { + Presentation presentation = e.getPresentation(); + final ConfigurationContext context = ConfigurationContext.getFromContext(e.getDataContext()); + Location location = context.getLocation(); + if (location != null && location.getPsiElement().getContainingFile() != null && location.getPsiElement().getContainingFile().getFileType() == PythonFileType.INSTANCE) { + presentation.setEnabled(true); + presentation.setText("Run '" + location.getPsiElement().getContainingFile().getName() + "'"); + } + } + + @Override + public void actionPerformed(AnActionEvent e) { + final ConfigurationContext context = ConfigurationContext.getFromContext(e.getDataContext()); + + run(context); + } + + public static void run(@NotNull ConfigurationContext context) { + RunnerAndConfigurationSettings configuration = context.findExisting(); + final RunManagerEx runManager = (RunManagerEx)context.getRunManager(); + if (configuration == null) { + configuration = context.getConfiguration(); + if (configuration == null) { + return; + } + runManager.setTemporaryConfiguration(configuration); + } + runManager.setSelectedConfiguration(configuration); + + ExecutionUtil.runConfiguration(configuration, DefaultRunExecutor.getRunExecutorInstance()); + } +} |