From 94bebf31ac063f87d659fb868334a8599619f4a9 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 5 Feb 2015 19:30:11 -0800 Subject: [PATCH] Pre-collect info about options on field init - When initializing fields use the configuration to determine the format - Cache the line for each option for fastest string compare / replace - Add logging levels for debugging --- Marlin/configurator/index.html | 9 + Marlin/configurator/js/configurator.js | 224 ++++++++++++++++++------- 2 files changed, 176 insertions(+), 57 deletions(-) diff --git a/Marlin/configurator/index.html b/Marlin/configurator/index.html index 65299e3a22..aa2c106a69 100644 --- a/Marlin/configurator/index.html +++ b/Marlin/configurator/index.html @@ -48,6 +48,15 @@ + + + + + + + + +

Marlin/Configuration.h


         

Marlin/Configuration_adv.h

diff --git a/Marlin/configurator/js/configurator.js b/Marlin/configurator/js/configurator.js index dfd91119d5..30ca5ef3a6 100644 --- a/Marlin/configurator/js/configurator.js +++ b/Marlin/configurator/js/configurator.js @@ -34,6 +34,10 @@ String.prototype.zeroPad = function(len) { return len ? this.prePad(len, '0') : this; }; +String.prototype.regEsc = function() { + return this.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&"); +} + /** * selectField.addOptions takes an array or keyed object */ @@ -66,6 +70,7 @@ var configuratorApp = (function(){ // Return this anonymous object as configuratorApp return { my_public_var: 4, + logging: 1, init: function() { self = this; // a 'this' for use when 'this' is something else @@ -74,7 +79,7 @@ var configuratorApp = (function(){ var $uploader = $('#file-upload'); var fileUploader = new BinaryFileUploader({ element: $uploader[0], - onFileLoad: function(file) { console.log(this); self.handleFileLoad(file, $uploader); } + onFileLoad: function(file) { self.handleFileLoad(file, $uploader); } }); if (!fileUploader.hasFileUploaderSupport()) alert('Your browser doesn\'t support the file reading API'); @@ -107,6 +112,7 @@ var configuratorApp = (function(){ success: function(txt) { // File contents into the textarea $config.text(txt); + // Get thermistor info too self.initThermistorsFromText(txt); }, error: errFunc @@ -130,7 +136,7 @@ var configuratorApp = (function(){ initBoardsFromText: function(txt) { boards_list = {}; - var r, findDef = new RegExp('[ \\t]*#define[ \\t]+(BOARD_[^ \\t]+)[ \\t]+(\\d+)[ \\t]*(//[ \\t]*)?(.+)?', 'gm'); + var r, findDef = new RegExp('[ \\t]*#define[ \\t]+(BOARD_[\\w_]+)[ \\t]+(\\d+)[ \\t]*(//[ \\t]*)?(.+)?', 'gm'); while((r = findDef.exec(txt)) !== null) { boards_list[r[1]] = r[2].prePad(3, '  ') + " — " + r[4].replace(/\).*/, ')'); } @@ -165,7 +171,7 @@ var configuratorApp = (function(){ this.initField('MOTHERBOARD'); break; default: - console.log("Can't parse "+filename); + this.log("Can't parse "+filename, 1); break; } }, @@ -247,6 +253,10 @@ var configuratorApp = (function(){ this.initField('TEMP_SENSOR_2'); this.initField('TEMP_SENSOR_BED'); + this.initField('TEMP_SENSOR_1_AS_REDUNDANT'); + this.initField('MAX_REDUNDANT_TEMP_SENSOR_DIFF'); + + this.initField('TEMP_RESIDENCY_TIME'); $('#serial_stepper').jstepper({ min: 0, @@ -266,58 +276,108 @@ var configuratorApp = (function(){ // prettyPrint(); }, + /** + * initField - make a field responsive and get info + * about its configuration file define + */ initField: function(name) { - var $elm = $('#'+name), isText = $elm.attr('type') == 'text'; + var $elm = $('#'+name), elm = $elm[0]; + if (elm.configInfo === undefined) { + elm.configInfo = this.getDefineInfo(name); + $elm.on($elm.attr('type') == 'text' ? 'input' : 'change', this.handleChange); + } this.setFieldFromDefine(name); - isText ? $elm.bind('input', this.handleChange) : $elm.change(this.handleChange) }, handleChange: function(e) { - self.updateDefineForField(e.target); + self.updateDefineForField(e.target.id); }, handleSwitch: function(e) { var $elm = $(e.target), $prev = $elm.prev(); var on = $elm.prop('checked') || false; $prev.attr('disabled', !on); - self.setDefineEnabled($prev[0], on); + self.setDefineEnabled($prev[0].id, on); }, - setDefineEnabled: function(elm, val) { - var $elm = $(elm); + setDefineEnabled: function(name, val) { + this.log('setDefineEnabled:'+name,3); - // console.log("Enable: " + elm.id + " = " + val); + var $elm = $('#'+name), elm = $elm[0], inf = elm.configInfo; + var $c = $config; // for now + var txt = $c.text(); - var txt = $config.text(); + var slash = val ? '' : '// '; + var newline = inf.line + .replace(/^([ \t]*)(\/\/)([ \t]*)/, '$1$3') // remove slashes + .replace('#define', slash + '#define'); // add them back - var findDef = new RegExp('^[ \\t]*(//[ \\t]*)?(#define[ \\t]+' + elm.id + '([ \\t].*)?)$', 'm'); - txt = txt.replace(findDef, val ? '$2': '//$2'); + txt = txt.replace(inf.line, newline); + inf.line = newline; + this.log(newline, 2); - // Now set the text in the field - $config.text(txt); + $c.text(txt); }, - updateDefineForField: function(elm) { - var $elm = $(elm), - isCheck = $elm.attr('type') == 'checkbox', + defineIsEnabled: function(name, adv) { + this.log('defineIsEnabled:'+name,4); + var $elm = $('#'+name), elm = $elm[0]; + var $c = adv ? $config_adv : $config; + + var result = elm.configInfo.regex.exec($c.text()); + this.log(result,2); + + var on = result !== null ? result[1].trim() != '//' : true; + this.log(name + ' = ' + on, 4); + + return on; + }, + + updateDefineForField: function(name, adv) { + this.log('updateDefineForField:'+name,4); + var $elm = $('#'+name), elm = $elm[0], inf = elm.configInfo; + var $c = adv ? $config_adv : $config; + var txt = $c.text(); + + // var result = inf.repl.exec(txt); + // this.log(result, 2); + + var isCheck = $elm.attr('type') == 'checkbox', val = isCheck ? $elm.prop('checked') : $elm.val(); - // console.log("Set: " + elm.id + " = " + val); - - var txt = $config.text(); - - if (isCheck) { - var findDef = new RegExp('^([ \\t]*)(//[ \\t]*)?(#define[ \\t]+' + elm.id + '([ \\t].*)?)$', 'm'); - txt = txt.replace(findDef, val ? '$1$3': '$1//$3'); + var newline; + switch(inf.type) { + case 'switch': + var slash = val ? '' : '//'; + newline = (inf.pre + slash + inf.define + inf.post); + break; + case 'quoted': + if (isCheck) { + this.log(name + ' should not be a checkbox', 1); + var slash = val ? '' : '//'; + newline = (inf.pre + slash + inf.define + '"'+val+'"' + inf.post); + } + else { + newline = inf.pre + inf.define + '"'+val+'"' + inf.post; + } + break; + case 'plain': + if (isCheck) { + this.log(name + ' should not be a checkbox', 1); + var slash = val ? '' : '//'; + newline = (inf.pre + slash + inf.define + val + inf.post); + } + else { + newline = inf.pre + inf.define + val + inf.post; + } + break; } - else { - // Match the define name, 1 = "#define name ", 3=value, 4=comment - var findDef = new RegExp('^([ \\t]*(//)?[ \\t]*#define[ \\t]+' + elm.id + '[ \\t]+)(.*)([ \\t]*(//)?.*)$', 'm'); - if ($elm.hasClass('quote')) val = '"' + val + '"' - txt = txt.replace(findDef, '$1!!REGEXP!!$4').replace('!!REGEXP!!', val); - } - // Now set the text in the field - $config.text(txt); + + txt = txt.replace(inf.line, newline); + inf.line = newline; + this.log(newline, 2); + + $c.text(txt); }, setFieldFromDefine: function(name, adv) { @@ -325,6 +385,8 @@ var configuratorApp = (function(){ var isCheck = $elm.attr('type') == 'checkbox'; var val = this.defineValue(name, adv); + this.log('setFieldFromDefine:' + name + ' to ' + val, 4); + isCheck ? $elm.prop('checked', val) : $elm.val("" + val); // If the item has a checkbox then set enabled state too @@ -336,40 +398,88 @@ var configuratorApp = (function(){ } }, - defineValue: function(name, adv) { + getDefineInfo: function(name, adv) { + this.log('getDefineInfo:'+name,4); var $elm = $('#'+name), elm = $elm[0]; var $c = adv ? $config_adv : $config; - if ($elm.attr('type') == 'checkbox') { - // maybe spaces, maybe comment, #define, spaces, name, maybe a comment - var findDef = new RegExp('^[ \\t]*(//[ \\t]*)?(#define[ \\t]+' + elm.id + '([ \\t]*(//)?.*)?)$', 'm'); - var result = findDef.exec($c.text()); - return (result ? result[1] == undefined || result[1].trim() != '//' : false); + + // a switch line with no value + var findDef = new RegExp('^(.*//)?(.*#define[ \\t]+' + elm.id + ')([ \\t]*/[*/].*)?$', 'm'); + var result = findDef.exec($c.text()); + if (result !== null) { + var info = { + type: 'switch', + line: result[0], // whole line + pre: result[1] === undefined ? '' : result[1].replace('//',''), + define: result[2], + post: result[3] === undefined ? '' : result[3] + }; + info.regex = new RegExp('(.*//)?(.*' + info.define.regEsc() + info.post.regEsc() + ')', 'm'); + info.repl = info.regex; + this.log(info,2); + return info; } - else { - // maybe spaces, maybe comment, #define, spaces, name, one or more spaces, value, maybe a comment - var findDef = new RegExp('^([ \\t]*(//[ \\t]*)?#define[ \\t]+' + elm.id + '[ \\t]+)(.*)([ \\t]*(//)?.*)$', 'm'); - var result = findDef.exec($c.text()); - if (result !== null) { - var val = result[3]; - if (val.search(/^".*"$/) >= 0) $elm.addClass('quote'); - if ($elm.hasClass('quote')) val = val.replace(/^"(.*)"$/, '$1'); - return val; - } - return 'fail'; + + // a define with quotes + findDef = new RegExp('^(.*//)?(.*#define[ \\t]+' + elm.id + '[ \\t]+)("[^"]*")([ \\t]*/[*/].*)?$', 'm'); + result = findDef.exec($c.text()); + if (result !== null) { + var info = { + type: 'quoted', + line: result[0], + pre: result[1] === undefined ? '' : result[1].replace('//',''), + define: result[2], + post: result[4] === undefined ? '' : result[4] + }; + info.regex = new RegExp('(.*//)?.*' + info.define.regEsc() + '"([^"]*)"' + info.post.regEsc(), 'm'); + info.repl = new RegExp('((.*//)?.*' + info.define.regEsc() + '")[^"]*("' + info.post.regEsc() + ')', 'm'); + this.log(info,2); + return info; + } + + // a define with no quotes + findDef = new RegExp('^(.*//)?(.*#define[ \\t]+' + elm.id + '[ \\t]+)(\\S*)([ \\t]*/[*/].*)?$', 'm'); + result = findDef.exec($c.text()); + if (result !== null) { + var info = { + type: 'plain', + line: result[0], + pre: result[1] === undefined ? '' : result[1].replace('//',''), + define: result[2], + post: result[4] === undefined ? '' : result[4] + }; + info.regex = new RegExp('(.*//)?.*' + info.define.regEsc() + '(\\S*)' + info.post.regEsc(), 'm'); + info.repl = new RegExp('((.*//)?.*' + info.define.regEsc() + ')\\S*(' + info.post.regEsc() + ')', 'm'); + this.log(info,2); + return info; + } + + return null; + }, + + defineValue: function(name, adv) { + this.log('defineValue:'+name,4); + var $elm = $('#'+name), elm = $elm[0]; + var $c = adv ? $config_adv : $config; + var inf = elm.configInfo; + + var result = inf.regex.exec($c.text()); + this.log(result,2); + switch(inf.type) { + case 'switch': return result[1] != '//'; + case 'quoted': return result[2]; + case 'plain': return result[2]; } }, - defineIsEnabled: function(name, adv) { - var $elm = $('#'+name); - var $c = adv ? $config_adv : $config; - var findDef = new RegExp('^[ \\t]*(//[ \\t]*)?(#define[ \\t]+' + name + '([ \\t]*(//)?.*)?)$', 'm'); - var result = findDef.exec($c.text()); - return (result ? result[1].trim() != '//' : false); + log: function(o,l) { + if (l === undefined) l = 0; + if (this.logging>=l*1) console.log(o); }, logOnce: function(o) { if (typeof o.didLogThisObject === 'undefined') { - console.log(o); + this.log(o); o.didLogThisObject = true; } },