Skip to content

Commit 566e2f7

Browse files
committed
v1.3.0
* Support % and $ commands * Add new `flatten` option to flatten the output array
1 parent 37e70b3 commit 566e2f7

File tree

4 files changed

+117
-43
lines changed

4 files changed

+117
-43
lines changed

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ var fs = require('fs');
1212
var parser = require('gcode-parser');
1313

1414
// parseLine
15-
var line = 'G0 X0 Y0';
16-
var result = parser.parseLine(line);
17-
console.log(result);
15+
parser.parseLine('G0 X0 Y0');
16+
// => { line: 'G0 X0 Y0', words: [ [ 'G', 0 ], [ 'X', 0 ], [ 'Y', 0 ] ] }
17+
18+
// parseLine (flatten mode)
19+
parser.parseLine('G0 X0 Y0', { flatten: true });
20+
// => { line: 'G0 X0 Y0', words: [ 'G0', 'X0', 'Y0' ] }
1821

1922
// parseFile
2023
var file = 'example.nc';
@@ -81,6 +84,17 @@ Default: `1000`
8184

8285
The batch size.
8386

87+
### flatten
88+
89+
Type: `Boolean`
90+
Default: `false`
91+
92+
True to flatten the array, false otherwise.
93+
94+
```js
95+
parser.parseLine('G0 X0 Y0', { flatten: true });
96+
```
97+
8498
### noParseLine
8599

86100
Type: `Boolean`

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gcode-parser",
3-
"version": "1.2.0",
3+
"version": "1.3.0",
44
"description": "G-code parser for Node.js",
55
"author": "Cheton Wu <cheton@gmail.com>",
66
"homepage": "https://github.com/cncjs/gcode-parser",

