diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java index 1b711f818b90..be2f399ffe58 100644 --- a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java +++ b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java @@ -6,6 +6,8 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; + public class PyStudyLanguageManager implements StudyLanguageManager { @Nullable @Override @@ -28,6 +30,17 @@ public class PyStudyLanguageManager implements StudyLanguageManager { return getInternalTemplateByName(project, "tests.py"); } + @Override + public boolean packFile(File pathname) { + String name = pathname.getName(); + return !name.contains("__pycache__") && !name.contains(".pyc"); + } + + @Override + public String[] getAdditionalFilesToPack() { + return new String[]{"test_helper.py"}; + } + private static FileTemplate getInternalTemplateByName(@NotNull final Project project, String name) { return FileTemplateManager.getInstance(project).getInternalTemplate(name); } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java index 8b9659353313..f49baee259f1 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java @@ -25,6 +25,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.xmlb.XmlSerializer; @@ -184,11 +186,13 @@ public class CCProjectService implements PersistentStateComponent { return Integer.parseInt(fullName.substring(logicalName.length())) - 1; } public static String getRealTaskFileName(String name) { - if (!name.contains(".answer")) { + String nameWithoutExtension = FileUtil.getNameWithoutExtension(name); + String extension = FileUtilRt.getExtension(name); + if (!nameWithoutExtension.endsWith(".answer")) { return null; } int nameEnd = name.indexOf(".answer"); - return name.substring(0, nameEnd) + ".py"; + return name.substring(0, nameEnd) + "." + extension; } public static boolean setCCActionAvailable(@NotNull AnActionEvent e) { diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java index 1e82811a6d8d..d453a59c92ae 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java @@ -1,6 +1,7 @@ package com.jetbrains.edu.coursecreator; import com.intellij.ide.projectView.actions.MarkRootActionBase; +import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.ApplicationManager; @@ -12,7 +13,9 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.coursecreator.format.Course; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class CCUtils { private static final Logger LOG = Logger.getInstance(CCUtils.class.getName()); @@ -56,4 +59,10 @@ public class CCUtils { return -1; } } + + @Nullable + public static StudyLanguageManager getStudyLanguageManager(@NotNull final Course course) { + Language language = Language.findLanguageByID(course.getLanguage()); + return language == null ? null : StudyLanguageManager.INSTANCE.forLanguage(language); + } } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java index bdef802bab94..cce016575e09 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java @@ -6,6 +6,8 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; + public interface StudyLanguageManager { LanguageExtension INSTANCE = new LanguageExtension("Edu.StudyLanguageManager"); @@ -17,4 +19,8 @@ public interface StudyLanguageManager { @Nullable FileTemplate getTestsTemplate(@NotNull final Project project); + + boolean packFile(File pathname); + + String[] getAdditionalFilesToPack(); } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java index f34aacba345f..ac774b3659e7 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java @@ -21,6 +21,8 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.io.ZipUtil; import com.jetbrains.edu.coursecreator.CCDocumentListener; import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.StudyLanguageManager; import com.jetbrains.edu.coursecreator.format.*; import com.jetbrains.edu.coursecreator.ui.CreateCourseArchiveDialog; import org.jetbrains.annotations.NotNull; @@ -92,7 +94,7 @@ public class CCCreateCourseArchive extends DumbAwareAction { } } generateJson(project); - packCourse(baseDir, lessons); + packCourse(baseDir, lessons, course); resetTaskFiles(taskFiles); synchronize(project); } @@ -204,11 +206,11 @@ public class CCCreateCourseArchive extends DumbAwareAction { } } - private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Map lessons) { + private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Map lessons, @NotNull final Course course) { try { File zipFile = new File(myLocationDir, myZipName + ".zip"); ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); - + final StudyLanguageManager manager = CCUtils.getStudyLanguageManager(course); for (Map.Entry entry : lessons.entrySet()) { final VirtualFile lessonDir = baseDir.findChild(entry.getKey()); if (lessonDir == null) continue; @@ -217,13 +219,21 @@ public class CCCreateCourseArchive extends DumbAwareAction { public boolean accept(File pathname) { String name = pathname.getName(); String nameWithoutExtension = FileUtil.getNameWithoutExtension(pathname); - return !nameWithoutExtension.endsWith(".answer") && !name.contains("__pycache__") && !name.contains("_windows") && !name.contains(".pyc"); + if (nameWithoutExtension.endsWith(".answer") || name.contains("_windows")) { + return false; + } + return manager == null || manager.packFile(pathname); } }, null); } - ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "hints"), "hints", null, null); - ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "course.json"), "course.json", null, null); - ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "test_helper.py"), "test_helper.py", null, null); + packFile("hints", zos, baseDir); + packFile("course.json", zos, baseDir); + if (manager != null) { + String[] additionalFilesToPack = manager.getAdditionalFilesToPack(); + for (String filename: additionalFilesToPack) { + packFile(filename, zos, baseDir); + } + } zos.close(); Messages.showInfoMessage("Course archive was saved to " + zipFile.getPath(), "Course Archive Was Created Successfully"); } @@ -271,4 +281,19 @@ public class CCCreateCourseArchive extends DumbAwareAction { return true; } } + + private static void packFile(@NotNull final String filename, + @NotNull final ZipOutputStream zipOutputStream, + @NotNull final VirtualFile baseDir) { + try { + File file = new File(baseDir.getPath(), filename); + if (!file.exists()) { + return; + } + ZipUtil.addFileOrDirRecursively(zipOutputStream, null, file, filename, null, null); + } + catch (IOException e) { + LOG.error(e); + } + } } \ No newline at end of file diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java index fefa795f4ff6..538fc76b59f2 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java @@ -18,6 +18,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -80,25 +81,23 @@ public class CCCreateTask extends DumbAwareAction { final StudyLanguageManager studyLanguageManager = StudyLanguageManager.INSTANCE.forLanguage(language); CCUtils.markDirAsSourceRoot(taskDirectory.getVirtualFile(), project); + final Task task = new Task(taskName); + task.setIndex(size + 1); + lesson.addTask(task, taskDirectory); + createFromTemplateAndOpen(taskDirectory, studyLanguageManager.getTestsTemplate(project), view); createFromTemplateAndOpen(taskDirectory, FileTemplateManager.getInstance(project).getInternalTemplate("task.html"), view); String defaultExtension = studyLanguageManager.getDefaultTaskFileExtension(); - String taskFileName = null; if (defaultExtension != null) { FileTemplate taskFileTemplate = studyLanguageManager.getTaskFileTemplateForExtension(project, defaultExtension); createFromTemplateAndOpen(taskDirectory, taskFileTemplate, view); if (taskFileTemplate != null) { - taskFileName = taskFileTemplate.getName(); + String taskFileName = FileUtil.getNameWithoutExtension(taskFileTemplate.getName()); + task.addTaskFile(taskFileName + "." + defaultExtension, size + 1); } } - final Task task = new Task(taskName); - task.setIndex(size + 1); - lesson.addTask(task, taskDirectory); - if (taskFileName != null) { - task.addTaskFile(taskFileName, size + 1); - } ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java index 73b50d39b3be..374a141fa067 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java @@ -7,7 +7,6 @@ import com.intellij.ide.fileTemplates.FileTemplateUtil; import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.ide.util.EditorHelper; -import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.LangDataKeys; @@ -21,6 +20,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; import com.jetbrains.edu.coursecreator.StudyLanguageManager; import com.jetbrains.edu.coursecreator.format.Course; import com.jetbrains.edu.coursecreator.format.Lesson; @@ -57,7 +57,7 @@ public class CCCreateTaskFile extends DumbAwareAction { final int index = task.getTaskFiles().size() + 1; String generatedName = "file" + index; - CreateTaskFileDialog dialog = new CreateTaskFileDialog(project, generatedName); + CreateTaskFileDialog dialog = new CreateTaskFileDialog(project, generatedName, course); dialog.show(); if (dialog.getExitCode() != OK_EXIT_CODE) { return; @@ -68,11 +68,10 @@ public class CCCreateTaskFile extends DumbAwareAction { if (type == null) { return; } - Language language = Language.findLanguageByID(course.getLanguage()); - if (language == null) { + final StudyLanguageManager studyLanguageManager = CCUtils.getStudyLanguageManager(course); + if (studyLanguageManager == null) { return; } - final StudyLanguageManager studyLanguageManager = StudyLanguageManager.INSTANCE.forLanguage(language); final String extension = type.getDefaultExtension(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java index e8ea54843535..bb4187026691 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java @@ -18,6 +18,7 @@ package com.jetbrains.edu.coursecreator.actions; import com.intellij.execution.Location; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.icons.AllIcons; +import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; @@ -34,6 +35,8 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.containers.HashMap; import com.jetbrains.edu.coursecreator.CCProjectService; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.StudyLanguageManager; import com.jetbrains.edu.coursecreator.format.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -130,8 +133,16 @@ public abstract class CCRunTestsAction extends AnAction { clearTestEnvironment(taskDir, project); for (final Map.Entry entry : task.getTaskFiles().entrySet()) { final String name = entry.getKey(); + StudyLanguageManager manager = CCUtils.getStudyLanguageManager(course); + if (manager == null) { + return; + } createTestEnvironment(taskDir, name, entry.getValue(), project); - VirtualFile testFile = taskDir.findChild("tests.py"); + FileTemplate testsTemplate = manager.getTestsTemplate(project); + if (testsTemplate == null) { + return; + } + VirtualFile testFile = taskDir.findChild(testsTemplate.getName()); if (testFile == null) { return; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java index 42fa66169633..7dfed6ef223d 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java @@ -30,7 +30,6 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; @@ -92,6 +91,9 @@ public class CCShowPreview extends DumbAwareAction { Lesson lesson = course.getLesson(lessonDir.getName()); Task task = lesson.getTask(taskDir.getName()); TaskFile taskFile = task.getTaskFile(file.getName()); + if (taskFile == null) { + return; + } final Map taskFilesCopy = new HashMap(); for (final Map.Entry entry : task.getTaskFiles().entrySet()) { if (entry.getValue() == taskFile) { @@ -103,7 +105,10 @@ public class CCShowPreview extends DumbAwareAction { }); } } - String userFileName = FileUtil.getNameWithoutExtension(file.getName()) + ".py"; + String userFileName = CCProjectService.getRealTaskFileName(file.getName()); + if (userFileName == null) { + return; + } VirtualFile userFile = taskDir.getVirtualFile().findChild(userFileName); if (userFile == null) { LOG.info("Generated file " + userFileName + "was not found"); diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java index 40abda126c58..6c79854aaba8 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java @@ -8,21 +8,25 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.ui.DoubleClickListener; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.components.JBList; +import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.StudyLanguageManager; +import com.jetbrains.edu.coursecreator.format.Course; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.awt.event.MouseEvent; public class CreateTaskFileDialog extends DialogWrapper { + private final Course myCourse; private JPanel myPanel; private JBList myList; private JTextField myTextField; @SuppressWarnings("unchecked") - public CreateTaskFileDialog(@Nullable Project project, String generatedFileName) { + public CreateTaskFileDialog(@Nullable Project project, String generatedFileName, @NotNull final Course course) { super(project); + myCourse = course; FileType[] fileTypes = FileTypeManager.getInstance().getRegisteredFileTypes(); DefaultListModel model = new DefaultListModel(); @@ -51,16 +55,11 @@ public class CreateTaskFileDialog extends DialogWrapper { } }.installOn(myList); - myList.getSelectionModel().addListSelectionListener( - new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - //TODO: do smth to check validness - } - } - ); - - ListScrollingUtil.selectItem(myList, FileTypeManager.getInstance().getFileTypeByExtension("py")); + StudyLanguageManager manager = CCUtils.getStudyLanguageManager(myCourse); + if (manager != null) { + String extension = manager.getDefaultTaskFileExtension(); + ListScrollingUtil.selectItem(myList, FileTypeManager.getInstance().getFileTypeByExtension(extension != null ? extension : "txt")); + } return myPanel; }