├── .gitignore ├── .gitmodules ├── CLionArduinoPlugin.zip ├── META-INF └── plugin.xml ├── README.md ├── lib ├── commons-io-2.4-javadoc.jar ├── commons-io-2.4-sources.jar └── commons-io-2.4.jar └── src └── io └── github └── francoiscambell └── clionarduinoplugin ├── ArduinoSketchFileCreator.java ├── CMakeListsEditor.java ├── actions ├── NewArduinoProject.java └── NewSketchFile.java ├── components └── ArduinoFileTypeRegistration.java ├── resources ├── ArduinoToolchainFiles.java ├── Strings.java └── icons │ ├── ArduinoIcon.java │ ├── Arduino_Logo.png │ ├── Arduino_Logo@2x.png │ ├── Arduino_Logo@2x_dark.png │ └── Arduino_Logo_dark.png └── wizards ├── NewArduinoProjectForm.java └── NewArduinoProjectWizard.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion 4 | 5 | *.iml 6 | 7 | ## Directory-based project format: 8 | .idea/ 9 | # if you remove the above rule, at least ignore the following: 10 | 11 | # User-specific stuff: 12 | # .idea/workspace.xml 13 | # .idea/tasks.xml 14 | # .idea/dictionaries 15 | 16 | # Sensitive or high-churn files: 17 | # .idea/dataSources.ids 18 | # .idea/dataSources.xml 19 | # .idea/sqlDataSources.xml 20 | # .idea/dynamic.xml 21 | # .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | # .idea/gradle.xml 25 | # .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | # .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.ipr 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | /out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | 50 | /*.zip 51 | 52 | *.DS_Store 53 | 54 | 55 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/io/github/francoiscambell/clionarduinoplugin/resources/arduino-cmake"] 2 | path = src/io/github/francoiscambell/clionarduinoplugin/resources/arduino-cmake 3 | url = git://github.com/francoiscampbell/arduino-cmake.git 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /CLionArduinoPlugin.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/CLionArduinoPlugin.zip -------------------------------------------------------------------------------- /META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 37 | ]> 38 | 39 | io.github.francoiscambell.clionarduinoplugin2017 40 | Arduino 41 | 1.2.3 42 | Francois Campbell 43 | 44 | CLion Arduino Plugin v2 46 |
47 | This is a branch of the original CLionArduinoPlugin written by Francois Cambell to resolve crash issues. 48 |
49 | Branched Repo | 50 | Original Repo | 51 | Issues 52 |
53 |
54 | This is a plugin that integrates Arduino CMake into the IDE. 55 |
56 |
57 | The current features are to create an Arduino CMake project in one click, and to create new sketch files. 58 |
59 |
60 | Future features are to add menu option to easily change the board type, port number, import existing Arduino projects, etc. 61 | ]]>
62 | 63 | 1.2.3 65 | 69 | 1.2.2 70 | 73 | 1.2.1 74 | 77 | 1.2.0 78 | 81 | 1.1.0 82 | 85 | 1.0.2 86 | 89 | 1.0.1 90 | 93 | 1.0 94 | 105 | ]]> 106 | 107 | 108 | 109 | 110 | 111 | 113 | com.intellij.modules.clion 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | io.github.francoiscambell.clionarduinoplugin.components.ArduinoFileTypeRegistration 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 140 | 141 | 142 | 146 | 147 | 148 | 149 | 150 | 151 |
152 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #CLion Arduino Plugin 2 | 3 | This is a JetBrains CLion plugin that integrates [Arduino CMake](https://github.com/francoiscampbell/arduino-cmake) into the IDE. 4 | 5 | The current features are to create an Arduino CMake project in one click, and to create new sketch files. 6 | 7 | For those asking how to upload, you need to specify the serial port in the CMakeLists.txt file. For example: 8 | 9 | set(${CMAKE_PROJECT_NAME}_BOARD uno) 10 | set(${CMAKE_PROJECT_NAME}_PORT /dev/ttys0) 11 | 12 | This will create the 'upload' configuration in your Run Configurations and you can click the Run button or use the keyboard shortcut to upload. 13 | 14 | Future features are to add menu option to easily change the board type, port number, import existing Arduino projects, etc. 15 | 16 | ## Update on status: 17 | It seems that arduino-cmake (the backing plugin) development has pretty much stalled, which is the root cause of most of the issues here, so I've got my own fork and I've tried to implement most of the fixes from previous forks of the project, which are also mostly dead. This project was just an exercise in making a JetBrains plugin that turned out well, but I don't have a lot of free time on my hands to do this though, what with full-time university and what not, so I can't give a definite date on what will be fixed when, but I will make an effort to get it done. 18 | 19 | ## Release Notes 20 | 21 | **1.2.2** 22 | 23 | * Fixed .ino and .pde files not refactorable. Increased compatibility for Servo library 24 | 25 | **1.2.1** 26 | 27 | * Re-compiled for Java 6 28 | 29 | **1.2.0** 30 | 31 | * Added new project creation to Welcome Screen and File menu 32 | 33 | **1.1.0** 34 | 35 | * Compatiblity with Arduino SDK 1.6 on Mac OS X 36 | 37 | **1.0.2** 38 | 39 | * Removed Groovy runtime, no longer necessary 40 | 41 | **1.0.1** 42 | 43 | * Fixed organization 44 | 45 | **1.0** 46 | 47 | * Convert a project to Arduino CMake. This replaces CMakeLists.txt with a default one, deletes the default main.cpp file, copies in the Arduino CMake toolchain files, and deletes the build direcory to start fresh 48 | * Associates .ino and .pde files as C++ source, so you get syntax highlighting and prediction, etc. 49 | * Create a new sketch file in any directory. If you omit the extension, it will add .ino automatically 50 | * Adds import for Arduino.h to all newly created sketch files to enable code completion 51 | * Compiled with Java 6 for compatibility with OS X out of the box 52 | -------------------------------------------------------------------------------- /lib/commons-io-2.4-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/lib/commons-io-2.4-javadoc.jar -------------------------------------------------------------------------------- /lib/commons-io-2.4-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/lib/commons-io-2.4-sources.jar -------------------------------------------------------------------------------- /lib/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/lib/commons-io-2.4.jar -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/ArduinoSketchFileCreator.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin; 2 | 3 | import com.intellij.openapi.application.*; 4 | import com.intellij.openapi.command.*; 5 | import com.intellij.openapi.editor.*; 6 | import com.intellij.openapi.fileEditor.*; 7 | import com.intellij.openapi.project.*; 8 | import com.intellij.openapi.vfs.*; 9 | import io.github.francoiscambell.clionarduinoplugin.resources.*; 10 | 11 | import java.io.*; 12 | 13 | /** 14 | * Created by francois on 15-08-04. 15 | */ 16 | public class ArduinoSketchFileCreator { 17 | 18 | public static VirtualFile createSketchFileWithName(final Project project, final VirtualFile directory, final String name) { 19 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 20 | @Override 21 | public void run() { 22 | try { 23 | VirtualFile sketch = directory.createChildData(this, name); 24 | final Document sketchDocument = FileDocumentManager.getInstance().getDocument(sketch); 25 | if (sketchDocument != null) { 26 | CommandProcessor.getInstance().executeCommand(project, new Runnable() { 27 | @Override 28 | public void run() { 29 | sketchDocument.setText(Strings.DEFAULT_ARDUINO_SKETCH_CONTENTS); 30 | } 31 | }, null, null, sketchDocument); 32 | } 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | }); 38 | return directory.findChild(name); 39 | } 40 | 41 | public static void addFileToCMakeLists(final Project project, final VirtualFile file) { 42 | CMakeListsEditor.getInstance(project.getBaseDir()).set("SOURCE_FILES", file.getName()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/CMakeListsEditor.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin; 2 | 3 | import com.intellij.openapi.application.*; 4 | import com.intellij.openapi.command.*; 5 | import com.intellij.openapi.editor.*; 6 | import com.intellij.openapi.fileEditor.*; 7 | import com.intellij.openapi.vfs.*; 8 | 9 | import java.util.*; 10 | 11 | /** 12 | * Created by francois on 15-08-04. 13 | */ 14 | public class CMakeListsEditor { 15 | private static Map INSTANCES = new WeakHashMap(); 16 | private VirtualFile cMakeListsVirtualFile; 17 | 18 | private CMakeListsEditor(VirtualFile cMakeLists) { 19 | this.cMakeListsVirtualFile = cMakeLists; 20 | } 21 | 22 | public static CMakeListsEditor getInstance(VirtualFile cMakeLists) { 23 | if (!INSTANCES.containsKey(cMakeLists)) { 24 | INSTANCES.put(cMakeLists, new CMakeListsEditor(cMakeLists)); 25 | } 26 | return INSTANCES.get(cMakeLists); 27 | } 28 | 29 | private VirtualFile getCMakeListsVirtualFile() { 30 | return cMakeListsVirtualFile; 31 | } 32 | 33 | private Document getCMakeListsDocument() { 34 | return FileDocumentManager.getInstance().getDocument(getCMakeListsVirtualFile()); 35 | } 36 | 37 | public void clear() { 38 | final Document cMakeLists = getCMakeListsDocument(); 39 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 40 | @Override 41 | public void run() { 42 | CommandProcessor.getInstance().executeCommand(null, new Runnable() { 43 | @Override 44 | public void run() { 45 | cMakeLists.deleteString(0, cMakeLists.getTextLength()); 46 | FileDocumentManager.getInstance().saveDocument(cMakeLists); 47 | } 48 | }, null, null, cMakeLists); 49 | } 50 | }); 51 | } 52 | 53 | public void addLine(int line, final String text) { 54 | final Document cMakeLists = getCMakeListsDocument(); 55 | final int lineEndOffset = cMakeLists.getLineEndOffset(line); 56 | 57 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 58 | @Override 59 | public void run() { 60 | CommandProcessor.getInstance().executeCommand(null, new Runnable() { 61 | @Override 62 | public void run() { 63 | cMakeLists.insertString(lineEndOffset, text + "\n"); 64 | FileDocumentManager.getInstance().saveDocument(cMakeLists); 65 | } 66 | }, null, null, cMakeLists); 67 | } 68 | }); 69 | } 70 | 71 | public void appendLine(String text) { 72 | int lastLine = getCMakeListsDocument().getLineCount(); 73 | if (lastLine != 0) { 74 | lastLine--; 75 | } 76 | addLine(lastLine, text); 77 | } 78 | 79 | public void blankLine() { 80 | appendLine(""); 81 | } 82 | 83 | public void minVersion(String minVersion) { 84 | method("cmake_minimum_required", "VERSION", minVersion); 85 | } 86 | 87 | public void set(String var, String value) { 88 | method("set", var, value); 89 | } 90 | 91 | public void project(String projectName) { 92 | method("project", projectName); 93 | } 94 | 95 | public void method(String methodName, String... args) { 96 | StringBuilder builder = new StringBuilder(methodName); 97 | builder.append('('); 98 | for (String arg : args) { 99 | builder.append(arg); 100 | builder.append(' '); 101 | } 102 | if (args.length > 0) { 103 | builder.deleteCharAt(builder.length() - 1); 104 | } 105 | builder.append(')'); 106 | appendLine(builder.toString()); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/actions/NewArduinoProject.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.actions; 2 | 3 | import com.intellij.icons.*; 4 | import com.intellij.openapi.actionSystem.*; 5 | import com.intellij.openapi.wm.impl.welcomeScreen.*; 6 | import io.github.francoiscambell.clionarduinoplugin.wizards.NewArduinoProjectWizard; 7 | 8 | /** 9 | * Created by francois on 15-08-14. 10 | */ 11 | public class NewArduinoProject extends AnAction { 12 | public void update(AnActionEvent event) { 13 | Presentation presentation = event.getPresentation(); 14 | if (ActionPlaces.isMainMenuOrActionSearch(event.getPlace())) { 15 | presentation.setIcon(null); 16 | } 17 | 18 | if (NewWelcomeScreen.isNewWelcomeScreen(event)) { 19 | event.getPresentation().setIcon(AllIcons.Welcome.CreateNewProject); 20 | } 21 | 22 | } 23 | 24 | @Override 25 | public void actionPerformed(AnActionEvent e) { 26 | (new NewArduinoProjectWizard()).runWizard(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/actions/NewSketchFile.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.actions; 2 | 3 | import com.intellij.ide.*; 4 | import com.intellij.openapi.actionSystem.*; 5 | import com.intellij.openapi.application.*; 6 | import com.intellij.openapi.fileEditor.*; 7 | import com.intellij.openapi.project.*; 8 | import com.intellij.openapi.ui.*; 9 | import com.intellij.openapi.vfs.*; 10 | import com.intellij.psi.*; 11 | import io.github.francoiscambell.clionarduinoplugin.*; 12 | import io.github.francoiscambell.clionarduinoplugin.resources.*; 13 | import io.github.francoiscambell.clionarduinoplugin.resources.icons.*; 14 | import org.jetbrains.annotations.*; 15 | 16 | import java.io.*; 17 | 18 | /** 19 | * Created by francois on 15-08-02. 20 | */ 21 | public class NewSketchFile extends AnAction { 22 | 23 | public void actionPerformed(AnActionEvent e) { 24 | final Project project = e.getRequiredData(CommonDataKeys.PROJECT); 25 | final IdeView view = e.getRequiredData(LangDataKeys.IDE_VIEW); 26 | 27 | PsiDirectory directory = view.getOrChooseDirectory(); 28 | if (directory == null) { 29 | return; 30 | } 31 | final VirtualFile directoryVirtualFile = directory.getVirtualFile(); 32 | 33 | boolean loop = false; 34 | do { 35 | String filename = getDesiredFilename(project); 36 | if (filename == null) { //cancel 37 | return; 38 | } 39 | if (filename.isEmpty()) { //no name entered 40 | showEmptyFilenameError(project); 41 | loop = true; 42 | continue; 43 | } 44 | filename = correctExtension(filename); //add .ino if the current filename doesn't end with .ino or .pde 45 | 46 | VirtualFile existingFile = directoryVirtualFile.findChild(filename); 47 | if (existingFile != null) { 48 | int overwriteChoice = getOverwriteChoice(project); //ask to overwrite file 49 | switch (overwriteChoice) { 50 | case Messages.YES: 51 | deleteVirtualFile(existingFile); 52 | loop = false; 53 | break; 54 | case Messages.NO: 55 | loop = true; 56 | continue; 57 | case Messages.CANCEL: 58 | return; 59 | } 60 | } 61 | VirtualFile sketch = ArduinoSketchFileCreator 62 | .createSketchFileWithName(project, directoryVirtualFile, filename); 63 | // ArduinoSketchFileCreator.addFileToCMakeLists(project, sketch); //not sure if i need to do this or not 64 | FileEditorManager.getInstance(project).openFile(sketch, true, true); //open in editor 65 | } while (loop); 66 | } 67 | 68 | private void showEmptyFilenameError(Project project) { 69 | Messages.showErrorDialog(project, Strings.ENTER_FILENAME, Strings.ERROR); 70 | } 71 | 72 | private int getOverwriteChoice(Project project) { 73 | return Messages 74 | .showYesNoCancelDialog(project, Strings.QUESTION_OVERWRITE, Strings.FILE_ALREADY_EXISTS, ArduinoIcon.ARDUINO_ICON); 75 | } 76 | 77 | private String getDesiredFilename(Project project) { 78 | return Messages 79 | .showInputDialog(project, Strings.ENTER_FILENAME, Strings.SKETCH_NAME, ArduinoIcon.ARDUINO_ICON); 80 | } 81 | 82 | @NotNull 83 | private String correctExtension(String filename) { 84 | if (!(filename.endsWith(Strings.DOT_INO_EXT) || filename.endsWith(Strings.DOT_PDE_EXT))) { 85 | filename = filename + Strings.DOT_INO_EXT; 86 | } 87 | return filename; 88 | } 89 | 90 | 91 | private void deleteVirtualFile(final VirtualFile virtualFile) { 92 | if (virtualFile == null) { 93 | return; 94 | } 95 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 96 | @Override 97 | public void run() { 98 | try { 99 | virtualFile.delete(this); 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | } 103 | } 104 | }); 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/components/ArduinoFileTypeRegistration.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.components; 2 | 3 | import com.intellij.openapi.application.*; 4 | import com.intellij.openapi.components.*; 5 | import com.intellij.openapi.fileTypes.*; 6 | import io.github.francoiscambell.clionarduinoplugin.resources.*; 7 | import org.jetbrains.annotations.*; 8 | 9 | /** 10 | * Created by francois on 15-08-03. 11 | */ 12 | public class ArduinoFileTypeRegistration implements ApplicationComponent { 13 | 14 | public void initComponent() { 15 | ApplicationManager.getApplication().invokeLater(new Runnable() { 16 | @Override 17 | public void run() { 18 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 19 | @Override 20 | public void run() { 21 | FileType cpp = FileTypeManager.getInstance().getFileTypeByExtension(Strings.CPP_EXT); 22 | FileTypeManager.getInstance().associateExtension(cpp, Strings.INO_EXT); 23 | FileTypeManager.getInstance().associateExtension(cpp, Strings.PDE_EXT); 24 | } 25 | }); 26 | } 27 | }); 28 | } 29 | 30 | public void disposeComponent() { 31 | ApplicationManager.getApplication().invokeLater(new Runnable() { 32 | @Override 33 | public void run() { 34 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 35 | @Override 36 | public void run() { 37 | FileType cpp = FileTypeManager.getInstance().getFileTypeByExtension(Strings.CPP_EXT); 38 | FileTypeManager.getInstance().removeAssociatedExtension(cpp, Strings.INO_EXT); 39 | FileTypeManager.getInstance().removeAssociatedExtension(cpp, Strings.PDE_EXT); 40 | } 41 | }); 42 | } 43 | }); 44 | } 45 | 46 | @NotNull 47 | public String getComponentName() { 48 | return "ArduinoFileTypeRegistration"; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/ArduinoToolchainFiles.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.resources; 2 | 3 | import com.intellij.openapi.application.ApplicationManager; 4 | import com.intellij.openapi.vfs.VirtualFile; 5 | import org.apache.commons.io.IOUtils; 6 | 7 | import java.io.Closeable; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.OutputStream; 11 | 12 | /** 13 | * Created by francois on 15-08-03. 14 | */ 15 | public class ArduinoToolchainFiles { 16 | public static InputStream getArduinoToolchainCmake() { 17 | return ArduinoToolchainFiles.class.getResourceAsStream("arduino-cmake/cmake/ArduinoToolchain.cmake"); 18 | } 19 | 20 | public static InputStream getArduinoCmake() { 21 | return ArduinoToolchainFiles.class.getResourceAsStream("arduino-cmake/cmake/Platform/Arduino.cmake"); 22 | } 23 | 24 | public static void copyToDirectory(final VirtualFile projectRoot) { 25 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 26 | @Override 27 | public void run() { 28 | try { 29 | VirtualFile cmakeDirectory = projectRoot.createChildDirectory(this, "cmake"); 30 | VirtualFile platformDirectory = cmakeDirectory.createChildDirectory(this, "Platform"); 31 | 32 | VirtualFile arduinoToolchain = cmakeDirectory.createChildData(this, "ArduinoToolchain.cmake"); 33 | VirtualFile arduino = platformDirectory.createChildData(this, "Arduino.cmake"); 34 | 35 | OutputStream arduinoToolchainOutputStream = arduinoToolchain.getOutputStream(this); 36 | OutputStream arduinoOutputStream = arduino.getOutputStream(this); 37 | 38 | InputStream arduinoToolchainInputStream = getArduinoToolchainCmake(); 39 | InputStream arduinoInputStream = getArduinoCmake(); 40 | 41 | try { 42 | IOUtils.copy(arduinoToolchainInputStream, arduinoToolchainOutputStream); 43 | IOUtils.copy(arduinoInputStream, arduinoOutputStream); 44 | } finally { 45 | closeStreams(arduinoToolchainOutputStream, 46 | arduinoOutputStream, 47 | arduinoToolchainInputStream, 48 | arduinoInputStream); 49 | } 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | }); 55 | } 56 | 57 | private static void closeStreams(Closeable... streams) { 58 | for (Closeable c : streams) { 59 | IOUtils.closeQuietly(c); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/Strings.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.resources; 2 | 3 | /** 4 | * Created by francois on 15-08-04. 5 | */ 6 | public class Strings { 7 | public static final String CMAKE_LISTS_FILENAME = "CMakeLists.txt"; 8 | public static final String CPP_EXT = "cpp"; 9 | public static final String DEFAULT_ARDUINO_SKETCH_CONTENTS = "#include \n\nvoid setup() {\n\n}\n\nvoid loop() {\n\n}"; 10 | public static final String ENTER_FILENAME = "Enter filename"; 11 | public static final String ERROR = "Error"; 12 | public static final String FILE_ALREADY_EXISTS = "File Already Exists"; 13 | public static final String INO_EXT = "ino"; 14 | public static final String DOT_INO_EXT = "." + INO_EXT; 15 | public static final String MAIN_CPP_FILENAME = "main.cpp"; 16 | public static final String PDE_EXT = "PDE"; 17 | public static final String DOT_PDE_EXT = "." + PDE_EXT; 18 | public static final String QUESTION_OVERWRITE = "Do you wish to overwrite the existing file?"; 19 | public static final String SKETCH_NAME = "Sketch Name"; 20 | } 21 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/icons/ArduinoIcon.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.resources.icons; 2 | 3 | import com.intellij.openapi.util.*; 4 | 5 | import javax.swing.*; 6 | 7 | /** 8 | * Created by francois on 15-08-04. 9 | */ 10 | public class ArduinoIcon { 11 | public static final Icon ARDUINO_ICON = IconLoader.getIcon("Arduino_Logo.png"); 12 | } 13 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo.png -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo@2x.png -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo@2x_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo@2x_dark.png -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjuang/CLionArduinoPlugin/0932733d5ffd952776e2a39922f88dcb174c3420/src/io/github/francoiscambell/clionarduinoplugin/resources/icons/Arduino_Logo_dark.png -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/wizards/NewArduinoProjectForm.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.wizards; 2 | 3 | import com.intellij.openapi.fileChooser.FileChooserDescriptor; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.openapi.project.ProjectManager; 6 | import com.intellij.openapi.ui.TextBrowseFolderListener; 7 | import com.intellij.openapi.ui.TextFieldWithBrowseButton; 8 | import com.jetbrains.cidr.cpp.cmake.projectWizard.CMakeProjectStepAdapter; 9 | import com.jetbrains.cidr.cpp.cmake.workspace.CMakeWorkspace; 10 | 11 | import javax.swing.*; 12 | import javax.swing.event.DocumentEvent; 13 | import javax.swing.event.DocumentListener; 14 | import java.awt.*; 15 | import java.awt.event.*; 16 | import java.beans.PropertyChangeEvent; 17 | import java.beans.PropertyChangeListener; 18 | 19 | import static java.awt.GridBagConstraints.HORIZONTAL; 20 | import static java.awt.GridBagConstraints.LINE_END; 21 | import static java.awt.GridBagConstraints.LINE_START; 22 | 23 | /** 24 | * Created by radford on 1/9/17. 25 | */ 26 | public class NewArduinoProjectForm extends CMakeProjectStepAdapter { 27 | private JTextField projectNameTextField; 28 | private TextFieldWithBrowseButton projectPathField; 29 | 30 | private JPanel mainPanel; 31 | private String lastSelectedPath; 32 | 33 | public NewArduinoProjectForm(String defaultProjectName, String defaultProjectPath) { 34 | lastSelectedPath = defaultProjectPath; 35 | 36 | mainPanel = new JPanel(new GridBagLayout()); 37 | 38 | projectNameTextField = new JTextField(defaultProjectName, 20); 39 | 40 | GridBagConstraints constraints = new GridBagConstraints(); 41 | constraints.ipadx = 5; 42 | constraints.fill = HORIZONTAL; 43 | 44 | constraints.gridx = 0; 45 | constraints.gridy = 0; 46 | constraints.weightx = 0.2; 47 | constraints.anchor = LINE_END; 48 | 49 | mainPanel.add(new JLabel("Project Name"), constraints); 50 | 51 | constraints.gridx = 1; 52 | constraints.gridy = 0; 53 | constraints.weightx = 0.8; 54 | constraints.anchor = LINE_START; 55 | 56 | mainPanel.add(projectNameTextField, constraints); 57 | 58 | projectPathField = new TextFieldWithBrowseButton( 59 | new JTextField( 60 | defaultProjectPath, 61 | 20), 62 | new ActionListener() { 63 | @Override 64 | public void actionPerformed(ActionEvent e) { 65 | lastSelectedPath = projectPathField.getText(); 66 | } 67 | } 68 | ); 69 | 70 | projectPathField.addBrowseFolderListener( 71 | "Select Target Project Directory", 72 | null, 73 | null, 74 | new FileChooserDescriptor(false, 75 | true, 76 | false, 77 | false, 78 | false, 79 | false)); 80 | 81 | 82 | projectNameTextField.getDocument().addDocumentListener( 83 | new DocumentListener() { 84 | @Override 85 | public void insertUpdate(DocumentEvent e) { 86 | syncFields(); 87 | } 88 | 89 | @Override 90 | public void removeUpdate(DocumentEvent e) { 91 | syncFields(); 92 | } 93 | 94 | @Override 95 | public void changedUpdate(DocumentEvent e) { 96 | syncFields(); 97 | } 98 | 99 | private void syncFields() { 100 | String projectName = "/" + projectNameTextField.getText(); 101 | if (!lastSelectedPath.endsWith(projectName)) { 102 | projectPathField.setText(lastSelectedPath.concat(projectName)); 103 | projectPathField.setAutoscrolls(true); 104 | } 105 | } 106 | } 107 | ); 108 | 109 | constraints.gridx = 0; 110 | constraints.gridy = 1; 111 | constraints.weightx = 0.2; 112 | constraints.anchor = LINE_END; 113 | mainPanel.add(new JLabel("Project Path"), constraints); 114 | 115 | constraints.gridx = 1; 116 | constraints.gridy = 1; 117 | constraints.weightx = 0.8; 118 | constraints.anchor = LINE_START; 119 | mainPanel.add(projectPathField, constraints); 120 | } 121 | 122 | @Override 123 | protected void init() { 124 | mainPanel.setVisible(true); 125 | } 126 | 127 | @Override 128 | public JComponent getPreferredFocusedComponent() { 129 | return mainPanel; 130 | } 131 | 132 | @Override 133 | public void dispose() { 134 | mainPanel.setVisible(false); 135 | } 136 | 137 | public String getName() { 138 | return projectNameTextField.getText().replaceAll("-", "_"); 139 | } 140 | 141 | public String getLocation() { 142 | return projectPathField.getText(); 143 | } 144 | 145 | @Override 146 | public JComponent getComponent() { 147 | return mainPanel; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/io/github/francoiscambell/clionarduinoplugin/wizards/NewArduinoProjectWizard.java: -------------------------------------------------------------------------------- 1 | package io.github.francoiscambell.clionarduinoplugin.wizards; 2 | 3 | import com.intellij.ide.RecentDirectoryProjectsManager; 4 | import com.intellij.ide.RecentProjectsManager; 5 | import com.intellij.ide.util.DirectoryUtil; 6 | import com.intellij.ide.util.PropertiesComponent; 7 | import com.intellij.openapi.application.ApplicationManager; 8 | import com.intellij.openapi.components.impl.stores.DirectoryStorageUtil; 9 | import com.intellij.openapi.fileEditor.OpenFileDescriptor; 10 | import com.intellij.openapi.project.Project; 11 | import com.intellij.openapi.project.ProjectManager; 12 | import com.intellij.openapi.ui.Messages; 13 | import com.intellij.openapi.util.io.FileUtil; 14 | import com.intellij.openapi.vfs.LocalFileSystem; 15 | import com.intellij.openapi.vfs.VfsUtil; 16 | import com.intellij.openapi.vfs.VirtualFile; 17 | import com.jetbrains.cidr.cpp.CPPLog; 18 | import com.jetbrains.cidr.cpp.cmake.CMakeProjectOpenProcessor; 19 | import com.jetbrains.cidr.cpp.cmake.projectWizard.*; 20 | import io.github.francoiscambell.clionarduinoplugin.CMakeListsEditor; 21 | import io.github.francoiscambell.clionarduinoplugin.resources.ArduinoToolchainFiles; 22 | import io.github.francoiscambell.clionarduinoplugin.resources.Strings; 23 | import org.jdom.JDOMException; 24 | 25 | import java.io.File; 26 | import java.io.FilenameFilter; 27 | import java.io.IOException; 28 | import java.util.Optional; 29 | 30 | import static com.jetbrains.cidr.cpp.cmake.projectWizard.CLionProjectWizardUtils.refreshProjectDir; 31 | 32 | 33 | /** 34 | * Created by francois on 15-08-14. 35 | */ 36 | public class NewArduinoProjectWizard extends CMakeProjectWizard { 37 | 38 | private String lastDir = Optional.ofNullable(RecentProjectsManager.getInstance().getLastProjectCreationLocation()) 39 | .orElse(""); 40 | 41 | private NewArduinoProjectForm adapter = new NewArduinoProjectForm( 42 | "untitled-0", 43 | new File(lastDir).getPath()); 44 | 45 | public NewArduinoProjectWizard() { 46 | super("New Arduino Sketch Project", "NewArduinoSketchProject"); 47 | initWithStep(adapter); 48 | } 49 | 50 | @Override 51 | protected boolean tryFinish() { 52 | String projectRootPath = adapter.getLocation(); 53 | 54 | File projectRootDir = new File(projectRootPath); 55 | if (projectRootDir.exists()) { 56 | String[] fileList = projectRootDir.list(new FilenameFilter() { 57 | public boolean accept(File dir, String name) { 58 | return !".DS_Store".equalsIgnoreCase(name) && !"Thumbs.db".equalsIgnoreCase(name); 59 | } 60 | }); 61 | if (fileList != null && fileList.length > 0) { 62 | int dialogAnswer = Messages.showYesNoDialog(String 63 | .format("Directory \'%s\' already exists and not empty.\nWould you like to continue?", projectRootPath), "Project Directory Already Exists", Messages 64 | .getQuestionIcon()); 65 | if (dialogAnswer != 0) { 66 | return false; 67 | } 68 | } 69 | } else { 70 | try { 71 | VfsUtil.createDirectories(projectRootPath); 72 | } catch (IOException | RuntimeException e) { 73 | CPPLog.LOG.warn(e); 74 | return false; 75 | } 76 | } 77 | 78 | String projectRootDirParentPath = projectRootDir.getParent(); 79 | if (projectRootDirParentPath != null) { 80 | RecentProjectsManager.getInstance().setLastProjectCreationLocation(projectRootDirParentPath); 81 | } 82 | 83 | try { 84 | createProject(this.adapter.getName(), projectRootPath); 85 | return true; 86 | } catch (IOException e) { 87 | CPPLog.LOG.warn(e); 88 | return false; 89 | } 90 | } 91 | 92 | public static String createProject(String projectName, String projectRootPath) throws IOException { 93 | File projectRoot = new File(projectRootPath); 94 | File cMakeLists = new File(projectRoot, "CMakeLists.txt"); 95 | if (!cMakeLists.exists() && !cMakeLists.createNewFile()) { 96 | throw new IOException("Cannot create file " + cMakeLists); 97 | } else { 98 | projectName = FileUtil.sanitizeFileName(projectName); 99 | File mainSketchFile = new File(projectRoot, projectName + ".ino"); 100 | if (!mainSketchFile.exists() && !mainSketchFile.createNewFile()) { 101 | throw new IOException("Cannot create file " + mainSketchFile); 102 | } else { 103 | FileUtil.writeToFile(mainSketchFile, Strings.DEFAULT_ARDUINO_SKETCH_CONTENTS); 104 | 105 | VirtualFile cMakeListsVirtualFile = VfsUtil.findFileByIoFile(cMakeLists, true); 106 | CMakeListsEditor cMakeListsEditor = CMakeListsEditor.getInstance(cMakeListsVirtualFile); 107 | cMakeListsEditor.clear(); 108 | cMakeListsEditor.minVersion("2.8.4"); 109 | cMakeListsEditor.set("CMAKE_TOOLCHAIN_FILE", "${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake"); 110 | cMakeListsEditor.set("PROJECT_NAME", projectName); 111 | cMakeListsEditor.project("${PROJECT_NAME}"); 112 | cMakeListsEditor.blankLine(); 113 | cMakeListsEditor.set("${CMAKE_PROJECT_NAME}_SKETCH", projectName + ".ino"); 114 | cMakeListsEditor.blankLine(); 115 | cMakeListsEditor.appendLine("#### Uncomment below additional settings as needed."); 116 | cMakeListsEditor.appendLine("# set(${CMAKE_PROJECT_NAME}_BOARD mega)"); 117 | cMakeListsEditor.appendLine("# set(${CMAKE_PROJECT_NAME}_PORT /dev/ttyACM0)"); 118 | cMakeListsEditor.appendLine("# set(mega.build.mcu atmega2560)"); 119 | cMakeListsEditor.appendLine("# set(mega.upload.protocol wiring)"); 120 | cMakeListsEditor.appendLine("# set(mega.upload.speed 115200)"); 121 | cMakeListsEditor.blankLine(); 122 | cMakeListsEditor.method("generate_arduino_firmware", "${CMAKE_PROJECT_NAME}"); 123 | 124 | ArduinoToolchainFiles.copyToDirectory(VfsUtil.findFileByIoFile(projectRoot, true)); 125 | 126 | return projectName; 127 | } 128 | } 129 | } 130 | 131 | @Override 132 | protected void doRunWizard() { 133 | VirtualFile projectRoot = LocalFileSystem.getInstance().refreshAndFindFileByPath(this.adapter.getLocation()); 134 | if (projectRoot == null) { 135 | return; 136 | } 137 | refreshProjectDir(projectRoot); 138 | final VirtualFile cMakeLists = projectRoot.findChild("CMakeLists.txt"); 139 | if (cMakeLists == null) { 140 | return; 141 | } 142 | final VirtualFile mainSketchFile = projectRoot.findChild(this.adapter.getName() + ".ino"); 143 | if (mainSketchFile == null) { 144 | return; 145 | } 146 | 147 | final Project project; 148 | try { 149 | project = ProjectManager.getInstance().loadAndOpenProject(cMakeLists.getPath()); 150 | } catch (IOException | JDOMException e) { 151 | CPPLog.LOG.warn(e); 152 | return; 153 | } 154 | 155 | if (project == null) { 156 | return; 157 | } 158 | 159 | CMakeProjectOpenProcessor.OpenProjectSpec projectSpec = CMakeProjectOpenProcessor.getHelper() 160 | .getAndClearFileToOpenData(project); 161 | 162 | deleteBuildOutputDir(projectSpec); 163 | (new OpenFileDescriptor(project, cMakeLists)).navigate(false); 164 | (new OpenFileDescriptor(project, mainSketchFile)).navigate(true); 165 | } 166 | 167 | private void deleteBuildOutputDir(CMakeProjectOpenProcessor.OpenProjectSpec projectSpec) { 168 | if (projectSpec != null && projectSpec.generationDir != null) { 169 | FileUtil.delete(projectSpec.generationDir); 170 | } 171 | } 172 | } 173 | --------------------------------------------------------------------------------