src/index.js

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -70,53 +70,74 @@ const parseLine = (() => {
7070
const re3 = new RegExp(/\s+/g);
7171
return (line => line.replace(re1, '').replace(re2, '').replace(re3, ''));
7272
})();
73-
const re = /([a-zA-Z][0-9\+\-\.]*)|(\*[0-9]+)|(\$[a-zA-Z0-9$#]*)/igm;
73+
const re = /(%[a-zA-Z][a-zA-Z0-9_]*)|([a-zA-Z][0-9\+\-\.]*)|(\*[0-9]+)|((?:\$\$)|(?:\$[a-zA-Z0-9#]*))/igm;
7474

7575
return (line, options) => {
7676
options = options || {};
77-
options.noParseLine = options.noParseLine || false;
77+
options.flatten = !!options.flatten;
78+
options.noParseLine = !!options.noParseLine;
7879

7980
const result = {
8081
line: line
8182
};
8283

83-
if (!options.noParseLine) {
84-
result.words = [];
85-
86-
let ln; // Line number
87-
let cs; // Checksum
88-
const words = stripComments(line).match(re) || [];
89-
for (let i = 0; i < words.length; ++i) {
90-
const word = words[i];
91-
const letter = word[0].toUpperCase();
92-
const argument = word.slice(1);
93-
94-
// $: Grbl-specific commands
95-
if (letter === '$') {
96-
continue;
97-
}
98-
99-
// N: Line number
100-
if (letter === 'N' && typeof ln === 'undefined') {
101-
// Line (block) number in program
102-
ln = Number(argument);
103-
continue;
104-
}
105-
106-
// *: Checksum
107-
if (letter === '*' && typeof cs === 'undefined') {
108-
cs = Number(argument);
109-
continue;
110-
}
84+
if (options.noParseLine) {
85+
return result;
86+
}
11187

112-
result.words.push([letter, Number(argument)]);
88+
result.words = [];
89+
90+
let ln; // Line number
91+
let cs; // Checksum
92+
const words = stripComments(line).match(re) || [];
93+
94+
for (let i = 0; i < words.length; ++i) {
95+
const word = words[i];
96+
const letter = word[0].toUpperCase();
97+
const argument = word.slice(1);
98+
99+
// Parse % commands for bCNC and CNCjs
100+
// - %wait Wait until the planner queue is empty
101+
if (letter === '%') {
102+
result.cmds = (result.cmds || []).concat(`${letter}${argument}`);
103+
continue;
104+
}
105+
106+
// Parse $ commands for Grbl
107+
// - $C Check gcode mode
108+
// - $H Run homing cycle
109+
if (letter === '$') {
110+
result.cmds = (result.cmds || []).concat(`${letter}${argument}`);
111+
continue;
113112
}
114113

115-
(typeof(ln) !== 'undefined') && (result.ln = ln); // Line number
116-
(typeof(cs) !== 'undefined') && (result.cs = cs); // Checksum
117-
if (result.cs && (computeChecksum(line) !== result.cs)) {
118-
result.err = true; // checksum failed
114+
// N: Line number
115+
if (letter === 'N' && typeof ln === 'undefined') {
116+
// Line (block) number in program
117+
ln = Number(argument);
118+
continue;
119119
}
120+
121+
// *: Checksum
122+
if (letter === '*' && typeof cs === 'undefined') {
123+
cs = Number(argument);
124+
continue;
125+
}
126+
127+
if (options.flatten) {
128+
result.words.push(`${letter}${argument}`);
129+
} else {
130+
result.words.push([letter, Number(argument)]);
131+
}
132+
}
133+
134+
// Line number
135+
(typeof(ln) !== 'undefined') && (result.ln = ln);
136+
137+
// Checksum
138+
(typeof(cs) !== 'undefined') && (result.cs = cs);
139+
if (result.cs && (computeChecksum(line) !== result.cs)) {
140+
result.err = true; // checksum failed
120141
}
121142

122143
return result;
@@ -184,7 +205,7 @@ const parseString = (str, options, callback = noop) => {
184205
};
185206

186207
const parseStringSync = (str, options) => {
187-
const { noParseLine = false } = { ...options };
208+
const { flatten = false, noParseLine = false } = { ...options };
188209
const results = [];
189210
const lines = str.split('\n');
190211

@@ -193,7 +214,10 @@ const parseStringSync = (str, options) => {
193214
if (line.length === 0) {
194215
continue;
195216
}
196-
const result = parseLine(line, { noParseLine });
217+
const result = parseLine(line, {
218+
flatten,
219+
noParseLine
220+
});
197221
results.push(result);
198222
}
199223

@@ -218,6 +242,7 @@ class GCodeLineStream extends Transform {
218242

219243
// @param {object} [options] The options object
220244
// @param {number} [options.batchSize] The batch size.
245+
// @param {boolean} [options.flatten] True to flatten the array, false otherwise.
221246
// @param {boolean} [options.noParseLine] True to not parse line, false otherwise.
222247
constructor(options = {}) {
223248
super({ objectMode: true });
@@ -271,6 +296,7 @@ class GCodeLineStream extends Transform {
271296
line = line.trim();
272297
if (line.length > 0) {
273298
const result = parseLine(line, {
299+
flatten: this.options.flatten,
274300
noParseLine: this.options.noParseLine
275301
});
276302
this.push(result);
@@ -282,6 +308,7 @@ class GCodeLineStream extends Transform {
282308
const line = this.lineBuffer.trim();
283309
if (line.length > 0) {
284310
const result = parseLine(line, {
311+
flatten: this.options.flatten,
285312
noParseLine: this.options.noParseLine
286313
});
287314
this.push(result);

test/index.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import chai from 'chai';
22
import fs from 'fs';
33
import {
44
GCodeParser,
5+
parseLine,
56
parseStream,
67
parseString,
78
parseStringSync,
@@ -64,8 +65,27 @@ describe('gcode-parser', () => {
6465
});
6566
});
6667

68+
describe('Commands', () => {
69+
it('should parse $ commands for Grbl.', (done) => {
70+
const data = parseLine('$H $C');
71+
expect(data).to.be.an('object');
72+
expect(data.line).to.be.an('string');
73+
expect(data.words).to.be.empty;
74+
expect(data.cmds).to.deep.equal(['$H', '$C']);
75+
done();
76+
});
77+
it('should parse % commands for bCNC and CNCjs.', (done) => {
78+
const data = parseLine('%wait');
79+
expect(data).to.be.an('object');
80+
expect(data.line).to.be.an('string');
81+
expect(data.words).to.be.empty;
82+
expect(data.cmds).to.deep.equal(['%wait']);
83+
done();
84+
});
85+
});
86+
6787
describe('Comments', () => {
68-
it('should strip everything after %, #, or ; to the end of the loine including preceding spaces.', (done) => {
88+
it('should strip everything after a semi-colon to the end of the loine including preceding spaces.', (done) => {
6989
const sampleText = [
7090
' % ',
7191
' #',
@@ -122,7 +142,6 @@ describe('gcode-parser', () => {
122142

123143
parseString(sampleText, (err, results) => {
124144
results = results.map(result => {
125-
console.error('###', result);
126145
const words = result.words.map(word => {
127146
return word.join('');
128147
});
@@ -192,6 +211,20 @@ describe('gcode-parser', () => {
192211
});
193212
});
194213

214+
describe('parseLine()', () => {
215+
it('should return expected results.', (done) => {
216+
expect(parseLine('G0 X0 Y0')).to.deep.equal({
217+
line: 'G0 X0 Y0',
218+
words: [ [ 'G', 0 ], [ 'X', 0 ], [ 'Y', 0 ] ]
219+
});
220+
expect(parseLine('G0 X0 Y0', { flatten: true })).to.deep.equal({
221+
line: 'G0 X0 Y0',
222+
words: [ 'G0', 'X0', 'Y0' ]
223+
});
224+
done();
225+
});
226+
});
227+
195228
describe('parseStream()', () => {
196229
const expectedResults = [
197230
{

0 commit comments

Comments
 (0)