Skip to content
This repository was archived by the owner on Mar 25, 2019. It is now read-only.

Commit f74a002

Browse files
author
Ilia Motornyi
authored
Guess board file (#102)
1 parent b49bda3 commit f74a002

File tree

6 files changed

+196
-38
lines changed

6 files changed

+196
-38
lines changed

src/xyz/elmot/clion/cubemx/ConvertProject.java

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
import com.intellij.openapi.vfs.VirtualFile;
1717
import com.intellij.util.exception.RootRuntimeException;
1818
import com.jetbrains.cidr.cpp.cmake.workspace.CMakeWorkspace;
19-
import com.jetbrains.cidr.cpp.execution.CMakeAppRunConfiguration;
2019
import org.apache.commons.lang.text.StrSubstitutor;
2120
import org.jdom.Attribute;
2221
import org.jdom.Element;
2322
import org.jdom.JDOMException;
2423
import org.jdom.xpath.XPath;
2524
import org.jetbrains.annotations.NotNull;
25+
import org.jetbrains.annotations.Nullable;
2626
import xyz.elmot.clion.openocd.Informational;
27+
import xyz.elmot.clion.openocd.OpenOcdConfiguration;
2728
import xyz.elmot.clion.openocd.OpenOcdConfigurationType;
2829

2930
import java.io.IOException;
@@ -55,27 +56,8 @@ public ConvertProject() {
5556

5657
public static void updateProject(Project project) {
5758
if (project == null) return;
58-
Element cProject = detectAndLoadFile(project, CPROJECT_FILE_NAME);
59-
Element dotProject = detectAndLoadFile(project, PROJECT_FILE_NAME);
60-
if (dotProject == null || cProject == null) {
61-
return;
62-
}
63-
Context context = new Context(cProject);
64-
ProjectData projectData = new ProjectData();
65-
//noinspection ConstantConditions
66-
projectData.setProjectName(dotProject.getChild("name").getText());
67-
try {
68-
String linkerScript = fetchValueBySuperClass(context, "fr.ac6.managedbuild.tool.gnu.cross.c.linker.script");
69-
projectData.setLinkerScript(linkerScript.replace("../", ""));
70-
projectData.setMcuFamily(fetchValueBySuperClass(context, "fr.ac6.managedbuild.option.gnu.cross.mcu"));
71-
projectData.setLinkerFlags(fetchValueBySuperClass(context, "gnu.c.link.option.ldflags"));
72-
73-
projectData.setDefines(loadDefines(context));
74-
projectData.setIncludes(loadIncludes(context));
75-
projectData.setSources(loadSources(context));
76-
} catch (JDOMException e) {
77-
Messages.showErrorDialog(project, "Xml data error", String.format("XML data retrieval error\n Key: %s ", context.currentKey));
78-
}
59+
ProjectData projectData = loadProjectData(project);
60+
if (projectData == null) return;
7961

8062
Application application = ApplicationManager.getApplication();
8163
application.saveAll();
@@ -127,6 +109,32 @@ public static void updateProject(Project project) {
127109
);
128110
}
129111

112+
@Nullable
113+
public static ProjectData loadProjectData(Project project) {
114+
Element cProject = detectAndLoadFile(project, CPROJECT_FILE_NAME);
115+
Element dotProject = detectAndLoadFile(project, PROJECT_FILE_NAME);
116+
if (dotProject == null || cProject == null) {
117+
return null;
118+
}
119+
Context context = new Context(cProject);
120+
ProjectData projectData = new ProjectData();
121+
//noinspection ConstantConditions
122+
projectData.setProjectName(dotProject.getChild("name").getText());
123+
try {
124+
String linkerScript = fetchValueBySuperClass(context, "fr.ac6.managedbuild.tool.gnu.cross.c.linker.script");
125+
projectData.setLinkerScript(linkerScript.replace("../", ""));
126+
projectData.setMcuFamily(fetchValueBySuperClass(context, "fr.ac6.managedbuild.option.gnu.cross.mcu"));
127+
projectData.setLinkerFlags(fetchValueBySuperClass(context, "gnu.c.link.option.ldflags"));
128+
projectData.setBoard(fetchValueBySuperClass(context, "fr.ac6.managedbuild.option.gnu.cross.board"));
129+
projectData.setDefines(loadDefines(context));
130+
projectData.setIncludes(loadIncludes(context));
131+
projectData.setSources(loadSources(context));
132+
} catch (JDOMException e) {
133+
Messages.showErrorDialog(project, "Xml data error", String.format("XML data retrieval error\n Key: %s ", context.currentKey));
134+
}
135+
return projectData;
136+
}
137+
130138
@NotNull
131139
private static String loadCmakeTemplateFromResources() throws IOException {
132140
return FileUtil.loadTextAndClose(ConvertProject.class.getResourceAsStream("tmpl_CMakeLists.txt"));
@@ -153,14 +161,17 @@ private static void modifyCMakeConfigs(Project project, ProjectData projectData)
153161
if (runManager.findConfigurationByTypeAndName(OpenOcdConfigurationType.TYPE_ID, name) == null) {
154162
RunnerAndConfigurationSettings newRunConfig = runManager.createRunConfiguration(name, factory);
155163
newRunConfig.setSingleton(true);
156-
((CMakeAppRunConfiguration) newRunConfig.getConfiguration()).setupDefaultTargetAndExecutable();
157-
ApplicationManager.getApplication().invokeLater(() ->
158-
ApplicationManager.getApplication().runWriteAction(() ->
159-
{
160-
runManager.addConfiguration(newRunConfig);
161-
runManager.makeStable(newRunConfig);
162-
runManager.setSelectedConfiguration(newRunConfig);
163-
}));
164+
OpenOcdConfiguration configuration = (OpenOcdConfiguration) newRunConfig.getConfiguration();
165+
configuration.setupDefaultTargetAndExecutable();
166+
ApplicationManager.getApplication().invokeLater(() -> {
167+
configuration.setBoardConfigFile(SelectBoardDialog.selectBoardByPriority(projectData, project));
168+
ApplicationManager.getApplication().runWriteAction(() ->
169+
{
170+
runManager.addConfiguration(newRunConfig);
171+
runManager.makeStable(newRunConfig);
172+
runManager.setSelectedConfiguration(newRunConfig);
173+
});
174+
});
164175
}
165176
}
166177

src/xyz/elmot/clion/cubemx/ProjectData.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* (c) elmot on 28.9.2017.
88
*/
99
@SuppressWarnings({"WeakerAccess", "unused"})
10-
class ProjectData {
10+
public class ProjectData {
1111
private String projectName;
1212
private String linkerScript;
1313
private String mcuFamily;
@@ -17,6 +17,7 @@ class ProjectData {
1717
private String includes;
1818
private String sources;
1919
private String mcpu;
20+
private String board;
2021

2122
public void setProjectName(String projectName) {
2223
this.projectName = projectName;
@@ -88,6 +89,10 @@ public String getMcpu() {
8889
return mcpu;
8990
}
9091

92+
public String getBoard() {
93+
return board;
94+
}
95+
9196
public void setDefines(String defines) {
9297
this.defines = defines;
9398
}
@@ -100,6 +105,10 @@ public void setSources(String sources) {
100105
this.sources = sources;
101106
}
102107

108+
public void setBoard(String board) {
109+
this.board = board;
110+
}
111+
103112
@Override
104113
public String toString() {
105114
return "projectName='" + projectName + '\'' +
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package xyz.elmot.clion.cubemx;
2+
3+
import com.intellij.openapi.diagnostic.Logger;
4+
import com.intellij.openapi.project.Project;
5+
import com.intellij.openapi.ui.DialogWrapper;
6+
import com.intellij.openapi.util.Pair;
7+
import com.intellij.openapi.vfs.LocalFileSystem;
8+
import com.intellij.openapi.vfs.VfsUtil;
9+
import com.intellij.openapi.vfs.VirtualFile;
10+
import com.intellij.ui.ListSpeedSearch;
11+
import com.intellij.ui.components.JBList;
12+
import com.intellij.ui.components.JBScrollPane;
13+
import xyz.elmot.clion.openocd.OpenOcdSettingsState;
14+
15+
import javax.swing.*;
16+
import java.awt.event.MouseAdapter;
17+
import java.awt.event.MouseEvent;
18+
import java.io.IOException;
19+
import java.util.ArrayList;
20+
import java.util.Comparator;
21+
import java.util.List;
22+
import java.util.Objects;
23+
import java.util.stream.Stream;
24+
25+
import static xyz.elmot.clion.openocd.OpenOcdComponent.require;
26+
27+
public class SelectBoardDialog extends DialogWrapper {
28+
private static Logger LOGGER = Logger.getInstance(DialogWrapper.class);
29+
private final String[] values;
30+
private int result = 0;
31+
32+
private SelectBoardDialog(Project project, String[] values) {
33+
super(project, false, false);
34+
this.values = values;
35+
setTitle("Board Config Files");
36+
init();
37+
}
38+
39+
@Override
40+
protected JComponent createCenterPanel() {
41+
//todo normal texts
42+
JBList<String> boardList = new JBList<>(values);
43+
boardList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
44+
boardList.setSelectedIndex(result);
45+
boardList.addListSelectionListener(e -> result = boardList.getSelectedIndex());
46+
boardList.addMouseListener(new MouseAdapter() {
47+
@Override
48+
public void mouseClicked(MouseEvent e) {
49+
if (!e.isPopupTrigger() && e.getClickCount() > 1) {
50+
clickDefaultButton();
51+
}
52+
}
53+
});
54+
new ListSpeedSearch<>(boardList);
55+
return new JBScrollPane(boardList);
56+
}
57+
58+
public static String selectBoardByPriority(ProjectData projectData, Project project) {
59+
try {
60+
List<Pair<String, Integer>> keywordWeight = new ArrayList<>();
61+
String board = Objects.toString(projectData.getBoard(), "").toUpperCase();
62+
if (board.isEmpty()) {
63+
LOGGER.info("Board is not defined in the project");
64+
return null;
65+
}
66+
keywordWeight.add(Pair.pair(board, 1000));
67+
Stream.of("NUCLEO", "EVAL").filter(board::contains).findFirst().ifPresent(s -> keywordWeight.add(Pair.pair(s, 100)));
68+
if (board.contains("DISCOVERY")) {
69+
keywordWeight.add(Pair.pair("DISCOVERY", 100));
70+
keywordWeight.add(Pair.pair("DISC", 20));
71+
} else if (board.contains("DISC")) {
72+
keywordWeight.add(Pair.pair("DISC", 100));
73+
keywordWeight.add(Pair.pair("DISCOVERY", 20));
74+
}
75+
String mcuFamily = Objects.toString(projectData.getMcuFamily(), "").toUpperCase();
76+
for (int i = mcuFamily.length() - 1; i >= 6; i--) {
77+
keywordWeight.add(Pair.pair(mcuFamily.substring(0, i), i));
78+
}
79+
OpenOcdSettingsState ocdSettings = project.getComponent(OpenOcdSettingsState.class);
80+
VirtualFile ocdHome = require(LocalFileSystem.getInstance().findFileByPath(ocdSettings.openOcdHome));
81+
VirtualFile ocdScripts = require(OpenOcdSettingsState.findOcdScripts(ocdHome));
82+
VirtualFile[] ocdBoards = require(ocdScripts.findChild("board")).getChildren();
83+
Stream<String> boardByScores =
84+
Stream.of(ocdBoards).parallel().map(ocdBoard ->
85+
{
86+
try {
87+
String text = VfsUtil.loadText(ocdBoard).toUpperCase();
88+
int weight = keywordWeight.parallelStream()
89+
.filter(entry -> text.contains(entry.getFirst()))
90+
.mapToInt(pair -> pair.getSecond()).sum();
91+
return Pair.pair(ocdBoard.getName(), weight);
92+
} catch (IOException e) {
93+
e.printStackTrace();
94+
return Pair.pair(ocdBoard.getName(), 0);
95+
}
96+
}
97+
98+
)
99+
// Show all
100+
//.filter(p -> p.getSecond() != 0)
101+
.sorted(Comparator.comparingInt(p -> -p.getSecond()))
102+
.map(p -> p.getFirst());
103+
String[] values = boardByScores.toArray(String[]::new);
104+
SelectBoardDialog dialog = new SelectBoardDialog(project, values);
105+
dialog.show();
106+
int i = dialog.getExitCode();
107+
if (i == OK_EXIT_CODE) {
108+
return "board/" + dialog.values[dialog.result];
109+
}
110+
} catch (Throwable e) {
111+
LOGGER.error(e);
112+
}
113+
return null;
114+
}
115+
116+
}

src/xyz/elmot/clion/openocd/OpenOcdComponent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static GeneralCommandLine createOcdCommandLine(OpenOcdConfiguration confi
102102
}
103103

104104
@NotNull
105-
private static VirtualFile require(VirtualFile fileToCheck) throws ConfigurationException {
105+
public static VirtualFile require(VirtualFile fileToCheck) throws ConfigurationException {
106106
if (fileToCheck == null) {
107107
openOcdNotFound();
108108
}

src/xyz/elmot/clion/openocd/OpenOcdConfigurationEditor.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@
55
import com.intellij.openapi.project.Project;
66
import com.intellij.openapi.vfs.VfsUtil;
77
import com.intellij.ui.components.fields.IntegerField;
8+
import com.intellij.ui.components.panels.HorizontalBox;
89
import com.intellij.util.ui.GridBag;
910
import com.jetbrains.cidr.cpp.execution.CMakeAppRunConfiguration;
1011
import com.jetbrains.cidr.cpp.execution.CMakeAppRunConfigurationSettingsEditor;
1112
import com.jetbrains.cidr.cpp.execution.CMakeBuildConfigurationHelper;
1213
import org.jdesktop.swingx.JXRadioGroup;
1314
import org.jetbrains.annotations.NotNull;
15+
import xyz.elmot.clion.cubemx.ConvertProject;
16+
import xyz.elmot.clion.cubemx.ProjectData;
17+
import xyz.elmot.clion.cubemx.SelectBoardDialog;
1418
import xyz.elmot.clion.openocd.OpenOcdConfiguration.DownloadType;
1519
import xyz.elmot.clion.openocd.OpenOcdConfiguration.ResetType;
1620

1721
import javax.swing.*;
1822
import java.awt.*;
23+
import java.awt.event.ActionEvent;
1924

2025
public class OpenOcdConfigurationEditor extends CMakeAppRunConfigurationSettingsEditor {
2126
private IntegerField gdbPort;
@@ -58,7 +63,6 @@ protected void resetEditorFrom(@NotNull CMakeAppRunConfiguration cMakeAppRunConf
5863

5964
boardConfigFile.setText(ocd.getBoardConfigFile());
6065

61-
6266
gdbPort.setText("" + ocd.getGdbPort());
6367

6468
telnetPort.setText("" + ocd.getTelnetPort());
@@ -76,9 +80,8 @@ protected void createEditorInner(JPanel panel, GridBag gridBag) {
7680
}
7781
}
7882

79-
panel.add(new JLabel("Board config file"), gridBag.nextLine().next());
80-
boardConfigFile = new FileChooseInput.BoardCfg("Board config", VfsUtil.getUserHomeDir(), this::getOpenocdHome);
81-
panel.add(boardConfigFile, gridBag.next().coverLine());
83+
JPanel boardPanel = createBoardSelector(panel, gridBag);
84+
panel.add(boardPanel, gridBag.next().coverLine());
8285

8386
JPanel portsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
8487

@@ -97,6 +100,25 @@ protected void createEditorInner(JPanel panel, GridBag gridBag) {
97100
panel.add(resetGroup, gridBag.next());
98101
}
99102

103+
@NotNull
104+
private JPanel createBoardSelector(JPanel panel, GridBag gridBag) {
105+
panel.add(new JLabel("Board config file"), gridBag.nextLine().next());
106+
JPanel boardPanel = new HorizontalBox();
107+
boardPanel.add(new JButton(new AbstractAction("Assist...") {
108+
@Override
109+
public void actionPerformed(ActionEvent e) {
110+
ProjectData projectData = ConvertProject.loadProjectData(myProject);
111+
String selectedBoard = SelectBoardDialog.selectBoardByPriority(projectData, myProject);
112+
if(selectedBoard!=null && !"".equals(selectedBoard)) {
113+
boardConfigFile.setText(selectedBoard);
114+
}
115+
}
116+
}));
117+
boardConfigFile = new FileChooseInput.BoardCfg("Board config", VfsUtil.getUserHomeDir(), this::getOpenocdHome);
118+
boardPanel.add(boardConfigFile);
119+
return boardPanel;
120+
}
121+
100122
private IntegerField addPortInput(JPanel portsPanel, String label, int defaultValue) {
101123
portsPanel.add(new JLabel(label + ": "));
102124
IntegerField field = new IntegerField(label, 1024, 65535);

src/xyz/elmot/clion/openocd/OpenOcdConfigurationType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ public static Icon getPluginIcon() {
5252
}
5353

5454
@Override
55-
public SettingsEditor<? extends CMakeAppRunConfiguration> createEditor(@NotNull Project project) {
55+
public OpenOcdConfigurationEditor createEditor(@NotNull Project project) {
5656
return new OpenOcdConfigurationEditor(project, getHelper(project));
5757
}
5858

5959
@NotNull
6060
@Override
61-
protected CMakeAppRunConfiguration createRunConfiguration(@NotNull Project project, @NotNull ConfigurationFactory configurationFactory) {
61+
protected OpenOcdConfiguration createRunConfiguration(@NotNull Project project, @NotNull ConfigurationFactory configurationFactory) {
6262
return new OpenOcdConfiguration(project, factory, "");
6363
}
6464
}

0 commit comments

Comments
 (0)