Skip to content

Commit 828bd87

Browse files
committed
Allow leading underscore in sketch filenames
The Arduino Sketch Specification defines the allowed format of sketch folder names and sketch code filenames. Arduino IDE enforces compliance with the specification in order to ensure sketches created with Arduino IDE can be used with any other Arduino development tool. The Arduino Sketch Specification has been changed to allow a leading underscore in sketch folder names and sketch code filenames so IDE's sketch name validation must be updated accordingly.
1 parent 24dc0bb commit 828bd87

File tree

4 files changed

+16
-18
lines changed

4 files changed

+16
-18
lines changed

arduino-ide-extension/src/common/protocol/sketches-service.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ export namespace Sketch {
176176
// (non-API) exported for the tests
177177
export const invalidSketchFolderNameMessage = nls.localize(
178178
'arduino/sketch/invalidSketchName',
179-
'The name must start with a letter or number, followed by letters, numbers, dashes, dots and underscores. Maximum length is 63 characters.'
179+
'The name must start with a letter, number, or underscore, followed by letters, numbers, dashes, dots and underscores. Maximum length is 63 characters.'
180180
);
181181
const invalidCloudSketchFolderNameMessage = nls.localize(
182182
'arduino/sketch/invalidCloudSketchName',
183-
'The name must start with a letter or number, followed by letters, numbers, dashes, dots and underscores. Maximum length is 36 characters.'
183+
'The name must start with a letter, number, or underscore, followed by letters, numbers, dashes, dots and underscores. Maximum length is 36 characters.'
184184
);
185185
/**
186186
* `undefined` if the candidate sketch folder name is valid. Otherwise, the validation error message.
@@ -193,7 +193,7 @@ export namespace Sketch {
193193
if (validFilenameError) {
194194
return validFilenameError;
195195
}
196-
return /^[0-9a-zA-Z]{1}[0-9a-zA-Z_\.-]{0,62}$/.test(candidate)
196+
return /^[0-9a-zA-Z_]{1}[0-9a-zA-Z_\.-]{0,62}$/.test(candidate)
197197
? undefined
198198
: invalidSketchFolderNameMessage;
199199
}
@@ -208,7 +208,7 @@ export namespace Sketch {
208208
if (validFilenameError) {
209209
return validFilenameError;
210210
}
211-
return /^[0-9a-zA-Z]{1}[0-9a-zA-Z_\.-]{0,35}$/.test(candidate)
211+
return /^[0-9a-zA-Z_]{1}[0-9a-zA-Z_\.-]{0,35}$/.test(candidate)
212212
? undefined
213213
: invalidCloudSketchFolderNameMessage;
214214
}
@@ -253,7 +253,7 @@ export namespace Sketch {
253253
}
254254
const validName = candidate
255255
? candidate
256-
.replace(/^[^0-9a-zA-Z]{1}/g, defaultFallbackFirstChar)
256+
.replace(/^[^0-9a-zA-Z_]{1}/g, defaultFallbackFirstChar)
257257
.replace(/[^0-9a-zA-Z_]/g, defaultFallbackChar)
258258
.slice(0, 63)
259259
: defaultSketchFolderName;
@@ -284,7 +284,7 @@ export namespace Sketch {
284284
}
285285
return candidate
286286
? candidate
287-
.replace(/^[^0-9a-zA-Z]{1}/g, defaultFallbackFirstChar)
287+
.replace(/^[^0-9a-zA-Z_]{1}/g, defaultFallbackFirstChar)
288288
.replace(/[^0-9a-zA-Z_]/g, defaultFallbackChar)
289289
.slice(0, 36)
290290
: defaultSketchFolderName;

arduino-ide-extension/src/test/browser/workspace-commands.test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,22 @@ describe('workspace-commands', () => {
171171
});
172172

173173
it('code files cannot start with number (no extension)', async () => {
174-
const actual = await testMe('_invalid');
174+
const actual = await testMe('-invalid');
175175
expect(actual).to.be.equal(Sketch.invalidSketchFolderNameMessage);
176176
});
177177

178178
it('code files cannot start with number (trailing dot)', async () => {
179-
const actual = await testMe('_invalid.');
179+
const actual = await testMe('-invalid.');
180180
expect(actual).to.be.equal(Sketch.invalidSketchFolderNameMessage);
181181
});
182182

183183
it('code files cannot start with number (trailing dot)', async () => {
184-
const actual = await testMe('_invalid.cpp');
184+
const actual = await testMe('-invalid.cpp');
185185
expect(actual).to.be.equal(Sketch.invalidSketchFolderNameMessage);
186186
});
187187

188188
it('should warn about invalid extension first', async () => {
189-
const actual = await testMe('_invalid.xxx');
189+
const actual = await testMe('-invalid.xxx');
190190
expect(actual).to.be.equal(invalidExtensionMessage('.xxx'));
191191
});
192192

@@ -196,7 +196,7 @@ describe('workspace-commands', () => {
196196
});
197197

198198
it('should ignore non-code filename validation from the spec', async () => {
199-
const actual = await testMe('_invalid.json');
199+
const actual = await testMe('-invalid.json');
200200
expect(actual).to.be.empty;
201201
});
202202

arduino-ide-extension/src/test/common/sketches-service.test.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ describe('sketch', () => {
4343
['trailing.dots...', false],
4444
['no.trailing.dots.._', true],
4545
['No Spaces', false],
46-
['_invalidToStartWithUnderscore', false],
46+
['_validToStartWithUnderscore', true],
4747
['Invalid+Char.ino', false],
4848
['', false],
4949
['/', false],
@@ -81,7 +81,7 @@ describe('sketch', () => {
8181
['can.contain.dots', true],
8282
['-cannot-start-with-dash', false],
8383
['.cannot.start.with.dash', false],
84-
['_cannot_start_with_underscore', false],
84+
['_can_start_with_underscore', true],
8585
['No Spaces', false],
8686
['Invalid+Char.ino', false],
8787
['', false],
@@ -115,7 +115,7 @@ describe('sketch', () => {
115115
'012345678901234567890123456789012345678901234567890123456789012',
116116
],
117117
['foo bar', 'foo_bar'],
118-
['_foobar', '0foobar'],
118+
['-foobar', '0foobar'],
119119
['vAlid', 'vAlid'],
120120
['COM1', Sketch.defaultSketchFolderName],
121121
['COM1.', 'COM1_'],
@@ -166,9 +166,7 @@ describe('sketch', () => {
166166
['dots...', 'dots___'],
167167
['.dots...', '0dots___'],
168168
['-dashes---', '0dashes___'],
169-
['_underscore___', '0underscore___'],
170169
['No Spaces', 'No_Spaces'],
171-
['_startsWithUnderscore', '0startsWithUnderscore'],
172170
['Invalid+Char.ino', 'Invalid_Char_ino'],
173171
['', 'sketch'],
174172
['/', '0'],

i18n/en.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,11 @@
419419
"editInvalidSketchFolderLocationQuestion": "Do you want to try saving the sketch to a different location?",
420420
"editInvalidSketchFolderQuestion": "Do you want to try saving the sketch with a different name?",
421421
"exportBinary": "Export Compiled Binary",
422-
"invalidCloudSketchName": "The name must start with a letter or number, followed by letters, numbers, dashes, dots and underscores. Maximum length is 36 characters.",
422+
"invalidCloudSketchName": "The name must start with a letter, number, or underscore, followed by letters, numbers, dashes, dots and underscores. Maximum length is 36 characters.",
423423
"invalidSketchFolderLocationDetails": "You cannot save a sketch into a folder inside itself.",
424424
"invalidSketchFolderLocationMessage": "Invalid sketch folder location: '{0}'",
425425
"invalidSketchFolderNameMessage": "Invalid sketch folder name: '{0}'",
426-
"invalidSketchName": "The name must start with a letter or number, followed by letters, numbers, dashes, dots and underscores. Maximum length is 63 characters.",
426+
"invalidSketchName": "The name must start with a letter, number, or underscore, followed by letters, numbers, dashes, dots and underscores. Maximum length is 63 characters.",
427427
"moving": "Moving",
428428
"movingMsg": "The file \"{0}\" needs to be inside a sketch folder named \"{1}\".\nCreate this folder, move the file, and continue?",
429429
"new": "New Sketch",

0 commit comments

Comments
 (0)