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 elements, @NotNull Collection result) { for (PsiElement element : elements) { if (isFirstCodeLine(element)) { result.add(new LineMarkerInfo( element, element.getTextRange(), AllIcons.Actions.Execute, Pass.UPDATE_OVERRIDEN_MARKERS, new Function() { @Override public String fun(PsiElement e) { return "Execute '" + e.getContainingFile().getName() + "'"; } }, new GutterIconNavigationHandler() { @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); } }