Skip to content

Commit 4e70374

Browse files
committed
Roll saveOnSend plugin into codeWriter, where it makes more sense (for espruino/EspruinoWebIDE#312)
1 parent bab35c9 commit 4e70374

4 files changed

Lines changed: 119 additions & 141 deletions

File tree

core/codeWriter.js

Lines changed: 117 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,126 @@
2929
type : "boolean",
3030
defaultValue : true
3131
});
32+
Espruino.Core.Config.add("SAVE_ON_SEND", {
33+
section : "Communications",
34+
subSection: "Storage",
35+
name : "Save on Send",
36+
descriptionHTML : 'How should code be uploaded? See <a href="http://www.espruino.com/Saving" target="_blank">espruino.com/Saving</a> for more information.<br>'+
37+
"<b>NOTE:</b> Avoid 'Direct to flash, even after <code>reset()</code>' for normal development - it can make it hard to recover if your code crashes the device.",
38+
type : {
39+
// -1: is used by the app loader to signify that we want the code as-is (app loader adds write statements). Allows pretokenise to correctly check if we're writing to RAM or not
40+
0: "To RAM (default) - execute code while uploading. Use 'save()' to save a RAM image to Flash",
41+
1: "Direct to Flash (execute code at boot)",
42+
2: "Direct to Flash (execute code at boot, even after 'reset()') - USE WITH CARE",
43+
3: "To Storage File (see 'File in Storage to send to')",
44+
},
45+
defaultValue : 0
46+
});
47+
Espruino.Core.Config.add("SAVE_STORAGE_FILE", {
48+
section : "Communications",
49+
subSection: "Storage",
50+
name : "Send to File in Storage",
51+
descriptionHTML : "If <code>Save on Send</code> is set to <code>To Storage File</code>, this is the name of the file to write to.",
52+
type : "string",
53+
defaultValue : "myapp"
54+
});
55+
Espruino.Core.Config.add("LOAD_STORAGE_FILE", {
56+
section : "Communications",
57+
subSection: "Storage",
58+
name : "Load after saving",
59+
descriptionHTML : "This applies only if saving to Flash (not RAM)",
60+
type : {
61+
0: "Don't load",
62+
1: "Load default application",
63+
2: "Load the Storage File just written to"
64+
},
65+
defaultValue : 2
66+
});
67+
}
68+
69+
/** Convert code into the JS commands needed to upload that code */
70+
function getUploadCommands(code) {
71+
// convert any non-0..255 charcodes to UTF8 encoding
72+
code = Espruino.Core.Utils.asUTF8Bytes(code);
73+
// Depending on settings, choose how we package code for upload (see Espruino.Core.Send.SEND_MODE_* constants)
74+
var isFlashPersistent = Espruino.Config.SAVE_ON_SEND == 2;
75+
var isStorageUpload = Espruino.Config.SAVE_ON_SEND == 3;
76+
var isSDCardUpload = Espruino.Config.SAVE_ON_SEND == 4;
77+
var isFlashUpload = Espruino.Config.SAVE_ON_SEND == 1 || isFlashPersistent || isStorageUpload;
78+
if (!isFlashUpload && !isSDCardUpload) {
79+
// Just uploading to RAM
80+
/* hack around non-K&R code formatting that would have
81+
broken Espruino CLI's bracket counting */
82+
return reformatCodeForREPL(code);
83+
}
84+
85+
var asJS = Espruino.Core.Utils.toJSONishString;
3286

87+
// Check environment vars
88+
var hasStorage = false;
89+
var ENV = Espruino.Core.Env.getData();
90+
if (ENV &&
91+
ENV.VERSION_MAJOR &&
92+
ENV.VERSION_MINOR!==undefined) {
93+
if (ENV.VERSION_MAJOR>1 ||
94+
ENV.VERSION_MINOR>=96) {
95+
hasStorage = true;
96+
}
97+
}
98+
const CHUNKSIZE = 1024;
99+
100+
// Now create the commands to do the upload
101+
console.log("Uploading "+code.length+" bytes to flash");
102+
// FIXME: We should use Serial's Connection class packet stuff for file uploads
103+
if (!hasStorage) { // old style
104+
if (isStorageUpload || isSDCardUpload) {
105+
Espruino.Core.Notifications.error("You have pre-1v96 firmware - unable to upload to Storage");
106+
code = "";
107+
} else {
108+
Espruino.Core.Notifications.error("You have pre-1v96 firmware. Upload size is limited by available RAM");
109+
code = "E.setBootCode("+asJS(code)+(isFlashPersistent?",true":"")+");";
110+
}
111+
} else if (isSDCardUpload) {
112+
var filename = Espruino.Config.SAVE_STORAGE_FILE;;
113+
var newCode = [ `let _ul = E.openFile(${asJS(filename)},"w");` ];
114+
var len = code.length;
115+
for (var i=0;i<len;i+=CHUNKSIZE)
116+
newCode.push(`_ul.write(${asJS(code.substr(i,CHUNKSIZE))});`);
117+
newCode.push(`_ul.close();delete _ul;`);
118+
code = "\x10"+newCode.join("\n\x10")+"\n";
119+
} else { // new style
120+
var filename;
121+
if (isStorageUpload)
122+
filename = Espruino.Config.SAVE_STORAGE_FILE;
123+
else
124+
filename = isFlashPersistent ? ".bootrst" : ".bootcde";
125+
if (!filename || filename.length>28) {
126+
Espruino.Core.Notifications.error("Invalid Storage file name "+JSON.stringify(filename));
127+
code = "";
128+
} else {
129+
var newCode = [];
130+
var len = code.length;
131+
newCode.push('require("Storage").write('+asJS(filename)+','+asJS(code.substr(0,CHUNKSIZE))+',0,'+len+');');
132+
for (var i=CHUNKSIZE;i<len;i+=CHUNKSIZE)
133+
newCode.push('require("Storage").write('+asJS(filename)+','+asJS(code.substr(i,CHUNKSIZE))+','+i+');');
134+
code = "\x10"+newCode.join("\n\x10")+"\n";
135+
}
136+
}
137+
if (Espruino.Config.LOAD_STORAGE_FILE==2 && isStorageUpload)
138+
code += "\x10load("+asJS(filename)+")\n";
139+
else if (Espruino.Config.LOAD_STORAGE_FILE!=0)
140+
code += "\x10load()\n";
141+
return code;
33142
}
34143

