Skip to content

Commit e868241

Browse files
committed
Library configuration file management (issue arduino#1734)
When an application uses a library supporting configuration: - the library configuration file is stored in the sketch folder as a project ressource. - a sketch tab is created in Arduino IDE to edit the library configuration file This commit manages following actions: - create configuration file tab when opening a sketch which uses a Library configuration file - copy the configuration file in the sketch folder and create a configuration file tab when importing a library which uses a library configuration file - add the library configuration file (from sketch) as include file when compiling the library only Added as an example, Morse library supporting configuration file
1 parent 63e33be commit e868241

File tree

12 files changed

+613
-12
lines changed

12 files changed

+613
-12
lines changed

app/src/processing/app/Sketch.java

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ public class Sketch {
7373

7474
/** code folder location for this sketch (may not exist yet) */
7575
private File codeFolder;
76-
76+
77+
/** configuration folder location for this sketch (may not exist yet) */
78+
private File configFolder;
79+
7780
private SketchCode current;
7881
private int currentIndex;
7982
/**
@@ -160,15 +163,24 @@ public Sketch(Editor editor, String path) throws IOException {
160163
protected void load() throws IOException {
161164
codeFolder = new File(folder, "code");
162165
dataFolder = new File(folder, "data");
166+
configFolder = new File(folder, "configuration");
163167

164168
// get list of files in the sketch folder
165169
String list[] = folder.list();
170+
// get list of files in the library configuration folder
171+
String list1[] = configFolder.list();
166172

167173
// reset these because load() may be called after an
168174
// external editor event. (fix for 0099)
169175
codeCount = 0;
170-
171-
code = new SketchCode[list.length];
176+
177+
// Add files from library configuration folder if exists
178+
if (configFolder.exists()) {
179+
code = new SketchCode[list.length+list1.length];
180+
}
181+
else {
182+
code = new SketchCode[list.length];
183+
}
172184

173185
String[] extensions = getExtensions();
174186

@@ -203,6 +215,38 @@ protected void load() throws IOException {
203215
if (codeCount == 0)
204216
throw new IOException(_("No valid code files found"));
205217

218+
//Check library configuration folder to create tabs for library configuration files
219+
if (configFolder.exists()) {
220+
for (String filename : list1) {
221+
// Ignoring the dot prefix files is especially important to avoid files
222+
// with the ._ prefix on Mac OS X. (You'll see this with Mac files on
223+
// non-HFS drives, i.e. a thumb drive formatted FAT32.)
224+
if (filename.startsWith(".")) continue;
225+
226+
// Don't let some wacko name a directory blah.pde or bling.java.
227+
if (new File(configFolder, filename).isDirectory()) continue;
228+
229+
// figure out the name without any extension
230+
String base = filename;
231+
// now strip off the .pde and .java extensions
232+
for (String extension : extensions) {
233+
if (base.toLowerCase().endsWith("." + extension)) {
234+
base = base.substring(0, base.length() - (extension.length() + 1));
235+
236+
// Don't allow people to use files with invalid names, since on load,
237+
// it would be otherwise possible to sneak in nasty filenames. [0116]
238+
if (Sketch.isSanitaryName(base)) {
239+
code[codeCount++] = new SketchCode(new File(configFolder, filename), extension);
240+
// Don't forget to declare it as configuration file
241+
code[codeCount-1].setConfig(true);
242+
} else {
243+
editor.console.message(I18n.format("File name {0} is invalid: ignored", filename), true, false);
244+
}
245+
}
246+
}
247+
}
248+
}
249+
206250
// Remove any code that wasn't proper
207251
code = (SketchCode[]) PApplet.subset(code, 0, codeCount);
208252

@@ -878,7 +922,14 @@ protected boolean saveAs() throws IOException {
878922

879923
// now make a fresh copy of the folder
880924
newFolder.mkdirs();
881-
925+
926+
// If exists, make a copy of the configuration folder
927+
File newConfigFolder= new File(newFolder, "configuration");
928+
if (configFolder.exists()) {
929+
Base.copyDir(configFolder, newConfigFolder);
930+
}
931+
932+
882933
// grab the contents of the current tab before saving
883934
// first get the contents of the editor text area
884935
if (current.isModified()) {
@@ -887,10 +938,17 @@ protected boolean saveAs() throws IOException {
887938

888939
// save the other tabs to their new location
889940
for (int i = 1; i < codeCount; i++) {
890-
File newFile = new File(newFolder, code[i].getFileName());
941+
// Library configuration file is not saved in the sketch folder but in the configuration folder
942+
File newFile;
943+
if (code[i].isConfig() && configFolder.exists()) {
944+
newFile = new File(newConfigFolder, code[i].getFileName());
945+
}
946+
else {
947+
newFile = new File(newFolder, code[i].getFileName());
948+
}
891949
code[i].saveAs(newFile);
892950
}
893-
951+
894952
// re-copy the data folder (this may take a while.. add progress bar?)
895953
if (dataFolder.exists()) {
896954
File newDataFolder = new File(newFolder, "data");
@@ -1117,12 +1175,28 @@ public void importLibrary(File jarPath) throws IOException {
11171175

11181176
String list[] = Base.headerListFromIncludePath(jarPath);
11191177

1178+
// If exists, make a copy of the library configuration file in the sketch folder
1179+
File LibConfigFolder = new File(jarPath, "configuration");
1180+
if (LibConfigFolder.exists()) {
1181+
System.out.println("Library configuration files found" );
1182+
File NewLibConfigFolder = (new File(folder,"configuration"));
1183+
Base.copyDir(LibConfigFolder, NewLibConfigFolder);
1184+
// Update editor tabs
1185+
load();
1186+
// Need to switch between tabs to refresh the current content
1187+
if (code[1].fileExists()) {
1188+
setCurrentCode(1);
1189+
}
1190+
setCurrentCode(0);
1191+
}
1192+
11201193
// import statements into the main sketch file (code[0])
11211194
// if the current code is a .java file, insert into current
11221195
//if (current.flavor == PDE) {
11231196
if (hasDefaultExtension(current)) {
11241197
setCurrentCode(0);
11251198
}
1199+
11261200
// could also scan the text in the file to see if each import
11271201
// statement is already in there, but if the user has the import
11281202
// commented out, then this will be a problem.
@@ -1136,6 +1210,7 @@ public void importLibrary(File jarPath) throws IOException {
11361210
buffer.append(editor.getText());
11371211
editor.setText(buffer.toString());
11381212
editor.setSelection(0, 0); // scroll to start
1213+
11391214
setModified(true);
11401215
}
11411216

@@ -1405,7 +1480,20 @@ public void preprocess(String buildPath, PdePreprocessor preprocessor) throws Ru
14051480
// shtuff so that unicode bunk is properly handled
14061481
String filename = sc.getFileName(); //code[i].name + ".java";
14071482
try {
1408-
Base.saveFile(sc.getProgram(), new File(buildPath, filename));
1483+
// Is it a Library configuration file ?
1484+
if (sc.isConfig()) {
1485+
File TempLibConfigFolder = new File(buildPath, "configuration");
1486+
// Create the Library Configuration folder if it doesn't exist
1487+
if(!TempLibConfigFolder.exists()){
1488+
TempLibConfigFolder.mkdir();
1489+
}
1490+
// Copy file in configuration folder
1491+
Base.saveFile(sc.getProgram(), new File(TempLibConfigFolder.getAbsolutePath(), filename));
1492+
}
1493+
else {
1494+
// Copy file in build folder
1495+
Base.saveFile(sc.getProgram(), new File(buildPath, filename));
1496+
}
14091497
} catch (IOException e) {
14101498
e.printStackTrace();
14111499
throw new RunnerException(I18n.format(_("Problem moving {0} to the build folder"), filename));
@@ -1962,6 +2050,25 @@ public File prepareCodeFolder() {
19622050
return codeFolder;
19632051
}
19642052

2053+
/**
2054+
* Returns the location of the sketch's configuration folder. (It may not exist yet.)
2055+
*/
2056+
public File getConfigFolder() {
2057+
return configFolder;
2058+
}
2059+
2060+
2061+
/**
2062+
* Create the config folder if it does not exist already. As a convenience,
2063+
* it also returns the config folder, since it's likely about to be used.
2064+
*/
2065+
public File prepareConfigFolder() {
2066+
if (!configFolder.exists()) {
2067+
configFolder.mkdirs();
2068+
}
2069+
return configFolder;
2070+
}
2071+
19652072

19662073
public String getClassPath() {
19672074
return classPath;

app/src/processing/app/SketchCode.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class SketchCode {
6363
private int scrollPosition;
6464

6565
private boolean modified;
66+
private boolean config = false; // This attribute allows to differentiate Library configuration files (if true) from other files ( if false)
6667

6768
/** name of .java file after preproc */
6869
// private String preprocName;
@@ -126,11 +127,15 @@ public boolean accept(File pathname) {
126127

127128

128129
protected boolean renameTo(File what, String ext) {
129-
boolean success = file.renameTo(what);
130-
if (success) {
131-
file = what;
132-
extension = ext;
133-
makePrettyName();
130+
boolean success = false;
131+
// rename is not allowed for Library configuration files
132+
if (!config) {
133+
success = file.renameTo(what);
134+
if (success) {
135+
file = what;
136+
extension = ext;
137+
makePrettyName();
138+
}
134139
}
135140
return success;
136141
}
@@ -186,6 +191,16 @@ public boolean isModified() {
186191
}
187192

188193

194+
public void setConfig(boolean _config) {
195+
this.config = _config;
196+
}
197+
198+
199+
public boolean isConfig() {
200+
return config;
201+
}
202+
203+
189204
// public void setPreprocName(String preprocName) {
190205
// this.preprocName = preprocName;
191206
// }

app/src/processing/app/debug/Compiler.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,11 @@ private void compileLibrary(Library lib, List<File> includeFolders)
633633
throws RunnerException {
634634
File libFolder = lib.getSrcFolder();
635635
File libBuildFolder = prefs.getFile(("build.path"), lib.getName());
636+
// Manage library configuration files
637+
File libConfigFolder = prefs.getFile(("build.path"), "configuration");
638+
if (libConfigFolder.exists()) {
639+
includeFolders.add(libConfigFolder);
640+
}
636641

637642
if (lib.useRecursion()) {
638643
// libBuildFolder == {build.path}/LibName
@@ -654,6 +659,11 @@ private void compileLibrary(Library lib, List<File> includeFolders)
654659
// other libraries should not see this library's utility/ folder
655660
includeFolders.remove(utilityFolder);
656661
}
662+
// other libraries should not see this library configuration folder
663+
if (libConfigFolder.exists()) {
664+
includeFolders.remove(libConfigFolder);
665+
}
666+
657667
}
658668

659669
private void recursiveCompileFilesInFolder(File srcBuildFolder, File srcFolder, List<File> includeFolders) throws RunnerException {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
LibMorseConf.h - Morse library configuration file.
3+
Created by Gilles De Vos, December 10, 2013.
4+
Released into the public domain.
5+
*/
6+
7+
#ifndef LIBMORSECONF_H
8+
#define LIBMORSECONF_H
9+
10+
11+
#define LIB_MORSE_UNIT 100 //!< Time duration (ms) of elementary Morse code
12+
13+
// International Morse code elements
14+
#define LIB_MORSE_DOT_DURATION LIB_MORSE_UNIT //!< Time duration (ms) of a dot
15+
#define LIB_MORSE_DASH_DURATION 3*LIB_MORSE_UNIT //!< Time duration (ms) of a dash
16+
#define LIB_MORSE_INTR_CHAR_GAP LIB_MORSE_UNIT //!< Time duration (ms) between the dots and dashes within a character
17+
#define LIB_MORSE_SHORT_GAP 3*LIB_MORSE_UNIT //!< Time duration (ms) between characters
18+
#define LIB_MORSE_MEDIUM_GAP 7*LIB_MORSE_UNIT //!< Time duration (ms) between words
19+
20+
#define LIB_MORSE_ALPHABET_AVAILABLE //!< Encoded characters are available
21+
22+
#endif //LIBMORSECONF_H
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
#include <Morse.h>
3+
4+
Morse morse(13);
5+
6+
void setup()
7+
{
8+
}
9+
10+
void loop()
11+
{
12+
morse._S();
13+
morse._O();
14+
morse._S();
15+
morse.endword();
16+
17+
}
18+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
LibMorseConf.h - Morse library configuration file.
3+
Created by Gilles De Vos, December 10, 2013.
4+
Released into the public domain.
5+
*/
6+
7+
#ifndef LIBMORSECONF_H
8+
#define LIBMORSECONF_H
9+
10+
11+
#define LIB_MORSE_UNIT 250 //!< Time duration (ms) of elementary Morse code
12+
13+
// International Morse code elements
14+
#define LIB_MORSE_DOT_DURATION LIB_MORSE_UNIT //!< Time duration (ms) of a dot
15+
#define LIB_MORSE_DASH_DURATION 3*LIB_MORSE_UNIT //!< Time duration (ms) of a dash
16+
#define LIB_MORSE_INTR_CHAR_GAP LIB_MORSE_UNIT //!< Time duration (ms) between the dots and dashes within a character
17+
#define LIB_MORSE_SHORT_GAP 3*LIB_MORSE_UNIT //!< Time duration (ms) between characters
18+
#define LIB_MORSE_MEDIUM_GAP 7*LIB_MORSE_UNIT //!< Time duration (ms) between words
19+
20+
//#define LIB_MORSE_ALPHABET_AVAILABLE //!< Encoded characters are available
21+
22+
#endif //LIBMORSECONF_H
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
#include <Morse.h>
3+
4+
Morse morse(13);
5+
6+
void setup()
7+
{
8+
}
9+
10+
void loop()
11+
{
12+
morse.dot(); morse.dot(); morse.dot(); morse.endchar();
13+
morse.dash(); morse.dash(); morse.dash(); morse.endchar();
14+
morse.dot(); morse.dot(); morse.dot(); morse.endchar();
15+
morse.endword();
16+
}
17+

0 commit comments

Comments
 (0)