diff --git a/web/package-lock.json b/web/package-lock.json index d268683e86..7d1c95809f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -80,7 +80,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "arr-union": { @@ -104,13 +104,13 @@ "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", "dev": true }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", "dev": true }, "assign-symbols": { @@ -128,7 +128,7 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", "dev": true }, "atob": { @@ -578,7 +578,7 @@ "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", "dev": true, "requires": { "color-name": "^1.1.1" @@ -644,7 +644,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "cookie": { @@ -716,7 +716,7 @@ "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -1816,7 +1816,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -2087,7 +2087,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, "is-builtin-module": { @@ -2275,7 +2275,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -2300,7 +2300,7 @@ "karma-chrome-launcher": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=", "dev": true, "requires": { "fs-access": "^1.0.0", @@ -2310,7 +2310,7 @@ "karma-edge-launcher": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/karma-edge-launcher/-/karma-edge-launcher-0.4.2.tgz", - "integrity": "sha512-YAJZb1fmRcxNhMIWYsjLuxwODBjh2cSHgTW/jkVmdpGguJjLbs9ZgIK/tEJsMQcBLUkO+yO4LBbqYxqgGW2HIw==", + "integrity": "sha1-PZUpsJsTyQnF887uEtAOf5qYmz0=", "dev": true, "requires": { "edge-launcher": "1.2.2" @@ -2319,7 +2319,7 @@ "karma-firefox-launcher": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz", - "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==", + "integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=", "dev": true }, "karma-fixture": { @@ -2386,7 +2386,7 @@ "ansi-styles": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -2432,7 +2432,7 @@ "karma-teamcity-reporter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/karma-teamcity-reporter/-/karma-teamcity-reporter-1.1.0.tgz", - "integrity": "sha512-Ca1uhHGtNqUuzsnW3I+QykNuS/jF9vdxnIrkbLCVJRunCc6yWJq+ai1UobQT13j0e3JVUOf0mKo3QHZ6A6mG9Q==", + "integrity": "sha1-eYD33JHmqwhH4SKt4Ls0x8b0KBY=", "dev": true }, "kind-of": { @@ -2484,7 +2484,7 @@ "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", "dev": true, "requires": { "chalk": "^2.0.1" @@ -2493,7 +2493,7 @@ "ansi-styles": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -2632,7 +2632,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -2790,7 +2790,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -3099,7 +3099,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -3236,7 +3236,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", "dev": true }, "safe-regex": { @@ -3612,7 +3612,7 @@ "streamroller": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", "dev": true, "requires": { "date-format": "^1.2.0", @@ -3652,7 +3652,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -3695,7 +3695,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -3792,7 +3792,7 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", "dev": true }, "underscore": { @@ -4025,7 +4025,7 @@ "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "dev": true, "requires": { "isexe": "^2.0.0" @@ -4062,7 +4062,7 @@ "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", "dev": true, "requires": { "async-limiter": "~1.0.0", diff --git a/web/testing/regression-tests/src/known-failures.js b/web/testing/regression-tests/src/known-failures.js index a5ba9a9488..f493227863 100644 --- a/web/testing/regression-tests/src/known-failures.js +++ b/web/testing/regression-tests/src/known-failures.js @@ -12,13 +12,20 @@ * Hint: searching for "FAILED TO LOAD" in logs finds the first reference to the * failure for any given keyboard. */ + const knownFailures = { - 'fv_gwichin': { /*, knownGoodCompilerVersion: '12.0.333.0', knownGoodEngineVersion: '12.0.444'*/ reason: 'Chrome ladder bug #183?' }, - 'fv_han': { reason: 'Chrome ladder bug #183?' }, - 'fv_northern_tutchone': { reason: 'Chrome ladder bug #183?' }, - 'fv_southern_tutchone': { reason: 'Chrome ladder bug #183?' }, - 'fv_tagizi_dene': { reason: 'Chrome ladder bug #183?' }, + 'clavbur9': { reason: 'KCCM generated but not supported #1711' }, + 'fv_gwichin': { /*, knownGoodCompilerVersion: '12.0.333.0', knownGoodEngineVersion: '12.0.444'*/ reason: 'Chrome ladder bug #183' }, + 'fv_han': { reason: 'Chrome ladder bug #183' }, + 'fv_northern_tutchone': { reason: 'Chrome ladder bug #183' }, + 'fv_southern_tutchone': { reason: 'Chrome ladder bug #183' }, + 'fv_tagizi_dene': { reason: 'Chrome ladder bug #183' }, 'hieroglyphic': { reason: 'Chrome ladder bug #183' }, 'nailangs': { reason: 'kmanalyze is corrupting the .tests file' }, 'sil_ipa': { reason: 'kmanalyze is corrupting the .tests file' } -}; \ No newline at end of file +}; + +// Node compatibility +if(typeof module === 'object') { + module.exports = knownFailures; +} \ No newline at end of file diff --git a/web/testing/regression-tests/test-builder.js b/web/testing/regression-tests/test-builder.js index b85e1292f7..a61725f781 100644 --- a/web/testing/regression-tests/test-builder.js +++ b/web/testing/regression-tests/test-builder.js @@ -41,7 +41,7 @@ keyboards.forEach(function(keyboard) { it('should generate a set of results for "all" possible inputs', function() { return windowLoad .then(() => testRunner.loadTests(locator)) - .then((shouldRun) => { if(shouldRun) { testRunner.runTests(id); } return shouldRun; }) + .then((shouldRun) => { if(shouldRun) { return testRunner.runTests(id); } }) .then(() => testRunner.saveTestResults(locator, (testRunner.keyboards[id] || {}).results)); }).timeout(0); }); diff --git a/web/testing/regression-tests/test.js b/web/testing/regression-tests/test.js index ec1273eac3..adca5e9fcb 100644 --- a/web/testing/regression-tests/test.js +++ b/web/testing/regression-tests/test.js @@ -14,6 +14,7 @@ const rimraf = require('rimraf'); const config = require('./node_src/config.js'); const util = require('./node_src/util.js'); const keyname = require('./node_src/keyname.js'); +const knownFailures = require('./src/known-failures.js'); function list(val) { return val.split(','); @@ -25,6 +26,7 @@ program .option('-e, --engine-versions [versions]', 'Specify KeymanWeb engine version(s) to test. Can specify "stable", "source" or a specific version number.', list, ['stable','source']) .option('-k, --keyboards [keyboards]', 'Builds and tests specific keyboard source files. If -k is not specified, then test all keyboards in the keyboards repository.', list, []) .option('-f, --fail-fast', "Don't attempt to continue tests after the first keyboard test fails") + .option('-d, --debug', "Build keyboard with debug symbols") .option('--deep', "Compare all version combinations against base version, instead of just one; only valid when comparing 1 version of each against base") .option('--skip-analysis', "Don't create .tests files, assume they are already present") .option('-l, --log-all-failures', "Log all test failures to console, not just the first failure for each keyboard"); @@ -189,7 +191,7 @@ cleanKeyboards.then(() => { return util.runProcess( `${bash.command}`, - [].concat(bash.params, ['build.sh', /*TODO: waiting on keyboards repo support for this param: '-T', 'kmn',*/ keyboard]), + [].concat(bash.params, ['build.sh'], program.debug?['-d']:[], [/*TODO: waiting on keyboards repo support for this param: '-T', 'kmn',*/ keyboard]), { cwd: config.KEYBOARDS_ROOT }); }; @@ -326,6 +328,12 @@ cleanKeyboards.then(() => { keyboards.forEach((keyboard) => { if(!program.keyboards.length || program.keyboards.indexOf(keyboard.shortname+'/'+keyboard.id) >= 0) { // Validate each of the test files against the first tested compiler+engine version + + let localFailCount = 0; + const localFail = knownFailures.hasOwnProperty([keyboard.id]) ? + (msg) => { if(++localFailCount == 1) console.warn(`WARN: Not failing test because ${keyboard.id} is in known-failures.`); console.warn(`WARN: ${msg}`); } : + fail; + try { const baseResultFilename = path.join(KEYBOARDS_ROOT, keyboard.shortname, keyboard.id, 'tests', `${keyboard.id}-${baseCompilerVersion}-${baseEngineVersion}.results`); const baseResult = fs.readFileSync(baseResultFilename, 'utf8'); @@ -333,15 +341,21 @@ cleanKeyboards.then(() => { const testsFilename = path.join(KEYBOARDS_ROOT, keyboard.shortname, keyboard.id, 'tests', `${keyboard.id}.tests`); const testsJSON = JSON.parse(fs.readFileSync(testsFilename, 'utf8')); + const numTests = Object.keys(testsJSON.inputTests).length; // First, check the base result for errors for(let k in baseResultJSON) { if(typeof baseResultJSON[k] !== 'string') { let input = `${testsJSON.inputTests[k].context ? `"${testsJSON.inputTests[k].context}" ` : ""}+ ${keyname(testsJSON.inputTests[k].modifier, testsJSON.inputTests[k].key)}`; - fail(`${keyboard.shortname}/${keyboard.id}[${k}]: error in test: ${input}: ${baseResultJSON[k].error}`, 5); + localFail(`${keyboard.shortname}/${keyboard.id}[${k}]: error in test: ${input}: ${baseResultJSON[k].error}`, 5); } } + // Make sure every test is in the base result set + if(Object.keys(baseResultJSON).length != numTests) { + localFail(`${keyboard.shortname}/${keyboard.id}: base result set has fewer results (${Object.keys(baseResultJSON).length}) than expected (${numTests})`, 6); + } + //console.log(baseResultFilename, baseResult); testedCompilerVersions.forEach((cv) => { testedEngineVersions.forEach((ev) => { @@ -365,13 +379,12 @@ cleanKeyboards.then(() => { } } } - fail(`${keyboard.shortname}/${keyboard.id} ${errors} test(s) mismatched between (${baseCompilerVersion} / ${baseEngineVersion}) and (${cv} / ${ev})`, 4); + localFail(`${keyboard.shortname}/${keyboard.id} ${errors}/${numTests} test(s) mismatched between (${baseCompilerVersion} / ${baseEngineVersion}) and (${cv} / ${ev})`, 4); } }); }); } catch(e) { - // TODO: only continue if in known-failures? - console.warn(`Failed to load test results for ${keyboard.shortname}/${keyboard.id}: ${typeof e == 'object' ? e.message : e}`); + localFail(`Failed to load test results for ${keyboard.shortname}/${keyboard.id}: ${typeof e == 'object' ? e.message : e}`, 7); } } }); diff --git a/windows/src/developer/TIKE/compile/CompileKeymanWeb.pas b/windows/src/developer/TIKE/compile/CompileKeymanWeb.pas index fd11a313e4..2036b8041c 100644 --- a/windows/src/developer/TIKE/compile/CompileKeymanWeb.pas +++ b/windows/src/developer/TIKE/compile/CompileKeymanWeb.pas @@ -211,7 +211,9 @@ type FTabStop: string; // I3681 fMnemonic: Boolean; FCompilerWarningsAsErrors: Boolean; - FTouchLayoutFont: string; // I4872 + FTouchLayoutFont: string; + FFix183_LadderLength: Integer; + FCloseBrace: Boolean; // I4872 function JavaScript_String(ch: DWord): string; // I2242 @@ -227,8 +229,10 @@ type function JavaScript_Key(fkp: PFILE_KEY; FMnemonic: Boolean): Integer; function JavaScript_KeyAsString(fkp: PFILE_KEY; FMnemonic: Boolean): string; function JavaScript_ContextLength(Context: PWideChar): Integer; - function JavaScript_OutputString(fkp: PFILE_KEY; pwszOutput: PWideChar; fgp: PFILE_GROUP): string; + function JavaScript_OutputString(FTabstops: string; fkp: PFILE_KEY; pwszOutput: PWideChar; fgp: PFILE_GROUP): string; function JavaScript_ContextMatch(fkp: PFILE_KEY; context: PWideChar): string; + function JavaScript_Rule(FTabStops, FElse: string; fgp: PFILE_GROUP; fkp: PFILE_KEY): string; + function JavaScript_Rules(fgp: PFILE_GROUP): string; function JavaScript_CompositeContextValue(fkp: PFILE_KEY; pwsz: PWideChar): string; function JavaScript_FullContextValue(fkp: PFILE_KEY; pwsz: PWideChar): string; function RuleIsExcludedByPlatform(fkp: PFILE_KEY): Boolean; @@ -264,6 +268,7 @@ uses CompileErrorCodes, JsonUtil, + KeymanDeveloperOptions, KeyboardParser, Keyman.System.KeyboardUtils, KeymanWebKeyCodes, @@ -377,6 +382,7 @@ end; constructor TCompileKeymanWeb.Create; begin FillChar(fk, sizeof(fk), 0); + FFix183_LadderLength := FKeymanDeveloperOptions.Fix183_LadderLength; // How frequently to break ladders end; destructor TCompileKeymanWeb.Destroy; @@ -637,6 +643,142 @@ begin else Result := JavaScript_CompositeContextValue(fkp, context); end; +function TCompileKeymanWeb.JavaScript_Rule(FTabStops, FElse: string; fgp: PFILE_GROUP; fkp: PFILE_KEY): string; +var + predicate, linecomment: string; + FIndent: string; +begin + Result := ''; + + if (fkp.Line > 0) and FDebug // I4384 + then linecomment := Format(' // Line %d', [fkp.Line]) // I4373 + else linecomment := ''; + + if xstrlen(fkp.dpContext) > 0 + then predicate := JavaScript_ContextMatch(fkp, fkp.dpContext) + else predicate := '1'; // Always pass + + FIndent := FTabStops+FTabStop; + FCloseBrace := True; + Result := Result + Format('%s%sif(%s){%s', [ + FTabStops, + FElse, + predicate, + nl + ]); + + if(fgp.fUsingKeys) // I1959 + then Result := Result + Format('%sr=m=1;%s%s', [FIndent,linecomment,JavaScript_OutputString(FIndent, fkp, fkp.dpOutput, fgp)]) // I1959 // I3681 + else Result := Result + Format('%sm=1;%s%s', [FIndent,linecomment,JavaScript_OutputString(FIndent, fkp, fkp.dpOutput, fgp)]); // I1959 // I3681 + if not FCloseBrace + then Result := Result + nl + else Result := Result + Format('%s%s}%s', [nl, FTabStops, nl]); // I3681 +end; + +function TCompileKeymanWeb.JavaScript_Rules(fgp: PFILE_GROUP): string; + function IsEqualKey(k1, k2: PFILE_KEY): Boolean; + begin + Result := + (JavaScript_Key(k1, FMnemonic) = JavaScript_Key(k2, FMnemonic)) and + (JavaScript_Shift(k1, FMnemonic) = JavaScript_Shift(k2, FMnemonic)); + end; + +var + j, j2: Integer; + HasRules: Boolean; + fkp2, fkp: PFILE_KEY; + processed_rule: array of Boolean; + LocalHasRules: Boolean; + LocalCounter: Integer; + Counter: Integer; +begin + Result := ''; + fkp := fgp.dpKeyArray; + HasRules := False; + + SetLength(processed_rule, fgp.cxKeyArray); + for j := 0 to Integer(fgp.cxKeyArray) - 1 do + processed_rule[j] := False; + + j := 0; + Counter := 0; + while j < Integer(fgp.cxKeyArray) do // I1964 + begin + if not processed_rule[j] and not RuleIsExcludedByPlatform(fkp) then + begin + // Break down by key code + // We know the rules are sorted by context length and then key code. + // First pass, break the grouping down by key code. + + if fgp.fUsingKeys then + begin + Result := Result + Format('%s%sif(k.KKM(e,%s,%s)) {%s', + [ + FTabStop+FTabStop, + IfThen(HasRules, 'else ', ''), + JavaScript_ShiftAsString(fkp, fMnemonic), + JavaScript_KeyAsString(fkp, fMnemonic), + nl + ]); + + HasRules := True; + Inc(Counter); + + LocalHasRules := False; + fkp2 := fkp; + j2 := j; + LocalCounter := 0; + while (j < Integer(fgp.cxKeyArray)) do + begin + if not processed_rule[j] and not RuleIsExcludedByPlatform(fkp) and IsEqualKey(fkp, fkp2) then + begin + processed_rule[j] := True; + Result := Result + JavaScript_Rule(FTabStop + FTabStop + FTabStop, IfThen(LocalHasRules, 'else ', ''), fgp, fkp); + Inc(LocalCounter); + + if (FFix183_LadderLength <> 0) and ((LocalCounter mod FFix183_LadderLength) = 0) then + begin + // Break if/else ladders + Result := Result + Format('%sif(m) {}%s', [FTabStop + FTabStop + FTabStop, nl]); + end; + LocalHasRules := True; + end; + + Inc(fkp); + Inc(j); + end; + + Result := Result + FTabStop + FTabStop + '}' + nl; + fkp := fkp2; + j := j2 + 1; + Inc(fkp); + // Inc(j); + end + else + begin + // TODO: context character level switches instead of full context comparisons + Result := Result + JavaScript_Rule(FTabStop + FTabStop + FTabStop, IfThen(HasRules, 'else ', ''), fgp, fkp); + HasRules := True; + Inc(Counter); + Inc(fkp); + Inc(j); + end; + + if (FFix183_LadderLength <> 0) and ((Counter mod FFix183_LadderLength) = 0) then + begin + // Break if/else ladders + // We need to only match if no previous line is matched (i.e. m is false) + Result := Result + Format('%sif(m) {}%s', [FTabStop + FTabStop + FTabStop, nl]); + end; + end + else + begin + Inc(fkp); + Inc(j); + end; + end; +end; + const // I1585 - add space to conversion USEnglishUnshift: WideString = ' `' + '1234567890' + '-' + '=' + 'qwertyuiop' + '[' + ']' + '\' + 'asdfghjkl' + ';' + '''' + 'zxcvbnm' + ',' + '.' + '/'; USEnglishShift: WideString = #$FF'~' + '!@#$%^&*()' + '_' + '+' + 'QWERTYUIOP' + '{' + '}' + '|' + 'ASDFGHJKL' + ':' + '"' + 'ZXCVBNM' + '<' + '>' + '?'; @@ -738,7 +880,7 @@ begin end; end; -function TCompileKeymanWeb.JavaScript_OutputString(fkp: PFILE_KEY; pwszOutput: PWideChar; fgp: PFILE_GROUP): string; +function TCompileKeymanWeb.JavaScript_OutputString(FTabstops: string; fkp: PFILE_KEY; pwszOutput: PWideChar; fgp: PFILE_GROUP): string; var i, n, len: Integer; InQuotes: Boolean; @@ -816,7 +958,7 @@ var end; begin - nlt := nl + FTabstop+FTabstop+FTabstop; // I3681 + nlt := nl + FTabStops; // I3681 Result := ''; InQuotes := False; @@ -1869,47 +2011,55 @@ begin fkp := fgp.dpKeyArray; HasRules := False; - for j := 0 to Integer(fgp.cxKeyArray) - 1 do // I1964 + + if FFix183_LadderLength <> 0 then begin - if not RuleIsExcludedByPlatform(fkp) then + Result := Result + JavaScript_Rules(fgp); + end + else + begin + for j := 0 to Integer(fgp.cxKeyArray) - 1 do // I1964 begin - Result := Result + FTabstop+FTabstop; // I3681 - if HasRules then Result := Result + 'else '; - HasRules := TRue; - if fgp.fUsingKeys then + if not RuleIsExcludedByPlatform(fkp) then begin - Result := Result + Format('if(k.KKM(e,%s,%s)', - [JavaScript_ShiftAsString(fkp, fMnemonic), - JavaScript_KeyAsString(fkp, fMnemonic)]); + Result := Result + FTabstop+FTabstop; // I3681 + if HasRules then Result := Result + 'else '; + HasRules := TRue; + if fgp.fUsingKeys then + begin + Result := Result + Format('if(k.KKM(e,%s,%s)', + [JavaScript_ShiftAsString(fkp, fMnemonic), + JavaScript_KeyAsString(fkp, fMnemonic)]); + end; + + if xstrlen(fkp.dpContext) > 0 then + begin + if not fgp.fUsingKeys + then Result := Result + 'if(' + else Result := Result + '&&'; + + Result := Result + JavaScript_ContextMatch(fkp, fkp.dpContext); + end + else if not fgp.fUsingKeys then + Result := Result + 'if(1'; + + if (fkp.Line > 0) and FDebug // I4384 + then linecomment := Format(' // Line %d', [fkp.Line]) // I4373 + else linecomment := ''; + + Result := Result + Format( + ') {%s%s'+ + '%s', + [linecomment, nl, + FTabstop+FTabstop+FTabstop]); // I3681 + if(fgp.fUsingKeys) // I1959 + then Result := Result + Format('r=m=1;%s', [JavaScript_OutputString(FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp)]) // I1959 // I3681 + else Result := Result + Format('m=1;%s', [JavaScript_OutputString(FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp)]); // I1959 // I3681 + Result := Result + Format('%s%s}%s', [nl, FTabstop+FTabstop, nl]); // I3681 end; - - if xstrlen(fkp.dpContext) > 0 then - begin - if not fgp.fUsingKeys - then Result := Result + 'if(' - else Result := Result + '&&'; - - Result := Result + JavaScript_ContextMatch(fkp, fkp.dpContext); - end - else if not fgp.fUsingKeys then - Result := Result + 'if(1'; - - if (fkp.Line > 0) and FDebug // I4384 - then linecomment := Format(' // Line %d', [fkp.Line]) // I4373 - else linecomment := ''; - - Result := Result + Format( - ') {%s%s'+ - '%s', - [linecomment, nl, - FTabstop+FTabstop+FTabstop]); // I3681 - if(fgp.fUsingKeys) // I1959 - then Result := Result + Format('r=m=1;%s', [JavaScript_OutputString(fkp, fkp.dpOutput, fgp)]) // I1959 // I3681 - else Result := Result + Format('m=1;%s', [JavaScript_OutputString(fkp, fkp.dpOutput, fgp)]); // I1959 // I3681 - Result := Result + Format('%s%s}%s', [nl, FTabstop+FTabstop, nl]); // I3681 + Inc(fkp); end; - Inc(fkp); - end; + end; if Assigned(fgp.dpMatch) then Result := Result + Format( @@ -1917,7 +2067,7 @@ begin '%s%s%s'+ '%s}%s', [FTabstop+FTabstop, nl, - FTabstop+Ftabstop, JavaScript_OutputString(nil, fgp.dpMatch, fgp), nl, + FTabstop+Ftabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpMatch, fgp), nl, FTabstop+FTabstop, nl]); // I3681 if Assigned(fgp.dpNoMatch) then if fgp.fUsingKeys then // I1382 - fixup m=1 to m=g() @@ -1926,7 +2076,7 @@ begin '%sr=1;%s%s'+ '%s}%s', [FTabstop+FTabstop, nl, - FTabstop+FTabstop+FTabstop, JavaScript_OutputString(nil, fgp.dpNoMatch, fgp), nl, + FTabstop+FTabstop+FTabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpNoMatch, fgp), nl, FTabstop+FTabstop, nl]) // I1959. part 2, I2224 // I3681 else Result := Result + Format( @@ -1934,7 +2084,7 @@ begin '%s%s%s'+ '%s}%s', [FTabstop+FTabstop, nl, - FTabstop+FTabstop, JavaScript_OutputString(nil, fgp.dpNoMatch, fgp), nl, + FTabstop+FTabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpNoMatch, fgp), nl, FTabstop+FTabstop, nl]); // I1959 // I3681 Result := Result + Format('%sreturn r;%s'+ diff --git a/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas b/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas index f5c9fcfc78..237b40033b 100644 --- a/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas +++ b/windows/src/developer/TIKE/main/KeymanDeveloperOptions.pas @@ -59,6 +59,7 @@ type FOpenKeyboardFilesInSourceView: Boolean; // I4751 FDisplayTheme: string; FEditorTheme: string; + FFix183_LadderLength: Integer; procedure CloseRegistry; procedure OpenRegistry; function regReadString(const nm, def: string): string; @@ -83,6 +84,7 @@ type property CharMapAutoLookup: Boolean read FCharMapAutoLookup write FCharMapAutoLookup; property CharMapDisableDatabaseLookups: Boolean read FCharMapDisableDatabaseLookups write FCharMapDisableDatabaseLookups; + property Fix183_LadderLength: Integer read FFix183_LadderLength write FFix183_LadderLength; property DebuggerBreakWhenExitingLine: Boolean read FDebuggerBreakWhenExitingLine write FDebuggerBreakWhenExitingLine; property DebuggerSingleStepAfterBreak: Boolean read FDebuggerSingleStepAfterBreak write FDebuggerSingleStepAfterBreak; property DebuggerShowStoreOffset: Boolean read FDebuggerShowStoreOffset write FDebuggerShowStoreOffset; @@ -196,6 +198,8 @@ begin FExternalEditorPath := regReadString(SRegValue_IDEOptExternalEditorPath, ''); FSMTPServer := regReadString(SRegValue_IDEOptSMTPServer, ''); // I4506 FTestEmailAddresses := regReadString(SRegValue_IDEOptTestEmailAddresses, ''); // I4506 + + FFix183_LadderLength := regReadInt(SRegValue_IDEOpt_WebLadderLength, CRegValue_IDEOpt_WebLadderLength_Default); finally CloseRegistry; end; @@ -233,6 +237,8 @@ begin regWriteString(SRegValue_IDEOptExternalEditorPath, FExternalEditorPath); regWriteString(SRegValue_IDEOptSMTPServer, FSMTPServer); // I4506 regWriteString(SRegValue_IDEOptTestEmailAddresses, FTestEmailAddresses); // I4506 + + regWriteInt(SRegValue_IDEOpt_WebLadderLength, FFix183_LadderLength); finally CloseRegistry; end; diff --git a/windows/src/global/delphi/general/RegistryKeys.pas b/windows/src/global/delphi/general/RegistryKeys.pas index 1b51a67f66..d1bf0c393a 100644 --- a/windows/src/global/delphi/general/RegistryKeys.pas +++ b/windows/src/global/delphi/general/RegistryKeys.pas @@ -394,6 +394,9 @@ const SRegValue_IDEOptSMTPServer = 'smtp server'; // CU // I4506 SRegValue_IDEOptTestEmailAddresses = 'test email addresses'; // CU // I4506 + SRegValue_IDEOpt_WebLadderLength = 'web ladder length'; // CU + CRegValue_IDEOpt_WebLadderLength_Default = 100; + { SRegKey_KCT values } // SRegValue_KCTTemplatePath = 'template path'; // LM