144+
35145
function writeToEspruino(code, callback) {
36-
/* hack around non-K&R code formatting that would have
37-
broken Espruino CLI's bracket counting */
38-
code = reformatCode(code);
39146
if (code === undefined) return; // it should already have errored
40147

148+
/* If needed, convert code to upload to a set of JS commands
149+
which will upload the code into Espruino's flash/etc */
150+
code = getUploadCommands(code);
151+
41152
// We want to make sure we've got a prompt before sending. If not,
42153
// this will issue a Ctrl+C
43154
Espruino.Core.Utils.getEspruinoPrompt(function() {
@@ -81,7 +192,7 @@
81192
* @param {string} code
82193
* @returns {string | undefined}
83194
*/
84-
function reformatCode(code) {
195+
function reformatCodeForREPL(code) {
85196
var APPLY_LINE_NUMBERS = false;
86197
var lineNumberOffset = 0;
87198
var ENV = Espruino.Core.Env.getData();
@@ -211,7 +322,7 @@
211322
if (previousBrackets==0 &&
212323
previousString.indexOf("\n")>=0 &&
213324
previousString.indexOf("\x1B\x0A")<0) {
214-
previousString = "\n\x10";
325+
previousString = "\n\x10";//FIXME
215326
// Apply line numbers to each new line sent, to aid debugger
216327
if (APPLY_LINE_NUMBERS && tok.lineNumber && (tok.lineNumber+lineNumberOffset)>0) {
217328
// Esc [ 1234 d
@@ -242,6 +353,6 @@
242353
Espruino.Core.CodeWriter = {
243354
init : init,
244355
writeToEspruino : writeToEspruino, // call this to send to Espruino
245-
reformatCode : reformatCode // Parse and fix issues like `if (false)\n foo` in the root scope
356+
reformatCodeForREPL : reformatCodeForREPL // Parse and fix issues like `if (false)\n foo` in the root scope
246357
};
247358
}());

plugins/pretokenise.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@
313313

314314
Espruino.Plugins.Pretokenise = {
315315
init : init,
316-
sortOrder : 100, // after most plugins, before saveOnSend
316+
sortOrder : 100, // after most plugins
317317
isTokenised : isTokenised, // could the given data be tokenised JS?
318318
untokenise : untokenise, // fn(code) convert a file containing tokens back into strings
319319
tokenise : tokenise // fn(code) convert a file containing tokens back into strings

plugins/saveOnSend.js

Lines changed: 0 additions & 133 deletions
This file was deleted.

plugins/setTime.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@
3636

3737
Espruino.Plugins.SetTime = {
3838
init : init,
39-
sortOrder : 1100, // after pretty much everything, speficically saveOnSend
39+
sortOrder : 1100, // after pretty much everything
4040
};
4141
}());

0 commit comments

Comments
 (0)